def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Raises: util.Error: if the cluster is unreachable or not running. """ util.CheckKubectlInstalled() adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args) cluster_ref = adapter.ParseCluster(args.name, location) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning( self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) log.status.Print('Fetching cluster endpoint and auth data.') # Call DescribeCluster to get auth info and cache for next time cluster = adapter.GetCluster(cluster_ref) auth = cluster.masterAuth has_creds = (auth and ((auth.clientCertificate and auth.clientKey) or (auth.username and auth.password))) if not has_creds and not util.ClusterConfig.UseGCPAuthProvider( cluster): raise util.Error( 'get-credentials requires edit permission on {0}'.format( cluster_ref.projectId)) if not adapter.IsRunning(cluster): log.warn(NOT_RUNNING_MSG.format(cluster_ref.clusterId)) util.ClusterConfig.Persist(cluster, cluster_ref.projectId)
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. """ adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning( self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) cluster_ref = adapter.ParseCluster(args.name, location) cluster = adapter.GetCluster(cluster_ref) pool = adapter.FindNodePool(cluster, args.node_pool) console_io.PromptContinue( message=('Pool [{pool}] for [{cluster_name}] will be resized to ' '{new_size}.').format(pool=pool.name, cluster_name=cluster.name, new_size=args.size), throw_if_unattended=True, cancel_on_no=True) op_ref = adapter.ResizeNodePool(cluster_ref, pool.name, args.size) if not args. async: adapter.WaitForOperation( op_ref, 'Resizing {0}'.format(cluster_ref.clusterId)) log.UpdatedResource(cluster_ref)
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Some value that we want to have printed later. """ adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning(self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) cluster_ref = adapter.ParseCluster(args.name, location) # Make sure it exists (will raise appropriate error if not) cluster = adapter.GetCluster(cluster_ref) options = api_adapter.UpdateClusterOptions( version=args.cluster_version, update_master=args.master, update_nodes=(not args.master), node_pool=args.node_pool, image_type=args.image_type) upgrade_message = container_command_util.ClusterUpgradeMessage( cluster, master=args.master, node_pool=args.node_pool, new_version=options.version) console_io.PromptContinue( message=upgrade_message, throw_if_unattended=True, cancel_on_no=True) try: op_ref = adapter.UpdateCluster(cluster_ref, options) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) if not args.async: adapter.WaitForOperation( op_ref, 'Upgrading {0}'.format(cluster_ref.clusterId)) log.UpdatedResource(cluster_ref)
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Some value that we want to have printed later. """ adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning( self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) self._upgrade_hint = None vv = VersionVerifier() c = adapter.GetCluster(adapter.ParseCluster(args.name, location)) ver_status = vv.Compare(c.currentMasterVersion, c.currentNodeVersion) if ver_status == VersionVerifier.UPGRADE_AVAILABLE: self._upgrade_hint = UpgradeHelpText.UPGRADE_AVAILABLE elif ver_status == VersionVerifier.SUPPORT_ENDING: self._upgrade_hint = UpgradeHelpText.SUPPORT_ENDING elif ver_status == VersionVerifier.UNSUPPORTED: self._upgrade_hint = UpgradeHelpText.UNSUPPORTED if ver_status != VersionVerifier.UP_TO_DATE: self._upgrade_hint += UpgradeHelpText.UPGRADE_COMMAND.format( name=c.name) return c
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Some value that we want to have printed later. """ adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning( self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) cluster_refs = [] for name in args.names: cluster_refs.append(adapter.ParseCluster(name, location)) console_io.PromptContinue(message=util.ConstructList( 'The following clusters will be deleted.', [ '[{name}] in [{zone}]'.format(name=ref.clusterId, zone=adapter.Zone(ref)) for ref in cluster_refs ]), throw_if_unattended=True, cancel_on_no=True) operations = [] errors = [] # Issue all deletes first for cluster_ref in cluster_refs: try: # Make sure it exists (will raise appropriate error if not) adapter.GetCluster(cluster_ref) op_ref = adapter.DeleteCluster(cluster_ref) operations.append((op_ref, cluster_ref)) except apitools_exceptions.HttpError as error: errors.append( str(exceptions.HttpException(error, util.HTTP_ERROR_FORMAT))) except util.Error as error: errors.append(error) if not args. async: # Poll each operation for completion for operation_ref, cluster_ref in operations: try: adapter.WaitForOperation(operation_ref, 'Deleting cluster {0}'.format( cluster_ref.clusterId), timeout_s=args.timeout) # Purge cached config files util.ClusterConfig.Purge(cluster_ref.clusterId, adapter.Zone(cluster_ref), cluster_ref.projectId) if properties.VALUES.container.cluster.Get( ) == cluster_ref.clusterId: properties.PersistProperty( properties.VALUES.container.cluster, None) log.DeletedResource(cluster_ref) except apitools_exceptions.HttpError as error: errors.append( exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)) except util.Error as error: errors.append(error) if errors: raise util.Error( util.ConstructList('Some requests did not succeed:', errors))
class Create(base.CreateCommand): """Create a cluster for running containers.""" @staticmethod def Args(parser): _Args(parser) _AddAdditionalZonesFlag(parser) flags.AddAddonsFlags(parser, hide_addons_flag=True, deprecate_disable_addons_flag=False) flags.AddClusterAutoscalingFlags(parser) flags.AddEnableAutoRepairFlag(parser, suppressed=True) flags.AddEnableKubernetesAlphaFlag(parser, suppressed=True) flags.AddEnableLegacyAuthorizationFlag(parser, hidden=True) flags.AddIPAliasFlags(parser, hidden=True) flags.AddLabelsFlag(parser, suppressed=True) flags.AddLocalSSDFlag(parser, suppressed=True) flags.AddMaintenanceWindowFlag(parser, hidden=True) flags.AddMasterAuthorizedNetworksFlags(parser, hidden=True) flags.AddNetworkPolicyFlags(parser, hidden=True) flags.AddNodeTaintsFlag(parser, hidden=True) flags.AddOldClusterNodeIdentityFlags(parser) flags.AddPreemptibleFlag(parser, suppressed=True) flags.AddNodeVersionFlag(parser, hidden=True) def ParseCreateOptions(self, args): return ParseCreateOptionsBase(args) def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Cluster message for the successfully created cluster. Raises: util.Error, if creation failed. """ if args. async and not args.IsSpecified('format'): args.format = util.OPERATIONS_FORMAT util.CheckKubectlInstalled() adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args) if not args.scopes: args.scopes = [] cluster_ref = adapter.ParseCluster(args.name, location) options = self.ParseCreateOptions(args) if options.enable_kubernetes_alpha: console_io.PromptContinue( message=constants.KUBERNETES_ALPHA_PROMPT, throw_if_unattended=True, cancel_on_no=True) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning( self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) # TODO(b/68496825): Remove this completely after regional clusters beta # launch. if self._release_track == base.ReleaseTrack.ALPHA: console_io.PromptContinue( message=constants.KUBERNETES_REGIONAL_CHARGES_PROMPT, throw_if_unattended=True, cancel_on_no=True) if options.enable_autorepair is not None: log.status.Print( messages.AutoUpdateUpgradeRepairMessage( options.enable_autorepair, 'autorepair')) if options.enable_autoupgrade is not None: log.status.Print( messages.AutoUpdateUpgradeRepairMessage( options.enable_autoupgrade, 'autoupgrade')) operation = None try: operation_ref = adapter.CreateCluster(cluster_ref, options) if args. async: return adapter.GetCluster(cluster_ref) operation = adapter.WaitForOperation(operation_ref, 'Creating cluster {0}'.format( cluster_ref.clusterId), timeout_s=args.timeout) cluster = adapter.GetCluster(cluster_ref) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) log.CreatedResource(cluster_ref) if operation.detail: # Non-empty detail on a DONE create operation should be surfaced as # a warning to end user. log.warning(operation.detail) try: util.ClusterConfig.Persist(cluster, cluster_ref.projectId) except kconfig.MissingEnvVarError as error: log.warning(error.message) return [cluster]
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Some value that we want to have printed later. """ adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning( self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) cluster_ref = adapter.ParseCluster(args.name, location) # Make sure it exists (will raise appropriate error if not) cluster = adapter.GetCluster(cluster_ref) # locations will be None if additional-zones was specified, an empty list # if it was specified with no argument, or a populated list if zones were # provided. We want to distinguish between the case where it isn't # specified (and thus shouldn't be passed on to the API) and the case where # it's specified as wanting no additional zones, in which case we must pass # the cluster's primary zone to the API. # TODO(b/29578401): Remove the hasattr once the flag is GA. locations = None if hasattr(args, 'additional_zones') and args.additional_zones is not None: locations = sorted([cluster_ref.zone] + args.additional_zones) if hasattr(args, 'node_locations') and args.node_locations is not None: locations = sorted(args.node_locations) if args.generate_password or args.set_password: if args.generate_password: password = '' options = api_adapter.SetMasterAuthOptions( action=api_adapter.SetMasterAuthOptions.GENERATE_PASSWORD, password=password) else: password = raw_input('Please enter the new password:'******'Enabling/Disabling Network Policy causes a rolling ' 'update of all cluster nodes, similar to performing a cluster ' 'upgrade. This operation is long-running and will block other ' 'operations on the cluster (including delete) until it has run ' 'to completion.', cancel_on_no=True) options = api_adapter.SetNetworkPolicyOptions( enabled=args.enable_network_policy) try: op_ref = adapter.SetNetworkPolicy(cluster_ref, options) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif args.start_ip_rotation: console_io.PromptContinue( message= 'This will start an IP Rotation on cluster [{name}]. The ' 'master will be updated to serve on a new IP address in addition to ' 'the current IP address. Container Engine will then recreate all ' 'nodes ({num_nodes} nodes) to point to the new IP address. This ' 'operation is long-running and will block other operations on the ' 'cluster (including delete) until it has run to completion.'. format(name=cluster.name, num_nodes=cluster.currentNodeCount), cancel_on_no=True) try: op_ref = adapter.StartIpRotation(cluster_ref) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif args.complete_ip_rotation: console_io.PromptContinue( message= 'This will complete the in-progress IP Rotation on cluster ' '[{name}]. The master will be updated to stop serving on the old IP ' 'address and only serve on the new IP address. Make sure all API ' 'clients have been updated to communicate with the new IP address ' '(e.g. by running `gcloud container clusters get-credentials ' '--project {project} --zone {zone} {name}`). This operation is long-' 'running and will block other operations on the cluster (including ' 'delete) until it has run to completion.'.format( name=cluster.name, project=cluster_ref.projectId, zone=cluster.zone), cancel_on_no=True) try: op_ref = adapter.CompleteIpRotation(cluster_ref) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif args.update_labels is not None: try: op_ref = adapter.UpdateLabels(cluster_ref, args.update_labels) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif args.remove_labels is not None: try: op_ref = adapter.RemoveLabels(cluster_ref, args.remove_labels) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif args.logging_service is not None: try: op_ref = adapter.SetLoggingService(cluster_ref, args.logging_service) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif args.maintenance_window is not None: try: op_ref = adapter.SetMaintenanceWindow(cluster_ref, args.maintenance_window) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) else: if args.enable_legacy_authorization is not None: op_ref = adapter.SetLegacyAuthorization( cluster_ref, args.enable_legacy_authorization) else: options = self.ParseUpdateOptions(args, locations) op_ref = adapter.UpdateCluster(cluster_ref, options) if not args. async: adapter.WaitForOperation( op_ref, 'Updating {0}'.format(cluster_ref.clusterId)) log.UpdatedResource(cluster_ref) if args.start_ip_rotation or args.complete_ip_rotation: cluster = adapter.GetCluster(cluster_ref) try: util.ClusterConfig.Persist(cluster, cluster_ref.projectId) except kconfig.MissingEnvVarError as error: log.warning(error.message)
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Returns: Some value that we want to have printed later. """ adapter = self.context['api_adapter'] location_get = self.context['location_get'] location = location_get(args, ignore_property=True, required=False) if getattr(args, 'region', None): message = messages.NonGAFeatureUsingV1APIWarning( self._release_track) if message: console_io.PromptContinue(message=message, cancel_on_no=True) project = properties.VALUES.core.project.Get(required=True) def sort_key(cluster): return (cluster.zone, cluster.name) try: clusters = adapter.ListClusters(project, location) clusters.clusters = sorted(clusters.clusters, key=sort_key) if clusters.missingZones: log.warning( 'The following zones did not respond: {0}. List results may be ' 'incomplete.'.format(', '.join(clusters.missingZones))) upgrade_available = False support_ending = False unsupported = False expiring = False self._upgrade_hint = '' self._expire_warning = '' vv = VersionVerifier() for c in clusters.clusters: time_left = transforms.ParseExpireTime(c.expireTime) if time_left and time_left.days < constants.EXPIRE_WARNING_DAYS: expiring = True if c.enableKubernetesAlpha: # Don't print upgrade hints for alpha clusters, they aren't # upgradeable. continue ver_status = vv.Compare(c.currentMasterVersion, c.currentNodeVersion) if ver_status == VersionVerifier.UPGRADE_AVAILABLE: c.currentNodeVersion += ' *' upgrade_available = True elif ver_status == VersionVerifier.SUPPORT_ENDING: c.currentNodeVersion += ' **' support_ending = True elif ver_status == VersionVerifier.UNSUPPORTED: c.currentNodeVersion += ' ***' unsupported = True if upgrade_available: self._upgrade_hint += UpgradeHelpText.UPGRADE_AVAILABLE if support_ending: self._upgrade_hint += UpgradeHelpText.SUPPORT_ENDING if unsupported: self._upgrade_hint += UpgradeHelpText.UNSUPPORTED if self._upgrade_hint: self._upgrade_hint += UpgradeHelpText.UPGRADE_COMMAND.format( name='NAME') if expiring: self._expire_warning = constants.EXPIRE_WARNING return clusters.clusters except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)