def SetUp(self): resource_registry = resources.REGISTRY self.project_collection = resource_registry.GetCollectionInfo( 'cloudresourcemanager.projects') resource_registry.registered_apis['example'] = ['v1'] self.book_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects.shelves.books', 'projects/{projectsId}/shelves/{shelvesId}/books/{booksId}', {'': 'projects/{projectsId}/shelves/{shelvesId}/books/{booksId}'}, ['projectsId', 'shelvesId', 'booksId']) self.shelf_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects.shelves', 'projects/{projectsId}/shelves/{shelvesId}', {'': 'projects/{projectsId}/shelves/{shelvesId}'}, ['projectsId', 'shelvesId']) # pylint:disable=protected-access resource_registry._RegisterCollection(self.book_collection) resource_registry._RegisterCollection(self.shelf_collection) # pylint:enable=protected-access self.mock_client = mock.MagicMock() self.StartObjectPatch(arg_utils, '_GetField') self.StartObjectPatch(apis, 'GetClientInstance', return_value=self.mock_client) self.presentation_spec = presentation_specs.ResourcePresentationSpec( '--book', self.resource_spec_auto_completers, 'a resource', flag_name_overrides={'project': '--book-project'}, prefixes=False) self.resource_info = concept_parsers.ConceptParser( [self.presentation_spec]).GetInfo(self.presentation_spec.name) self.cloudresourcemanager_format = True
def MockCollections(self, *collections): """Mocks out the foo API to have mock collections.""" mock_collections = {} all_collections = [] for c in collections: full_collection_name, is_relative, api_version = ( self._ReadCollectionTuple(c)) # pylint:disable=protected-access api_name, collection_name = registry._SplitFullCollectionName( full_collection_name) base_url = 'https://{0}.googleapis.com/{1}/'.format( api_name, api_version) flat_params, flat_path = self._FlatPath(collection_name) if is_relative: collection = resource.CollectionInfo( api_name, api_version, base_url, 'https://cloud.google.com/docs', name=collection_name, path='{+name}', flat_paths={'': flat_path}, params=['name']) else: collection = resource.CollectionInfo( api_name, api_version, base_url, 'https://cloud.google.com/docs', name=collection_name, path=flat_path, flat_paths={}, params=flat_params) mock_collections.setdefault(api_name, {}) mock_collections[api_name].setdefault(api_version, []) mock_collections[api_name][api_version].append(collection) all_collections.append(collection) # pylint:disable=protected-access try: resources.REGISTRY._RegisterCollection(collection) # It's OK if it's already registered. except resources.AmbiguousAPIException: pass self.MockAPIs(*[(c.api_name, c.api_version, True) for c in all_collections]) collection_mock = self.StartObjectPatch(apis_internal, '_GetApiCollections') collection_mock.side_effect = lambda n, v: mock_collections[n][v]
def _GetServiceCollection(api_name, api_version, api_client, service): """Extract collection info from given service for an API. Args: api_name: str, name of api to register under. api_version: str, Use this api version to registerr resources. api_client: base_api.BaseApiClient, The client for a Google Cloud API. service: base_api.BaseApiService, the service with collection. Returns: CollectionInfo for this service. Raises: _ResourceWithoutGetException: If given service does not have Get method. """ try: method_config = service.GetMethodConfig('Get') except KeyError: raise _ResourceWithoutGetException() match = _METHOD_ID_RE.match(method_config.method_id) if not match: raise _ResourceWithoutGetException() collection = match.group('collection') collection = collection.split('.', 1)[1] # drop api name request_type = getattr(api_client.MESSAGES_MODULE, method_config.request_type_name) url = api_client.BASE_URL + method_config.relative_path _, _, path = _APINameAndVersionFromURL(url) base_url = url[:-len(path)] return resource.CollectionInfo( api_name, api_version, base_url, collection, request_type, path, method_config.ordered_params)
def _MakeResourceCollection(self, api_version, collection_name, path, flat_path=None): """Make resource collection object given its name and path.""" if flat_path == path: flat_path = None # Normalize base url so it includes api_version. url = self.base_url + path url_api_name, url_api_vesion, path = ( resource_util.SplitDefaultEndpointUrl(url)) if url_api_vesion != api_version: raise UnsupportedDiscoveryDoc( 'Collection {0} for version {1}/{2} is using url {3} ' 'with version {4}'.format(collection_name, self.api_name, api_version, url, url_api_vesion)) if flat_path: _, _, flat_path = resource_util.SplitDefaultEndpointUrl( self.base_url + flat_path) # Use url_api_name instead as it is assumed to be source of truth. # Also note that api_version not always equal to url_api_version, # this is the case where api_version is an alias. url = url[:-len(path)] return resource_util.CollectionInfo( url_api_name, api_version, url, self.docs_url, collection_name, path, {DEFAULT_PATH_NAME: flat_path} if flat_path else {}, resource_util.GetParamsFromPath(path))
def SetUp(self): reg = resources.REGISTRY reg.registered_apis['foo'] = ['v1'] zone_collection = resource_util.CollectionInfo( 'foo', 'v1', '', '', 'projects.zones', 'projects/{projectsId}/zones/{zonesId}', {'': 'projects/{projectsId}/zones/{zonesId}'}, ['projectsId', 'zonesId']) # pylint:disable=protected-access reg._RegisterCollection(zone_collection)
def testGetParentCollection(self, collection_name, flat_path, parent_name, parent_path): collection_info = resource.CollectionInfo('api_name', 'api_version', 'base_url', 'docs_url', collection_name, 'atomic_path', {'': flat_path}, []) self.assertEqual( resource_generator._GetParentCollection(collection_info), (parent_name, parent_path))
def MakeResourceCollection(self, collection_name, path, enable_uri_parsing, api_version): _, url_api_version, _ = resource_util.SplitDefaultEndpointUrl( self.base_url) if url_api_version: base_url = self.base_url else: base_url = '{}{}/'.format(self.base_url, api_version) return resource_util.CollectionInfo( self.api_name, api_version, base_url, self.docs_url, collection_name, path, {}, resource_util.GetParamsFromPath(path), enable_uri_parsing)
def testNoParamsCollectionRaises(self): """Tests creating resource from the collection with no config overrides.""" empty_collection = resource_util.CollectionInfo( 'example', 'v1', '', '', 'books', '', {'': ''}, []) self.StartObjectPatch(resources.Registry, 'GetCollectionInfo', return_value=empty_collection) with self.AssertRaisesExceptionMatches( concepts.ResourceConfigurationError, 'Resource [book] has no parameters'): concepts.ResourceSpec('books', resource_name='book', api_version='v1')
def _GetApiCollections(api_name, api_version): """Yields all collections for for given api.""" try: resources_module = _GetResourceModule(api_name, api_version) except ImportError: pass else: for collection in resources_module.Collections: yield resource_util.CollectionInfo( api_name, api_version, resources_module.BASE_URL, resources_module.DOCS_URL, collection.collection_name, collection.path, collection.flat_paths, collection.params)
def SetUp(self): registry = resources.REGISTRY registry.registered_apis['example'] = ['v1'] self.book_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects.shelves.books', 'projects/{projectsId}/shelves/{shelvesId}/books/{booksId}', {'': 'projects/{projectsId}/shelves/{shelvesId}/books/{booksId}'}, ['projectsId', 'shelvesId', 'booksId']) self.shelf_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects.shelves', 'projects/{projectsId}/shelves/{shelvesId}', {'': 'projects/{projectsId}/shelves/{shelvesId}'}, ['projectsId', 'shelvesId']) self.project_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects', 'projects/{projectsId}', {'': 'projects/{projectsId}'}, ['projectsId']) # pylint:disable=protected-access registry._RegisterCollection(self.book_collection) registry._RegisterCollection(self.shelf_collection) registry._RegisterCollection(self.project_collection)
def testDefaultSubcollection(self): collection_info = resource_util.CollectionInfo( 'sql', 'v1beta4', base_url='http://base_url.com/v1beta4', docs_url='https://cloud.google.com/docs', name='backupRuns', path=('projects/{project}/instances/{instance}/' 'backupRuns/{backupConfiguration}/dueTime/{dueTime}'), flat_paths=[], params=['project', 'instance', 'backupConfiguration', 'dueTime']) self.assertEqual( ['project', 'instance', 'backupConfiguration', 'dueTime'], collection_info.GetParams('')) self.assertEqual( 'projects/{project}/instances/{instance}/' 'backupRuns/{backupConfiguration}/dueTime/{dueTime}', collection_info.GetPath(''))
def _ExtractResources(api_name, api_version, base_url, infos): """Extract resource definitions from discovery doc.""" collections = [] for name, info in infos.iteritems(): if name == 'methods': get_method = info.get('get') if get_method: method_id = get_method['id'] match = _METHOD_ID_RE.match(method_id) if match: collection_name = match.group('collection') request_type = ''.join([ s[0].upper() + s[1:] for s in re.findall(r'[^\._]+', collection_name) ]) + 'GetRequest' # Remove api name from collection. It might not match passed in, or # even api name in url. We choose to use api name as defined by url. collection_name = collection_name.split('.', 1)[1] flat_path = get_method.get('flatPath') path = get_method.get('path') if flat_path == path: flat_path = None # Normalize base url so it includes api_version. url = base_url + path url_api_name, _, path = resource_util.SplitDefaultEndpointUrl( url) if flat_path: _, _, flat_path = resource_util.SplitDefaultEndpointUrl( base_url + flat_path) # Use url_api_name instead as it is assumed to be source of truth. # Also note that api_version not always equal to url_api_version, # this is the case where api_version is an alias. url = url[:-len(path)] collection_info = resource_util.CollectionInfo( url_api_name, api_version, url, collection_name, request_type, path, {_DEFAULT_PATH_NAME: flat_path} if flat_path else {}, resource_util.GetParamsFromPath(path)) collections.append(collection_info) else: subresource_collections = _ExtractResources( api_name, api_version, base_url, info) collections.extend(subresource_collections) return collections
def testMultitypeResourceArgMismatchedCollection(self): self.MockCRUDMethods(('foo.projects.zones', True), ('foo.projects.regions', True)) r = resource_arg_schema.YAMLMultitypeResourceArgument.FromData( { 'name': 'location', 'is_positional': False, 'help_text': 'group help', 'spec': { 'name': 'region-or-zone', 'resources': [self._zone_spec, self._region_spec]}}) collection_info = resource_util.CollectionInfo( 'bar', 'v1', '', '', 'projects.zones', 'projects/{projectsId}/zones/{zonesId}', {'': 'projects/{projectsId}/zones/{zonesId}'}, ['projectsId', 'zonesId']) with self.assertRaisesRegex( util.InvalidSchemaError, re.escape( 'Collection names do not match for resource argument specification ' '[region-or-zone]. Expected [bar.projects.zones version v1], and ' 'no contained resources matched. Given collections: ' '[foo.projects.regions None, foo.projects.zones None]')): r.GenerateResourceSpec(collection_info)
def MakeResourceCollection(self, collection_name, path, enable_uri_parsing, api_version): return resource_util.CollectionInfo( self.api_name, api_version, self.base_url, self.docs_url, collection_name, path, {}, resource_util.GetParamsFromPath(path), enable_uri_parsing)
def SetUp(self): registry = resources.REGISTRY self.proj_case_book_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects.cases.books', 'projects/{projectsId}/cases/{casesId}/books/{booksId}', {'': 'projects/{projectsId}/cases/{casesId}/books/{booksId}'}, ['projectsId', 'casesId', 'booksId']) self.proj_case_shelf_book_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects.cases.shelves.books', 'projects/{projectsId}/cases/{casesId}/shelves/{shelvesId}/' 'books/{booksId}', { '': 'projects/{projectsId}/cases/{casesId}/shelves/{shelvesId}/' 'books/{booksId}' }, ['projectsId', 'casesId', 'shelvesId', 'booksId']) self.proj_case_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'projects.cases', 'projects/{projectsId}/cases/{casesId}', {'': 'projects/{projectsId}/cases/{casesId}'}, ['projectsId', 'casesId']) self.org_shelf_book_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'organizations.shelves.books', 'organizations/{organizationsId}/shelves/{shelvesId}/books/{booksId}', { '': 'organizations/{organizationsId}/shelves/{shelvesId}/books/{booksId}' }, ['organizationsId', 'shelvesId', 'booksId']) self.org_shelf_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'organizations.shelves', 'organizations/{organizationsId}/shelves/{shelvesId}', {'': 'organizations/{organizationsId}/shelves/{shelvesId}'}, ['organizationsId', 'shelvesId']) self.organization_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'organizations', 'organizations/{organizationsId}', {'': 'organizations/{organizationsId}'}, ['organizationsId']) self.org_case_book_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'organizations.cases.books', 'organizations/{organizationsId}/cases/{casesId}/books/{booksId}', { '': 'organizations/{organizationsId}/cases/{casesId}/books/{booksId}' }, ['organizationsId', 'casesId', 'booksId']) self.org_case_collection = resource_util.CollectionInfo( 'example', 'v1', 'https://example.googleapis.com/v1/', '', 'organizations.cases', 'organizations/{organizationsId}/cases/{casesId}', {'': 'organizations/{organizationsId}/cases/{casesId}'}, ['organizationsId', 'casesId']) for collection in [ self.proj_case_book_collection, self.proj_case_shelf_book_collection, self.proj_case_collection, self.org_shelf_book_collection, self.org_shelf_collection, self.organization_collection, self.org_case_book_collection, self.org_case_collection ]: registry._RegisterCollection(collection) # pylint:disable=protected-access
def MakeResourceCollection(self, collection_name, path, api_version=None): api_version = api_version or self.api_verison return resource_util.CollectionInfo( self.api_name, api_version, self.base_url, collection_name, path, {}, resource_util.GetParamsFromPath(path))
def testArguments(self): registry = resources.REGISTRY registry.registered_apis['foo'] = ['v1'] zone_collection = resource_util.CollectionInfo( 'foo', 'v1', '', '', 'projects.zones', 'projects/{projectsId}/zones/{zonesId}', {'': 'projects/{projectsId}/zones/{zonesId}'}, ['projectsId', 'zonesId']) # pylint:disable=protected-access registry._RegisterCollection(zone_collection) r = yaml_command_schema.Arguments({ 'resource': { 'help_text': 'group help', 'spec': {'name': 'zone', 'collection': 'foo.projects.zones', 'attributes': [ {'parameter_name': 'projectsId', 'attribute_name': 'project', 'help': 'help1'}, {'parameter_name': 'zonesId', 'attribute_name': 'zone', 'help': 'help2'}]}, 'removed_flags': ['zone'], }, 'params': [ { 'help_text': 'foo-help', 'api_field': 'foo', 'arg_name': 'f', }, { 'help_text': 'bar-help', 'api_field': 'bar', 'arg_name': 'b', 'choices': [ {'arg_value': 'w', 'enum_value': 'x'}, {'arg_value': 'y', 'enum_value': 'z'}, ], }, { 'group': { 'required': True, 'mutex': True, 'params': [ { 'help_text': 'a-help', 'api_field': 'aaa', 'arg_name': 'a', }, { 'help_text': 'b-help', 'api_field': 'bbb', 'arg_name': 'b', }, ], }, }, ], 'labels': { 'api_field': 'instance.labels' } }) self.assertEqual(r.resource.group_help, 'group help') self.assertEqual(r.resource.removed_flags, ['zone']) mock_resource = mock.MagicMock( full_name='foo.projects.zones', api_version='v1', detailed_params=['projectsId', 'zonesId']) spec = r.resource.GenerateResourceSpec(mock_resource) project_attr, zone_attr = spec.attributes[0], spec.attributes[1] self.assertEqual(project_attr.name, 'project') self.assertEqual(project_attr.help_text, 'help1') self.assertEqual(zone_attr.name, 'zone') self.assertEqual(zone_attr.help_text, 'help2') foo_flag = r.params[0] self.assertTrue(isinstance(foo_flag, yaml_command_schema.Argument)) self.assertFalse(isinstance(foo_flag, yaml_command_schema.ArgumentGroup)) self.assertEqual(foo_flag.arg_name, 'f') self.assertEqual(foo_flag.help_text, 'foo-help') self.assertEqual(foo_flag.choices, None) bar_flag = r.params[1] self.assertTrue(isinstance(bar_flag, yaml_command_schema.Argument)) self.assertFalse(isinstance(bar_flag, yaml_command_schema.ArgumentGroup)) self.assertEqual(bar_flag.arg_name, 'b') self.assertEqual(bar_flag.help_text, 'bar-help') self.assertEqual(bar_flag.choices[0].arg_value, 'w') self.assertEqual(bar_flag.choices[0].enum_value, 'x') self.assertEqual(bar_flag.choices[1].arg_value, 'y') self.assertEqual(bar_flag.choices[1].enum_value, 'z') group = r.params[2] self.assertFalse(isinstance(group, yaml_command_schema.Argument)) self.assertTrue(isinstance(group, yaml_command_schema.ArgumentGroup)) self.assertEqual(group.required, True) self.assertEqual(group.mutex, True) args = group.arguments self.assertEqual(args[0].arg_name, 'a') self.assertEqual(args[0].help_text, 'a-help') self.assertEqual(args[1].arg_name, 'b') self.assertEqual(args[1].help_text, 'b-help') labels = r.labels self.assertIsInstance(labels, yaml_command_schema.Labels) self.assertEqual(labels.api_field, 'instance.labels')