# -*- coding: utf-8 -*- # # Copyright 2021 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. """Flags for the deploy command group.""" import textwrap from googlecloudsdk.calliope import arg_parsers from googlecloudsdk.calliope import base _SOURCE_HELP_TEXT = """ The location of the source that contains skaffold.yaml. The location can be a directory on a local disk or a gzipped archive file (.tar.gz) in Google Cloud Storage. 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. """ def AddGcsSourceStagingDirFlag(parser, hidden=False): """Adds a Google Cloud Storage directory flag for staging the build.""" parser.add_argument( '--gcs-source-staging-dir', hidden=hidden, help=( 'A directory in Google Cloud Storage to copy the source used for ' 'staging the build. If the specified bucket does not exist, Cloud ' "Deploy will create one. If you don't set this field, " '```gs://[DELIVERY_PIPELINE_ID]_clouddeploy/source``` is used.' ), ) def AddIgnoreFileFlag(parser, hidden=False): """Adds an ignore file flag.""" parser.add_argument( '--ignore-file', hidden=hidden, help=( 'Override the `.gcloudignore` file and use the specified file ' 'instead.' ), ) def AddToTargetFlag(parser, hidden=False): """Adds to-target flag.""" parser.add_argument( '--to-target', hidden=hidden, help='Specifies a target to deliver into upon release creation', ) def AddImagesGroup(parser, hidden=False): """Adds Images flag.""" images_group = parser.add_mutually_exclusive_group() images_group.add_argument( '--images', metavar='NAME=TAG', type=arg_parsers.ArgDict(), hidden=hidden, help=textwrap.dedent("""\ Reference to a collection of individual image name to image full path replacements. For example: $ gcloud deploy releases create foo \\ --images image1=path/to/image1:v1@sha256:45db24 """), ) images_group.add_argument( '--build-artifacts', hidden=hidden, help=( 'Reference to a Skaffold build artifacts output file from skaffold' " build --file-output=BUILD_ARTIFACTS. If you aren't using Skaffold," ' use the --images flag below to specify the' ' image-names-to-tagged-image references.' ), ) def AddConfigFile(parser, hidden=False): """Adds config flag.""" parser.add_argument( '--file', hidden=hidden, required=True, help=( 'Path to yaml file containing Delivery Pipeline(s), Target(s)' ' declarative definitions.' ), ) def AddToTarget(parser, hidden=False): """Adds to-target flag.""" parser.add_argument( '--to-target', hidden=hidden, help='Destination target to promote into.' ) def AddRolloutID(parser, hidden=False): """Adds rollout-id flag.""" parser.add_argument( '--rollout-id', hidden=hidden, help='ID to assign to the generated rollout for promotion.', ) def AddRelease(parser, help_text, hidden=False): """Adds release flag.""" parser.add_argument('--release', hidden=hidden, help=help_text) def AddForce(parser, help_text, hidden=False): """Adds force flag.""" parser.add_argument( '--force', hidden=hidden, action='store_true', help=help_text, ) def AddDescription(parser, help_text, name='--description'): """Adds description related flag.""" parser.add_argument( name, help=help_text, ) def AddDeliveryPipeline(parser, required=True): """Adds delivery pipeline flag.""" parser.add_argument( '--delivery-pipeline', help='The name of the Cloud Deploy delivery pipeline', required=required, ) def AddAnnotationsFlag(parser, resource_type): """Adds --annotations flag.""" help_text = textwrap.dedent("""\ Annotations to apply to the %s. Annotations take the form of key/value string pairs. Examples: Add annotations: $ {command} --annotations="from_target=test,status=stable" """) % (resource_type) parser.add_argument( '--annotations', metavar='KEY=VALUE', type=arg_parsers.ArgDict(), help=help_text, ) def AddLabelsFlag(parser, resource_type): """Add --labels flag.""" help_text = textwrap.dedent("""\ Labels to apply to the %s. Labels take the form of key/value string pairs. Examples: Add labels: $ {command} --labels="commit=abc123,author=foo" """) % (resource_type) parser.add_argument( '--labels', metavar='KEY=VALUE', type=arg_parsers.ArgDict(), help=help_text, ) def AddDockerVersion(parser): """Adds docker version flag.""" parser.add_argument( '--docker-version', help='Version of the Docker binary.', type=str, ) def AddHelmVersion(parser): """Adds helm version flag.""" parser.add_argument( '--helm-version', help='Version of the Helm binary.', type=str, ) def AddKptVersion(parser): """Adds kpt version flag.""" parser.add_argument( '--kpt-version', help='Version of the Kpt binary.', type=str, ) def AddKubectlVersion(parser): """Adds kubectl version flag.""" parser.add_argument( '--kubectl-version', help='Version of the Kubectl binary.', type=str, ) def AddKustomizeVersion(parser): """Adds kustomize version flag.""" parser.add_argument( '--kustomize-version', help='Version of the Kustomize binary.', type=str, ) def AddSkaffoldVersion(parser): """Adds skaffold version flag.""" parser.add_argument( '--skaffold-version', help='Version of the Skaffold binary.', type=str ) def AddSkaffoldFileFlag(): """Add --skaffold-file flag.""" help_text = textwrap.dedent("""\ Path of the skaffold file absolute or relative to the source directory. Examples: Use Skaffold file with relative path: The current working directory is expected to be some part of the skaffold path (e.g. the current working directory could be /home/user) $ {command} --source=/home/user/source --skaffold-file=config/skaffold.yaml The skaffold file absolute file path is expected to be: /home/user/source/config/skaffold.yaml Use Skaffold file with absolute path and with or without source argument: $ {command} --source=/home/user/source --skaffold-file=/home/user/source/config/skaffold.yaml $ {command} --skaffold-file=/home/user/source/config/skaffold.yaml """) return base.Argument('--skaffold-file', help=help_text) def AddSourceFlag(): """Adds source flag.""" return base.Argument( '--source', help=_SOURCE_HELP_TEXT, default='.' ) # By default, the current directory is used. def AddKubernetesFileFlag(): return base.Argument( '--from-k8s-manifest', help=( 'The path to a Kubernetes manifest, which Cloud Deploy will use to ' 'generate a skaffold.yaml file for you (for example, ' 'foo/bar/k8.yaml). The generated Skaffold file will be available in ' 'the Google Cloud Storage source staging directory (see ' '--gcs-source-staging-dir flag) after the release is complete.' ), ) def AddCloudRunFileFlag(): return base.Argument( '--from-run-manifest', help=( 'The path to a Cloud Run manifest, which Cloud Deploy will use to' ' generate a skaffold.yaml file for you (for example,' ' foo/bar/service.yaml). The generated Skaffold file will be' ' available in the Google Cloud Storage source staging directory (see' ' --gcs-source-staging-dir flag) after the release is complete.' ), ) def AddSkaffoldSources(parser): """Add Skaffold sources.""" config_group = parser.add_mutually_exclusive_group() AddKubernetesFileFlag().AddToParser(config_group) AddCloudRunFileFlag().AddToParser(config_group) source_group = config_group.add_group(mutex=False) AddSourceFlag().AddToParser(source_group) AddSkaffoldFileFlag().AddToParser(source_group) def AddDescriptionFlag(parser): """Add --description flag.""" parser.add_argument( '--description', help='Description of rollout created during a rollback.', hidden=False, default=None, required=False, ) def AddListAllPipelines(parser): """Add --list-all-pipelines flag.""" help_text = textwrap.dedent("""\ List all Delivery Pipelines associated with a target. Usage: $ {command} --list-all-pipelines """) parser.add_argument( '--list-all-pipelines', action='store_true', default=None, help=help_text ) def AddSkipPipelineLookup(parser): """Add --skip-pipeline-lookup flag.""" help_text = textwrap.dedent("""\ If set, skip fetching details of associated pipelines when describing a target. Usage: $ {command} --skip-pipeline-lookup """) parser.add_argument( '--skip-pipeline-lookup', action='store_true', default=False, help=help_text, ) def AddRollbackOfRollout(parser): """Add --rollback-of-rollout flag.""" help_text = textwrap.dedent("""\ If set, this validates whether the rollout name specified by the flag matches the rollout on the target. Examples: Validate that `test-rollout` is the rollout to rollback on the target. $ {command} --rollback-of-rollout=projects/test-project/locations/us-central1/deliveryPipelines/test-pipeline/releases/test-release/rollouts/test-rollout """) parser.add_argument( '--rollback-of-rollout', help=help_text, hidden=False, # By default, None is used. default=None, required=False, ) def AddStartingPhaseId(parser): """Add --starting-phase-id flag.""" help_text = textwrap.dedent("""\ If set, starts the created rollout at the specified phase. Start rollout at `stable` phase: $ {command} --starting-phase-id=stable """) parser.add_argument( '--starting-phase-id', help=help_text, hidden=False, # By default, None is used. default=None, required=False, ) def AddInitialRolloutLabelsFlag(): """Add --initial-rollout-labels flag.""" help_text = textwrap.dedent("""\ Labels to apply to the initial rollout when creating the release. Labels take the form of key/value string pairs. Examples: Add labels: $ {command} initial-rollout-labels="commit=abc123,author=foo" """) return base.Argument( '--initial-rollout-labels', help=help_text, metavar='KEY=VALUE', type=arg_parsers.ArgDict(), ) def AddInitialRolloutAnnotationsFlag(): """Adds --initial-rollout-annotations flag.""" help_text = textwrap.dedent("""\ Annotations to apply to the initial rollout when creating the release. Annotations take the form of key/value string pairs. Examples: Add annotations: $ {command} --initial-rollout-annotations="from_target=test,status=stable" """) return base.Argument( '--initial-rollout-annotations', help=help_text, metavar='KEY=VALUE', type=arg_parsers.ArgDict(), ) def AddInitialRolloutPhaseIDFlag(): """Adds --initial-rollout-phase-id flag.""" help_text = textwrap.dedent("""\ The phase to start the initial rollout at when creating the release. The phase ID must be a valid phase on the rollout. If not specified, then the rollout will start at the first phase. Examples: Start rollout at `stable` phase: $ {command} --initial-rollout-phase-id=stable """) return base.Argument( '--initial-rollout-phase-id', help=help_text, hidden=False, # By default, None is used. default=None, required=False, ) def AddEnableInitialRolloutFlag(): """Adds --enable-initial-rollout flag.""" return base.Argument( '--enable-initial-rollout', action='store_const', help=( 'Creates a rollout in the first target defined in the delivery' ' pipeline. This is the default behavior.' ), const=True, ) def AddDisableInitialRolloutFlag(): """Adds --disable-initial-rollout flag.""" return base.Argument( '--disable-initial-rollout', action='store_const', help=( 'Skips creating a rollout in the first target defined in the delivery' ' pipeline.' ), const=True, ) def AddInitialRolloutGroup(parser): """Adds initial-rollout flag group.""" group = parser.add_mutually_exclusive_group() # Create a group that contains the flags to enable an initial rollout and add # labels and annotations to that rollout. The group itself is mutually # exclusive of the disable initial rollout group. enable_initial_rollout_group = group.add_group(mutex=False) AddInitialRolloutLabelsFlag().AddToParser(enable_initial_rollout_group) AddInitialRolloutAnnotationsFlag().AddToParser(enable_initial_rollout_group) AddInitialRolloutPhaseIDFlag().AddToParser(enable_initial_rollout_group) AddEnableInitialRolloutFlag().AddToParser(enable_initial_rollout_group) # Add the disable initial rollout flag to the mutex group. AddDisableInitialRolloutFlag().AddToParser(group) def AddJobId(parser, hidden=False): """Adds job-id flag.""" parser.add_argument( '--job-id', hidden=hidden, help='Job ID on a rollout resource', required=True, ) def AddPhaseId(parser, required=True, hidden=False): """Adds phase-id flag.""" parser.add_argument( '--phase-id', hidden=hidden, help='Phase ID on a rollout resource', required=required, ) def AddDeployParametersFlag(parser, hidden=False): """Add --deploy-parameters flag.""" help_text = textwrap.dedent("""\ Deployment parameters to apply to the release. Deployment parameters take the form of key/value string pairs. Examples: Add deployment parameters: $ {command} --deploy-parameters="key1=value1,key2=value2" """) parser.add_argument( '--deploy-parameters', metavar='KEY=VALUE', type=arg_parsers.ArgDict(), hidden=hidden, help=help_text, ) def AddOverrideDeployPolicies(parser, hidden=False): """Adds override-deploy-policies flag.""" parser.add_argument( '--override-deploy-policies', metavar='POLICY', hidden=hidden, type=arg_parsers.ArgList(), help='Deploy policies to override', )