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) cluster_ref = adapter.ParseCluster(args.name, location) cluster_name = args.name cluster_node_count = None cluster_zone = cluster_ref.zone cluster_is_required = self.IsClusterRequired(args) try: # Attempt to get cluster for better prompts and to validate args. # Error is a warning but not fatal. Should only exit with a failure on # the actual update API calls below. cluster = adapter.GetCluster(cluster_ref) cluster_name = cluster.name cluster_node_count = cluster.currentNodeCount cluster_zone = cluster.zone except (exceptions.HttpException, apitools_exceptions.HttpForbiddenError, util.Error) as error: if cluster_is_required: raise log.warning( ('Problem loading details of cluster to update:\n\n{}\n\n' 'You can still attempt updates to the cluster.\n').format( console_attr.SafeText(error))) # 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.IsSpecified('username') or args.IsSpecified( 'enable_basic_auth'): flags.MungeBasicAuthFlags(args) options = api_adapter.SetMasterAuthOptions( action=api_adapter.SetMasterAuthOptions.SET_USERNAME, username=args.username, password=args.password) try: op_ref = adapter.SetMasterAuth(cluster_ref, options) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif (args.generate_password or args.set_password or args.IsSpecified('password')): if args.generate_password: password = '' options = api_adapter.SetMasterAuthOptions( action=api_adapter.SetMasterAuthOptions.GENERATE_PASSWORD, password=password) else: password = args.password if not args.IsSpecified('password'): password = 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 or args.start_credential_rotation: if args.start_ip_rotation: msg_tmpl = """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. Kubernetes 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.""" rotate_credentials = False elif args.start_credential_rotation: msg_tmpl = """This will start an IP and Credentials Rotation on cluster\ [{name}]. The master will be updated to serve on a new IP address in addition \ to the current IP address, and cluster credentials will be rotated. Kubernetes \ 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.""" rotate_credentials = True console_io.PromptContinue(message=msg_tmpl.format( name=cluster_name, num_nodes=cluster_node_count if cluster_node_count else '?'), cancel_on_no=True) try: op_ref = adapter.StartIpRotation( cluster_ref, rotate_credentials=rotate_credentials) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif args.complete_ip_rotation or args.complete_credential_rotation: if args.complete_ip_rotation: msg_tmpl = """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.""" elif args.complete_credential_rotation: msg_tmpl = """This will complete the in-progress Credential 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. Old cluster credentials will be \ invalidated. 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.""" console_io.PromptContinue(message=msg_tmpl.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 and args.monitoring_service is 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.SetDailyMaintenanceWindow( cluster_ref, cluster.maintenancePolicy, args.maintenance_window) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif getattr(args, 'maintenance_window_start', None) is not None: try: op_ref = adapter.SetRecurringMaintenanceWindow( cluster_ref, cluster.maintenancePolicy, args.maintenance_window_start, args.maintenance_window_end, args.maintenance_window_recurrence) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif getattr(args, 'clear_maintenance_window', None): try: op_ref = adapter.RemoveMaintenanceWindow( cluster_ref, cluster.maintenancePolicy) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif getattr(args, 'add_maintenance_exclusion_end', None) is not None: try: op_ref = adapter.AddMaintenanceExclusion( cluster_ref, cluster.maintenancePolicy, args.add_maintenance_exclusion_name, args.add_maintenance_exclusion_start, args.add_maintenance_exclusion_end) except apitools_exceptions.HttpError as error: raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT) elif getattr(args, 'remove_maintenance_exclusion', None) is not None: try: op_ref = adapter.RemoveMaintenanceExclusion( cluster_ref, cluster.maintenancePolicy, args.remove_maintenance_exclusion) 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), timeout_s=1800) log.UpdatedResource(cluster_ref) cluster_url = util.GenerateClusterUrl(cluster_ref) log.status.Print( 'To inspect the contents of your cluster, go to: ' + cluster_url) if (args.start_ip_rotation or args.complete_ip_rotation or args.start_credential_rotation or args.complete_credential_rotation): cluster = adapter.GetCluster(cluster_ref) try: util.ClusterConfig.Persist(cluster, cluster_ref.projectId) except kconfig.MissingEnvVarError as error: log.warning(error)
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'] cluster_ref = adapter.ParseCluster(args.name) # Make sure it exists (will raise appropriate error if not) 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 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:'******'Updating {0}'.format(cluster_ref.clusterId)) log.UpdatedResource(cluster_ref)