def _PromptForProjectId(project_ids, limit_exceeded): """Prompt the user for a project ID, based on the list of available IDs. Also allows an option to create a project. Args: project_ids: list of str or None, the project IDs to prompt for. If this value is None, the listing was unsuccessful and we prompt the user free-form (and do not validate the input). If it's empty, we offer to create a project for the user. limit_exceeded: bool, whether or not the project list limit was reached. If this limit is reached, then user will be prompted with a choice to manually enter a project id, create a new project, or list all projects. Returns: str, the project ID to use, or _CREATE_PROJECT_SENTINEL (if a project should be created), or None """ if project_ids is None: return console_io.PromptResponse( 'Enter project id you would like to use: ') or None elif not project_ids: if not console_io.PromptContinue( 'This account has no projects.', prompt_string='Would you like to create one?'): return None return _CREATE_PROJECT_SENTINEL elif limit_exceeded: idx = console_io.PromptChoice( ['Enter a project ID', 'Create a new project', 'List projects'], message=( 'This account has a lot of projects! Listing them all can ' 'take a while.')) if idx is None: return None elif idx == 0: return console_io.PromptWithValidator( _IsExistingProject, 'Project ID does not exist or is not active. Please enter an ' 'existing and active Project ID.', 'Enter an existing project id you would like to use: ') elif idx == 1: return _CREATE_PROJECT_SENTINEL else: project_ids = _GetProjectIds() idx = console_io.PromptChoice( project_ids + ['Create a new project'], message='Pick cloud project to use: ', allow_freeform=True, freeform_suggester=usage_text.TextChoiceSuggester()) if idx is None: return None elif idx == len(project_ids): return _CREATE_PROJECT_SENTINEL return project_ids[idx]
def testChoiceErrors(self): with self.assertRaisesRegex(ValueError, r'at least one option'): console_io.PromptChoice([]) with self.assertRaisesRegex(ValueError, r'at least one option'): console_io.PromptChoice(None) with self.assertRaisesRegex( ValueError, r'Default option \[-1\] is not a valid index '): console_io.PromptChoice(['a', 'b', 'c'], default=-1) with self.assertRaisesRegex( ValueError, r'Default option \[3\] is not a valid index'): console_io.PromptChoice(['a', 'b', 'c'], default=3)
def _PickRepo(self): """Allows user to clone one of the projects repositories.""" cmd = ['alpha', 'source', 'repos', 'list'] repos = self._RunExperimentalCmd(cmd) if repos: repos = sorted(repo.name or 'default' for repo in repos) log.status.write( 'This project has one or more associated git repositories.\n') idx = console_io.PromptChoice( ['[{0}]'.format(repo) for repo in repos] + ['Do not clone'], message='Pick repository to clone to your local machine:', prompt_string=None) if idx >= 0 and idx < len(repos): repo_name = repos[idx] else: return elif repos is None: log.status.write( 'Could not retrieve list of repos via [gcloud {0}]\n'.format( ' '.join(cmd))) log.status.write('Perhaps alpha commands are not enabled ' 'or the repos list command failed.\n' '\n') answer = console_io.PromptContinue( prompt_string= 'Generally projects have a repository named [default]. ' 'Would you like to try clone it?') if not answer: return repo_name = 'default' else: return self._CloneRepo(repo_name)
def SetProperty(name, default_value, list_command): """Set named compute property to default_value or get via list command.""" if default_value: log.status.write( 'Your project default compute {0} has been set to ' '[{1}].\nYou can change it by running ' '[gcloud config set compute/{0} NAME].\n\n'.format( name, default_value['name'])) else: values = self._RunCmd(list_command) if values is None: return values = list(values) idx = console_io.PromptChoice( ['[{0}]'.format(value['name']) for value in values] + ['Do not set default {0}'.format(name)], message=('Which compute {0} would you like ' 'to use as project default?'.format(name)), prompt_string=None) if idx is None or idx == len(values): return default_value = values[idx] self._RunCmd(['config', 'set'], ['compute/{0}'.format(name), default_value['name']]) return default_value
def GetRegion(args, prompt=False): """Prompt for region if not provided. Region is decided in the following order: - region argument; - run/region gcloud config; - compute/region gcloud config; - prompt user. Args: args: Namespace, The args namespace. prompt: bool, whether to attempt to prompt. Returns: A str representing region. """ if getattr(args, 'region', None): return args.region if properties.VALUES.run.region.IsExplicitlySet(): return properties.VALUES.run.region.Get() if properties.VALUES.compute.region.IsExplicitlySet(): return properties.VALUES.compute.region.Get() if prompt and console_io.CanPrompt(): client = global_methods.GetServerlessClientInstance() all_regions = global_methods.ListRegions(client) idx = console_io.PromptChoice(all_regions, message='Please specify a region:\n', cancel_option=True) region = all_regions[idx] # set the region on args, so we're not embarassed the next time we call # GetRegion args.region = region log.status.Print('To make this the default region, run ' '`gcloud config set run/region {}`.\n'.format(region)) return region
def _PromptForScopeList(self, ambiguous_refs, attributes, resource_type, choice_resources, raise_on_prompt_failure): """Prompt to resolve abiguous resources. Either returns str or throws.""" # targetInstances -> target instances resource_name = utils.CamelCaseToOutputFriendly(resource_type) # Resource names should be surrounded by brackets while choices should not names = ['[{0}]'.format(name) for name, _, _ in ambiguous_refs] # Print deprecation state for choices. choice_names = [] choice_mapping = [] for attribute in attributes: for choice_resource in choice_resources[attribute]: deprecated = choice_resource.deprecated if deprecated: choice_name = '{0} ({1})'.format(choice_resource.name, deprecated.state) else: choice_name = choice_resource.name if len(attributes) > 1: choice_name = '{0}: {1}'.format(attribute, choice_name) choice_mapping.append((attribute, choice_resource.name)) choice_names.append(choice_name) title = utils.ConstructList( 'For the following {0}:'.format(resource_name), names) idx = console_io.PromptChoice(options=choice_names, message='{0}choose a {1}:'.format( title, ' or '.join(attributes))) if idx is None: raise_on_prompt_failure() else: return choice_mapping[idx]
def Run(self, args): project = properties.VALUES.core.project.GetOrFail() memberships = base.ListMemberships(project) if not memberships: raise exceptions.Error('No Memberships available in Hub.') # User should choose an existing membership if not provide one if not args.membership: index = console_io.PromptChoice( options=memberships, message= 'Please specify a membership to delete configmanagement:\n') membership = memberships[index] else: membership = args.membership if membership not in memberships: raise exceptions.Error( 'Membership {} is not in Hub.'.format(membership)) client = core_apis.GetClientInstance('gkehub', 'v1alpha1') msg = client.MESSAGES_MODULE applied_config = msg.ConfigManagementFeatureSpec.MembershipConfigsValue.AdditionalProperty( key=membership, value=msg.MembershipConfig()) m_configs = msg.ConfigManagementFeatureSpec.MembershipConfigsValue( additionalProperties=[applied_config]) self.RunCommand( 'configmanagement_feature_spec.membership_configs', configmanagementFeatureSpec=msg.ConfigManagementFeatureSpec( membershipConfigs=m_configs))
def Run(self, args): if not args.config_membership: memberships = base.ListMemberships() if not memberships: raise exceptions.Error('No Memberships available in the fleet.') index = console_io.PromptChoice( options=memberships, message='Please specify a config membership:\n') config_membership = memberships[index] else: # Strip to the final path component to allow short and long names. # Assumes long names are for the same project and global location. # TODO(b/192580393): Use the resource args instead of this hack. config_membership = os.path.basename(args.config_membership) config_membership = self.MembershipResourceName(config_membership) # MCI requires MCSD. Enablement of the fleet feature for MCSD is taken care # of by CLH but we need to enable the OP API before that happens. If not, # CLH will return an error asking for the API to be enabled. mcsd_api = info.Get('multiclusterservicediscovery').api enable_api.EnableServiceIfDisabled(self.Project(), mcsd_api) f = self.messages.Feature( spec=self.messages.CommonFeatureSpec( multiclusteringress=self.messages.MultiClusterIngressFeatureSpec( configMembership=config_membership))) result = self.Enable(f) # We only want to poll for usability if everything above succeeded. if result is not None: self.PollForUsability()
def _PickAccount(self): """Checks if current credentials are valid, if not runs auth login. Returns: bool, True if valid credentials are setup. """ auth_info = self._RunCmd(['auth', 'list']) if auth_info and auth_info.accounts: idx = console_io.PromptChoice(auth_info.accounts + ['Login with new credentials'], message='Pick credentials to use:', prompt_string=None) if idx is None: return None new_credentials = idx == len(auth_info.accounts) else: answer = console_io.PromptContinue( prompt_string= 'To continue, you must login. Would you like to login') if not answer: return False new_credentials = True if new_credentials: # gcloud auth login may have user interaction, do not suppress it. self._RunCmd(['auth', 'login'], disable_user_output=False) else: account = auth_info.accounts[idx] self._RunCmd(['config', 'set'], ['account', account]) log.status.write('\nYou are now logged in as: [{0}]\n'.format( properties.VALUES.core.account.Get())) return True
def _Prompt(self, parsed_args): """Fallthrough to reading the cluster name from an interactive prompt. Only prompt for cluster name if cluster location is already defined. Args: parsed_args: Namespace, the args namespace. Returns: A cluster name string """ cluster_location = (getattr(parsed_args, 'cluster_location', None) or properties.VALUES.run.cluster_location.Get()) if cluster_location: clusters = global_methods.ListClusters(cluster_location) if not clusters: raise exceptions.ConfigurationError( 'No clusters found for cluster location [{}]. ' 'Ensure your clusters have Cloud Run on GKE enabled.'. format(cluster_location)) cluster_names = [c.name for c in clusters] idx = console_io.PromptChoice(cluster_names, message='GKE cluster name:', cancel_option=True) name = cluster_names[idx] log.status.Print( 'To make this the default cluster, run ' '`gcloud config set run/cluster {}`.\n'.format(name)) return name
def PromptForWhoisPrivacy(choices): index = console_io.PromptChoice( options=choices, default=0, message='Specify WHOIS privacy setting') return ParseWhoisPrivacy( flags.WHOIS_PRIVACY_ENUM_MAPPER.GetChoiceForEnum(choices[index]))
def Run(self, args): # Get fleet memberships (cluster registered with fleet) from GCP Project. memberships = base.ListMemberships() if not memberships: raise exceptions.Error('No Memberships available in the fleet.') # Acquire membership. membership = None # Prompt user for an existing fleet membership if none is provided. if not args.membership: index = 0 if len(memberships) > 1: index = console_io.PromptChoice( options=memberships, message= 'Please specify a membership to delete Identity Service {}:\n' ) membership = memberships[index] sys.stderr.write('Selecting membership [{}].\n'.format(membership)) else: membership = args.membership if membership not in memberships: raise exceptions.Error( 'Membership {} is not in the fleet.'.format(membership)) # Setup a patch to set the MembershipSpec to the empty proto ("delete"). membership_key = self.MembershipResourceName(membership) specs = {membership_key: self.messages.MembershipFeatureSpec()} patch = self.messages.Feature( membershipSpecs=self.hubclient.ToMembershipSpecs(specs)) self.Update(['membership_specs'], patch)
def _PromptForProjectId(project_ids): """Prompt the user for a project ID, based on the list of available IDs. Also allows an option to create a project. Args: project_ids: list of str or None, the project IDs to prompt for. If this value is None, the listing was unsuccessful and we prompt the user free-form (and do not validate the input). If it's empty, we offer to create a project for the user. Returns: str, the project ID to use, or _CREATE_PROJECT_SENTINEL (if a project should be created), or None """ if project_ids is None: return console_io.PromptResponse( 'Enter project id you would like to use: ') or None elif not project_ids: if not console_io.PromptContinue( 'This account has no projects.', prompt_string='Would you like to create one?'): return None return _CREATE_PROJECT_SENTINEL else: idx = console_io.PromptChoice( project_ids + ['Create a new project'], message='Pick cloud project to use: ', allow_freeform=True, freeform_suggester=usage_text.TextChoiceSuggester()) if idx is None: return None elif idx == len(project_ids): return _CREATE_PROJECT_SENTINEL return project_ids[idx]
def PromptForOpRegion(): """Prompt for region from list of online prediction available regions. This method is referenced by the declaritive iam commands as a fallthrough for getting the region. Returns: The region specified by the user, str Raises: RequiredArgumentException: If can not prompt a console for region. """ if console_io.CanPrompt(): all_regions = list(constants.SUPPORTED_OP_REGIONS) idx = console_io.PromptChoice(all_regions, message='Please specify a region:\n', cancel_option=True) region = all_regions[idx] log.status.Print('To make this the default region, run ' '`gcloud config set ai/region {}`.\n'.format(region)) return region raise exceptions.RequiredArgumentException( '--region', ('Cannot prompt a console for region. Region is required. ' 'Please specify `--region` to select a region.'))
def select_memberships(args): """Returns a list of memberships to which to apply the command, given the arguments. Args: args: object containing arguments passed as flags with the command Returns: memberships: A list of membership name strings """ memberships = [] all_memberships = base.ListMemberships() if args.all_memberships: memberships = all_memberships elif args.memberships: memberships = args.memberships.split(',') for membership in memberships: if membership not in all_memberships: raise exceptions.Error('Membership {} not found'.format(membership)) else: index = console_io.PromptChoice( options=all_memberships, message='Please specify a membership:\n') memberships = [all_memberships[index]] if not memberships: raise exceptions.Error('A membership is required for this command.') return memberships
def _get_or_prompt_membership(args, project): """Retrieves the membership name from args or prompts the user. Args: args: command line args project: project id Returns: membership: A membership name Raises: Error, if specified membership could not be found """ memberships = base.ListMemberships(project) if not memberships: raise exceptions.Error('No Memberships available in Hub.') # User should choose an existing membership if this arg wasn't provided if not args.membership: index = console_io.PromptChoice( options=memberships, message='Please specify a membership to upgrade:\n') membership = memberships[index] else: membership = args.membership if membership not in memberships: raise exceptions.Error( 'Membership {} is not in Hub.'.format(membership)) return membership
def CreateAppInteractively(api_client, project): """Interactively choose a region and create an App Engine app. The caller is responsible for calling this method only when the user can be prompted interactively. Example interaction: Which region? [1] us-east1 (supports standard and flexible) [2] europe-west (supports standard) [3] us-central (supports standard and flexible) Please enter your numeric choice: 1 Args: api_client: The App Engine Admin API client project: The GCP project Raises: AppAlreadyExistsError if app already exists """ all_regions = sorted(set(api_client.ListRegions())) idx = console_io.PromptChoice( all_regions, message= ('Please choose a region for your application. After choosing a region, ' 'it cannot be changed. Which region would you like to choose?\n\n')) region = all_regions[idx] CreateApp(api_client, project, region.region)
def CreateAppInteractively(api_client, project): """Interactively choose a region and create an App Engine app. The caller is responsible for calling this method only when the user can be prompted interactively. Example interaction: Which region? [1] us-east1 (supports standard and flexible) [2] europe-west (supports standard) [3] us-central (supports standard and flexible) [4] cancel Please enter your numeric choice: 1 Args: api_client: The App Engine Admin API client project: The GCP project Raises: AppAlreadyExistsError if app already exists """ log.status.Print( 'You are creating an app for project [{}].'.format(project)) log.warn(APP_CREATE_WARNING) all_regions = sorted(set(api_client.ListRegions())) idx = console_io.PromptChoice( all_regions, message=('Please choose the region where you want your App Engine ' 'application located:\n\n'), cancel_option=True) region = all_regions[idx] CreateApp(api_client, project, region.region, suppress_warning=True)
def CreateAppInteractively(api_client, project): """Interactively choose a region and create an App Engine app. The caller is responsible for calling this method only when the user can be prompted interactively. Example interaction: Which region? [1] us-east1 (supports standard and flexible) [2] europe-west (supports standard) [3] us-central (supports standard and flexible) [4] cancel Please enter your numeric choice: 1 Args: api_client: The App Engine Admin API client project: The GCP project Raises: AppAlreadyExistsError if app already exists """ log.warn('You are creating an app for project [{project}]. Creating ' 'an app for a project is irreversible.\n'.format(project=project)) all_regions = sorted(set(api_client.ListRegions())) idx = console_io.PromptChoice(all_regions, message=('Please choose a region for your ' 'application. After choosing a ' 'region, you cannot change it. Which ' 'region would you like to choose?' '\n\n'), cancel_option=True) region = all_regions[idx] CreateApp(api_client, project, region.region, suppress_warning=True)
def _PickConfiguration(self): """Allows user to re-initialize, create or pick new configuration. Returns: Configuration name or None. """ configs = named_configs.ConfigurationStore.AllConfigs() active_config = named_configs.ConfigurationStore.ActiveConfig() if not configs or active_config.name not in configs: # Listing the configs will automatically create the default config. The # only way configs could be empty here is if there are no configurations # and the --configuration flag or env var is set to something that does # not exist. If configs has items, but the active config is not in there, # that similarly means that hey are using the flag or the env var and that # config does not exist. In either case, just create it and go with that # one as the one that as they have already selected it. named_configs.ConfigurationStore.CreateConfig(active_config.name) # Need to active it in the file, not just the environment. active_config.Activate() return active_config.name # If there is a only 1 config, it is the default, and there are no # properties set, assume it was auto created and that it should be # initialized as if it didn't exist. if len(configs) == 1: default_config = configs.get(named_configs.DEFAULT_CONFIG_NAME, None) if default_config and not default_config.GetProperties(): default_config.Activate() return default_config.name choices = [] log.status.write('Settings from your current configuration [{0}] are:\n' .format(active_config.name)) log.status.flush() log.status.write(yaml.dump(properties.VALUES.AllValues(), default_flow_style=False)) log.out.flush() log.status.write('\n') log.status.flush() choices.append( 'Re-initialize this configuration [{0}] with new settings '.format( active_config.name)) choices.append('Create a new configuration') config_choices = [name for name, c in sorted(configs.iteritems()) if not c.is_active] choices.extend('Switch to and re-initialize ' 'existing configuration: [{0}]'.format(name) for name in config_choices) idx = console_io.PromptChoice(choices, message='Pick configuration to use:') if idx is None: return None if idx == 0: # If reinitialize was selected. self._CleanCurrentConfiguration() return active_config.name if idx == 1: # Second option is to create new configuration. return self._CreateConfiguration() config_name = config_choices[idx - 2] named_configs.ConfigurationStore.ActivateConfig(config_name) return config_name
def GetPlatform(): """Returns the platform to run on. If not set by the user, this prompts the user to choose a platform and sets the property so future calls to this method do continue to prompt. Raises: ArgumentError: if not platform is specified and prompting is not allowed. """ platform = properties.VALUES.run.platform.Get() if platform is None: if console_io.CanPrompt(): platform_descs = [_PLATFORM_SHORT_DESCRIPTIONS[k] for k in _PLATFORMS] index = console_io.PromptChoice( platform_descs, message='Please choose a target platform:', cancel_option=True) platform = list(_PLATFORMS.keys())[index] # Set platform so we don't re-prompt on future calls to this method # and so it's available to anyone who wants to know the platform. properties.VALUES.run.platform.Set(platform) log.status.Print( 'To specify the platform yourself, pass `--platform {0}`. ' 'Or, to make this the default target platform, run ' '`gcloud config set run/platform {0}`.\n'.format(platform)) else: raise ArgumentError( 'No platform specified. Pass the `--platform` flag or set ' 'the [run/platform] property to specify a target platform.\n' 'Available platforms:\n{}'.format( '\n'.join( ['- {}: {}'.format(k, v) for k, v in _PLATFORMS.items()]))) return platform
def testEOF(self): result = console_io.PromptContinue() self.assertTrue(result) result = console_io.PromptContinue(default=False) self.assertFalse(result) with self.assertRaisesRegex(console_io.UnattendedPromptError, 'This prompt could not be answered'): result = console_io.PromptContinue(throw_if_unattended=True) result = console_io.PromptResponse(message='') self.assertEqual(result, None) result = console_io.PromptWithDefault(message='') self.assertEqual(result, None) result = console_io.PromptChoice(['a', 'b', 'c']) self.assertEqual(result, None) result = console_io.PromptChoice(['a', 'b', 'c'], default=2) self.assertEqual(result, 2)
def Run(self, args): log.warning( 'Are you sure you want to update your config membership? Any ' 'differences in your MCI and MCS resources between the old and ' 'new config membership can trigger load balancer updates which ' 'could cause traffic interruption.') console_io.PromptContinue(default=False, cancel_on_no=True) project = properties.VALUES.core.project.GetOrFail() if not args.config_membership: memberships = base.ListMemberships(project) if not memberships: raise exceptions.Error('No Memberships available in Hub.') index = console_io.PromptChoice( options=memberships, message='Please specify a config membership:\n') config_membership = memberships[index] else: config_membership = args.config_membership config_membership = ( 'projects/{0}/locations/global/memberships/{1}'.format( project, os.path.basename(config_membership))) self.RunCommand( 'multiclusteringress_feature_spec.config_membership', multiclusteringressFeatureSpec=( base.CreateMultiClusterIngressFeatureSpec(config_membership)))
def _Prompt(self, parsed_args): """Fallthrough to reading the cluster location from an interactive prompt. Only prompt for cluster location if the user-specified platform is GKE and if cluster name is already defined. Args: parsed_args: Namespace, the args namespace. Returns: A cluster location string """ cluster_name = (getattr(parsed_args, 'cluster', None) or properties.VALUES.run.cluster.Get()) if flags.IsGKE(parsed_args) and cluster_name: clusters = [ c for c in global_methods.ListClusters() if c.name == cluster_name ] if not clusters: raise exceptions.ConfigurationError( 'No cluster locations found for cluster [{}]. ' 'Ensure your clusters have Cloud Run on GKE enabled.'. format(cluster_name)) cluster_locations = [c.zone for c in clusters] idx = console_io.PromptChoice( cluster_locations, message='GKE cluster location for [{}]:'.format(cluster_name), cancel_option=True) location = cluster_locations[idx] log.status.Print( 'To make this the default cluster location, run ' '`gcloud config set run/cluster_location {}`.\n'.format( location)) return location
def GetPreferredAuthForCluster(cluster, config_file, force_update=False): """Get preferredAuthentication value for cluster.""" configs = file_parsers.YamlConfigFile(config_file, file_parsers.LoginConfigObject) cluster_config = _GetClusterConfig(configs, cluster) try: auth_method = cluster_config.GetPreferredAuth() except KeyError: auth_method = None except file_parsers.YamlConfigObjectFieldError: # gracefully quit for config versions older than v2alpha1 that # do not support 'preferredAuthentication' field. return None if not auth_method or force_update: prompt_message = ('Please select your preferred authentication option for ' 'cluster [{}]'.format(cluster)) override_warning = ('. Note: This will overwrite current preferred auth ' 'method [{}] in config file.') if auth_method and force_update: prompt_message = prompt_message + override_warning.format(auth_method) # do the prompting providers = cluster_config.GetAuthProviders() index = console_io.PromptChoice(providers, message=prompt_message, cancel_option=True) auth_method = providers[index] log.status.Print( 'Setting Preferred Authentication option to [{}]'.format(auth_method)) cluster_config.SetPreferredAuth(auth_method) configs.WriteToDisk() return auth_method
def Run(self, args): log.warning( 'Are you sure you want to update your config membership? Any ' 'differences in your MCI and MCS resources between the old and ' 'new config membership can trigger load balancer updates which ' 'could cause traffic interruption.') console_io.PromptContinue(default=True, cancel_on_no=True) config_membership = args.config_membership if not config_membership: memberships = base.ListMemberships() if not memberships: raise exceptions.Error( 'No Memberships available in the fleet.') index = console_io.PromptChoice( options=memberships, message='Please specify a config membership:\n') config_membership = memberships[index] else: # Strip to the final path component to allow short and long names. # Assumes long names are for the same project and global location. # TODO(b/192580393): Use the resource args instead of this hack. config_membership = os.path.basename(args.config_membership) config_membership = self.MembershipResourceName(config_membership) f = self.messages.Feature(spec=self.messages.CommonFeatureSpec( multiclusteringress=self.messages.MultiClusterIngressFeatureSpec( configMembership=config_membership))) self.Update(['spec.multiclusteringress.config_membership'], f)
def SetProperty(name, default_value, list_command): """Set named compute property to default_value or get via list command.""" if not default_value: values = self._RunCmd(list_command) if values is None: return values = list(values) message = ( 'Which Google Compute Engine {0} would you like to use as project ' 'default?\n' 'If you do not specify a {0} via a command line flag while working ' 'with Compute Engine resources, the default is assumed.').format( name) idx = console_io.PromptChoice( [value['name'] for value in values] + ['Do not set default {0}'.format(name)], message=message, prompt_string=None, allow_freeform=True, freeform_suggester=usage_text.TextChoiceSuggester()) if idx is None or idx == len(values): return default_value = values[idx] properties.PersistProperty(properties.VALUES.compute.Property(name), default_value['name']) log.status.write('Your project default Compute Engine {0} has been set ' 'to [{1}].\nYou can change it by running ' '[gcloud config set compute/{0} NAME].\n\n' .format(name, default_value['name'])) return default_value
def GetRegion(args, prompt=False): """Prompt for region if not provided. Region is decided in the following order: - region argument; - local config file; - run/region gcloud config; - compute/region gcloud config; - prompt user. Args: args: Namespace, The args namespace. prompt: bool, whether to attempt to prompt. Returns: A str representing region. """ if getattr(args, 'region', None): return args.region conf = GetLocalConfig(args) if conf and conf.region: return conf.region if properties.VALUES.run.region.IsExplicitlySet(): return properties.VALUES.run.region.Get() if properties.VALUES.compute.region.IsExplicitlySet(): return properties.VALUES.compute.region.Get() if prompt and console_io.CanPrompt(): all_regions = global_methods.ListRegions() idx = console_io.PromptChoice(all_regions, message='Please specify a region:\n', cancel_option=True) region = all_regions[idx] log.status.Print('To make this the default region, run ' '`gcloud config set run/region {}`.\n'.format(region)) return region
def _Prompt(self, parsed_args): """Fallthrough to reading the cluster name from an interactive prompt. Only prompt for cluster name if the user-specified platform is GKE. Args: parsed_args: Namespace, the args namespace. Returns: A cluster name string """ if platforms.GetPlatform() != platforms.PLATFORM_GKE: return project = properties.VALUES.core.project.Get(required=True) cluster_location = ( getattr(parsed_args, 'cluster_location', None) or properties.VALUES.run.cluster_location.Get()) cluster_location_msg = ' in [{}]'.format( cluster_location) if cluster_location else '' cluster_refs = global_methods.MultiTenantClustersForProject( project, cluster_location) if not cluster_refs: raise exceptions.ConfigurationError( 'No compatible clusters found{}. ' 'Ensure your cluster has Cloud Run enabled.'.format( cluster_location_msg)) cluster_refs_descs = [ self._GetClusterDescription(c, cluster_location, project) for c in cluster_refs ] idx = console_io.PromptChoice( cluster_refs_descs, message='GKE cluster{}:'.format(cluster_location_msg), cancel_option=True) cluster_ref = cluster_refs[idx] if cluster_location: location_help_text = '' else: location_help_text = ( ' && gcloud config set run/cluster_location {}'.format( cluster_ref.zone)) cluster_name = cluster_ref.Name() if cluster_ref.projectId != project: cluster_name = cluster_ref.RelativeName() location_help_text = '' log.status.Print('To make this the default cluster, run ' '`gcloud config set run/cluster {cluster}' '{location}`.\n'.format( cluster=cluster_name, location=location_help_text)) return cluster_ref.SelfLink()
def testLongPrompt(self): self.SetAnswers('list', '1', 'value10', '1', '2', '3', '1', '101') indices = list(range(1, 101)) values = ['value{x}'.format(x=x) for x in indices] options_lines = [ ' [{index}] {value}'.format(index=index, value=value) for (index, value) in zip(indices, values) ] result = console_io.PromptChoice(values, allow_freeform=True) expected = '\n'.join( options_lines[:console_io.PROMPT_OPTIONS_OVERFLOW]) remaining = len(options_lines) - console_io.PROMPT_OPTIONS_OVERFLOW self.assertIn(expected, self.GetErr()) self.assertIn(('Did not print [{remaining}] options.\n' 'Too many options [{total}]. Enter "list" at prompt to ' 'print choices fully.\nPlease enter numeric choice or ' 'text value (must exactly match list \nitem):').format( remaining=remaining, total=len(options_lines)), self.GetErr()) options_lines = [ ' [{index}] {value}'.format(index=index, value=value) for (index, value) in zip(indices, values) ] expected = '\n'.join(options_lines) self.assertIn(expected, self.GetErr()) self.assertEqual(result, 0) result = console_io.PromptChoice(values, allow_freeform=True) self.assertEqual(result, 9) result = console_io.PromptChoice(values, allow_freeform=True) self.assertEqual(result, 0) result = console_io.PromptChoice(values, allow_freeform=True) self.assertEqual(result, 1) result = console_io.PromptChoice(values, allow_freeform=True) self.assertEqual(result, 2) result = console_io.PromptChoice(values, allow_freeform=True, cancel_option=True) self.assertEqual(result, 0) with self.assertRaises(console_io.OperationCancelledError): result = console_io.PromptChoice(values, allow_freeform=True, cancel_option=True)