def CreateReusableConfigResourceSpec(associated_resource): """Create a resource spec for a ReusableConfig. Defaults to the predefined project for reusable configs. Args: associated_resource: The name of the resource that this reusable config is associated with. This will be used in the helptext. Returns: A concepts.ResourceSpec for a reusable config. """ # For now, reusable configs exist in a single project. location_fallthrough = deps.Fallthrough( function=lambda: '', hint='location will default to the same location as the {}'.format( associated_resource), active=False, plural=False) project_fallthrough = deps.Fallthrough( function=lambda: api_constants.PREDEFINED_REUSABLE_CONFIG_PROJECT, hint='project will default to {}'.format( api_constants.PREDEFINED_REUSABLE_CONFIG_PROJECT), active=False, plural=False) return concepts.ResourceSpec( 'privateca.projects.locations.reusableConfigs', resource_name='reusable config', reusableConfigsId=ReusableConfigAttributeConfig(), locationsId=LocationAttributeConfig(fallthroughs=[location_fallthrough]), projectsId=ProjectAttributeConfig(fallthroughs=[project_fallthrough]))
def testInitializeWithAnchor(self, proj_value, case_value, shelf_value, book_value, expected): book_fallthrough = deps.Fallthrough(lambda: book_value, 'h', active=True) fallthroughs_map = { 'project': [ deps.FullySpecifiedAnchorFallthrough(book_fallthrough, self.book_collection, 'projectsId'), deps.Fallthrough(lambda: proj_value, 'h', active=True) ], 'case': [ deps.FullySpecifiedAnchorFallthrough(book_fallthrough, self.book_collection, 'casesId'), deps.Fallthrough(lambda: case_value, 'h', active=True) ], 'shelf': [ deps.FullySpecifiedAnchorFallthrough(book_fallthrough, self.book_collection, 'shelvesId'), deps.Fallthrough(lambda: shelf_value, 'h') ], 'book': [book_fallthrough] } self.assertEqual( expected, self.resource.Initialize(fallthroughs_map).result.RelativeName())
def testParsePluralAnchorFallthroughMultiple( self, is_multitype, fallthrough_value, args, expected): """Tests plural resource args parse when there's an anchor fallthrough.""" spec = copy.deepcopy( self.SetUpFallthroughSpec( deps.Fallthrough(lambda: ['xyz'], hint='h'), is_multitype=is_multitype)) fallthrough = deps.Fallthrough(lambda: fallthrough_value, hint='h', active=True) for attribute in spec.attributes: if attribute.name == 'book': attribute.fallthroughs = [fallthrough] + attribute.fallthroughs resource = self.PresentationSpecType(is_multitype=is_multitype)( '--books', spec, 'Group Help', prefixes=False, plural=True, flag_name_overrides={'project': '--book-project'} ) concept_parser = concept_parsers.ConceptParser([resource]) concept_parser.AddToParser(self.parser) namespace = self.parser.parser.parse_args(args) self.AssertParsedListEquals( expected, namespace.CONCEPTS.books.Parse(), is_multitype=is_multitype)
def CreateReusableConfigResourceSpec(): """Create a resource spec for a ReusableConfig. Defaults to the predefined location + project for reusable configs. Returns: A concepts.ResourceSpec for a reusable config. """ # For now, reusable configs exist in a single location and project. location_fallthrough = deps.Fallthrough( function=lambda: PREDEFINED_REUSABLE_CONFIG_LOCATION, hint='location must be specified', active=False, plural=False) project_fallthrough = deps.Fallthrough( function=lambda: PREDEFINED_REUSABLE_CONFIG_PROJECT, hint='project must be specified', active=False, plural=False) return concepts.ResourceSpec( 'privateca.projects.locations.reusableConfigs', resource_name='reusable config', reusableConfigsId=ReusableConfigAttributeConfig(), locationsId=LocationAttributeConfig( fallthroughs=[location_fallthrough]), projectsId=ProjectAttributeConfig(fallthroughs=[project_fallthrough]))
def testParseFullySpecifiedAnchorFallthrough(self, book_arg, plural, expected_value): """Only get values from a parsed anchor if that anchor is being used.""" fallthroughs = [ deps.Fallthrough( lambda: 'projects/junk/shelves/junk/books/junk', hint='h')] spec = copy.deepcopy(self.resource_spec) spec.attributes[-1].fallthroughs = fallthroughs # These should be used as fallthroughs unless the anchor fallthrough comes # from the fully specified fallthrough. spec.attributes[0].fallthroughs = [ deps.Fallthrough(lambda: 'exampleproject', hint='h')] spec.attributes[1].fallthroughs = [ deps.Fallthrough(lambda: 'exampleshelf', hint='h')] concept_parser = concept_parsers.ConceptParser.ForResource( '--book', spec, 'The book to act upon.', plural=plural) concept_parser.AddToParser(self.parser) parsed_args = self.parser.parser.parse_args(['--book', book_arg]) if plural: result = [book.RelativeName() for book in parsed_args.CONCEPTS.book.Parse()] else: result = parsed_args.CONCEPTS.book.Parse().RelativeName() self.assertEqual(expected_value, result)
def testInitializeNotFullySpecified(self): book_fallthrough = deps.Fallthrough(lambda: 'my-book', 'h', active=True) fallthroughs_map = { 'project': [ deps.FullySpecifiedAnchorFallthrough(book_fallthrough, self.book_collection, 'projectsId'), deps.Fallthrough(lambda: 'my-project', 'h') ], 'organization': [ deps.FullySpecifiedAnchorFallthrough( book_fallthrough, self.org_shelf_book_collection, 'organizationsId'), deps.Fallthrough(lambda: 'my-org', 'h', active=True) ], 'shelf': [ deps.FullySpecifiedAnchorFallthrough( book_fallthrough, self.org_shelf_book_collection, 'shelvesId'), deps.FullySpecifiedAnchorFallthrough(book_fallthrough, self.book_collection, 'shelvesId'), deps.Fallthrough(lambda: None, 'h') ], 'book': [book_fallthrough] } with self.assertRaisesRegexp(concepts.InitializationError, re.escape('[shelf]')): self.resource.Initialize(fallthroughs_map).result.RelativeName()
def testAllFallthrough(self): """Test a resource where everything has a fallthough.""" def Fallthrough(): return '!' resource = presentation_specs.ResourcePresentationSpec( 'book', concepts.ResourceSpec( 'example.projects.shelves.books', 'project', projectsId=concepts.ResourceParameterAttributeConfig( name='project', help_text='Auxilio aliis.', fallthroughs=[ deps.PropertyFallthrough(properties.VALUES.core.project)]), shelvesId=concepts.ResourceParameterAttributeConfig( name='shelf', help_text='Auxilio aliis.', fallthroughs=[deps.Fallthrough(Fallthrough, hint='hint')]), booksId=concepts.ResourceParameterAttributeConfig( name='book', help_text='Auxilio aliis.', fallthroughs=[deps.Fallthrough(Fallthrough, hint='hint')])), 'Group Help', prefixes=False) concept_parser = concept_parsers.ConceptParser([resource]) concept_parser.AddToParser(self.parser) properties.VALUES.core.project.Set('foo') namespace = self.parser.parser.parse_args([]) self.assertEqual('projects/foo/shelves/!/books/!', namespace.CONCEPTS.book.Parse().RelativeName())
def testInitialize(self, active, expected): fallthroughs_map = { 'project': [deps.Fallthrough(lambda: 'my-project', 'h', active=True)], 'shelf': [deps.Fallthrough(lambda: 'my-shelf', 'h', active=True)], 'case': [deps.Fallthrough(lambda: 'my-case', 'h', active=active)], 'book': [deps.Fallthrough(lambda: 'my-book', 'h', active=True)] } self.assertEqual( expected, self.resource.Initialize(fallthroughs_map).result.RelativeName())
def testInitializeNotFullySpecified(self): fallthroughs_map = { 'project': [deps.Fallthrough(lambda: 'exampleproject', 'h', active=True)], 'shelf': [deps.Fallthrough(lambda: None, 'h')], 'book': [deps.Fallthrough(lambda: 'examplebook', 'h', active=True)] } with self.assertRaisesRegexp(concepts.InitializationError, re.escape('[shelf]')): self.resource.Initialize(fallthroughs_map).RelativeName()
def testInitializeConceptNotFullySpecified(self): fallthroughs_map = { 'project': [deps.Fallthrough(lambda: 'my-project', 'h')], 'organization': [deps.Fallthrough(lambda: 'my-org', 'h', active=True)], 'shelf': [deps.Fallthrough(lambda: 'my-shelf', 'h', active=True)], 'case': [deps.Fallthrough(lambda: None, 'h')], 'book': [deps.Fallthrough(lambda: None, 'h')] } with self.assertRaisesRegexp(concepts.InitializationError, re.escape('[book]')): self.resource.Initialize(fallthroughs_map)
def testInitialize(self, proj_active, org_value, org_active, expected): fallthroughs_map = { 'project': [deps.Fallthrough(lambda: 'my-project', 'h', active=proj_active)], 'organization': [deps.Fallthrough(lambda: org_value, 'h', active=org_active)], 'shelf': [deps.Fallthrough(lambda: 'my-shelf', 'h')], 'book': [deps.Fallthrough(lambda: 'my-book', 'h', active=True)] } self.assertEqual( expected, self.resource.Initialize(fallthroughs_map).result.RelativeName())
def testInitializeError(self, proj_value, org_value, expected_error): fallthroughs_map = { 'project': [deps.Fallthrough(lambda: proj_value, 'h', active=True)], 'organization': [deps.Fallthrough(lambda: org_value, 'h', active=True)], 'shelf': [deps.Fallthrough(lambda: 'my-shelf', 'h', active=True)], 'book': [deps.Fallthrough(lambda: 'my-book', 'h', active=True)] } with self.assertRaisesRegexp(multitype.ConflictingTypesError, re.escape(expected_error)): self.resource.Initialize(fallthroughs_map).result.RelativeName()
def testInitializeError(self, proj_value, proj_active, shelf_value, shelf_active, book_value, book_active, expected_error): fallthroughs_map = { 'project': [deps.Fallthrough(lambda: proj_value, 'h', active=proj_active)], 'shelf': [deps.Fallthrough(lambda: shelf_value, 'h', active=shelf_active)], 'book': [deps.Fallthrough(lambda: book_value, 'h', active=book_active)] } with self.assertRaisesRegexp(concepts.InitializationError, re.escape(expected_error)): self.resource.Initialize(fallthroughs_map)
def testGetValueWithPromptingFallthrough(self, current_value): properties.VALUES.core.disable_prompts.Set(current_value) spec = copy.deepcopy(self.resource_spec) def GetValue(): return console_io.PromptResponse('value? >') spec.attributes[0].fallthroughs = [deps.Fallthrough(GetValue, 'hint')] presentation_spec = presentation_specs.ResourcePresentationSpec( '--book', spec, 'a resource', flag_name_overrides={'project': '--book-project'}, prefixes=False) resource_info = concept_parsers.ConceptParser( [presentation_spec]).GetInfo(presentation_spec.name) ns = core_completer_test_base.MockNamespace(args={}, handler_info=resource_info) argument = mock.MagicMock(dest='book') parameter_info = resource_parameter_info.ResourceParameterInfo( resource_info, ns, argument) self.assertEqual(None, parameter_info.GetValue('projectsId')) # Ensure that the property is restored after GetValue. self.assertEqual(current_value, properties.VALUES.core.disable_prompts.GetBool()) properties.VALUES.core.disable_prompts.Set(True)
def CreateReusableConfigResourceSpec(location_fallthroughs=None): """Create a resource spec for a ReusableConfig. Defaults to the predefined project for reusable configs. Args: location_fallthroughs: List of fallthroughs to use for the location of the reusable config, if not explicitly provided. Returns: A concepts.ResourceSpec for a reusable config. """ # For now, reusable configs exist in a single project. project_fallthrough = deps.Fallthrough( function=lambda: api_constants.PREDEFINED_REUSABLE_CONFIG_PROJECT, hint='project will default to {}'.format( api_constants.PREDEFINED_REUSABLE_CONFIG_PROJECT), active=False, plural=False) return concepts.ResourceSpec( 'privateca.projects.locations.reusableConfigs', resource_name='reusable config', reusableConfigsId=ReusableConfigAttributeConfig(), locationsId=LocationAttributeConfig( fallthroughs=location_fallthroughs), projectsId=ProjectAttributeConfig(fallthroughs=[project_fallthrough]))
def Args(parser): concept_parsers.ConceptParser([ presentation_specs.ResourcePresentationSpec( '--issuer', resource_args.CreateCertificateAuthorityResourceSpec( 'CERTIFICATE_AUTHORITY', ca_id_fallthroughs=[ deps.Fallthrough( function=lambda: '-', hint=('defaults to all Certificate Authorities in the ' 'given location'), active=False, plural=False) ]), 'The issuing Certificate Authority. If this is omitted, ' 'Certificates issued by all Certificate Authorities in the given ' 'location will be listed.', required=True), ]).AddToParser(parser) base.PAGE_SIZE_FLAG.SetDefault(parser, 100) parser.display_info.AddFormat(""" table( name.basename(), name.scope().segment(-3):label=ISSUER, name.scope().segment(-5):label=LOCATION, revocation_details.yesno(yes="REVOKED", no="ACTIVE"):label=REVOCATION_STATUS, certificate_description.subject_description.not_before_time():label=NOT_BEFORE, certificate_description.subject_description.not_after_time():label=NOT_AFTER) """) parser.display_info.AddTransforms({ 'not_before_time': text_utils.TransformNotBeforeTime, 'not_after_time': text_utils.TransformNotAfterTime })
def LocationAttributeConfig(): return concepts.ResourceParameterAttributeConfig( name='location', help_text='The Cloud location for the {resource}.', fallthroughs=[ deps.Fallthrough(lambda: 'global', 'location is always global') ])
def _CreateAttribute(data): """Creates a single resource attribute from YAML data. Args: data: {}, The dict of data from the YAML file for this single attribute. Returns: ResourceParameterAttributeConfig, the generated attribute. """ attribute_name = data['attribute_name'] help_text = data['help'] fallthrough_paths = data.get('fallthroughs', []) fallthroughs = [ deps.Fallthrough(util.Hook.FromPath(p), hint='') for p in fallthrough_paths ] prop_string = data.get('property') prop = properties.FromString(prop_string) if prop_string else None prop = prop or _DEFAULT_PROPS.get(attribute_name) if prop: fallthroughs.insert(0, deps.PropertyFallthrough(prop)) completer = data.get('completer') attribute = concepts.ResourceParameterAttributeConfig( name=attribute_name, help_text=help_text, completer=completer, fallthroughs=fallthroughs) return (data['parameter_name'], attribute)
def LocationAttributeConfig(): return concepts.ResourceParameterAttributeConfig( name='location', help_text='Google Cloud location for the {resource}.', fallthroughs=[ deps.Fallthrough(util.DefaultToGlobal, 'location is always global') ])
def _ParseFromPluralValue(self, attribute_to_args_map, base_fallthroughs_map, plural_attribute, parsed_args): """Helper for parsing a list of results from a plural fallthrough.""" attribute_name = plural_attribute.name fallthroughs_map = self.BuildFullFallthroughsMap( attribute_to_args_map, base_fallthroughs_map, plural=True, with_anchor_fallthroughs=False) current_fallthroughs = fallthroughs_map.get(attribute_name, []) # Iterate through the values provided to the argument, creating for # each a separate parsed resource. parsed_resources = [] for fallthrough in current_fallthroughs: try: values = fallthrough.GetValue(parsed_args) except deps_lib.FallthroughNotFoundError: continue for value in values: def F(return_value=value): return return_value new_fallthrough = deps_lib.Fallthrough( F, fallthrough.hint, active=fallthrough.active) fallthroughs_map[attribute_name] = [new_fallthrough] # Add the anchor fallthroughs for this particular value, so that the # error messages will contain the appropriate hints. self._AddAnchorFallthroughs(plural_attribute, fallthroughs_map) parsed_resources.append( self.Initialize(fallthroughs_map, parsed_args=parsed_args)) return parsed_resources
def RegionAttributeConfig(prompt_func=region_util.PromptForRegion): return concepts.ResourceParameterAttributeConfig( name='region', help_text='Cloud region for the {resource}.', fallthroughs=[ deps.PropertyFallthrough(properties.VALUES.ai.region), deps.Fallthrough(function=prompt_func, hint='region') ])
def ApiAttributeConfig(name='api', wildcard=False): fallthroughs = [] if wildcard: fallthroughs.append( deps.Fallthrough(lambda: '-', 'Defaults to wildcard for all APIs')) return concepts.ResourceParameterAttributeConfig(name=name, fallthroughs=fallthroughs, help_text='API ID.')
def GetListingLocationResourceSpec(): location_attribute_config = GetLocationAttributeConfig() location_attribute_config.fallthroughs.insert( 0, deps.Fallthrough(lambda: '-', hint='uses all locations by default.')) return concepts.ResourceSpec( 'file.projects.locations', 'location', projectsId=resource_args.PROJECT_ATTRIBUTE_CONFIG, locationsId=location_attribute_config)
def _location_attribute_config(): return concepts.ResourceParameterAttributeConfig( name='location', help_text='Location of the key.', fallthroughs=[ deps.Fallthrough( function=lambda: 'global', hint='location will default to {}'.format('global'), active=True, plural=False) ])
def _ParseUncached(self, parsed_args=None): """Lazy parsing function for resource. Args: parsed_args: the parsed Namespace. Returns: the initialized resource or a list of initialized resources if the resource argument was pluralized. """ fallthroughs_map = self.BuildFullFallthroughsMap() if not self.plural: try: return self.concept_spec.Initialize( deps_lib.Deps(fallthroughs_map, parsed_args=parsed_args)) except concepts.InitializationError: if self.allow_empty: return None raise anchor = self.concept_spec.anchor.name anchor_fallthroughs = fallthroughs_map.get(anchor, []) # Iterate through the values provided to the anchor argument, creating for # each a separate parsed resource. resources = [] for i, anchor_fallthrough in enumerate(anchor_fallthroughs): try: anchor_values = anchor_fallthrough.GetValue(parsed_args) except deps_lib.FallthroughNotFoundError: continue for arg_value in anchor_values: def F(return_value=arg_value): return return_value fallthrough = deps_lib.Fallthrough( F, anchor_fallthrough.hint, active=anchor_fallthrough.active) fallthroughs_map[anchor] = (anchor_fallthroughs[:i] + [fallthrough] + anchor_fallthroughs[i:]) resources.append( self.concept_spec.Initialize( deps_lib.Deps(fallthroughs_map, parsed_args=parsed_args))) return resources if self.allow_empty: return resources return self.concept_spec.Initialize( deps_lib.Deps(fallthroughs_map, parsed_args=parsed_args))
def LocationAttributeConfig(): """Gets Google Cloud location resource attribute.""" return concepts.ResourceParameterAttributeConfig( name='location', help_text='Google Cloud location for the {resource}.', fallthroughs=[ deps.PropertyFallthrough(properties.VALUES.container_aws.location), deps.Fallthrough( _LocationFallthrough, 'set the property `{}` (deprecated)'.format( properties.VALUES.aws.location)) ])
def testParseEmptyRequired(self, name, plural, return_value): """Test Parse method with plural resources.""" concept_parsers.ConceptParser.ForResource( name, self.SetUpFallthroughSpec( deps_lib.Fallthrough(lambda: return_value, hint='h')), 'a resource', plural=plural, required=True).AddToParser(self.parser) namespace = self.parser.parser.parse_args([]) with self.assertRaises(handlers.ParseError): namespace.CONCEPTS.book.Parse()
def _GenerateCertificateIdFallthrough(cls): cls.id_fallthrough_was_used = False def FallthroughFn(): cls.id_fallthrough_was_used = True return certificate_utils.GenerateCertId() return deps.Fallthrough( function=FallthroughFn, hint='certificate id will default to an automatically generated id', active=False, plural=False)
def SetUp(self): # Set up a sample argparse parser. command = calliope_util.MockCommand('command') argparser = parser_extensions.ArgumentParser(calliope_command=command) self.parser = parser_arguments.ArgumentInterceptor( parser=argparser, cli_generator=None, allow_positional=True) command.ai = self.parser # Set up a default fallthrough. def Fallthrough(): return '!' self.fallthrough = deps.Fallthrough(Fallthrough, hint='h')
def Args(parser): concept_parsers.ConceptParser.ForResource( 'REUSABLE_CONFIG', resource_args.CreateReusableConfigResourceSpec( location_fallthrough=deps.Fallthrough( function=lambda: locations.GetSupportedLocations()[0], hint=( 'location will default to the first location supported ' 'by the service'), active=False, plural=False)), 'The reusable config to describe.', required=True).AddToParser(parser)