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 testPromptWithValidator(self): def simple_validator(s): return len(s) > 3 self.SetAnswers('1', '1234') result = console_io.PromptWithValidator(simple_validator, 'error', 'prompt', 'message') self.assertIn('message', self.GetErr()) self.assertIn('prompt', self.GetErr()) self.assertIn('error', self.GetErr()) self.assertEqual(result, '1234')
def PromptForWhoisContact(): """Interactively prompts for Whois Contact information.""" if not console_io.PromptContinue( 'Registrant contact information not provided', prompt_string='Do you want to enter it interactively', default=False): return None messages = registrations.GetMessagesModule() whois_contact = messages.WhoisContact() whois_contact.postalAddress = messages.PostalAddress() # TODO(b/110077203): Improve interactive address info. whois_contact.postalAddress.recipients.append( console_io.PromptWithValidator(validator=_ValidateNonEmpty, error_message='Name must not be empty.', prompt_string=' full name: ')) whois_contact.postalAddress.organization = console_io.PromptResponse( ' organization (if applicable): ') whois_contact.email = console_io.PromptWithDefault( message=' email', default=properties.VALUES.core.account.Get()) whois_contact.phoneNumber = console_io.PromptWithValidator( validator=_ValidateNonEmpty, error_message='Phone number must not be empty.', prompt_string=' phone number: ', message='Enter phone number with country code, e.g. "+1.1234567890".') whois_contact.postalAddress.regionCode = console_io.PromptWithValidator( validator=_ValidateRegionCode, error_message=( 'Country code must be in ISO 3166-1 format, e.g. "US" or "PL".\n' 'See https://support.google.com/business/answer/6270107 for a list ' 'of valid choices.'), prompt_string=' country code: ', message='Enter two-letter country code, e.g. "US" or "PL".') whois_contact.postalAddress.postalCode = console_io.PromptResponse( ' postal code/zipcode: ') whois_contact.postalAddress.administrativeArea = console_io.PromptResponse( ' state (if applicable): ') whois_contact.postalAddress.locality = console_io.PromptResponse( ' city: ') whois_contact.postalAddress.addressLines.append( console_io.PromptResponse(' street address (incl. building, apt): ')) return whois_contact
def _GetLdapUserAndPass(cluster_config, auth_name, cluster): """Prompt User for Ldap Username and Password.""" ldap_user = None ldap_pass = None if not cluster_config.IsLdap(): return None, None # do the prompting user_message = ('Please enter the ldap user for ' '[{}] on cluster [{}]: '.format(auth_name, cluster)) pass_message = ('Please enter the ldap password for ' '[{}] on cluster [{}]: '.format(auth_name, cluster)) ldap_user = console_io.PromptWithValidator( validator=lambda x: len(x) > 1, error_message='Error: Invalid username, please try again.', prompt_string=user_message) ldap_pass = console_io.PromptPassword( pass_message, validation_callable=lambda x: len(x) > 1) return _Base64EncodeLdap(ldap_user, ldap_pass)
def ResourceFromFreeformPrompt(name, long_name, list_func): """Prompts the user to select a resource. Args: name: the name of the resource. For example, "environment" or "developer". long_name: a longer form of `name` which the user will see in prompts. Should explain the context in which the resource will be used. For example, "the environment to be updated". list_func: a function that returns the names of existing resources. Returns: The resource's identifier if successful, or None if not. """ resource_list = [] try: resource_list = list_func() except errors.RequestError: # Organization list flakiness, no matches, etc. pass entity_names = resource_args.ENTITIES[name] if resource_list: enter_manually = "(some other %s)" % entity_names.docs_name choice = console_io.PromptChoice( resource_list + [enter_manually], prompt_string="Select %s:" % long_name) # If the user selected an option from resource_list, not the "enter # manually" option at the bottom... if choice < len(resource_list): return resource_list[choice] valid_pattern = resource_args.ValidPatternForEntity(name) validator = lambda response: valid_pattern.search(response) is not None error_str = "Doesn't match the expected format of a " + entity_names.docs_name prompt_message = "Enter %s: " % long_name return console_io.PromptWithValidator(validator, error_str, prompt_message)
def Run(self, args): """Run the deploy command.""" if args.organization is None: args.organization = defaults.OrganizationFromGCPProduct() if console_io.CanPrompt(): if args.organization is None: def _ListOrgs(): response = apigee.OrganizationsClient.List() if "organizations" in response: return [item["organization"] for item in response["organizations"]] else: return [] args.organization = prompts.ResourceFromFreeformPrompt( "organization", "the organization in which to create the API product", _ListOrgs) if args.INTERNAL_NAME is None: product_matcher = resource_args.ValidPatternForEntity("product") valid_product = lambda name: product_matcher.search(name) is not None args.INTERNAL_NAME = console_io.PromptWithValidator( valid_product, "Empty or invalid API product name.", "Enter an internal name for the new API product: ") org_identifier = {"organizationsId": args.organization} if args.environments is None: list_envs = lambda: apigee.EnvironmentsClient.List(org_identifier) choice = console_io.PromptChoice( ["Include all environments", "Choose environments to include"], prompt_string=("What environments should be accessible in the API " "product?")) if choice == 0: args.environments = [] else: args.environments = prompts.ResourceListFromPrompt( "environment", list_envs) if not args.apis and not args.resources and not args.all_proxies: choice = console_io.PromptChoice( [ "Include all API proxies", "Choose API proxies and/or basepaths to include" ], prompt_string=("What API proxies should be accessible in the API " "product?")) if choice == 0: args.all_proxies = True else: def _ListDeployedProxies(): response = apigee.DeploymentsClient.List(org_identifier) return sorted(list(set(item["apiProxy"] for item in response))) args.apis = prompts.ResourceListFromPrompt( "api", _ListDeployedProxies, "Include all deployed API proxies") resource_options = [ "Restrict proxy access by resource path", "Include all resource paths of the product's API proxies" ] if console_io.PromptChoice(resource_options) == 0: args.resources = prompts.ListFromFreeformPrompt( "Enter a resource path that should be included: ", "Include another resource path", "Include all resource paths of the product's API proxies") else: args.resources = [] if not args.resources and not args.apis: # User explicitly chose to include all proxies and resources. args.all_proxies = True if args.access is None: option = console_io.PromptChoice([ "Public - visible in the Apigee developer portal", ("Private - callable by external developers but not visible in the " "Apigee developer portal"), "Internal - not callable by external developers" ], message="Choose an access policy.") args.access = ["public", "private", "internal"][option] if args.environments is None: raise exceptions.OneOfArgumentsRequiredException( ["--environments", "--all-environments"], "All API products must include at least one environment.") if args.access is None: raise exceptions.OneOfArgumentsRequiredException([ "--public-access", "--private-access", "--internal-access" ], "All API products must specify whether they can be publicly accessed.") if not args.apis and not args.resources and not args.all_proxies: raise exceptions.OneOfArgumentsRequiredException( ["--apis", "--resources", "--all-proxies"], "All API products must include at least one API proxy or resource.") quota_args_missing = [ arg for arg in vars(args) if "quota" in arg and vars(args)[arg] is None ] if quota_args_missing: if len(quota_args_missing) < 3: raise exceptions.RequiredArgumentException( "--" + quota_args_missing[0].replace("_", "-"), "Must specify all quota arguments to use quotas.") else: args.quota = "%d" % args.quota args.quota_interval = "%d" % args.quota_interval attributes = [{"name": "access", "value": args.access}] if args.attributes: for key in args.attributes: attributes.append({"name": key, "value": args.attributes[key]}) identifiers = args.CONCEPTS.internal_name.Parse().AsDict() if args.display_name is None: args.display_name = identifiers["apiproductsId"] product = apigee.ProductsInfo( name=identifiers["apiproductsId"], displayName=args.display_name, approvalType="manual" if args.manual_approval else "auto", attributes=attributes, description=args.description, apiResources=args.resources if args.resources else None, environments=args.environments if args.environments else None, proxies=args.apis if args.apis else None, quota=args.quota, quotaInterval=args.quota_interval, quotaTimeUnit=args.quota_unit, scopes=args.oauth_scopes) return apigee.ProductsClient.Create(identifiers, product)