1# -*- coding: utf-8 -*- #
2# Copyright 2016 Google LLC. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#    http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Flags and helpers for the container related commands."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import unicode_literals
20
21from googlecloudsdk.api_lib.compute import constants as compute_constants
22from googlecloudsdk.api_lib.container import api_adapter
23from googlecloudsdk.api_lib.container import util
24from googlecloudsdk.api_lib.util import apis
25from googlecloudsdk.calliope import actions
26from googlecloudsdk.calliope import arg_parsers
27from googlecloudsdk.calliope import base
28from googlecloudsdk.calliope import exceptions
29from googlecloudsdk.command_lib.container import constants
30from googlecloudsdk.core import log
31from googlecloudsdk.core import properties
32
33_DATAPATH_PROVIDER = {
34    'legacy': 'Selects legacy datatpath for the cluster.',
35    'advanced': 'Selects advanced datapath for the cluster.',
36}
37
38_DNS_PROVIDER = {
39    'clouddns': 'Selects CloudDNS as the DNS provider for the cluster.',
40    'default': 'Selects the default DNS provider(kube-dns) for the cluster.',
41}
42
43_DNS_SCOPE = {
44    'cluster': 'Configures the CloudDNS zone to be private to the cluster.',
45    'vpc': 'Configures the CloudDNS zone to be private to the VPC Network.',
46}
47
48
49def AddBasicAuthFlags(parser):
50  """Adds basic auth flags to the given parser.
51
52  Basic auth flags are: --username, --enable-basic-auth, and --password.
53
54  Args:
55    parser: A given parser.
56  """
57  basic_auth_group = parser.add_group(help='Basic auth')
58  username_group = basic_auth_group.add_group(
59      mutex=True, help='Options to specify the username.')
60  username_help_text = """\
61The user name to use for basic auth for the cluster. Use `--password` to specify
62a password; if not, the server will randomly generate one."""
63  username_group.add_argument('--username', '-u', help=username_help_text)
64
65  enable_basic_auth_help_text = """\
66Enable basic (username/password) auth for the cluster.  `--enable-basic-auth` is
67an alias for `--username=admin`; `--no-enable-basic-auth` is an alias for
68`--username=""`. Use `--password` to specify a password; if not, the server will
69randomly generate one. For cluster versions before 1.12, if neither
70`--enable-basic-auth` nor `--username` is specified, `--enable-basic-auth` will
71default to `true`. After 1.12, `--enable-basic-auth` will default to `false`."""
72  username_group.add_argument(
73      '--enable-basic-auth',
74      help=enable_basic_auth_help_text,
75      action='store_true',
76      default=None)
77
78  basic_auth_group.add_argument(
79      '--password',
80      help='The password to use for cluster auth. Defaults to a '
81      'server-specified randomly-generated string.')
82
83
84def MungeBasicAuthFlags(args):
85  """Munges flags associated with basic auth.
86
87  If --enable-basic-auth is specified, converts it --username value, and checks
88  that --password is only specified if it makes sense.
89
90  Args:
91    args: an argparse namespace. All the arguments that were provided to this
92      command invocation.
93
94  Raises:
95    util.Error, if flags conflict.
96  """
97  if hasattr(args, 'enable_basic_auth') and \
98      args.IsSpecified('enable_basic_auth'):
99    if not args.enable_basic_auth:
100      args.username = ''
101    else:
102      args.username = 'admin'
103  if (hasattr(args, 'username') and hasattr(args, 'password')) and \
104      (not args.username and args.IsSpecified('password')):
105    raise util.Error(constants.USERNAME_PASSWORD_ERROR_MSG)
106
107
108def LogBasicAuthDeprecationWarning(args):
109  """Returns a deprecation warning if basic auth fields are modified.
110
111  Args:
112    args: an argparse namespace. All the arguments that were provided to this
113      command invocation.
114  """
115  if getattr(args, 'username', '') or getattr(args, 'password', '') or getattr(
116      args, 'enable_basic_auth', False):
117    log.warning(
118        'Warning: basic authentication is deprecated, and will be removed in GKE '
119        'control plane versions 1.19 and newer. For a list of recommended '
120        'authentication methods, see: '
121        'https://cloud.google.com/kubernetes-engine/docs/how-to/api-server-authentication'
122    )
123
124
125# TODO(b/28318474): move flags common across commands here.
126def AddImageTypeFlag(parser, target):
127  """Adds a --image-type flag to the given parser."""
128  help_text = """\
129The image type to use for the {target}. Defaults to server-specified.
130
131Image Type specifies the base OS that the nodes in the {target} will run on.
132If an image type is specified, that will be assigned to the {target} and all
133future upgrades will use the specified image type. If it is not specified the
134server will pick the default image type.
135
136The default image type and the list of valid image types are available
137using the following command.
138
139  $ gcloud container get-server-config
140""".format(target=target)
141
142  parser.add_argument('--image-type', help=help_text)
143
144
145def AddImageFlag(parser, hidden=False):
146  """Adds an --image flag to the given parser.
147
148  Args:
149    parser: A given parser.
150    hidden: if true, suppress help text for this option
151  """
152
153  help_text = """\
154A specific image to use on the new instances.
155"""
156
157  parser.add_argument('--image', help=help_text, hidden=hidden)
158
159
160def AddImageProjectFlag(parser, hidden=False):
161  """Adds an --image-project flag to the given parser.
162
163  Args:
164    parser: A given parser.
165    hidden: if true, suppresses help text for this option.
166  """
167  help_text = """/
168A specific project from which contains the os image or image family.  This is
169required when using --image-type=CUSTOM.
170"""
171
172  parser.add_argument('--image-project', help=help_text, hidden=hidden)
173
174
175def AddImageFamilyFlag(parser, hidden=False):
176  """Adds an --image-family flag to the given parser.
177
178  Args:
179    parser: A given parser.
180    hidden: if true, suppresses help text for this option.
181  """
182
183  help_text = """/
184A specific image-family from which the most recent image is used on new
185instances.  If both image and image family are specified, the image must be in
186the image family, and the image is used.
187"""
188  parser.add_argument('--image-family', help=help_text, hidden=hidden)
189
190
191def AddImageFlagsCreate(parser):
192  AddImageTypeFlag(parser, 'cluster')
193  AddImageFlag(parser, hidden=True)
194  AddImageProjectFlag(parser, hidden=True)
195  AddImageFamilyFlag(parser, hidden=True)
196
197
198def AddNodeVersionFlag(parser, hidden=False):
199  """Adds a --node-version flag to the given parser."""
200  help_text = """\
201The Kubernetes version to use for nodes. Defaults to server-specified.
202
203The default Kubernetes version is available using the following command.
204
205  $ gcloud container get-server-config
206"""
207
208  return parser.add_argument('--node-version', help=help_text, hidden=hidden)
209
210
211def AddClusterVersionFlag(parser, suppressed=False, help=None):  # pylint: disable=redefined-builtin
212  """Adds a --cluster-version flag to the given parser."""
213  if help is None:
214    help = """\
215The Kubernetes version to use for the master and nodes. Defaults to
216server-specified.
217
218The default Kubernetes version is available using the following command.
219
220  $ gcloud container get-server-config
221"""
222
223  return parser.add_argument('--cluster-version', help=help, hidden=suppressed)
224
225
226def AddNotificationConfigFlag(parser, hidden=False):
227  """Adds a --notification-config flag to the given parser."""
228  help_text = """\
229The notification configuration of the cluster. GKE supports publishing
230cluster upgrade notifications to any Pub/Sub topic you created in the same
231project. Create a subscription for the topic specified to receive notification
232messages. See https://cloud.google.com/pubsub/docs/admin on how to manage
233Pub/Sub topics and subscriptions.
234
235Example:
236
237    $ {command} example-cluster --notification-config=pubsub=ENABLED,pubsub-topic=projects/{project}/topics/{topic-name}
238
239The project of the Pub/Sub topic must be the same one as the cluster. It can
240be either the project ID or the project number.
241"""
242  return parser.add_argument(
243      '--notification-config',
244      type=arg_parsers.ArgDict(
245          spec={
246              'pubsub': str,
247              'pubsub-topic': str,
248          }, required_keys=['pubsub']),
249      metavar='pubsub=ENABLED|DISABLED,pubsub-topic=TOPIC',
250      help=help_text,
251      hidden=hidden)
252
253
254def AddReleaseChannelFlag(parser, is_update=False, hidden=False):
255  """Adds a --release-channel flag to the given parser."""
256  short_text = """\
257Release channel a cluster is subscribed to.
258
259"""
260  if is_update:
261    short_text = """\
262Subscribe or unsubscribe this cluster to a release channel.
263
264"""
265  help_text = short_text + """\
266When a cluster is subscribed to a release channel, Google maintains
267both the master version and the node version. Node auto-upgrade
268defaults to true and cannot be disabled.
269"""
270
271  choices = {
272      'rapid':
273          """\
274'rapid' channel is offered on an early access basis for customers who want
275to test new releases.
276
277WARNING: Versions available in the 'rapid' channel may be subject to
278unresolved issues with no known workaround and are not subject to any
279SLAs.
280""",
281      'regular':
282          """\
283Clusters subscribed to 'regular' receive versions that are considered GA
284quality. 'regular' is intended for production users who want to take
285advantage of new features.
286""",
287      'stable':
288          """\
289Clusters subscribed to 'stable' receive versions that are known to be
290stable and reliable in production.
291""",
292      'None':
293          """\
294Use 'None' to opt-out of any release channel.
295"""
296  }
297
298  return parser.add_argument(
299      '--release-channel',
300      metavar='CHANNEL',
301      choices=choices,
302      help=help_text,
303      hidden=hidden)
304
305
306def AddClusterAutoscalingFlags(parser, update_group=None, hidden=False):
307  """Adds autoscaling related flags to parser.
308
309  Autoscaling related flags are: --enable-autoscaling
310  --min-nodes --max-nodes flags.
311
312  Args:
313    parser: A given parser.
314    update_group: An optional group of mutually exclusive flag options to which
315      an --enable-autoscaling flag is added.
316    hidden: If true, suppress help text for added options.
317
318  Returns:
319    Argument group for autoscaling flags.
320  """
321
322  group = parser.add_argument_group('Cluster autoscaling')
323  autoscaling_group = group if update_group is None else update_group
324  autoscaling_group.add_argument(
325      '--enable-autoscaling',
326      default=None,
327      help="""\
328Enables autoscaling for a node pool.
329
330Enables autoscaling in the node pool specified by --node-pool or
331the default node pool if --node-pool is not provided.""",
332      hidden=hidden,
333      action='store_true')
334  group.add_argument(
335      '--max-nodes',
336      help="""\
337Maximum number of nodes per zone in the node pool.
338
339Maximum number of nodes per zone to which the node pool specified by --node-pool
340(or default node pool if unspecified) can scale. Ignored unless
341--enable-autoscaling is also specified.""",
342      hidden=hidden,
343      type=int)
344  group.add_argument(
345      '--min-nodes',
346      help="""\
347Minimum number of nodes per zone in the node pool.
348
349Minimum number of nodes per zone to which the node pool specified by --node-pool
350(or default node pool if unspecified) can scale. Ignored unless
351--enable-autoscaling is also specified.""",
352      hidden=hidden,
353      type=int)
354  return group
355
356
357def AddNodePoolAutoprovisioningFlag(parser, hidden=True):
358  """Adds --enable-autoprovisioning flag for node pool to parser.
359
360  Args:
361    parser: A given parser.
362    hidden: If true, suppress help text for added options.
363  """
364  parser.add_argument(
365      '--enable-autoprovisioning',
366      help="""\
367Enables Cluster Autoscaler to treat the node pool as if it was autoprovisioned.
368
369Cluster Autoscaler will be able to delete the node pool if it's unneeded.""",
370      hidden=hidden,
371      default=None,
372      action='store_true')
373
374
375def AddLocalSSDFlag(parser, suppressed=False, help_text=''):
376  """Adds a --local-ssd-count flag to the given parser."""
377  help_text += """\
378The number of local SSD disks to provision on each node, formatted and mounted
379in the filesystem.
380
381Local SSDs have a fixed 375 GB capacity per device. The number of disks that
382can be attached to an instance is limited by the maximum number of disks
383available on a machine, which differs by compute zone. See
384https://cloud.google.com/compute/docs/disks/local-ssd for more information."""
385  parser.add_argument(
386      '--local-ssd-count',
387      help=help_text,
388      hidden=suppressed,
389      type=int,
390      default=0)
391
392
393def AddBootDiskKmsKeyFlag(parser, suppressed=False, help_text=''):
394  """Adds a --boot-disk-kms-key flag to the given parser."""
395  help_text += """\
396The Customer Managed Encryption Key used to encrypt the boot disk attached
397to each node in the node pool. This should be of the form
398projects/[KEY_PROJECT_ID]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME].
399For more information about protecting resources with Cloud KMS Keys please
400see:
401https://cloud.google.com/compute/docs/disks/customer-managed-encryption"""
402  parser.add_argument(
403      '--boot-disk-kms-key',
404      help=help_text,
405      hidden=suppressed,
406      type=str,
407      default='')
408
409
410def AddAcceleratorArgs(parser):
411  """Adds Accelerator-related args."""
412  parser.add_argument(
413      '--accelerator',
414      type=arg_parsers.ArgDict(
415          spec={
416              'type': str,
417              'count': int,
418          },
419          required_keys=['type'],
420          max_length=2),
421      metavar='type=TYPE,[count=COUNT]',
422      help="""\
423      Attaches accelerators (e.g. GPUs) to all nodes.
424
425      *type*::: (Required) The specific type (e.g. nvidia-tesla-k80 for nVidia Tesla K80)
426      of accelerator to attach to the instances. Use ```gcloud compute
427      accelerator-types list``` to learn about all available accelerator types.
428
429      *count*::: (Optional) The number of accelerators to attach to the
430      instances. The default value is 1.
431      """)
432
433
434def AddAutoscalingProfilesFlag(parser, hidden=False):
435  """Adds autoscaling profiles flag to parser.
436
437  Autoscaling profiles flag is --autoscaling-profile.
438
439  Args:
440    parser: A given parser.
441    hidden: If true, suppress help text for added options.
442  """
443  parser.add_argument(
444      '--autoscaling-profile',
445      required=False,
446      default=None,
447      help="""\
448         Set autoscaling behaviour, choices are 'optimize-utilization' and 'balanced'.
449         Default is 'balanced'.
450      """,
451      hidden=hidden,
452      type=str)
453
454
455def AddAutoprovisioningFlags(parser, hidden=False, for_create=False):
456  """Adds node autoprovisioning related flags to parser.
457
458  Autoprovisioning related flags are: --enable-autoprovisioning
459  --min-cpu --max-cpu --min-memory --max-memory flags.
460
461  Args:
462    parser: A given parser.
463    hidden: If true, suppress help text for added options.
464    for_create: Add flags for create request.
465  """
466
467  group = parser.add_argument_group('Node autoprovisioning', hidden=hidden)
468  group.add_argument(
469      '--enable-autoprovisioning',
470      required=True,
471      default=None,
472      help="""\
473Enables  node autoprovisioning for a cluster.
474
475Cluster Autoscaler will be able to create new node pools. Requires maximum CPU
476and memory limits to be specified.""",
477      hidden=hidden,
478      action='store_true')
479
480  limits_group = group.add_mutually_exclusive_group()
481  limits_group.add_argument(
482      '--autoprovisioning-config-file',
483      type=arg_parsers.FileContents(),
484      hidden=hidden,
485      help="""\
486Path of the JSON/YAML file which contains information about the
487cluster's node autoprovisioning configuration. Currently it contains
488a list of resource limits, identity defaults for autoprovisioning, node upgrade
489settings, node management settings, minimum cpu platform, node locations for
490autoprovisioning, disk type and size configuration, Shielded instance settings,
491and customer-managed encryption keys settings.
492
493Resource limits are specified in the field 'resourceLimits'.
494Each resource limits definition contains three fields:
495resourceType, maximum and minimum.
496Resource type can be "cpu", "memory" or an accelerator (e.g.
497"nvidia-tesla-k80" for nVidia Tesla K80). Use gcloud compute accelerator-types
498list to learn about available accelerator types.
499Maximum is the maximum allowed amount with the unit of the resource.
500Minimum is the minimum allowed amount with the unit of the resource.
501
502Identity default contains at most one of the below fields:
503serviceAccount: The Google Cloud Platform Service Account to be used by node VMs in
504autoprovisioned node pools. If not specified, the project's default service account
505is used.
506scopes: A list of scopes to be used by node instances in autoprovisioned node pools.
507Multiple scopes can be specified, separated by commas. For information on defaults,
508look at:
509https://cloud.google.com/sdk/gcloud/reference/container/clusters/create#--scopes
510
511Node Upgrade settings are specified under the field
512'upgradeSettings', which has the following fields:
513maxSurgeUpgrade: Number of extra (surge) nodes to be created on
514each upgrade of an autoprovisioned node pool.
515maxUnavailableUpgrade: Number of nodes that can be unavailable at the
516same time on each upgrade of an autoprovisioned node pool.
517
518Node Management settings are specified under the field
519'nodeManagement', which has the following fields:
520enableAutoUpgrade: A boolean field that indicates if node
521autoupgrade is enabled for autoprovisioned node pools.
522enableAutoRepair: A boolean field that indicates if node
523autorepair is enabled for autoprovisioned node pools.
524
525minCpuPlatform: If specified, new autoprovisioned nodes will be
526scheduled on host with specified CPU architecture or a newer one.
527Note: Min CPU platform can only be specified in Beta and Alpha.
528
529Autoprovisioning locations is a set of zones where new node pools
530can be created by Autoprovisioning. Autoprovisioning locations are
531specified in the field 'autoprovisioningLocations'. All zones must
532be in the same region as the cluster's master(s).
533
534Disk type and size are specified under the 'diskType' and 'diskSizeGb' fields,
535respectively. If specified, new autoprovisioned nodes will be created with
536custom boot disks configured by these settings.
537
538Shielded instance settings are specified under the 'shieldedInstanceConfig'
539field, which has the following fields:
540enableSecureBoot: A boolean field that indicates if secure boot is enabled for
541autoprovisioned nodes.
542enableIntegrityMonitoring: A boolean field that indicates if integrity
543monitoring is enabled for autoprovisioned nodes.
544
545Customer Managed Encryption Keys (CMEK) used by new auto-provisioned node pools
546can be specified in the 'bootDiskKmsKey' field.
547""")
548
549  from_flags_group = limits_group.add_argument_group(
550      'Flags to configure autoprovisioned nodes')
551  from_flags_group.add_argument(
552      '--max-cpu',
553      required=for_create,
554      help="""\
555Maximum number of cores in the cluster.
556
557Maximum number of cores to which the cluster can scale.""",
558      hidden=hidden,
559      type=int)
560  from_flags_group.add_argument(
561      '--min-cpu',
562      help="""\
563Minimum number of cores in the cluster.
564
565Minimum number of cores to which the cluster can scale.""",
566      hidden=hidden,
567      type=int)
568  from_flags_group.add_argument(
569      '--max-memory',
570      required=for_create,
571      help="""\
572Maximum memory in the cluster.
573
574Maximum number of gigabytes of memory to which the cluster can scale.""",
575      hidden=hidden,
576      type=int)
577  from_flags_group.add_argument(
578      '--min-memory',
579      help="""\
580Minimum memory in the cluster.
581
582Minimum number of gigabytes of memory to which the cluster can scale.""",
583      hidden=hidden,
584      type=int)
585  accelerator_group = from_flags_group.add_argument_group(
586      'Arguments to set limits on accelerators:')
587  accelerator_group.add_argument(
588      '--max-accelerator',
589      type=arg_parsers.ArgDict(
590          spec={
591              'type': str,
592              'count': int,
593          },
594          required_keys=['type', 'count'],
595          max_length=2),
596      required=True,
597      metavar='type=TYPE,count=COUNT',
598      hidden=hidden,
599      help="""\
600Sets maximum limit for a single type of accelerators (e.g. GPUs) in cluster.
601
602*type*::: (Required) The specific type (e.g. nvidia-tesla-k80 for nVidia Tesla K80)
603of accelerator for which the limit is set. Use ```gcloud compute
604accelerator-types list``` to learn about all available accelerator types.
605
606*count*::: (Required) The maximum number of accelerators
607to which the cluster can be scaled.
608""")
609  accelerator_group.add_argument(
610      '--min-accelerator',
611      type=arg_parsers.ArgDict(
612          spec={
613              'type': str,
614              'count': int,
615          },
616          required_keys=['type', 'count'],
617          max_length=2),
618      metavar='type=TYPE,count=COUNT',
619      hidden=hidden,
620      help="""\
621Sets minimum limit for a single type of accelerators (e.g. GPUs) in cluster. Defaults
622to 0 for all accelerator types if it isn't set.
623
624*type*::: (Required) The specific type (e.g. nvidia-tesla-k80 for nVidia Tesla K80)
625of accelerator for which the limit is set. Use ```gcloud compute
626accelerator-types list``` to learn about all available accelerator types.
627
628*count*::: (Required) The minimum number of accelerators
629to which the cluster can be scaled.
630""")
631  identity_group = from_flags_group.add_argument_group(
632      'Flags to specify identity for autoprovisioned nodes:')
633  identity_group.add_argument(
634      '--autoprovisioning-service-account',
635      type=str,
636      hidden=hidden,
637      help="""\
638The Google Cloud Platform Service Account to be used by node VMs in
639autoprovisioned node pools. If not specified, the project default
640service account is used.
641""")
642  identity_group.add_argument(
643      '--autoprovisioning-scopes',
644      type=arg_parsers.ArgList(),
645      metavar='SCOPE',
646      hidden=hidden,
647      help="""\
648The scopes be used by node instances in autoprovisioned node pools.
649Multiple scopes can be specified, separated by commas. For information
650on defaults, look at:
651https://cloud.google.com/sdk/gcloud/reference/container/clusters/create#--scopes
652""")
653  upgrade_settings_group = from_flags_group.add_argument_group(
654      'Flags to specify upgrade settings for autoprovisioned nodes:',
655      hidden=hidden,
656  )
657  upgrade_settings_group.add_argument(
658      '--autoprovisioning-max-surge-upgrade',
659      type=int,
660      hidden=hidden,
661      required=True,
662      help="""\
663Number of extra (surge) nodes to be created on each upgrade of an
664autoprovisioned node pool.
665""")
666  upgrade_settings_group.add_argument(
667      '--autoprovisioning-max-unavailable-upgrade',
668      type=int,
669      hidden=hidden,
670      required=True,
671      help="""\
672Number of nodes that can be unavailable at the same time on each
673upgrade of an autoprovisioned node pool.
674""")
675  management_settings_group = from_flags_group.add_argument_group(
676      'Flags to specify node management settings for autoprovisioned nodes:',
677      hidden=hidden,
678  )
679  management_settings_group.add_argument(
680      '--enable-autoprovisioning-autoupgrade',
681      hidden=hidden,
682      default=None,
683      required=True,
684      action='store_true',
685      help="""\
686Enable node autoupgrade for autoprovisioned node pools.
687Use --no-enable-autoprovisioning-autoupgrade to disable.
688""")
689  management_settings_group.add_argument(
690      '--enable-autoprovisioning-autorepair',
691      default=None,
692      action='store_true',
693      hidden=hidden,
694      required=True,
695      help="""\
696Enable node autorepair for autoprovisioned node pools.
697Use --no-enable-autoprovisioning-autorepair to disable.
698""")
699  from_flags_group.add_argument(
700      '--autoprovisioning-locations',
701      hidden=hidden,
702      help="""\
703Set of zones where new node pools can be created by autoprovisioning.
704All zones must be in the same region as the cluster's master(s).
705Multiple locations can be specified, separated by commas.""",
706      metavar='ZONE',
707      type=arg_parsers.ArgList(min_length=1))
708  from_flags_group.add_argument(
709      '--autoprovisioning-min-cpu-platform',
710      hidden=hidden,
711      metavar='PLATFORM',
712      help="""\
713If specified, new autoprovisioned nodes will be scheduled on host with
714specified CPU architecture or a newer one.
715""")
716
717
718def AddEnableBinAuthzFlag(parser, hidden=False):
719  """Adds a --enable-binauthz flag to parser."""
720  help_text = """Enable Binary Authorization for this cluster."""
721  parser.add_argument(
722      '--enable-binauthz',
723      action='store_true',
724      default=None,
725      help=help_text,
726      hidden=hidden,
727  )
728
729
730def AddZoneAndRegionFlags(parser):
731  """Adds the --zone and --region flags to the parser."""
732  # TODO(b/33343238): Remove the short form of the zone flag.
733  # TODO(b/18105938): Add zone prompting
734  group = parser.add_mutually_exclusive_group()
735  group.add_argument(
736      '--zone',
737      '-z',
738      help='Compute zone (e.g. us-central1-a) for the cluster',
739      action=actions.StoreProperty(properties.VALUES.compute.zone))
740  group.add_argument(
741      '--region', help='Compute region (e.g. us-central1) for the cluster.')
742
743
744def AddAsyncFlag(parser):
745  """Adds the --async flags to the given parser."""
746  base.ASYNC_FLAG.AddToParser(parser)
747
748
749def AddEnableKubernetesAlphaFlag(parser):
750  """Adds a --enable-kubernetes-alpha flag to parser."""
751  help_text = """\
752Enable Kubernetes alpha features on this cluster. Selecting this
753option will result in the cluster having all Kubernetes alpha API groups and
754features turned on. Cluster upgrades (both manual and automatic) will be
755disabled and the cluster will be automatically deleted after 30 days.
756
757Alpha clusters are not covered by the Kubernetes Engine SLA and should not be
758used for production workloads."""
759  parser.add_argument(
760      '--enable-kubernetes-alpha', action='store_true', help=help_text)
761
762
763def _AddLegacyCloudRunFlag(parser, flag, **kwargs):
764  """Adds a flag with the new and old product name for KubeRun."""
765  new_kwargs = kwargs.copy()
766  new_kwargs['hidden'] = True
767  parser.add_argument(flag.format('kuberun'), **new_kwargs)
768  parser.add_argument(flag.format('cloud-run'), **kwargs)
769
770
771def AddEnableCloudRunAlphaFlag(parser):
772  """Adds the --enable-cloud-run-alpha flags to parser."""
773  help_text = """\
774Enable Cloud Run alpha features on this cluster. Selecting this
775option will result in the cluster having all Cloud Run alpha API groups and
776features turned on.
777
778Cloud Run alpha clusters are not covered by the Cloud Run SLA and should not be
779used for production workloads."""
780  _AddLegacyCloudRunFlag(
781      parser, '--enable-{0}-alpha', action='store_true', help=help_text)
782
783
784def AddCloudRunConfigFlag(parser, suppressed=False):
785  """Adds a --cloud-run-config flag to parser."""
786  help_text = """\
787Configurations for Cloud Run addon, requires `--addons=CloudRun` for create
788and `--update-addons=CloudRun=ENABLED` for update.
789
790*load-balancer-type*:::Optional Type of load-balancer-type EXTERNAL or INTERNAL
791Example:
792
793  $ {command} example-cluster --cloud-run-config=load-balancer-type=INTERNAL
794"""
795  _AddLegacyCloudRunFlag(
796      parser,
797      '--{0}-config',
798      metavar='load-balancer-type=EXTERNAL',
799      type=arg_parsers.ArgDict(spec={
800          'load-balancer-type': (lambda x: x.upper()),
801      }),
802      help=help_text,
803      hidden=suppressed)
804
805
806def GetLegacyCloudRunFlag(flag, args, get_default):
807  """Gets the value for a flag that supports cloud_run and kuberun."""
808  oldflag = flag.format('cloud_run')
809  newflag = flag.format('kuberun')
810  specified = args.GetSpecifiedArgNames()
811  oldarg = '--' + oldflag.replace('_', '-')
812  newarg = '--' + newflag.replace('_', '-')
813  if oldarg in specified and newarg in specified:
814    log.warning('{} and {} are both specified, ignoring the latter.'.format(
815        newarg, oldarg))
816  return get_default(oldflag) or get_default(newflag)
817
818
819def ValidateCloudRunConfigCreateArgs(cloud_run_config_args, addons_args):
820  """Validates flags specifying Cloud Run config for create.
821
822  Args:
823    cloud_run_config_args: parsed commandline arguments for --cloud-run-config.
824    addons_args: parsed commandline arguments for --addons.
825
826  Raises:
827    InvalidArgumentException: when load-balancer-type is not EXTERNAL nor
828    INTERNAL,
829    or --addons=CloudRun is not specified
830  """
831  if cloud_run_config_args:
832    load_balancer_type = cloud_run_config_args.get('load-balancer-type', '')
833    if load_balancer_type not in ['EXTERNAL', 'INTERNAL']:
834      raise exceptions.InvalidArgumentException(
835          '--kuberun-config',
836          'load-balancer-type is either EXTERNAL or INTERNAL'
837          'e.g. --kuberun-config load-balancer-type=EXTERNAL')
838    if all((v not in addons_args) for v in api_adapter.CLOUDRUN_ADDONS):
839      raise exceptions.InvalidArgumentException(
840          '--kuberun-config', '--addon=KubeRun must be specified when '
841          '--kuberun-config is given')
842
843
844def ValidateCloudRunConfigUpdateArgs(cloud_run_config_args, update_addons_args):
845  """Validates flags specifying Cloud Run config for update.
846
847  Args:
848    cloud_run_config_args: parsed comandline arguments for --cloud_run_config.
849    update_addons_args: parsed comandline arguments for --update-addons.
850
851  Raises:
852    InvalidArgumentException: when load-balancer-type is not MTLS_PERMISSIVE nor
853    MTLS_STRICT,
854    or --update-addons=CloudRun=ENABLED is not specified
855  """
856  if cloud_run_config_args:
857    load_balancer_type = cloud_run_config_args.get('load-balancer-type', '')
858    if load_balancer_type not in ['EXTERNAL', 'INTERNAL']:
859      raise exceptions.InvalidArgumentException(
860          '--kuberun-config', 'load-balancer-type must be one of EXTERNAL or '
861          'INTERNAL e.g. --kuberun-config load-balancer-type=EXTERNAL')
862    if any([(update_addons_args.get(v) or False)
863            for v in api_adapter.CLOUDRUN_ADDONS]):
864      raise exceptions.InvalidArgumentException(
865          '--kuberun-config',
866          '--update-addons=KubeRun=ENABLED must be specified '
867          'when --kuberun-config is given')
868
869
870def AddEnableStackdriverKubernetesFlag(parser):
871  """Adds a --enable-stackdriver-kubernetes flag to parser."""
872  help_text = """Enable Cloud Operations for GKE. To enable only Cloud
873    Monitoring use `--enable-stackdriver-kubernetes`
874    and `--no-enable-cloud-logging`. To enable only Cloud Logging use
875    `--enable-stackdriver-kubernetes` and `--no-enable-cloud-monitoring`.
876  """
877  parser.add_argument(
878      '--enable-stackdriver-kubernetes',
879      action='store_true',
880      default=None,
881      help=help_text)
882
883
884def AddEnableLoggingMonitoringSystemOnlyFlag(parser):
885  """Adds a --enable-stackdriver-kubernetes-system flag to parser."""
886  help_text = """Enable Cloud Operations system-only monitoring and logging."""
887  parser.add_argument(
888      '--enable-logging-monitoring-system-only',
889      action='store_true',
890      help=help_text)
891
892
893def AddEnableWorkloadMonitoringEapFlag(parser):
894  """Adds a --enable-workload-monitoring-eap flag to parser."""
895  help_text = """Enable workload monitoring (EAP)."""
896  parser.add_argument(
897      '--enable-workload-monitoring-eap',
898      action='store_true',
899      default=None,
900      help=help_text,
901      hidden=True,
902  )
903
904
905def AddEnableMasterSignalsFlags(parser, for_create=False):
906  """Adds --master-logs and --enable-master-metrics flags to parser."""
907
908  help_text = """\
909Set which master components logs should be sent to Cloud Operations.
910
911Example:
912
913  $ {command} --master-logs APISERVER,SCHEDULER
914"""
915  if for_create:
916    group = parser.add_group()
917  else:
918    group = parser.add_mutually_exclusive_group()
919
920  group.add_argument(
921      '--master-logs',
922      type=arg_parsers.ArgList(choices=api_adapter.PRIMARY_LOGS_OPTIONS),
923      help=help_text,
924      metavar='COMPONENT',
925      hidden=True,
926  )
927
928  if not for_create:
929    help_text = """\
930Disable sending logs from master components to Cloud Operations.
931"""
932    group.add_argument(
933        '--no-master-logs',
934        action='store_true',
935        default=False,
936        help=help_text,
937        hidden=True,
938    )
939
940  help_text = """\
941Enable sending metrics from master components to Cloud Operations.
942"""
943  group.add_argument(
944      '--enable-master-metrics',
945      action='store_true',
946      default=None,
947      help=help_text,
948      hidden=True,
949  )
950
951
952def AddNodeLabelsFlag(parser,
953                      for_node_pool=False,
954                      for_update=False,
955                      hidden=False):
956  """Adds a --node-labels flag to the given parser."""
957  if for_node_pool:
958    if for_update:
959      help_text = """\
960Replaces all the user specified kubernetes labels on all nodes in an existing
961node pool with the given labels. Example:
962
963  $ {command} node-pool-1 --cluster=example-cluster --node-labels=label1=value1,label2=value2
964"""
965    else:
966      help_text = """\
967Applies the given kubernetes labels on all nodes in the new node pool. Example:
968
969  $ {command} node-pool-1 --cluster=example-cluster --node-labels=label1=value1,label2=value2
970"""
971  else:
972    help_text = """\
973Applies the given kubernetes labels on all nodes in the new node pool. Example:
974
975  $ {command} example-cluster --node-labels=label-a=value1,label-2=value2
976"""
977  help_text += """
978New nodes, including ones created by resize or recreate, will have these labels
979on the kubernetes API node object and can be used in nodeSelectors.
980See [](http://kubernetes.io/docs/user-guide/node-selection/) for examples.
981
982Note that kubernetes labels, intended to associate cluster components
983and resources with one another and manage resource lifecycles, are different
984from Kubernetes Engine labels that are used for the purpose of tracking billing
985and usage information."""
986
987  parser.add_argument(
988      '--node-labels',
989      metavar='NODE_LABEL',
990      type=arg_parsers.ArgDict(),
991      help=help_text,
992      hidden=hidden)
993
994
995def AddLocalSSDsAlphaFlags(parser, for_node_pool=False, suppressed=False):
996  """Adds the --local-ssd-count and --local-ssd-volumes flags to the parser."""
997  local_ssd_relationship = """\
998--local-ssd-count is the equivalent of using --local-ssd-volumes with type=scsi,format=fs\n
999"""
1000  group = parser.add_mutually_exclusive_group()
1001  AddLocalSSDVolumeConfigsFlag(group, for_node_pool=for_node_pool)
1002  AddEphemeralStorageFlag(group, for_node_pool=for_node_pool, hidden=suppressed)
1003  AddLocalSSDFlag(
1004      group, suppressed=suppressed, help_text=local_ssd_relationship)
1005
1006
1007def AddLocalSSDsBetaFlags(parser, for_node_pool=False, suppressed=False):
1008  """Adds the --local-ssd-count flag to the parser."""
1009  group = parser.add_mutually_exclusive_group()
1010  AddLocalSSDFlag(group, suppressed=suppressed)
1011  AddEphemeralStorageFlag(group, for_node_pool=for_node_pool, hidden=suppressed)
1012
1013
1014def AddLocalSSDVolumeConfigsFlag(parser, for_node_pool=False, help_text=''):
1015  """Adds a --local-ssd-volumes flag to the given parser."""
1016  help_text += """\
1017Adds the requested local SSDs on all nodes in default node pool(s) in new cluster. Example:
1018
1019  $ {{command}} {0} --local-ssd-volumes count=2,type=nvme,format=fs
1020
1021'count' must be between 1-8\n
1022'type' must be either scsi or nvme\n
1023'format' must be either fs or block
1024
1025New nodes, including ones created by resize or recreate, will have these local SSDs.
1026
1027Local SSDs have a fixed 375 GB capacity per device. The number of disks that
1028can be attached to an instance is limited by the maximum number of disks
1029available on a machine, which differs by compute zone. See
1030https://cloud.google.com/compute/docs/disks/local-ssd for more information.
1031""".format('node-pool-1 --cluster=example-cluster'
1032           if for_node_pool else 'example_cluster')
1033  count_validator = arg_parsers.RegexpValidator(
1034      r'^[1-8]$', 'Count must be a number between 1 and 8')
1035  type_validator = arg_parsers.RegexpValidator(
1036      r'^(scsi|nvme)$', 'Type must be either "scsi" or "nvme"')
1037  format_validator = arg_parsers.RegexpValidator(
1038      r'^(fs|block)$', 'Format must be either "fs" or "block"')
1039  parser.add_argument(
1040      '--local-ssd-volumes',
1041      metavar='[count=COUNT],[type=TYPE],[format=FORMAT]',
1042      type=arg_parsers.ArgDict(
1043          spec={
1044              'count': count_validator,
1045              'type': type_validator,
1046              'format': format_validator,
1047          },
1048          required_keys=['count', 'type', 'format'],
1049          max_length=3),
1050      action='append',
1051      help=help_text)
1052
1053
1054def AddEphemeralStorageFlag(parser,
1055                            hidden=False,
1056                            for_node_pool=False,
1057                            help_text=''):
1058  """Adds --ephemeral-storage flag to the parser."""
1059  help_text += """\
1060Parameters for the ephemeral storage filesystem.
1061If unspecified, ephemeral storage is backed by the boot disk. Example:
1062
1063  $ {{command}} {0} --ephemeral-storage local-ssd-count=2
1064
1065'local-ssd-count' specifies the number of local SSDs to use to back ephemeral
1066storage. Local SDDs use NVMe interfaces and each is 375 GB in size.
1067If 'local-ssd-count=0', it means to disable using local SSDs as ephemeral storage.
1068
1069See https://cloud.google.com/compute/docs/disks/local-ssd for more information.
1070""".format('node-pool-1 --cluster=example cluster'
1071           if for_node_pool else 'example_cluster')
1072  parser.add_argument(
1073      '--ephemeral-storage',
1074      help=help_text,
1075      hidden=hidden,
1076      type=arg_parsers.ArgDict(
1077          spec={'local-ssd-count': int}, required_keys=['local-ssd-count']),
1078  )
1079
1080
1081def AddNodeTaintsFlag(parser,
1082                      for_node_pool=False,
1083                      for_update=False,
1084                      hidden=False):
1085  """Adds a --node-taints flag to the given parser."""
1086  if for_node_pool:
1087    if for_update:
1088      help_text = """\
1089Replaces all the user specified kubernetes taints on all nodes in an existing node pool, which can be used with tolerations for pod scheduling. Example:
1090
1091  $ {command} node-pool-1 --cluster=example-cluster --node-taints=key1=val1:NoSchedule,key2=val2:PreferNoSchedule
1092"""
1093    else:
1094      help_text = """\
1095Applies the given kubernetes taints on all nodes in the new node pool, which can be used with tolerations for pod scheduling. Example:
1096
1097  $ {command} node-pool-1 --cluster=example-cluster --node-taints=key1=val1:NoSchedule,key2=val2:PreferNoSchedule
1098"""
1099  else:
1100    help_text = """\
1101Applies the given kubernetes taints on all nodes in default node pool(s) in new cluster, which can be used with tolerations for pod scheduling. Example:
1102
1103  $ {command} example-cluster --node-taints=key1=val1:NoSchedule,key2=val2:PreferNoSchedule
1104"""
1105  help_text += """
1106Note, this feature uses `gcloud beta` commands. To use gcloud beta commands,
1107you must configure `gcloud` to use the v1beta1 API as described here: https://cloud.google.com/kubernetes-engine/docs/reference/api-organization#beta.
1108To read more about node-taints, see https://cloud.google.com/kubernetes-engine/docs/node-taints.
1109"""
1110
1111  parser.add_argument(
1112      '--node-taints',
1113      metavar='NODE_TAINT',
1114      type=arg_parsers.ArgDict(),
1115      help=help_text,
1116      hidden=hidden)
1117
1118
1119def AddPreemptibleFlag(parser, for_node_pool=False, suppressed=False):
1120  """Adds a --preemptible flag to parser."""
1121  if for_node_pool:
1122    help_text = """\
1123Create nodes using preemptible VM instances in the new node pool.
1124
1125  $ {command} node-pool-1 --cluster=example-cluster --preemptible
1126"""
1127  else:
1128    help_text = """\
1129Create nodes using preemptible VM instances in the new cluster.
1130
1131  $ {command} example-cluster --preemptible
1132"""
1133  help_text += """
1134New nodes, including ones created by resize or recreate, will use preemptible
1135VM instances. See https://cloud.google.com/kubernetes-engine/docs/preemptible-vm
1136for more information on how to use Preemptible VMs with Kubernetes Engine."""
1137
1138  parser.add_argument(
1139      '--preemptible', action='store_true', help=help_text, hidden=suppressed)
1140
1141
1142def AddNodePoolNameArg(parser, help_text):
1143  """Adds a name flag to the given parser.
1144
1145  Args:
1146    parser: A given parser.
1147    help_text: The help text describing the operation being performed.
1148  """
1149  parser.add_argument('name', metavar='NAME', help=help_text)
1150
1151
1152def AddNodePoolClusterFlag(parser, help_text):
1153  """Adds a --cluster flag to the parser.
1154
1155  Args:
1156    parser: A given parser.
1157    help_text: The help text describing usage of the --cluster flag being set.
1158  """
1159  parser.add_argument(
1160      '--cluster',
1161      help=help_text,
1162      action=actions.StoreProperty(properties.VALUES.container.cluster))
1163
1164
1165def AddEnableAutoRepairFlag(parser, for_node_pool=False, for_create=False):
1166  """Adds a --enable-autorepair flag to parser."""
1167  if for_node_pool:
1168    help_text = """\
1169Enable node autorepair feature for a node pool.
1170
1171  $ {command} node-pool-1 --cluster=example-cluster --enable-autorepair
1172"""
1173    if for_create:
1174      help_text += """
1175Node autorepair is enabled by default for node pools using COS, COS_CONTAINERD, UBUNTU or UBUNTU_CONTAINERD
1176as a base image, use --no-enable-autorepair to disable.
1177"""
1178  else:
1179    help_text = """\
1180Enable node autorepair feature for a cluster's default node pool(s).
1181
1182  $ {command} example-cluster --enable-autorepair
1183"""
1184    if for_create:
1185      help_text += """
1186Node autorepair is enabled by default for clusters using COS, COS_CONTAINERD, UBUNTU or UBUNTU_CONTAINERD
1187as a base image, use --no-enable-autorepair to disable.
1188"""
1189  help_text += """
1190See https://cloud.google.com/kubernetes-engine/docs/how-to/node-auto-repair for \
1191more info."""
1192
1193  parser.add_argument(
1194      '--enable-autorepair', action='store_true', default=None, help=help_text)
1195
1196
1197def AddEnableAutoUpgradeFlag(parser,
1198                             for_node_pool=False,
1199                             suppressed=False,
1200                             default=None):
1201  """Adds a --enable-autoupgrade flag to parser."""
1202  if for_node_pool:
1203    help_text = """\
1204Sets autoupgrade feature for a node pool.
1205
1206  $ {command} node-pool-1 --cluster=example-cluster --enable-autoupgrade
1207"""
1208  else:
1209    help_text = """\
1210Sets autoupgrade feature for a cluster's default node pool(s).
1211
1212  $ {command} example-cluster --enable-autoupgrade
1213"""
1214  help_text += """
1215See https://cloud.google.com/kubernetes-engine/docs/node-auto-upgrades for more \
1216info."""
1217
1218  parser.add_argument(
1219      '--enable-autoupgrade',
1220      action='store_true',
1221      default=default,
1222      help=help_text,
1223      hidden=suppressed)
1224
1225
1226def AddTagsFlag(parser, help_text):
1227  """Adds a --tags to the given parser."""
1228  parser.add_argument(
1229      '--tags',
1230      metavar='TAG',
1231      type=arg_parsers.ArgList(min_length=1),
1232      help=help_text)
1233
1234
1235def AddTagsCreate(parser):
1236  AddTagsFlag(
1237      parser, """\
1238Applies the given Compute Engine tags (comma separated) on all nodes in the new
1239node-pool. Example:
1240
1241  $ {command} example-cluster --tags=tag1,tag2
1242
1243New nodes, including ones created by resize or recreate, will have these tags
1244on the Compute Engine API instance object and can be used in firewall rules.
1245See https://cloud.google.com/sdk/gcloud/reference/compute/firewall-rules/create
1246for examples.
1247""")
1248
1249
1250def AddTagsNodePoolUpdate(parser, hidden=False):
1251  """Adds a --tags flag to the given parser."""
1252  help_text = """\
1253Replaces all the user specified Compute Engine tags on all nodes in an existing
1254node pool with the given tags (comma separated). Example
1255
1256  $ {command} node-pool-1 --cluster=example-cluster --tags=tag1,tag2
1257
1258New nodes, including ones created by resize or recreate, will have these tags
1259on the Compute Engine API instance object and these tags can be used in
1260firewall rules.
1261See https://cloud.google.com/sdk/gcloud/reference/compute/firewall-rules/create
1262for examples.
1263"""
1264  parser.add_argument(
1265      '--tags',
1266      metavar='TAG',
1267      type=arg_parsers.ArgList(),
1268      help=help_text,
1269      hidden=hidden)
1270
1271
1272def AddMasterAuthorizedNetworksFlags(parser, enable_group_for_update=None):
1273  """Adds Master Authorized Networks related flags to parser.
1274
1275  Master Authorized Networks related flags are:
1276  --enable-master-authorized-networks --master-authorized-networks.
1277
1278  Args:
1279    parser: A given parser.
1280    enable_group_for_update: An optional group of mutually exclusive flag
1281      options to which an --enable-master-authorized-networks flag is added in
1282      an update command.
1283  """
1284  if enable_group_for_update is None:
1285    # Flags are being added to the same group.
1286    master_flag_group = parser.add_argument_group('Master Authorized Networks')
1287    enable_flag_group = master_flag_group
1288  else:
1289    # Flags are being added to different groups, so the new one should have no
1290    # help text (has only one arg).
1291    master_flag_group = parser.add_argument_group('')
1292    enable_flag_group = enable_group_for_update
1293
1294  enable_flag_group.add_argument(
1295      '--enable-master-authorized-networks',
1296      default=None,
1297      help="""\
1298Allow only specified set of CIDR blocks (specified by the
1299`--master-authorized-networks` flag) to connect to Kubernetes master through
1300HTTPS. Besides these blocks, the following have access as well:\n
1301  1) The private network the cluster connects to if
1302  `--enable-private-nodes` is specified.
1303  2) Google Compute Engine Public IPs if `--enable-private-nodes` is not
1304  specified.\n
1305Use `--no-enable-master-authorized-networks` to disable. When disabled, public
1306internet (0.0.0.0/0) is allowed to connect to Kubernetes master through HTTPS.
1307""",
1308      action='store_true')
1309  master_flag_group.add_argument(
1310      '--master-authorized-networks',
1311      type=arg_parsers.ArgList(min_length=1),
1312      metavar='NETWORK',
1313      help='The list of CIDR blocks (up to {max_private} for private cluster, '
1314      '{max_public} for public cluster) that are allowed to connect '
1315      'to Kubernetes master through HTTPS. Specified in CIDR notation (e.g. '
1316      '1.2.3.4/30). Cannot be specified unless '
1317      '`--enable-master-authorized-networks` is also specified.'.format(
1318          max_private=api_adapter.MAX_AUTHORIZED_NETWORKS_CIDRS_PRIVATE,
1319          max_public=api_adapter.MAX_AUTHORIZED_NETWORKS_CIDRS_PUBLIC))
1320
1321
1322def AddNetworkPolicyFlags(parser, hidden=False):
1323  """Adds --enable-network-policy flags to parser."""
1324  parser.add_argument(
1325      '--enable-network-policy',
1326      action='store_true',
1327      default=None,
1328      hidden=hidden,
1329      help='Enable network policy enforcement for this cluster. If you are '
1330      'enabling network policy on an existing cluster the network policy '
1331      'addon must first be enabled on the master by using '
1332      '--update-addons=NetworkPolicy=ENABLED flag.')
1333
1334
1335def AddILBSubsettingFlags(parser, hidden=True):
1336  """Adds --enable-l4-ilb-subsetting flags to parser."""
1337  parser.add_argument(
1338      '--enable-l4-ilb-subsetting',
1339      action='store_true',
1340      default=None,
1341      hidden=hidden,
1342      help='Enable Subsetting for L4 ILB services created on this cluster.')
1343
1344
1345def AddClusterDNSFlags(parser, hidden=True):
1346  """Adds flags related to clusterDNS to parser.
1347
1348  This includes:
1349  --cluster-dns={clouddns|default},
1350  --cluster-dns-scope={cluster|vpc},
1351  --cluster-dns-domain=string
1352
1353  Args:
1354    parser: A given parser.
1355    hidden: Indicates that the flags are hidden.
1356  """
1357  group = parser.add_argument_group('ClusterDNS', hidden=hidden)
1358  group.add_argument(
1359      '--cluster-dns',
1360      choices=_DNS_PROVIDER,
1361      help=('DNS provider to use for this Cluster.'),
1362      hidden=hidden,
1363  )
1364  group.add_argument(
1365      '--cluster-dns-scope',
1366      choices=_DNS_SCOPE,
1367      help=("""
1368            DNS Scope for the CloudDNS zone created - valid only with
1369             `--cluster-dns=clouddns`"""),
1370      hidden=hidden,
1371  )
1372  group.add_argument(
1373      '--cluster-dns-domain',
1374      help=("""
1375            DNS Domain for this cluster.
1376            The default value is ``cluster.local''.
1377            is configurable when `--cluster-dns=clouddns` and
1378             `--cluster-dns-scope=vpc`.
1379            The value must be a valid DNS Subdomain as defined in RFC 1123.
1380            """),
1381      hidden=hidden,
1382  )
1383
1384
1385def AddPrivateClusterFlags(parser, default=None, with_deprecated=False):
1386  """Adds flags related to private clusters to parser."""
1387
1388  default = {} if default is None else default
1389  group = parser.add_argument_group('Private Clusters')
1390  if with_deprecated:
1391    if 'private_cluster' not in default:
1392      group.add_argument(
1393          '--private-cluster',
1394          help=('Cluster is created with no public IP addresses on the cluster '
1395                'nodes.'),
1396          default=None,
1397          action=actions.DeprecationAction(
1398              'private-cluster',
1399              warn='The --private-cluster flag is deprecated and will be removed '
1400              'in a future release. Use --enable-private-nodes instead.',
1401              action='store_true'))
1402
1403  if 'enable_private_nodes' not in default:
1404    group.add_argument(
1405        '--enable-private-nodes',
1406        help=('Cluster is created with no public IP addresses on the cluster '
1407              'nodes.'),
1408        default=None,
1409        action='store_true')
1410
1411  if 'enable_private_endpoint' not in default:
1412    group.add_argument(
1413        '--enable-private-endpoint',
1414        help=('Cluster is managed using the private IP address of the master '
1415              'API endpoint.'),
1416        default=None,
1417        action='store_true')
1418
1419  if 'master_ipv4_cidr' not in default:
1420    group.add_argument(
1421        '--master-ipv4-cidr',
1422        help=('IPv4 CIDR range to use for the master network.  This should have'
1423              ' a netmask of size /28 and should be used in conjunction with '
1424              'the --enable-private-nodes flag.'),
1425        default=None)
1426
1427
1428def AddEnableLegacyAuthorizationFlag(parser, hidden=False):
1429  """Adds a --enable-legacy-authorization flag to parser."""
1430  help_text = """\
1431Enables the legacy ABAC authentication for the cluster.
1432User rights are granted through the use of policies which combine attributes
1433together. For a detailed look at these properties and related formats, see
1434https://kubernetes.io/docs/admin/authorization/abac/. To use RBAC permissions
1435instead, create or update your cluster with the option
1436`--no-enable-legacy-authorization`.
1437"""
1438  parser.add_argument(
1439      '--enable-legacy-authorization',
1440      action='store_true',
1441      default=None,
1442      hidden=hidden,
1443      help=help_text)
1444
1445
1446def AddAuthenticatorSecurityGroupFlags(parser, hidden=False):
1447  """Adds --security-group to parser."""
1448  help_text = """\
1449The name of the RBAC security group for use with Google security groups
1450in Kubernetes RBAC
1451(https://kubernetes.io/docs/reference/access-authn-authz/rbac/).
1452
1453To include group membership as part of the claims issued by Google
1454during authentication, a group must be designated as a security group by
1455including it as a direct member of this group.
1456
1457If unspecified, no groups will be returned for use with RBAC."""
1458  parser.add_argument(
1459      '--security-group', help=help_text, default=None, hidden=hidden)
1460
1461
1462def AddStartIpRotationFlag(parser, hidden=False):
1463  """Adds a --start-ip-rotation flag to parser."""
1464  help_text = """\
1465Start the rotation of this cluster to a new IP. For example:
1466
1467  $ {command} example-cluster --start-ip-rotation
1468
1469This causes the cluster to serve on two IPs, and will initiate a node upgrade \
1470to point to the new IP."""
1471  parser.add_argument(
1472      '--start-ip-rotation',
1473      action='store_true',
1474      default=False,
1475      hidden=hidden,
1476      help=help_text)
1477
1478
1479def AddStartCredentialRotationFlag(parser, hidden=False):
1480  """Adds a --start-credential-rotation flag to parser."""
1481  help_text = """\
1482Start the rotation of IP and credentials for this cluster. For example:
1483
1484  $ {command} example-cluster --start-credential-rotation
1485
1486This causes the cluster to serve on two IPs, and will initiate a node upgrade \
1487to point to the new IP."""
1488  parser.add_argument(
1489      '--start-credential-rotation',
1490      action='store_true',
1491      default=False,
1492      hidden=hidden,
1493      help=help_text)
1494
1495
1496def AddCompleteIpRotationFlag(parser, hidden=False):
1497  """Adds a --complete-ip-rotation flag to parser."""
1498  help_text = """\
1499Complete the IP rotation for this cluster. For example:
1500
1501  $ {command} example-cluster --complete-ip-rotation
1502
1503This causes the cluster to stop serving its old IP, and return to a single IP \
1504state."""
1505  parser.add_argument(
1506      '--complete-ip-rotation',
1507      action='store_true',
1508      default=False,
1509      hidden=hidden,
1510      help=help_text)
1511
1512
1513def AddCompleteCredentialRotationFlag(parser, hidden=False):
1514  """Adds a --complete-credential-rotation flag to parser."""
1515  help_text = """\
1516Complete the IP and credential rotation for this cluster. For example:
1517
1518  $ {command} example-cluster --complete-credential-rotation
1519
1520This causes the cluster to stop serving its old IP, return to a single IP, and \
1521invalidate old credentials."""
1522  parser.add_argument(
1523      '--complete-credential-rotation',
1524      action='store_true',
1525      default=False,
1526      hidden=hidden,
1527      help=help_text)
1528
1529
1530def AddMaintenanceWindowGroup(parser,
1531                              hidden=False,
1532                              recurring_windows_hidden=False):
1533  """Adds a mutex for --maintenance-window and --maintenance-window-*."""
1534  maintenance_group = parser.add_group(hidden=hidden, mutex=True)
1535  maintenance_group.help = """\
1536One of either maintenance-window or the group of maintenance-window flags can
1537be set.
1538"""
1539  AddDailyMaintenanceWindowFlag(maintenance_group)
1540  AddRecurringMaintenanceWindowFlags(
1541      maintenance_group, hidden=recurring_windows_hidden)
1542
1543
1544def AddDailyMaintenanceWindowFlag(parser, hidden=False, add_unset_text=False):
1545  """Adds a --maintenance-window flag to parser."""
1546  help_text = """\
1547Set a time of day when you prefer maintenance to start on this cluster. \
1548For example:
1549
1550  $ {command} example-cluster --maintenance-window=12:43
1551
1552The time corresponds to the UTC time zone, and must be in HH:MM format.
1553
1554Non-emergency maintenance will occur in the 4 hour block starting at the
1555specified time.
1556
1557This is mutually exclusive with the recurring maintenance windows
1558and will overwrite any existing window. Compatible with maintenance
1559exclusions.
1560"""
1561  unset_text = """
1562To remove an existing maintenance window from the cluster, use
1563'--clear-maintenance-window'.
1564"""
1565  description = 'Maintenance windows must be passed in using HH:MM format.'
1566  unset_description = ' They can also be removed by using the word \"None\".'
1567
1568  if add_unset_text:
1569    help_text += unset_text
1570    description += unset_description
1571
1572  type_ = arg_parsers.RegexpValidator(
1573      r'^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$|^None$', description)
1574  parser.add_argument(
1575      '--maintenance-window',
1576      default=None,
1577      hidden=hidden,
1578      type=type_,
1579      metavar='START_TIME',
1580      help=help_text)
1581
1582
1583def AddRecurringMaintenanceWindowFlags(parser, hidden=False, is_update=False):
1584  """Adds flags related to recurring maintenance windows to the parser."""
1585  hidden_for_create = hidden and not is_update  # for surface spec validation
1586  if is_update:
1587    group = parser.add_group(hidden=hidden, mutex=True)
1588  else:
1589    group = parser
1590
1591  # See core/document_renderers/render_document.py for the formatting
1592  # weirdness. Newlines in group help text breaks help generation horribly.
1593  # These + symbols get us our paragraphs. Also, note that gcloud can wrap
1594  # long commands funny, so these examples have to be tailored to not go too
1595  # long without whitespace.
1596  set_window_group = group.add_group(
1597      hidden=hidden_for_create,
1598      help="""\
1599Set a flexible maintenance window by specifying a window that recurs per an
1600RFC 5545 RRULE. Non-emergency maintenance will occur in the recurring windows.
1601+
1602Examples:
1603+
1604For a 9-5 Mon-Wed UTC-4 maintenance window:
1605+
1606  $ {command} example-cluster \
1607  --maintenance-window-start=2000-01-01T09:00:00-04:00 \
1608  --maintenance-window-end=2000-01-01T17:00:00-04:00 \
1609  --maintenance-window-recurrence='FREQ=WEEKLY;BYDAY=MO,TU,WE'
1610+
1611For a daily window from 22:00 - 04:00 UTC:
1612+
1613  $ {command} example-cluster \
1614  --maintenance-window-start=2000-01-01T22:00:00Z \
1615  --maintenance-window-end=2000-01-02T04:00:00Z \
1616  --maintenance-window-recurrence=FREQ=DAILY
1617""")
1618
1619  set_window_group.add_argument(
1620      '--maintenance-window-start',
1621      type=arg_parsers.Datetime.Parse,
1622      required=True,
1623      hidden=hidden_for_create,
1624      metavar='TIME_STAMP',
1625      help="""\
1626Start time of the first window (can occur in the past). The start time
1627influences when the window will start for recurrences. See $ gcloud topic
1628datetimes for information on time formats.
1629""")
1630
1631  set_window_group.add_argument(
1632      '--maintenance-window-end',
1633      type=arg_parsers.Datetime.Parse,
1634      required=True,
1635      hidden=hidden_for_create,
1636      metavar='TIME_STAMP',
1637      help="""\
1638End time of the first window (can occur in the past). Must take place after the
1639start time. The difference in start and end time specifies the length of each
1640recurrence. See $ gcloud topic datetimes for information on time formats.
1641""")
1642
1643  set_window_group.add_argument(
1644      '--maintenance-window-recurrence',
1645      type=str,
1646      required=True,
1647      hidden=hidden_for_create,
1648      metavar='RRULE',
1649      help="""\
1650An RFC 5545 RRULE, specifying how the window will recur. Note that minimum
1651requirements for maintenance periods will be enforced. Note that FREQ=SECONDLY,
1652MINUTELY, and HOURLY are not supported.
1653""")
1654
1655  if is_update:
1656    group.add_argument(
1657        '--clear-maintenance-window',
1658        action='store_true',
1659        default=False,
1660        help="""\
1661If set, remove the maintenance window that was set with --maintenance-window
1662family of flags.
1663""")
1664    AddMaintenanceExclusionFlags(group)
1665
1666
1667def AddMaintenanceExclusionFlags(parser, hidden=False):
1668  """Adds flags related to adding a maintenance exclusion to the parser."""
1669  group = parser.add_group(
1670      hidden=hidden,
1671      help="""\
1672Sets a period of time in which maintenance should not occur. This is compatible
1673with both daily and recurring maintenance windows.
1674+
1675Example:
1676+
1677  $ {command} example-cluster \
1678  --add-maintenance-exclusion-name=holidays-2000 \
1679  --add-maintenance-exclusion-start=2000-11-20T00:00:00 \
1680  --add-maintenance-exclusion-end=2000-12-31T23:59:59
1681""")
1682
1683  group.add_argument(
1684      '--add-maintenance-exclusion-name',
1685      type=str,
1686      metavar='NAME',
1687      help="""\
1688A descriptor for the exclusion that can be used to remove it. If not specified,
1689it will be autogenerated.
1690""")
1691
1692  group.add_argument(
1693      '--add-maintenance-exclusion-start',
1694      type=arg_parsers.Datetime.Parse,
1695      metavar='TIME_STAMP',
1696      help="""\
1697Start time of the exclusion window (can occur in the past). If not specified,
1698the current time will be used. See $ gcloud topic datetimes for information on
1699time formats.
1700""")
1701
1702  group.add_argument(
1703      '--add-maintenance-exclusion-end',
1704      type=arg_parsers.Datetime.Parse,
1705      required=True,
1706      metavar='TIME_STAMP',
1707      help="""\
1708End time of the exclusion window. Must take place after the start time. See
1709$ gcloud topic datetimes for information on time formats.
1710""")
1711
1712  parser.add_argument(
1713      '--remove-maintenance-exclusion',
1714      type=str,
1715      hidden=hidden,
1716      metavar='NAME',
1717      help="""\
1718Name of a maintenance exclusion to remove. If you hadn't specified a name, one
1719was auto-generated. Get it with $ gcloud container clusters describe.
1720""")
1721
1722
1723def AddLabelsFlag(parser, suppressed=False):
1724  """Adds Labels related flags to parser.
1725
1726  Args:
1727    parser: A given parser.
1728    suppressed: Whether or not to suppress help text.
1729  """
1730
1731  help_text = """\
1732Labels to apply to the Google Cloud resources in use by the Kubernetes Engine
1733cluster. These are unrelated to Kubernetes labels.
1734Example:
1735
1736  $ {command} example-cluster --labels=label_a=value1,label_b=,label_c=value3
1737"""
1738  parser.add_argument(
1739      '--labels',
1740      metavar='KEY=VALUE',
1741      type=arg_parsers.ArgDict(),
1742      help=help_text,
1743      hidden=suppressed)
1744
1745
1746def AddUpdateLabelsFlag(parser):
1747  """Adds Update Labels related flags to parser.
1748
1749  Args:
1750    parser: A given parser.
1751  """
1752
1753  help_text = """\
1754Labels to apply to the Google Cloud resources in use by the Kubernetes Engine
1755cluster. These are unrelated to Kubernetes labels.
1756Example:
1757
1758  $ {command} example-cluster --update-labels=label_a=value1,label_b=value2
1759"""
1760  parser.add_argument(
1761      '--update-labels',
1762      metavar='KEY=VALUE',
1763      type=arg_parsers.ArgDict(),
1764      help=help_text)
1765
1766
1767def AddRemoveLabelsFlag(parser):
1768  """Adds Remove Labels related flags to parser.
1769
1770  Args:
1771    parser: A given parser.
1772  """
1773
1774  help_text = """\
1775Labels to remove from the Google Cloud resources in use by the Kubernetes Engine
1776cluster. These are unrelated to Kubernetes labels.
1777Example:
1778
1779  $ {command} example-cluster --remove-labels=label_a,label_b
1780"""
1781  parser.add_argument(
1782      '--remove-labels',
1783      metavar='KEY',
1784      type=arg_parsers.ArgList(),
1785      help=help_text)
1786
1787
1788def AddDiskSizeFlag(parser):
1789  parser.add_argument(
1790      '--disk-size',
1791      type=arg_parsers.BinarySize(lower_bound='10GB'),
1792      help='Size for node VM boot disks. Defaults to 100GB.')
1793
1794
1795def AddDiskTypeFlag(parser):
1796  """Adds a --disk-type flag to the given parser.
1797
1798  Args:
1799    parser: A given parser.
1800  """
1801  help_text = """\
1802Type of the node VM boot disk. Defaults to pd-standard.
1803"""
1804  parser.add_argument(
1805      '--disk-type',
1806      help=help_text,
1807      choices=['pd-standard', 'pd-ssd', 'pd-balanced'])
1808
1809
1810def AddIpAliasCoreFlag(parser):
1811  parser.add_argument(
1812      '--enable-ip-alias',
1813      action='store_true',
1814      default=None,
1815      help="""\
1816Enable use of alias IPs (https://cloud.google.com/compute/docs/alias-ip/)
1817for Pod IPs. This will require at least two secondary ranges in the
1818subnetwork, one for the pod IPs and another to reserve space for the
1819services range.
1820""")
1821
1822
1823def AddIPAliasRelatedFlags(parser):
1824  """Adds flags related to IP aliases to the parser.
1825
1826  Args:
1827    parser: A given parser.
1828  """
1829  parser.add_argument(
1830      '--services-ipv4-cidr',
1831      metavar='CIDR',
1832      help="""\
1833Set the IP range for the services IPs.
1834
1835Can be specified as a netmask size (e.g. '/20') or as in CIDR notion
1836(e.g. '10.100.0.0/20'). If given as a netmask size, the IP range will
1837be chosen automatically from the available space in the network.
1838
1839If unspecified, the services CIDR range will be chosen with a default
1840mask size.
1841
1842Can not be specified unless '--enable-ip-alias' is also specified.
1843""")
1844  parser.add_argument(
1845      '--create-subnetwork',
1846      metavar='KEY=VALUE',
1847      type=arg_parsers.ArgDict(),
1848      help="""\
1849Create a new subnetwork for the cluster. The name and range of the
1850subnetwork can be customized via optional 'name' and 'range' key-value
1851pairs.
1852
1853'name' specifies the name of the subnetwork to be created.
1854
1855'range' specifies the IP range for the new subnetwork. This can either
1856be a netmask size (e.g. '/20') or a CIDR range (e.g. '10.0.0.0/20').
1857If a netmask size is specified, the IP is automatically taken from the
1858free space in the cluster's network.
1859
1860Examples:
1861
1862Create a new subnetwork with a default name and size.
1863
1864      $ {command} --create-subnetwork ""
1865
1866Create a new subnetwork named "my-subnet" with netmask of size 21.
1867
1868      $ {command} --create-subnetwork name=my-subnet,range=/21
1869
1870Create a new subnetwork with a default name with the primary range of
187110.100.0.0/16.
1872
1873      $ {command} --create-subnetwork range=10.100.0.0/16
1874
1875Create a new subnetwork with the name "my-subnet" with a default range.
1876
1877      $ {command} --create-subnetwork name=my-subnet
1878
1879Can not be specified unless '--enable-ip-alias' is also specified. Can
1880not be used in conjunction with the '--subnetwork' option.
1881""")
1882  parser.add_argument(
1883      '--cluster-secondary-range-name',
1884      metavar='NAME',
1885      help="""\
1886Set the secondary range to be used as the source for pod IPs. Alias
1887ranges will be allocated from this secondary range.  NAME must be the
1888name of an existing secondary range in the cluster subnetwork.
1889
1890Must be used in conjunction with '--enable-ip-alias'. Cannot be used
1891with --create-subnetwork.
1892""")
1893  parser.add_argument(
1894      '--services-secondary-range-name',
1895      metavar='NAME',
1896      help="""\
1897Set the secondary range to be used for services (e.g. ClusterIPs).
1898NAME must be the name of an existing secondary range in the cluster
1899subnetwork.
1900
1901Must be used in conjunction with '--enable-ip-alias'. Cannot be used
1902with --create-subnetwork.
1903""")
1904
1905
1906def AddMaxPodsPerNodeFlag(parser, for_node_pool=False, hidden=False):
1907  """Adds max pod number constraints flags to the parser.
1908
1909  Args:
1910    parser: A given parser.
1911    for_node_pool: True if it's applied to a node pool. False if it's applied to
1912      a cluster.
1913    hidden: Whether or not to hide the help text.
1914  """
1915  parser.add_argument(
1916      '--max-pods-per-node',
1917      default=None,
1918      help="""\
1919The max number of pods per node for this node pool.
1920
1921This flag sets the maximum number of pods that can be run at the same time on a
1922node. This will override the value given with --default-max-pods-per-node flag
1923set at the cluster level.
1924
1925Must be used in conjunction with '--enable-ip-alias'.
1926""",
1927      hidden=hidden,
1928      type=int)
1929  if not for_node_pool:
1930    parser.add_argument(
1931        '--default-max-pods-per-node',
1932        default=None,
1933        help="""\
1934The default max number of pods per node for node pools in the cluster.
1935
1936This flag sets the default max-pods-per-node for node pools in the cluster. If
1937--max-pods-per-node is not specified explicitly for a node pool, this flag
1938value will be used.
1939
1940Must be used in conjunction with '--enable-ip-alias'.
1941""",
1942        hidden=hidden,
1943        type=int)
1944
1945
1946def AddMinCpuPlatformFlag(parser, for_node_pool=False, hidden=False):
1947  """Adds the --min-cpu-platform flag to the parser.
1948
1949  Args:
1950    parser: A given parser.
1951    for_node_pool: True if it's applied a non-default node pool.
1952    hidden: Whether or not to hide the help text.
1953  """
1954  if for_node_pool:
1955    help_text = """\
1956When specified, the nodes for the new node pool will be scheduled on host with
1957specified CPU architecture or a newer one.
1958
1959Examples:
1960
1961  $ {command} node-pool-1 --cluster=example-cluster --min-cpu-platform=PLATFORM
1962
1963"""
1964  else:
1965    help_text = """\
1966When specified, the nodes for the new cluster's default node pool will be
1967scheduled on host with specified CPU architecture or a newer one.
1968
1969Examples:
1970
1971  $ {command} example-cluster --min-cpu-platform=PLATFORM
1972
1973"""
1974
1975  help_text += """\
1976To list available CPU platforms in given zone, run:
1977
1978  $ gcloud beta compute zones describe ZONE --format="value(availableCpuPlatforms)"
1979
1980CPU platform selection is available only in selected zones.
1981"""
1982
1983  parser.add_argument(
1984      '--min-cpu-platform', metavar='PLATFORM', hidden=hidden, help=help_text)
1985
1986
1987def AddWorkloadMetadataFlag(parser, use_mode=True):
1988  """Adds the --workload-metadata flag to the parser.
1989
1990  Args:
1991    parser: A given parser.
1992    use_mode: Whether use Mode or NodeMetadata in WorkloadMetadataConfig.
1993  """
1994  choices = {
1995      'GCE_METADATA':
1996          "Pods running in this node pool have access to the node's "
1997          'underlying Compute Engine Metadata Server.',
1998      'GKE_METADATA':
1999          'Run the Kubernetes Engine Metadata Server on this node. The '
2000          'Kubernetes Engine Metadata Server exposes a metadata API to '
2001          'workloads that is compatible with the V1 Compute Metadata APIs '
2002          'exposed by the Compute Engine and App Engine Metadata Servers. '
2003          'This feature can only be enabled if Workload Identity is enabled '
2004          'at the cluster level.',
2005  }
2006  if not use_mode:
2007    choices.update({
2008        'SECURE': '[DEPRECATED] Prevents pods not in hostNetwork from '
2009                  'accessing certain VM metadata, specifically kube-env, which '
2010                  'contains Kubelet credentials, and the instance identity '
2011                  'token. This is a temporary security solution available '
2012                  'while the bootstrapping process for cluster nodes is '
2013                  'being redesigned with significant security improvements. '
2014                  'This feature is scheduled to be deprecated in the future '
2015                  'and later removed.',
2016        'EXPOSED':
2017            "[DEPRECATED] Pods running in this node pool have access to the node's "
2018            'underlying Compute Engine Metadata Server.',
2019        'GKE_METADATA_SERVER':
2020            '[DEPRECATED] Run the Kubernetes Engine Metadata Server on this node. The '
2021            'Kubernetes Engine Metadata Server exposes a metadata API to '
2022            'workloads that is compatible with the V1 Compute Metadata APIs '
2023            'exposed by the Compute Engine and App Engine Metadata Servers. '
2024            'This feature can only be enabled if Workload Identity is enabled '
2025            'at the cluster level.',
2026    })
2027
2028  parser.add_argument(
2029      '--workload-metadata',
2030      default=None,
2031      choices=choices,
2032      type=lambda x: x.upper(),
2033      help='Type of metadata server available to pods running in the node pool.'
2034  )
2035  parser.add_argument(
2036      '--workload-metadata-from-node',
2037      default=None,
2038      hidden=True,
2039      choices=choices,
2040      type=lambda x: x.upper(),
2041      help='Type of metadata server available to pods running in the node pool.'
2042  )
2043
2044
2045def AddTagOrDigestPositional(parser,
2046                             verb,
2047                             repeated=True,
2048                             tags_only=False,
2049                             arg_name=None,
2050                             metavar=None):
2051  """Adds a tag or digest positional arg."""
2052  digest_str = '*.gcr.io/PROJECT_ID/IMAGE_PATH@sha256:DIGEST or'
2053  if tags_only:
2054    digest_str = ''
2055
2056  if not arg_name:
2057    arg_name = 'image_names' if repeated else 'image_name'
2058    metavar = metavar or 'IMAGE_NAME'
2059
2060  parser.add_argument(
2061      arg_name,
2062      metavar=metavar or arg_name.upper(),
2063      nargs='+' if repeated else None,
2064      help=('The fully qualified name(s) of image(s) to {verb}. '
2065            'The name(s) should be formatted as {digest_str} '
2066            '*.gcr.io/PROJECT_ID/IMAGE_PATH:TAG.'.format(
2067                verb=verb, digest_str=digest_str)))
2068
2069
2070def AddImagePositional(parser, verb):
2071  image_path_format = '*.gcr.io/PROJECT_ID/IMAGE_PATH[:TAG|@sha256:DIGEST]'
2072  if verb == 'list tags for':
2073    image_path_format = '*.gcr.io/PROJECT_ID/IMAGE_PATH'
2074  parser.add_argument(
2075      'image_name',
2076      help=('The name of the image to {verb}. The name format should be '
2077            '{image_format}. '.format(
2078                verb=verb, image_format=image_path_format)))
2079
2080
2081def AddNodeLocationsFlag(parser):
2082  parser.add_argument(
2083      '--node-locations',
2084      type=arg_parsers.ArgList(min_length=1),
2085      metavar='ZONE',
2086      help="""\
2087The set of zones in which the specified node footprint should be replicated.
2088All zones must be in the same region as the cluster's master(s), specified by
2089the `--zone` or `--region` flag. Additionally, for zonal clusters,
2090`--node-locations` must contain the cluster's primary zone. If not specified,
2091all nodes will be in the cluster's primary zone (for zonal clusters) or spread
2092across three randomly chosen zones within the cluster's region (for regional
2093clusters).
2094
2095Note that `NUM_NODES` nodes will be created in each zone, such that if you
2096specify `--num-nodes=4` and choose two locations, 8 nodes will be created.
2097
2098Multiple locations can be specified, separated by commas. For example:
2099
2100  $ {command} example-cluster --zone us-central1-a --node-locations us-central1-a,us-central1-b
2101""")
2102
2103
2104def AddLoggingServiceFlag(parser):
2105  """Adds a --logging-service flag to the parser.
2106
2107  Args:
2108    parser: A given parser.
2109  """
2110  help_str = """\
2111Logging service to use for the cluster. Options are:
2112"logging.googleapis.com/kubernetes" (the Google Cloud Logging
2113service with Kubernetes-native resource model enabled),
2114"logging.googleapis.com" (the Google Cloud Logging service),
2115"none" (logs will not be exported from the cluster)
2116"""
2117
2118  parser.add_argument('--logging-service', help=help_str)
2119
2120
2121def AddMonitoringServiceFlag(parser):
2122  """Adds a --monitoring-service flag to the parser.
2123
2124  Args:
2125    parser: A given parser.
2126  """
2127
2128  help_str = """\
2129Monitoring service to use for the cluster. Options are:
2130"monitoring.googleapis.com/kubernetes" (the Google Cloud
2131Monitoring service with Kubernetes-native resource model enabled),
2132"monitoring.googleapis.com" (the Google Cloud Monitoring service),
2133"none" (no metrics will be exported from the cluster)
2134"""
2135
2136  parser.add_argument('--monitoring-service', help=help_str)
2137
2138
2139def AddNodeIdentityFlags(parser, example_target):
2140  """Adds node identity flags to the given parser.
2141
2142  Node identity flags are --scopes and --service-account.
2143
2144  Args:
2145    parser: A given parser.
2146    example_target: the target for the command, e.g. mycluster.
2147  """
2148  node_identity_group = parser.add_group(
2149      help='Options to specify the node identity.')
2150  scopes_group = node_identity_group.add_group(help='Scopes options.')
2151  scopes_group.add_argument(
2152      '--scopes',
2153      type=arg_parsers.ArgList(),
2154      metavar='SCOPE',
2155      default='gke-default',
2156      help="""\
2157Specifies scopes for the node instances. Examples:
2158
2159  $ {{command}} {example_target} --scopes=https://www.googleapis.com/auth/devstorage.read_only
2160
2161  $ {{command}} {example_target} --scopes=bigquery,storage-rw,compute-ro
2162
2163Multiple SCOPEs can be specified, separated by commas. `logging-write`
2164and/or `monitoring` are added unless Cloud Logging and/or Cloud Monitoring
2165are disabled (see `--enable-cloud-logging` and `--enable-cloud-monitoring`
2166for more information).
2167{scopes_help}
2168""".format(
2169    example_target=example_target, scopes_help=compute_constants.ScopesHelp()))
2170
2171  sa_help_text = (
2172      'The Google Cloud Platform Service Account to be used by the node VMs. '
2173      'If a service account is specified, the cloud-platform and '
2174      'userinfo.email scopes are used. If no Service Account is specified, the '
2175      'project default service account is used.')
2176  node_identity_group.add_argument('--service-account', help=sa_help_text)
2177
2178
2179def AddClusterNodeIdentityFlags(parser):
2180  """Adds node identity flags to the given parser.
2181
2182  This is a wrapper around AddNodeIdentityFlags for [alpha|beta] cluster, as it
2183  provides example-cluster as the example and uses non-deprecated scopes
2184  behavior.
2185
2186  Args:
2187    parser: A given parser.
2188  """
2189  AddNodeIdentityFlags(parser, example_target='example-cluster')
2190
2191
2192def AddNodePoolNodeIdentityFlags(parser):
2193  """Adds node identity flags to the given parser.
2194
2195  This is a wrapper around AddNodeIdentityFlags for (GA) node pools, as it
2196  provides node-pool-1 as the example and uses non-deprecated scopes behavior.
2197
2198  Args:
2199    parser: A given parser.
2200  """
2201  AddNodeIdentityFlags(
2202      parser, example_target='node-pool-1 --cluster=example-cluster')
2203
2204
2205def AddAddonsFlagsWithOptions(parser, addon_options):
2206  """Adds the --addons flag to the parser with the given addon options."""
2207  parser.add_argument(
2208      '--addons',
2209      type=arg_parsers.ArgList(
2210          choices=(addon_options + api_adapter.CLOUDRUN_ADDONS),
2211          visible_choices=(addon_options +
2212                           api_adapter.VISIBLE_CLOUDRUN_ADDONS)),
2213      metavar='ADDON',
2214      help="""\
2215Addons
2216(https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1/projects.locations.clusters#Cluster.AddonsConfig)
2217are additional Kubernetes cluster components. Addons specified by this flag will
2218be enabled. The others will be disabled. Default addons: {0}.
2219""".format(', '.join(api_adapter.DEFAULT_ADDONS)))
2220
2221
2222def AddAddonsFlags(parser):
2223  """Adds the --addons flag to the parser for the beta and GA tracks."""
2224  AddAddonsFlagsWithOptions(parser, api_adapter.ADDONS_OPTIONS)
2225
2226
2227def AddAlphaAddonsFlags(parser):
2228  """Adds the --addons flag to the parser for the alpha track."""
2229  AddAddonsFlagsWithOptions(parser, api_adapter.ALPHA_ADDONS_OPTIONS)
2230
2231
2232def AddBetaAddonsFlags(parser):
2233  """Adds the --addons flag to the parser for the beta track."""
2234  AddAddonsFlagsWithOptions(parser, api_adapter.BETA_ADDONS_OPTIONS)
2235
2236
2237def AddPodSecurityPolicyFlag(parser, hidden=False):
2238  """Adds a --enable-pod-security-policy flag to parser."""
2239  help_text = """\
2240Enables the pod security policy admission controller for the cluster.  The pod
2241security policy admission controller adds fine-grained pod create and update
2242authorization controls through the PodSecurityPolicy API objects. For more
2243information, see
2244https://cloud.google.com/kubernetes-engine/docs/how-to/pod-security-policies.
2245"""
2246  parser.add_argument(
2247      '--enable-pod-security-policy',
2248      action='store_true',
2249      default=None,
2250      hidden=hidden,
2251      help=help_text)
2252
2253
2254def AddAllowRouteOverlapFlag(parser):
2255  """Adds a --allow-route-overlap flag to parser."""
2256  help_text = """\
2257Allows the provided cluster CIDRs to overlap with existing routes
2258that are less specific and do not terminate at a VM.
2259
2260When enabled, `--cluster-ipv4-cidr` must be fully specified (e.g. `10.96.0.0/14`
2261, but not `/14`). If `--enable-ip-alias` is also specified, both
2262`--cluster-ipv4-cidr` and `--services-ipv4-cidr` must be fully specified.
2263
2264Must be used in conjunction with '--enable-ip-alias' or '--no-enable-ip-alias'.
2265"""
2266  parser.add_argument(
2267      '--allow-route-overlap',
2268      action='store_true',
2269      default=None,
2270      help=help_text)
2271
2272
2273def AddTpuFlags(parser, hidden=False, enable_tpu_service_networking=False):
2274  """Adds flags related to TPUs to the parser.
2275
2276  Args:
2277    parser: A given parser.
2278    hidden: Whether or not to hide the help text.
2279    enable_tpu_service_networking: Whether to add the
2280      enable_tpu_service_networking flag.
2281  """
2282
2283  tpu_group = parser.add_group(help='Flags relating to Cloud TPUs:')
2284
2285  tpu_group.add_argument(
2286      '--enable-tpu',
2287      action='store_true',
2288      default=None,
2289      hidden=hidden,
2290      help="""\
2291Enable Cloud TPUs for this cluster.
2292
2293Can not be specified unless `--enable-ip-alias` is also specified.
2294""")
2295
2296  group = tpu_group
2297
2298  if enable_tpu_service_networking:
2299    group = tpu_group.add_mutually_exclusive_group()
2300    group.add_argument(
2301        '--enable-tpu-service-networking',
2302        action='store_true',
2303        default=None,
2304        hidden=hidden,
2305        help="""\
2306Enable Cloud TPU's Service Networking mode. In this mode, the CIDR blocks used
2307by the Cloud TPUs will be allocated and managed by Service Networking, instead
2308of Kubernetes Engine.
2309
2310This cannot be specified if `tpu-ipv4-cidr` is specified.
2311""")
2312
2313  group.add_argument(
2314      '--tpu-ipv4-cidr',
2315      metavar='CIDR',
2316      hidden=hidden,
2317      help="""\
2318Set the IP range for the Cloud TPUs.
2319
2320Can be specified as a netmask size (e.g. '/20') or as in CIDR notion
2321(e.g. '10.100.0.0/20'). If given as a netmask size, the IP range will be chosen
2322automatically from the available space in the network.
2323
2324If unspecified, the TPU CIDR range will use automatic default '/20'.
2325
2326Can not be specified unless '--enable-tpu' and '--enable-ip-alias' are also
2327specified.
2328""")
2329
2330
2331def AddIssueClientCertificateFlag(parser):
2332  """Adds --issue-client-certificate flag to the parser."""
2333  help_text = """\
2334Issue a TLS client certificate with admin permissions.
2335
2336When enabled, the certificate and private key pair will be present in
2337MasterAuth field of the Cluster object. For cluster versions before 1.12, a
2338client certificate will be issued by default. As of 1.12, client certificates
2339are disabled by default.
2340"""
2341  parser.add_argument(
2342      '--issue-client-certificate',
2343      action='store_true',
2344      default=None,
2345      help=help_text)
2346
2347
2348def AddIstioConfigFlag(parser, suppressed=False):
2349  """Adds --istio-config flag to the parser.
2350
2351  Args:
2352    parser: A given parser.
2353    suppressed: Whether or not to suppress help text.
2354  """
2355
2356  help_text = """\
2357Configurations for Istio addon, requires --addons contains Istio for create,
2358or --update-addons Istio=ENABLED for update.
2359
2360*auth*:::Optional Type of auth MTLS_PERMISSIVE or MTLS_STRICT
2361Example:
2362
2363  $ {command} example-cluster --istio-config=auth=MTLS_PERMISSIVE
2364"""
2365  parser.add_argument(
2366      '--istio-config',
2367      metavar='auth=MTLS_PERMISSIVE',
2368      type=arg_parsers.ArgDict(spec={
2369          'auth': (lambda x: x.upper()),
2370      }),
2371      help=help_text,
2372      hidden=suppressed)
2373
2374
2375def ValidateIstioConfigCreateArgs(istio_config_args, addons_args):
2376  """Validates flags specifying Istio config for create.
2377
2378  Args:
2379    istio_config_args: parsed comandline arguments for --istio_config.
2380    addons_args: parsed comandline arguments for --addons.
2381
2382  Raises:
2383    InvalidArgumentException: when auth is not MTLS_PERMISSIVE nor MTLS_STRICT,
2384    or --addon=Istio is not specified
2385  """
2386  if istio_config_args:
2387    auth = istio_config_args.get('auth', '')
2388    if auth not in ['MTLS_PERMISSIVE', 'MTLS_STRICT']:
2389      raise exceptions.InvalidArgumentException(
2390          '--istio-config', 'auth is either MTLS_PERMISSIVE or MTLS_STRICT'
2391          'e.g. --istio-config auth=MTLS_PERMISSIVE')
2392    if 'Istio' not in addons_args:
2393      raise exceptions.InvalidArgumentException(
2394          '--istio-config', '--addon=Istio must be specified when '
2395          '--istio-config is given')
2396
2397
2398def ValidateIstioConfigUpdateArgs(istio_config_args, disable_addons_args):
2399  """Validates flags specifying Istio config for update.
2400
2401  Args:
2402    istio_config_args: parsed comandline arguments for --istio_config.
2403    disable_addons_args: parsed comandline arguments for --update-addons.
2404
2405  Raises:
2406    InvalidArgumentException: when auth is not MTLS_PERMISSIVE nor MTLS_STRICT,
2407    or --update-addons=Istio=ENABLED is not specified
2408  """
2409  if istio_config_args:
2410    auth = istio_config_args.get('auth', '')
2411    if auth not in ['MTLS_PERMISSIVE', 'MTLS_STRICT']:
2412      raise exceptions.InvalidArgumentException(
2413          '--istio-config', 'auth must be one of MTLS_PERMISSIVE or '
2414          'MTLS_STRICT e.g. --istio-config auth=MTLS_PERMISSIVE')
2415    disable_istio = disable_addons_args.get('Istio')
2416    if disable_istio is None or disable_istio:
2417      raise exceptions.InvalidArgumentException(
2418          '--istio-config', '--update-addons=Istio=ENABLED must be specified '
2419          'when --istio-config is given')
2420
2421
2422# TODO(b/110368338): Drop this warning when changing the default value of the
2423# flag.
2424def WarnForUnspecifiedIpAllocationPolicy(args):
2425  if not args.IsSpecified('enable_ip_alias'):
2426    log.warning(
2427        'Currently VPC-native is not the default mode during cluster creation. '
2428        'In the future, this will become the default mode and can be disabled '
2429        'using `--no-enable-ip-alias` flag. Use `--[no-]enable-ip-alias` flag '
2430        'to suppress this warning.')
2431
2432
2433def WarnForNodeModification(args, enable_autorepair):
2434  if (args.image_type or '').lower() != 'ubuntu':
2435    return
2436  if enable_autorepair or args.enable_autoupgrade:
2437    log.warning('Modifications on the boot disks of node VMs do not persist '
2438                'across node recreations. Nodes are recreated during '
2439                'manual-upgrade, auto-upgrade, auto-repair, and auto-scaling. '
2440                'To preserve modifications across node recreation, use a '
2441                'DaemonSet.')
2442
2443
2444def WarnForNodeVersionAutoUpgrade(args):
2445  if not hasattr(args, 'node_version'):
2446    return
2447  if not hasattr(args, 'enable_autoupgrade'):
2448    return
2449  if args.IsSpecified('node_version') and args.enable_autoupgrade:
2450    log.warning(util.WARN_NODE_VERSION_WITH_AUTOUPGRADE_ENABLED)
2451
2452
2453def AddMachineTypeFlag(parser):
2454  """Adds --machine-type flag to the parser.
2455
2456  Args:
2457    parser: A given parser.
2458  """
2459
2460  help_text = """\
2461The type of machine to use for nodes. Defaults to e2-medium.
2462The list of predefined machine types is available using the following command:
2463
2464  $ gcloud compute machine-types list
2465
2466You can also specify custom machine types with the string "custom-CPUS-RAM"
2467where ```CPUS``` is the number of virtual CPUs and ```RAM``` is the amount of
2468RAM in MiB.
2469
2470For example, to create a node pool using custom machines with 2 vCPUs and 12 GB
2471of RAM:
2472
2473  $ {command} high-mem-pool --machine-type=custom-2-12288
2474"""
2475
2476  parser.add_argument('--machine-type', '-m', help=help_text)
2477
2478
2479def AddWorkloadIdentityFlags(parser,
2480                             use_identity_provider=False,
2481                             use_workload_certificates=False):
2482  """Adds Workload Identity flags to the parser."""
2483  parser.add_argument(
2484      '--workload-pool',
2485      default=None,
2486      help="""\
2487Enable Workload Identity on the cluster.
2488
2489When enabled, Kubernetes service accounts will be able to act as Cloud IAM
2490Service Accounts, through the provided workload pool.
2491
2492Currently, the only accepted workload pool is the workload pool of
2493the Cloud project containing the cluster, `PROJECT_ID.svc.id.goog`.
2494
2495For more information on Workload Identity, see
2496
2497            https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
2498  """,
2499      required=False,
2500      type=arg_parsers.RegexpValidator(
2501          # Don't document hub.id.goog in the error, but still pass it through
2502          # for now.
2503          r'^[a-z][-a-z0-9]{4,}[a-z0-9]\.(svc|hub)\.id\.goog$',
2504          "Must be in format of '[PROJECT_ID].svc.id.goog'"
2505      ),
2506  )
2507  if use_identity_provider:
2508    parser.add_argument(
2509        '--identity-provider',
2510        default=None,
2511        help="""\
2512  Enable 3P identity provider on the cluster.
2513    """)
2514  if use_workload_certificates:
2515    parser.add_argument(
2516        '--workload-identity-certificate-authority',
2517        default=None,
2518        hidden=True,
2519        type=arg_parsers.RegexpValidator(
2520            r'^//privateca\.googleapis\.com/projects/[^/]+/locations/[^/]+/certificateAuthorities/[^/]+$',
2521            'Must be of the form //privateca.googleapis.com/projects/{project}/locations/{location}/certificateAuthorities/{ca}'
2522        ),
2523        help="""\
2524Enable issuance of Workload Identity certificates from this certificate authority.
2525
2526Must be a Private CA resource URL of the form
2527`//privateca.googleapis.com/projects/{project}/locations/{location}/certificateAuthorities/{ca}`.
2528""")
2529
2530
2531def AddWorkloadIdentityUpdateFlags(parser, use_workload_certificates=False):
2532  """Adds Workload Identity update flags to the parser."""
2533  parser.add_argument(
2534      '--disable-workload-identity',
2535      default=False,
2536      action='store_true',
2537      help="""\
2538Disable Workload Identity on the cluster.
2539
2540For more information on Workload Identity, see
2541
2542            https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
2543""")
2544
2545  if use_workload_certificates:
2546    parser.add_argument(
2547        '--disable-workload-identity-certificates',
2548        default=False,
2549        action='store_true',
2550        hidden=True,
2551        help="""\
2552Disable Workload Identity certificates on the cluster.
2553""")
2554
2555
2556def AddGkeOidcFlag(parser):
2557  parser.add_argument(
2558      '--enable-gke-oidc',
2559      default=None,
2560      action='store_true',
2561      help="""\
2562Enable GKE OIDC authentication on the cluster.
2563
2564When enabled, users would be able to authenticate to Kubernetes cluster after
2565properly setting OIDC config.
2566
2567GKE OIDC is by default disabled when creating a new cluster. To disable GKE OIDC
2568in an existing cluster, explicitly set flag `--no-enable-gke-oidc`.
2569""")
2570
2571
2572def AddResourceUsageExportFlags(parser, is_update=False, hidden=False):
2573  """Adds flags about exporting cluster resource usage to BigQuery."""
2574
2575  group = parser.add_group(
2576      "Exports cluster's usage of cloud resources", hidden=hidden)
2577  if is_update:
2578    group.is_mutex = True
2579    group.add_argument(
2580        '--clear-resource-usage-bigquery-dataset',
2581        action='store_true',
2582        hidden=hidden,
2583        default=None,
2584        help='Disables exporting cluster resource usage to BigQuery.')
2585    group = group.add_group()
2586
2587  dataset_help_text = """\
2588The name of the BigQuery dataset to which the cluster's usage of cloud
2589resources is exported. A table will be created in the specified dataset to
2590store cluster resource usage. The resulting table can be joined with BigQuery
2591Billing Export to produce a fine-grained cost breakdown.
2592
2593Example:
2594
2595  $ {command} example-cluster --resource-usage-bigquery-dataset=example_bigquery_dataset_name
2596"""
2597
2598  group.add_argument(
2599      '--resource-usage-bigquery-dataset',
2600      default=None,
2601      hidden=hidden,
2602      help=dataset_help_text)
2603
2604  network_egress_help_text = """\
2605Enable network egress metering on this cluster.
2606
2607When enabled, a DaemonSet is deployed into the cluster. Each DaemonSet pod
2608meters network egress traffic by collecting data from the conntrack table, and
2609exports the metered metrics to the specified destination.
2610
2611Network egress metering is disabled if this flag is omitted, or when
2612`--no-enable-network-egress-metering` is set.
2613"""
2614  group.add_argument(
2615      '--enable-network-egress-metering',
2616      action='store_true',
2617      default=None,
2618      hidden=hidden,
2619      help=network_egress_help_text)
2620
2621  resource_consumption_help_text = """\
2622Enable resource consumption metering on this cluster.
2623
2624When enabled, a table will be created in the specified BigQuery dataset to store
2625resource consumption data. The resulting table can be joined with the resource
2626usage table or with BigQuery billing export.
2627
2628Resource consumption metering is enabled unless `--no-enable-resource-
2629consumption-metering` is set.
2630"""
2631
2632  if is_update:
2633    resource_consumption_help_text = """\
2634Enable resource consumption metering on this cluster.
2635
2636When enabled, a table will be created in the specified BigQuery dataset to store
2637resource consumption data. The resulting table can be joined with the resource
2638usage table or with BigQuery billing export.
2639
2640To disable resource consumption metering, set `--no-enable-resource-consumption-
2641metering`. If this flag is omitted, then resource consumption metering will
2642remain enabled or disabled depending on what is already configured for this
2643cluster.
2644"""
2645  group.add_argument(
2646      '--enable-resource-consumption-metering',
2647      action='store_true',
2648      default=None,
2649      hidden=hidden,
2650      help=resource_consumption_help_text)
2651
2652
2653def AddEnablePrivateIpv6AccessFlag(parser, hidden=False):
2654  """Adds --enable-private-ipv6-access flag to the parser.
2655
2656  When enabled, this allows gRPC clients on this cluster's pods a fast
2657  path to access Google hosted services (eg. Cloud Spanner,
2658  Cloud Dataflow, Cloud Bigtable)
2659  This is currently only available on Alpha clusters, and needs
2660  '--enable-kubernetes-alpha' to be specified also.
2661
2662  Args:
2663    parser: A given parser.
2664    hidden: If true, suppress help text for added options.
2665  """
2666  parser.add_argument(
2667      '--enable-private-ipv6-access',
2668      default=None,
2669      help="""\
2670Enables private access to Google services over IPv6.
2671
2672When enabled, this allows gRPC clients on this cluster's pods a fast path to
2673access Google hosted services (eg. Cloud Spanner, Cloud Dataflow, Cloud
2674Bigtable).
2675
2676This is currently only available on Alpha clusters, specified by using
2677--enable-kubernetes-alpha.
2678      """,
2679      hidden=hidden,
2680      action='store_true')
2681
2682
2683def AddPrivateIpv6GoogleAccessTypeFlag(api_version, parser, hidden=False):
2684  """Adds --private-ipv6-google-access-type={disabled|outbound-only|bidirectional} flag."""
2685  messages = apis.GetMessagesModule('container', api_version)
2686  util.GetPrivateIpv6GoogleAccessTypeMapper(
2687      messages, hidden).choice_arg.AddToParser(parser)
2688
2689
2690def AddEnableIntraNodeVisibilityFlag(parser, hidden=False):
2691  """Adds --enable-intra-node-visibility flag to the parser.
2692
2693  When enabled, the intra-node traffic is visible to VPC network.
2694
2695  Args:
2696    parser: A given parser.
2697    hidden: If true, suppress help text for added options.
2698  """
2699  parser.add_argument(
2700      '--enable-intra-node-visibility',
2701      default=None,
2702      hidden=hidden,
2703      action='store_true',
2704      help="""\
2705Enable Intra-node visibility for this cluster.
2706
2707Enabling intra-node visibility makes your intra-node pod-to-pod traffic
2708visible to the networking fabric. With this feature, you can use VPC flow
2709logging or other VPC features for intra-node traffic.
2710
2711Enabling it on an existing cluster causes the cluster
2712master and the cluster nodes to restart, which might cause a disruption.
2713""")
2714
2715
2716def AddVerticalPodAutoscalingFlag(parser, hidden=False):
2717  """Adds vertical pod autoscaling related flag to the parser.
2718
2719  VerticalPodAutoscaling related flag is: --enable-vertical-pod-autoscaling
2720
2721  Args:
2722    parser: A given parser.
2723    hidden: If true, suppress help text for added options.
2724  """
2725
2726  parser.add_argument(
2727      '--enable-vertical-pod-autoscaling',
2728      default=None,
2729      help='Enable vertical pod autoscaling for a cluster.',
2730      hidden=hidden,
2731      action='store_true')
2732
2733
2734def AddSandboxFlag(parser, hidden=False):
2735  """Adds a --sandbox flag to the given parser.
2736
2737  Args:
2738    parser: A given parser.
2739    hidden: Whether or not to hide the help text.
2740  """
2741  type_validator = arg_parsers.RegexpValidator(r'^gvisor$',
2742                                               'Type must be "gvisor"')
2743  parser.add_argument(
2744      '--sandbox',
2745      type=arg_parsers.ArgDict(
2746          spec={'type': type_validator}, required_keys=['type'], max_length=1),
2747      metavar='type=TYPE',
2748      hidden=hidden,
2749      help="""\
2750Enables the requested sandbox on all nodes in the node pool. Example:
2751
2752  $ {command} node-pool-1 --cluster=example-cluster --sandbox="type=gvisor"
2753
2754The only supported type is 'gvisor'.
2755      """)
2756
2757
2758def AddSecurityProfileForCreateFlags(parser, hidden=False):
2759  """Adds flags related to Security Profile to the parser for cluster creation.
2760
2761  Args:
2762    parser: A given parser.
2763    hidden: Whether or not to hide the help text.
2764  """
2765
2766  group = parser.add_group(help='Flags for Security Profile:')
2767
2768  group.add_argument(
2769      '--security-profile',
2770      hidden=hidden,
2771      help="""\
2772Name and version of the security profile to be applied to the cluster.
2773
2774Example:
2775
2776  $ {command} example-cluster --security-profile=default-1.0-gke.0
2777""")
2778
2779  group.add_argument(
2780      '--security-profile-runtime-rules',
2781      default=True,
2782      action='store_true',
2783      hidden=hidden,
2784      help="""\
2785Apply runtime rules in the specified security profile to the cluster.
2786When enabled (by default), a security profile controller and webhook
2787are deployed on the cluster to enforce the runtime rules. If
2788--no-security-profile-runtime-rules is specified to disable this
2789feature, only bootstrapping rules are applied, and no security profile
2790controller or webhook are installed.
2791""")
2792
2793
2794def AddSecurityProfileForUpdateFlag(parser, hidden=False):
2795  """Adds --security-profile to specify security profile for cluster update.
2796
2797  Args:
2798    parser: A given parser.
2799    hidden: Whether or not to hide the help text.
2800  """
2801
2802  parser.add_argument(
2803      '--security-profile',
2804      hidden=hidden,
2805      help="""\
2806Name and version of the security profile to be applied to the cluster.
2807If not specified, the current setting of security profile will be
2808preserved.
2809
2810Example:
2811
2812  $ {command} example-cluster --security-profile=default-1.0-gke.1
2813""")
2814
2815
2816def AddSecurityProfileForUpgradeFlags(parser, hidden=False):
2817  """Adds flags related to Security Profile to the parser for cluster upgrade.
2818
2819  Args:
2820    parser: A given parser.
2821    hidden: Whether or not to hide the help text.
2822  """
2823
2824  group = parser.add_group(help='Flags for Security Profile:')
2825
2826  group.add_argument(
2827      '--security-profile',
2828      hidden=hidden,
2829      help="""\
2830Name and version of the security profile to be applied to the cluster.
2831If not specified, the current security profile settings are preserved.
2832If the current security profile is not supported in the new cluster
2833version, this option must be explicitly specified with a supported
2834security profile, otherwise the operation will fail.
2835
2836Example:
2837
2838  $ {command} example-cluster --security-profile=default-1.0-gke.1
2839""")
2840
2841  group.add_argument(
2842      '--security-profile-runtime-rules',
2843      default=None,
2844      action='store_true',
2845      hidden=hidden,
2846      help="""\
2847Apply runtime rules in the specified security profile to the cluster.
2848When enabled, a security profile controller and webhook
2849are deployed on the cluster to enforce the runtime rules. If
2850--no-security-profile-runtime-rules is specified to disable this
2851feature, only bootstrapping rules are applied, and no security profile
2852controller or webhook are installed.
2853""")
2854
2855
2856def AddNodeGroupFlag(parser):
2857  """Adds --node-group flag to the parser."""
2858  help_text = """\
2859Assign instances of this pool to run on the specified Google Compute Engine
2860node group. This is useful for running workloads on sole tenant nodes.
2861
2862To see available sole tenant node-groups, run:
2863
2864  $ gcloud compute sole-tenancy node-groups list
2865
2866To create a sole tenant node group, run:
2867
2868  $ gcloud compute sole-tenancy node-groups create [GROUP_NAME] \
2869    --zone [ZONE] --node-template [TEMPLATE_NAME] --target-size [TARGET_SIZE]
2870
2871See https://cloud.google.com/compute/docs/nodes for more
2872information on sole tenancy and node groups.
2873"""
2874
2875  parser.add_argument('--node-group', help=help_text)
2876
2877
2878def AddInitialNodePoolNameArg(parser, hidden=True):
2879  """Adds --node-pool-name argument to the parser."""
2880  help_text = """\
2881Name of the initial node pool that will be created for the cluster.
2882
2883Specifies the name to use for the initial node pool that will be created
2884with the cluster.  If the settings specified require multiple node pools
2885to be created, the name for each pool will be prefixed by this name.  For
2886example running the following will result in three node pools being
2887created, example-node-pool-0, example-node-pool-1 and
2888example-node-pool-2:
2889
2890  $ {command} example-cluster --num-nodes 9 --max-nodes-per-pool 3 \
2891    --node-pool-name example-node-pool
2892"""
2893
2894  parser.add_argument('--node-pool-name', hidden=hidden, help=help_text)
2895
2896
2897def AddMetadataFlags(parser):
2898  """Adds --metadata and --metadata-from-file flags to the given parser."""
2899  metadata_help = """\
2900      Compute Engine metadata to be made available to the guest operating system
2901      running on nodes within the node pool.
2902
2903      Each metadata entry is a key/value pair separated by an equals sign.
2904      Metadata keys must be unique and less than 128 bytes in length. Values
2905      must be less than or equal to 32,768 bytes in length. The total size of
2906      all keys and values must be less than 512 KB. Multiple arguments can be
2907      passed to this flag. For example:
2908
2909      ``--metadata key-1=value-1,key-2=value-2,key-3=value-3''
2910
2911      Additionally, the following keys are reserved for use by Kubernetes
2912      Engine:
2913
2914      * ``cluster-location''
2915      * ``cluster-name''
2916      * ``cluster-uid''
2917      * ``configure-sh''
2918      * ``enable-os-login''
2919      * ``gci-update-strategy''
2920      * ``gci-ensure-gke-docker''
2921      * ``instance-template''
2922      * ``kube-env''
2923      * ``startup-script''
2924      * ``user-data''
2925
2926      Google Kubernetes Engine sets the following keys by default:
2927
2928      * ``serial-port-logging-enable''
2929
2930      See also Compute Engine's
2931      link:https://cloud.google.com/compute/docs/storing-retrieving-metadata[documentation]
2932      on storing and retrieving instance metadata.
2933      """
2934
2935  parser.add_argument(
2936      '--metadata',
2937      type=arg_parsers.ArgDict(min_length=1),
2938      default={},
2939      help=metadata_help,
2940      metavar='KEY=VALUE',
2941      action=arg_parsers.StoreOnceAction)
2942
2943  metadata_from_file_help = """\
2944      Same as ``--metadata'' except that the value for the entry will
2945      be read from a local file.
2946      """
2947
2948  parser.add_argument(
2949      '--metadata-from-file',
2950      type=arg_parsers.ArgDict(min_length=1),
2951      default={},
2952      help=metadata_from_file_help,
2953      metavar='KEY=LOCAL_FILE_PATH')
2954
2955
2956def AddEnableShieldedNodesFlags(parser):
2957  """Adds a --enable-shielded-nodes flag to the given parser."""
2958  help_text = """\
2959Enable Shielded Nodes for this cluster. Enabling Shielded Nodes will enable a
2960more secure Node credential bootstrapping implementation. Starting with version
29611.18, clusters will have Shielded GKE nodes by default.
2962"""
2963  parser.add_argument(
2964      '--enable-shielded-nodes',
2965      action='store_true',
2966      default=None,
2967      help=help_text,
2968      hidden=False)
2969
2970
2971# pylint: disable=protected-access
2972def ValidateSurgeUpgradeSettings(args):
2973  """Raise exception if upgrade settings are not all-or-nothing."""
2974  if ('max_surge_upgrade' in args._specified_args and
2975      'max_unavailable_upgrade' not in args._specified_args):
2976    raise exceptions.InvalidArgumentException(
2977        '--max-surge-upgrade', util.INVALIID_SURGE_UPGRADE_SETTINGS)
2978  if ('max_surge_upgrade' not in args._specified_args and
2979      'max_unavailable_upgrade' in args._specified_args):
2980    raise exceptions.InvalidArgumentException(
2981        '--max-unavailable-upgrade', util.INVALIID_SURGE_UPGRADE_SETTINGS)
2982
2983
2984def ValidateNotificationConfigFlag(args):
2985  """Raise exception if validation of notification config fails."""
2986  if 'notification_config' in args._specified_args:
2987    if 'pubsub' in args.notification_config:
2988      pubsub = args.notification_config['pubsub']
2989      if pubsub != 'ENABLED' and pubsub != 'DISABLED':
2990        raise exceptions.InvalidArgumentException(
2991            '--notification-config', 'invalid [pubsub] value \"{0}\"; '
2992            'must be ENABLED or DISABLED.'.format(pubsub))
2993      if pubsub == 'ENABLED' and 'pubsub-topic' not in args.notification_config:
2994        raise exceptions.InvalidArgumentException(
2995            '--notification-config',
2996            'when [pubsub] is ENABLED, [pubsub-topic] must not be empty')
2997
2998
2999# pylint: enable=protected-access
3000
3001
3002def AddSurgeUpgradeFlag(parser, for_node_pool=False, default=None):
3003  """Adds --max-surge-upgrade flag to the parser."""
3004
3005  if for_node_pool:
3006    max_surge_help = """\
3007Number of extra (surge) nodes to be created on each upgrade of the node pool.
3008
3009Specifies the number of extra (surge) nodes to be created during this node
3010pool's upgrades. For example, running the following command will result in
3011creating an extra node each time the node pool is upgraded:
3012
3013  $ {command} node-pool-1 --cluster=example-cluster --max-surge-upgrade=1 \
3014  --max-unavailable-upgrade=0
3015
3016Must be used in conjunction with '--max-unavailable-upgrade'.
3017"""
3018  else:
3019    max_surge_help = """\
3020Number of extra (surge) nodes to be created on each upgrade of a node pool.
3021
3022Specifies the number of extra (surge) nodes to be created during this node
3023pool's upgrades. For example, running the following command will result in
3024creating an extra node each time the node pool is upgraded:
3025
3026  $ {command} example-cluster --max-surge-upgrade=1 --max-unavailable-upgrade=0
3027
3028Must be used in conjunction with '--max-unavailable-upgrade'.
3029"""
3030  parser.add_argument(
3031      '--max-surge-upgrade',
3032      type=int,
3033      default=default,
3034      help=max_surge_help,
3035      hidden=False)
3036
3037
3038def AddMaxUnavailableUpgradeFlag(parser, for_node_pool=False, is_create=False):
3039  """Adds --max-unavailable-upgrade flag to the parser."""
3040
3041  if for_node_pool:
3042    if is_create:
3043      max_unavailable_upgrade_help = """\
3044Number of nodes that can be unavailable at the same time on each upgrade of the
3045node pool.
3046
3047Specifies the number of nodes that can be unavailable at the same time during
3048this node pool's upgrades. For example, running the following command will
3049result in having 3 nodes being upgraded in parallel (1 + 2), but keeping always
3050at least 3 (5 - 2) available each time the node pool is upgraded:
3051
3052  $ {command} node-pool-1 --cluster=example-cluster --num-nodes=5 \
3053  --max-surge-upgrade=1 --max-unavailable-upgrade=2
3054
3055Must be used in conjunction with '--max-surge-upgrade'.
3056"""
3057    else:
3058      max_unavailable_upgrade_help = """\
3059Number of nodes that can be unavailable at the same time on each upgrade of the
3060node pool.
3061
3062Specifies the number of nodes that can be unavailable at the same time during
3063this node pool's upgrades. For example, assume the node pool has 5 nodes,
3064running the following command will result in having 3 nodes being upgraded in
3065parallel (1 + 2), but keeping always at least 3 (5 - 2) available each time the
3066node pool is upgraded:
3067
3068  $ {command} node-pool-1 --cluster=example-cluster --max-surge-upgrade=1 \
3069  --max-unavailable-upgrade=2
3070
3071Must be used in conjunction with '--max-surge-upgrade'.
3072"""
3073
3074  else:
3075    max_unavailable_upgrade_help = """\
3076Number of nodes that can be unavailable at the same time on each upgrade of a
3077node pool.
3078
3079Specifies the number of nodes that can be unavailable at the same time while
3080this node pool is being upgraded. For example, running the following command
3081will result in having 3 nodes being upgraded in parallel (1 + 2), but keeping
3082always at least 3 (5 - 2) available each time the node pool is upgraded:
3083
3084   $ {command} example-cluster --num-nodes=5 --max-surge-upgrade=1 \
3085     --max-unavailable-upgrade=2
3086
3087Must be used in conjunction with '--max-surge-upgrade'.
3088"""
3089  parser.add_argument(
3090      '--max-unavailable-upgrade',
3091      type=int,
3092      default=None,
3093      help=max_unavailable_upgrade_help,
3094      hidden=False)
3095
3096
3097def AddLinuxSysctlFlags(parser, for_node_pool=False):
3098  """Adds Linux sysctl flag to the given parser."""
3099  if for_node_pool:
3100    help_text = """\
3101Linux kernel parameters to be applied to all nodes in the new node pool as well
3102as the pods running on the nodes.
3103
3104Example:
3105
3106  $ {command} node-pool-1 --linux-sysctls="net.core.somaxconn=1024,net.ipv4.tcp_rmem=4096 87380 6291456"
3107"""
3108  else:
3109    help_text = """\
3110Linux kernel parameters to be applied to all nodes in the new cluster's default
3111node pool as well as the pods running on the nodes.
3112
3113Example:
3114
3115  $ {command} example-cluster --linux-sysctls="net.core.somaxconn=1024,net.ipv4.tcp_rmem=4096 87380 6291456"
3116"""
3117  parser.add_argument(
3118      '--linux-sysctls',
3119      type=arg_parsers.ArgDict(min_length=1),
3120      default={},
3121      help=help_text,
3122      metavar='KEY=VALUE',
3123      action=arg_parsers.StoreOnceAction)
3124
3125
3126def AddDisableDefaultSnatFlag(parser, for_cluster_create=False):
3127  """Adds disable-default-snat flag to the parser.
3128
3129  Args:
3130    parser: A given parser.
3131    for_cluster_create: Whether the flag is for cluster creation.
3132  """
3133
3134  if for_cluster_create:
3135    help_text = """\
3136Disable default source NAT rules applied in cluster nodes.
3137
3138By default, cluster nodes perform source network address translation (SNAT)
3139for packets sent from Pod IP address sources to destination IP addresses
3140that are not in the non-masquerade CIDRs list.
3141For more details about SNAT and IP masquerading, see:
3142https://cloud.google.com/kubernetes-engine/docs/how-to/ip-masquerade-agent#how_ipmasq_works
3143SNAT changes the packet's source IP address to the node's internal IP address.
3144
3145When this flag is set, GKE does not perform SNAT for packets sent to any destination.
3146You must set this flag if the cluster uses privately reused public IPs.
3147
3148The --disable-default-snat flag is only applicable to private GKE clusters, which are
3149inherently VPC-native. Thus, --disable-default-snat requires that you also set
3150--enable-ip-alias and --enable-private-nodes.
3151"""
3152  else:
3153    help_text = """\
3154Disable default source NAT rules applied in cluster nodes.
3155
3156By default, cluster nodes perform source network address translation (SNAT)
3157for packets sent from Pod IP address sources to destination IP addresses
3158that are not in the non-masquerade CIDRs list.
3159For more details about SNAT and IP masquerading, see:
3160https://cloud.google.com/kubernetes-engine/docs/how-to/ip-masquerade-agent#how_ipmasq_works
3161SNAT changes the packet's source IP address to the node's internal IP address.
3162
3163When this flag is set, GKE does not perform SNAT for packets sent to any destination.
3164You must set this flag if the cluster uses privately reused public IPs.
3165
3166The --disable-default-snat flag is only applicable to private GKE clusters, which are
3167inherently VPC-native. Thus, --disable-default-snat requires that the cluster was created
3168with both --enable-ip-alias and --enable-private-nodes.
3169"""
3170  parser.add_argument(
3171      '--disable-default-snat',
3172      default=(False if for_cluster_create else None),
3173      action='store_true',
3174      help=help_text)
3175
3176
3177def AddNodePoolLocationsFlag(parser, for_create=False):
3178  """Adds a --node-locations flag for node pool to parser."""
3179  if for_create:
3180    help_text = """
3181The set of zones in which the node pool's nodes should be located.
3182
3183Multiple locations can be specified, separated by commas. For example:
3184
3185  $ {command} node-pool-1 --node-locations=us-central1-a,us-central1-b"""
3186  else:
3187    help_text = """\
3188Set of zones in which the node pool's nodes should be located.
3189Changing the locations for a node pool will result in nodes being either created or removed
3190from the node pool, depending on whether locations are being added or removed.
3191
3192Multiple locations can be specified, separated by commas. For example:
3193
3194  $ {command} node-pool-1 --node-locations=us-central1-a,us-central1-b"""
3195  parser.add_argument(
3196      '--node-locations',
3197      type=arg_parsers.ArgList(min_length=1),
3198      metavar='ZONE',
3199      help=help_text)
3200
3201
3202def AddShieldedInstanceFlags(parser):
3203  """Adds Shielded Instance flags to the given parser."""
3204  secure_boot_help = """\
3205      The instance will boot with secure boot enabled.
3206      """
3207  parser.add_argument(
3208      '--shielded-secure-boot',
3209      default=None,
3210      action='store_true',
3211      help=secure_boot_help)
3212
3213  integrity_monitoring_help = """\
3214      Enables monitoring and attestation of the boot integrity of the
3215      instance. The attestation is performed against the integrity policy
3216      baseline. This baseline is initially derived from the implicitly
3217      trusted boot image when the instance is created.
3218      """
3219  parser.add_argument(
3220      '--shielded-integrity-monitoring',
3221      default=None,
3222      action='store_true',
3223      help=integrity_monitoring_help)
3224
3225
3226def AddDatabaseEncryptionFlag(parser):
3227  """Adds Database Encryption flags to the given parser."""
3228  parser.add_argument(
3229      '--database-encryption-key',
3230      default=None,
3231      help="""\
3232Enable Database Encryption.
3233
3234Enable database encryption that will be used to encrypt Kubernetes Secrets at
3235the application layer. The key provided should be the resource ID in the format of
3236`projects/[KEY_PROJECT_ID]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME]`.
3237For more information, see
3238https://cloud.google.com/kubernetes-engine/docs/how-to/encrypting-secrets.
3239""",
3240      required=False,
3241      type=arg_parsers.RegexpValidator(
3242          r'^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$',
3243          'Must be in format of \'projects/[KEY_PROJECT_ID]/locations/[LOCATION]/keyRings/[RING_NAME]/cryptoKeys/[KEY_NAME]\''
3244      ))
3245
3246
3247def AddDisableDatabaseEncryptionFlag(parser):
3248  parser.add_argument(
3249      '--disable-database-encryption',
3250      default=False,
3251      action='store_true',
3252      help="""\
3253Disable database encryption.
3254
3255Disable Database Encryption which encrypt Kubernetes Secrets at
3256the application layer. For more information, see
3257https://cloud.google.com/kubernetes-engine/docs/how-to/encrypting-secrets.
3258      """)
3259
3260
3261def AddSystemConfigFlag(parser, hidden=True):
3262  """Adds --system-config-from-file flag to the given parser."""
3263  parser.add_argument(
3264      '--system-config-from-file',
3265      type=arg_parsers.FileContents(),
3266      hidden=hidden,
3267      help="""
3268Path of the YAML/JSON file that contains the node configuration, including
3269Linux kernel parameters (sysctls) and kubelet configs.
3270
3271Example:
3272
3273    kubeletConfig:
3274      cpuManagerPolicy: static
3275    linuxConfig:
3276      sysctl:
3277        net.core.somaxconn: '2048'
3278        net.ipv4.tcp_rmem: '4096 87380 6291456'
3279
3280List of supported kubelet configs in 'kubeletConfig'.
3281
3282KEY               | VALUE
3283----------------- | ----------------------------------
3284cpuManagerPolicy  | either 'static' or 'none'
3285cpuCFSQuota       | true or false (enabled by default)
3286cpuCFSQuotaPeriod | interval (e.g., '100ms')
3287
3288List of supported sysctls in 'linuxConfig'.
3289
3290KEY                                        | VALUE
3291------------------------------------------ | ------------------------------------------
3292net.core.netdev_max_backlog                | Any positive integer, less than 2147483647
3293net.core.rmem_max                          | Any positive integer, less than 2147483647
3294net.core.wmem_default                      | Any positive integer, less than 2147483647
3295net.core.wmem_max                          | Any positive integer, less than 2147483647
3296net.core.optmem_max                        | Any positive integer, less than 2147483647
3297net.core.somaxconn                         | Must be [128, 2147483647]
3298net.ipv4.tcp_rmem                          | Any positive integer tuple
3299net.ipv4.tcp_wmem                          | Any positive integer tuple
3300net.ipv4.tcp_tw_reuse                      | Must be {0, 1}
3301
3302Note, updating the system configuration of an existing node pool requires recreation of the nodes which which might cause a disruption.
3303""")
3304
3305
3306def AddCostManagementConfigFlag(parser, is_update=False):
3307  """Adds flags related to GKE cost management to the given parser."""
3308  help_text = """
3309Enable the cost management feature.
3310
3311When enabled, you can get informational GKE cost breakdowns by cluster,
3312namespace and label in your billing data exported to BigQuery
3313(https://cloud.google.com/billing/docs/how-to/export-data-bigquery).
3314"""
3315
3316  if is_update:
3317    help_text += """\
3318
3319Use --no-enable-cost-management to disable this feature.
3320"""
3321  parser.add_argument(
3322      '--enable-cost-management',
3323      action='store_true',
3324      default=None,
3325      help=help_text)
3326
3327
3328def AddReservationAffinityFlags(parser, for_node_pool=False):
3329  """Adds the argument to handle reservation affinity configurations."""
3330  target = 'node pool' if for_node_pool else 'default initial node pool'
3331
3332  group_text = """\
3333Specifies the reservation for the {}.""".format(target)
3334  group = parser.add_group(help=group_text)
3335
3336  affinity_text = """\
3337The type of the reservation for the {}.""".format(target)
3338  group.add_argument(
3339      '--reservation-affinity',
3340      choices=['any', 'none', 'specific'],
3341      default=None,
3342      help=affinity_text)
3343  group.add_argument(
3344      '--reservation',
3345      default=None,
3346      help="""
3347The name of the reservation, required when `--reservation-affinity=specific`.
3348""")
3349
3350
3351def AddDatapathProviderFlag(parser, hidden=False):
3352  """Adds --datapath-provider={legacy|advanced} flag."""
3353  help_text = """
3354Select datapath provider for the cluster. Defaults to `legacy`.
3355
3356$ {command} --datapath-provider=legacy
3357$ {command} --datapath-provider=advanced
3358"""
3359  parser.add_argument(
3360      '--datapath-provider',
3361      choices=_DATAPATH_PROVIDER,
3362      help=help_text,
3363      hidden=hidden)
3364
3365
3366def AddDataplaneV2Flag(parser, hidden=False):
3367  """Adds --enable-dataplane-v2 boolean flag."""
3368  help_text = """
3369Enables the new eBPF dataplane for GKE clusters that is required for
3370network security, scalability and visibility features.
3371"""
3372  parser.add_argument(
3373      '--enable-dataplane-v2',
3374      action='store_true',
3375      help=help_text,
3376      hidden=hidden)
3377
3378
3379def AddMasterGlobalAccessFlag(parser, is_update=False):
3380  """Adds --enable-master-global-access boolean flag."""
3381  help_text_suffix = """\
3382
3383Must be used in conjunction with '--enable-ip-alias' and '--enable-private-nodes'.
3384"""
3385
3386  if is_update:
3387    help_text_suffix = """"""
3388
3389  help_text = """
3390Use with private clusters to allow access to the master's private endpoint from any Google Cloud region or on-premises environment regardless of the
3391private cluster's region.
3392""" + help_text_suffix
3393
3394  parser.add_argument(
3395      '--enable-master-global-access',
3396      help=help_text,
3397      default=None,
3398      action='store_true')
3399
3400
3401def AddEnableGvnicFlag(parser):
3402  help_text = """
3403Enable the use of GVNIC for this cluster. Requires re-creation of nodes using
3404either a node-pool upgrade or node-pool creation.
3405"""
3406
3407  parser.add_argument(
3408      '--enable-gvnic', help=help_text, default=None, action='store_true')
3409
3410
3411def AddEnableConfidentialNodesFlag(parser, hidden=False):
3412  """Adds a --enable-confidential-nodes flag to the given parser."""
3413  help_text = """
3414Enable Confidential Nodes for this cluster. Enabling Confidential Nodes will
3415create nodes on Confidential VM https://cloud.google.com/compute/confidential-vm/docs/about-cvm.
3416Note that, this flag needs to be used together with --machine-type with a
3417N2D machine type https://cloud.google.com/compute/docs/machine-types#n2d_machine_types.
3418"""
3419
3420  parser.add_argument(
3421      '--enable-confidential-nodes',
3422      help=help_text,
3423      default=None,
3424      hidden=hidden,
3425      action='store_true')
3426
3427
3428def AddKubernetesObjectsExportConfig(parser, for_create=False):
3429  """Adds kubernetes-objects-changes-target and kubernetes-objects-snapshots-target flags to parser."""
3430  help_text = """\
3431Set kubernetes objects changes target [Currently only CLOUD_LOGGING value is supported].
3432  """
3433  validation_description = 'Only value CLOUD_LOGGING is accepted'
3434  regexp = r'^CLOUD_LOGGING$|^NONE$'
3435  if for_create:
3436    regexp = r'^CLOUD_LOGGING$'
3437  type_ = arg_parsers.RegexpValidator(regexp, validation_description)
3438  group = parser.add_group()
3439  group.add_argument(
3440      '--kubernetes-objects-changes-target',
3441      default=None,
3442      hidden=True,
3443      type=type_,
3444      help=help_text)
3445  help_text = """\
3446Set kubernetes objects snapshots target [Currently only CLOUD_LOGGING value is supported].
3447  """
3448  group.add_argument(
3449      '--kubernetes-objects-snapshots-target',
3450      default=None,
3451      hidden=True,
3452      type=type_,
3453      help=help_text)
3454
3455
3456def AddEnableCloudLogging(parser):
3457  parser.add_argument(
3458      '--enable-cloud-logging',
3459      action=actions.DeprecationAction(
3460          '--enable-cloud-logging',
3461          show_message=lambda val: val,
3462          warn='Legacy Logging and Monitoring is deprecated. Thus, '
3463          'flag `--enable-cloud-logging` is also deprecated. Please use '
3464          '`--enable-stackdriver-kubernetes` '
3465          '(optionally with `--no-enable-cloud-monitoring`). '
3466          'For more details, please read: '
3467          'https://cloud.google.com/monitoring/kubernetes-engine/migration.',
3468          action='store_true'),
3469      help='Automatically send logs from the cluster to the Google Cloud '
3470      'Logging API.')
3471
3472
3473def AddEnableCloudMonitoring(parser):
3474  parser.add_argument(
3475      '--enable-cloud-monitoring',
3476      action=actions.DeprecationAction(
3477          '--enable-cloud-monitoring',
3478          show_message=lambda val: val,
3479          warn='Legacy Logging and Monitoring is deprecated. Thus, '
3480          'flag `--enable-cloud-monitoring` is also deprecated. Please use '
3481          '`--enable-stackdriver-kubernetes` '
3482          '(optionally with `--no-enable-cloud-logging`). '
3483          'For more details, please read: '
3484          'https://cloud.google.com/monitoring/kubernetes-engine/migration.',
3485          action='store_true'),
3486      help='Automatically send metrics from pods in the cluster to the Google '
3487      'Cloud Monitoring API. VM metrics will be collected by Google Compute '
3488      'Engine regardless of this setting.')
3489
3490
3491def AddMaxNodesPerPool(parser):
3492  parser.add_argument(
3493      '--max-nodes-per-pool',
3494      type=arg_parsers.BoundedInt(100, api_adapter.MAX_NODES_PER_POOL),
3495      help='The maximum number of nodes to allocate per default initial node '
3496      'pool. Kubernetes Engine will automatically create enough nodes pools '
3497      'such that each node pool contains less than '
3498      '`--max-nodes-per-pool` nodes. Defaults to {nodes} nodes, but can be set '
3499      'as low as 100 nodes per pool on initial create.'.format(
3500          nodes=api_adapter.MAX_NODES_PER_POOL))
3501
3502
3503def AddNumNodes(parser, default=3):
3504  parser.add_argument(
3505      '--num-nodes',
3506      type=arg_parsers.BoundedInt(1),
3507      help='The number of nodes to be created in each of the cluster\'s zones.',
3508      default=default)
3509
3510
3511def AddEnableGcfsFlag(parser, for_node_pool=False, hidden=True):
3512  """Adds the argument to handle GCFS configurations."""
3513  target = 'node pool' if for_node_pool else 'default initial node pool'
3514  help_text = """\
3515Specifies whether to enable GCFS on {}.""".format(target)
3516  parser.add_argument(
3517      '--enable-gcfs',
3518      help=help_text,
3519      default=None,
3520      hidden=hidden,
3521      action='store_true')
3522
3523
3524def AddDisableAutopilotFlag(parser, hidden=True):
3525  """Adds the argument to convert cluster from autopilot mode to standard mode."""
3526  help_text = """\
3527Convert an cluster from autopilot mode to standard mode."""
3528  parser.add_argument(
3529      '--disable-autopilot',
3530      help=help_text,
3531      default=None,
3532      hidden=hidden,
3533      action='store_true')
3534
3535
3536def AddPrivateEndpointSubnetworkFlag(parser, hidden=True):
3537  """Adds the argument to handle private endpoint subnetwork."""
3538  help_text = ' '
3539  parser.add_argument(
3540      '--private-endpoint-subnetwork',
3541      help=help_text,
3542      hidden=hidden,
3543      metavar='NAME')
3544
3545
3546def AddCrossConnectSubnetworksFlag(parser, hidden=True):
3547  """Adds the cross connect items to the operations."""
3548  help_text = ' '
3549
3550  parser.add_argument(
3551      '--cross-connect-subnetworks',
3552      help=help_text,
3553      hidden=hidden,
3554      type=arg_parsers.ArgList(min_length=1),
3555      metavar='SUBNETS')
3556
3557
3558def AddCrossConnectSubnetworkFlag(parser, hidden=True):
3559  """Adds the argument for identifying the cross connect subnet."""
3560  parser.add_argument(
3561      '--cross-connect-subnetwork',
3562      hidden=hidden,
3563      help='full path of cross connect subnet whose endpoint to persist')
3564
3565
3566def AddGetCredentialsArgs(parser):
3567  """Add common arguments for `get-credentials` command."""
3568  parser.add_argument(
3569      'name',
3570      help='Name of the cluster to get credentials for.',
3571      action=actions.StoreProperty(properties.VALUES.container.cluster))
3572  parser.add_argument(
3573      '--internal-ip',
3574      help='Whether to use the internal IP address of the cluster endpoint.',
3575      action='store_true')
3576
3577
3578def AddCrossConnectSubnetworksMutationFlags(parser, hidden=True):
3579  """Adds flags for mutating cross connect subnetworks in cluster update."""
3580  add_help_text = ' '
3581
3582  remove_help_text = ' '
3583
3584  clear_help_text = ' '
3585
3586  parser.add_argument(
3587      '--add-cross-connect-subnetworks',
3588      help=add_help_text,
3589      hidden=hidden,
3590      type=arg_parsers.ArgList(min_length=1),
3591      metavar='SUBNETS')
3592
3593  parser.add_argument(
3594      '--remove-cross-connect-subnetworks',
3595      help=remove_help_text,
3596      hidden=hidden,
3597      type=arg_parsers.ArgList(min_length=1),
3598      metavar='SUBNETS')
3599
3600  parser.add_argument(
3601      '--clear-cross-connect-subnetworks',
3602      help=clear_help_text,
3603      hidden=hidden,
3604      default=None,
3605      action='store_true')
3606
3607
3608def AddNetworkConfigFlags(parser):
3609  """Adds flags related to the network config for the node pool.
3610
3611  Args:
3612    parser: A given parser.
3613  """
3614  group = parser.add_mutually_exclusive_group()
3615
3616  group.add_argument(
3617      '--pod-ipv4-range',
3618      metavar='NAME',
3619      help="""
3620Set the pod range to be used as the source for pod IPs for the pods in this node
3621pool. NAME must be the name of an existing subnetwork secondary range in the
3622subnetwork for this cluster.
3623
3624Must be used in VPC native clusters. Cannot be used with
3625--create-ipv4-pod-range.
3626
3627Examples:
3628
3629Specify a pod range called ``other-range''
3630
3631      $ {command} --pod-ipv4-range other-range
3632""")
3633  group.add_argument(
3634      '--create-pod-ipv4-range',
3635      metavar='KEY=VALUE',
3636      type=arg_parsers.ArgDict(),
3637      help="""
3638Create a new pod range for the node pool. The name and range of the
3639pod range can be customized via optional ``name'' and ``range'' key-value
3640pairs.
3641
3642``name'' specifies the name of the secondary range to be created.
3643
3644``range'' specifies the IP range for the new secondary range. This can either
3645be a netmask size (e.g. '/20') or a CIDR range (e.g. '10.0.0.0/20').
3646If a netmask size is specified, the IP is automatically taken from the
3647free space in the cluster's network.
3648
3649Examples:
3650
3651Create a new pod range with a default name and size.
3652
3653      $ {command} --create-pod-ipv4-range ""
3654
3655Create a new pod range named ``my-range'' with netmask of size 21.
3656
3657      $ {command} --create-pod-ipv4-range name=my-range,range=/21
3658
3659Create a new pod range with a default name with the primary range of
366010.100.0.0/16.
3661
3662      $ {command} --create-pod-ipv4-range range=10.100.0.0/16
3663
3664Create a new pod range with the name ``my-range'' with a default range.
3665
3666      $ {command} --create-pod-ipv4-range name=my-range
3667
3668Must be used in VPC native clusters. Can not be used in conjunction with the
3669`--pod-ipv4-range` option.
3670""")
3671