# -*- coding: utf-8 -*- # # Copyright 2016 Google LLC. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Submit build command.""" from __future__ import absolute_import from __future__ import division from __future__ import unicode_literals import textwrap from googlecloudsdk.api_lib.cloudbuild import cloudbuild_util from googlecloudsdk.calliope import base from googlecloudsdk.command_lib.builds import flags from googlecloudsdk.command_lib.builds import submit_util def _CommonArgs(parser): """Register flags for this command. Args: parser: An argparse.ArgumentParser-like object. It is mocked out in order to capture some information, but behaves like an ArgumentParser. Returns: worker pool flag group """ source = parser.add_mutually_exclusive_group() source.add_argument( 'source', nargs='?', default='.', # By default, the current directory is used. help=( 'The location of the source to build. The location can be a directory' ' on a local disk, an archive file (e.g., .zip, .tar.gz) or a' ' manifest file (.json) in Google Cloud Storage, a Git repo url' ' starting with http:// or https://, a 2nd-gen Cloud Build repository' ' resource, or a Developer Connect GitRepositoryLink resource. If the' ' source is a local directory, this command skips the files specified' ' in the `--ignore-file`. If `--ignore-file` is not specified,' ' use`.gcloudignore` file. If a `.gcloudignore` file is absent and a' ' `.gitignore` file is present in the local source directory, gcloud' ' will use a generated Git-compatible `.gcloudignore` file that' ' respects your .gitignored files. The global `.gitignore` is not' ' respected. For more information on `.gcloudignore`, see `gcloud' ' topic gcloudignore`.' ), ) source.add_argument( '--no-source', action='store_true', help='Specify that no source should be uploaded with this build.', ) flags.AddRegionFlag(parser) flags.AddServiceAccountFlag(parser) flags.AddGcsSourceStagingDirFlag(parser) flags.AddGcsLogDirFlag(parser) flags.AddTimeoutFlag(parser) flags.AddPollingIntervalFlag(parser) flags.AddMachineTypeFlag(parser) flags.AddDiskSizeFlag(parser) flags.AddSubstitutionsFlag(parser) flags.AddDefaultBucketsBehaviorFlag(parser) worker_pools = flags.AddWorkerPoolFlag(parser) flags.AddNoCacheFlag(parser) flags.AddAsyncFlag(parser) flags.AddSuppressLogsFlag(parser) parser.display_info.AddFormat(""" table( id, createTime.date('%Y-%m-%dT%H:%M:%S%Oz', undefined='-'), duration(start=startTime,end=finishTime,precision=0,calendar=false,undefined=" -").slice(2:).join(""):label=DURATION, build_source(undefined="-"):label=SOURCE, build_images(undefined="-"):label=IMAGES, status ) """) # Do not try to create a URI to update the cache. parser.display_info.AddCacheUpdater(None) flags.AddIgnoreFileFlag(parser) flags.AddConfigFlags(parser) parser.add_argument( '--git-source-dir', help="""\ Directory, relative to the source root, in which to run the build. This must be a relative path. If a step's `dir` is specified and is an absolute path, this value is ignored for that step's execution. """, ) parser.add_argument( '--git-source-revision', help="""\ Revision to fetch from the Git repository such as a branch, a tag, a commit SHA, or any Git ref to run the build. Cloud Build uses `git fetch` to fetch the revision from the Git repository; therefore make sure that the string you provide for `revision` is parsable by the command. For information on string values accepted by `git fetch`, see https://git-scm.com/docs/gitrevisions#_specifying_revisions. For information on `git fetch`, see https://git-scm.com/docs/git-fetch. """, ) parser.add_argument( '--dir', help=textwrap.dedent("""\ Directory, relative to the source root, in which to run the build. This is used when the build source is a 2nd-gen Cloud Build repository resource, or a Developer Connect GitRepositoryLink resource. This must be a relative path. If a step's `dir` is specified and is an absolute path, this value is ignored for that step's execution. """), ) parser.add_argument( '--revision', help=textwrap.dedent("""\ Revision to fetch from the Git repository such as a branch, a tag, a commit SHA, or any Git ref to run the build. This is used when the build source is a 2nd-gen Cloud Build repository resource, or a Developer Connect GitRepositoryLink resource. Cloud Build uses `git fetch` to fetch the revision from the Git repository; therefore make sure that the string you provide for `revision` is parsable by the command. For information on string values accepted by `git fetch`, see https://git-scm.com/docs/gitrevisions#_specifying_revisions. For information on `git fetch`, see https://git-scm.com/docs/git-fetch. """), ) return worker_pools @base.UniverseCompatible @base.ReleaseTracks(base.ReleaseTrack.GA) class Submit(base.CreateCommand): """Submit a build using Cloud Build. Submit a build using Cloud Build. """ detailed_help = { 'DESCRIPTION': """\ {description} When the `builds/use_kaniko` property is `True`, builds submitted with `--tag` will use Kaniko (https://github.com/GoogleContainerTools/kaniko) to execute builds. Kaniko executes directives in a Dockerfile, with remote layer caching for faster builds. By default, Kaniko will cache layers for 6 hours. To override this, set the `builds/kaniko_cache_ttl` property. """, 'EXAMPLES': """ To submit a build with source located at storage URL `gs://bucket/object.zip`: $ {command} "gs://bucket/object.zip" --tag=gcr.io/my-project/image To submit a build with source located at storage URL `gs://bucket/object.zip` using config file `config.yaml`: $ {command} "gs://bucket/object.zip" --tag=gcr.io/my-project/image --config=config.yaml To submit a build with source from a source manifest: $ {command} "gs://bucket/manifest.json" --tag=gcr.io/my-project/image --config=config.yaml To submit a build with local source `source.tgz` asynchronously: $ {command} "source.tgz" --tag=gcr.io/my-project/image --async To submit a build with source from a Git repository `https://github.com/owner/repo`: $ {command} "https://github.com/owner/repo" --git-source-revision=main --config=config.yaml To submit a build with source from a 2nd-gen Cloud Build repository resource `projects/my-project/locations/us-west1/connections/my-conn/repositories/my-repo`: $ {command} "projects/my-project/locations/us-west1/connections/my-conn/repositories/my-repo" --revision=main To submit a build with source from a Developer Connect GitRepositoryLink resource `projects/my-project/locations/us-west1/connections/my-conn/gitRepositoryLinks/my-repo-link`: $ {command} "projects/my-project/locations/us-west1/connections/my-conn/gitRepositoryLinks/my-repo-link" --revision=main """, } _support_gcl = False @staticmethod def Args(parser): _CommonArgs(parser) def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Some value that we want to have printed later. Raises: FailedBuildException: If the build is completed and not 'SUCCESS'. """ build_region = args.region messages = cloudbuild_util.GetMessagesModule() # Create the build request. build_config = submit_util.CreateBuildConfig( args.tag, args.no_cache, messages, args.substitutions, args.config, args.IsSpecified('source'), args.no_source, args.source, args.gcs_source_staging_dir, args.ignore_file, args.gcs_log_dir, args.machine_type, args.disk_size, args.worker_pool, args.git_source_dir, args.git_source_revision, args.dir, args.revision, args.service_account, args.pack, False, args.default_buckets_behavior, skip_set_source=True, client_tag='gcloudsubmits', ) build_region = submit_util.DetermineBuildRegion(build_config, build_region) build_region = build_region or cloudbuild_util.DEFAULT_REGION # Set build_config source with updated build_region. build_config = submit_util.SetSource( build_config, messages, args.IsSpecified('source'), args.no_source, args.source, args.gcs_source_staging_dir, args.dir, args.revision, args.git_source_dir, args.git_source_revision, args.ignore_file, False, build_region, args.default_buckets_behavior, ) # Start the build. build, _ = submit_util.Build( messages, args.async_, build_config, build_region=build_region, support_gcl=self._support_gcl, suppress_logs=args.suppress_logs, polling_interval=args.polling_interval) return build @base.ReleaseTracks(base.ReleaseTrack.BETA) class SubmitBeta(Submit): """Submit a build using Cloud Build. Submit a build using Cloud Build. """ _support_gcl = True @base.ReleaseTracks(base.ReleaseTrack.ALPHA) class SubmitAlpha(SubmitBeta): """Submit a build using Cloud Build. Submit a build using Cloud Build. """ @staticmethod def Args(parser): worker_pools = _CommonArgs(parser) flags.AddConfigFlagsAlpha(worker_pools) def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Some value that we want to have printed later. Raises: FailedBuildException: If the build is completed and not 'SUCCESS'. """ build_region = args.region messages = cloudbuild_util.GetMessagesModule() # Create the build request. build_config = submit_util.CreateBuildConfigAlpha( args.tag, args.no_cache, messages, args.substitutions, args.config, args.IsSpecified('source'), args.no_source, args.source, args.gcs_source_staging_dir, args.ignore_file, args.gcs_log_dir, args.machine_type, args.disk_size, args.memory, args.vcpu_count, args.worker_pool, args.dir, args.revision, args.git_source_dir, args.git_source_revision, args.pack, False, args.default_buckets_behavior, skip_set_source=True, client_tag='gcloudsubmits', ) build_region = submit_util.DetermineBuildRegion(build_config, build_region) build_region = build_region or cloudbuild_util.DEFAULT_REGION # Set build_config source with updated build_region. build_config = submit_util.SetSource( build_config, messages, args.IsSpecified('source'), args.no_source, args.source, args.gcs_source_staging_dir, args.dir, args.revision, args.git_source_dir, args.git_source_revision, args.ignore_file, False, build_region, args.default_buckets_behavior, ) # Start the build. build, _ = submit_util.Build( messages, args.async_, build_config, build_region=build_region, support_gcl=True, polling_interval=args.polling_interval) return build