def test_get_index_extensions(self): data = {'extensions': {}} with mock.patch('requests.get', side_effect=mock_index_get_generator( DEFAULT_INDEX_URL, data)): self.assertEqual(get_index_extensions(), {}) obj = object() data = {'extensions': {'myext': obj}} with mock.patch('requests.get', side_effect=mock_index_get_generator( DEFAULT_INDEX_URL, data)): self.assertEqual(get_index_extensions().get('myext'), obj) with mock.patch('azure.cli.core.extension._index.logger.warning', autospec=True) as logger_mock: with mock.patch('requests.get', side_effect=mock_index_get_generator( DEFAULT_INDEX_URL, {})): self.assertEqual(get_index_extensions(), None) logger_mock.assert_called_once_with( ERR_UNABLE_TO_GET_EXTENSIONS) with mock.patch('azure.cli.core.extension._index.logger.warning', autospec=True) as logger_mock: with mock.patch('requests.get', side_effect=mock_index_get_generator( DEFAULT_INDEX_URL, {'v2extensions': []})): self.assertEqual(get_index_extensions(), None) logger_mock.assert_called_once_with( ERR_UNABLE_TO_GET_EXTENSIONS)
def test_get_index_cloud(self): from azure.cli.core.mock import DummyCli cli_ctx = DummyCli() default_data = {'extensions': {}} obj = object() cloud_data = {'extensions': {'myext': obj}} # cli_ctx not passed with mock.patch('requests.get', side_effect=mock_index_get_generator( DEFAULT_INDEX_URL, default_data)): self.assertEqual(get_index_extensions(), {}) # cli_ctx passed but endpoint not set delattr(cli_ctx.cloud.endpoints, 'azmirror_storage_account_resource_id') with mock.patch('requests.get', side_effect=mock_index_get_generator( DEFAULT_INDEX_URL, default_data)): self.assertEqual(get_index_extensions(cli_ctx=cli_ctx), {}) # cli_ctx passed and the endpoint is set cli_ctx.cloud.endpoints.azmirror_storage_account_resource_id = 'http://contoso.com' with mock.patch('requests.get', side_effect=mock_index_get_generator( 'http://contoso.com/extensions/index.json', cloud_data)): self.assertEqual( get_index_extensions(cli_ctx=cli_ctx).get('myext'), obj)
def resolve_from_index(extension_name, cur_version=None, index_url=None): candidates = get_index_extensions(index_url=index_url).get( extension_name, []) if not candidates: raise NoExtensionCandidatesError( "No extension found with name '{}'".format(extension_name)) filters = [ _is_not_platform_specific, _is_compatible_with_cli_version, _is_greater_than_cur_version(cur_version) ] for f in filters: logger.debug("Candidates %s", [c['filename'] for c in candidates]) candidates = list(filter(f, candidates)) if not candidates: raise NoExtensionCandidatesError("No suitable extensions found.") candidates_sorted = sorted( candidates, key=lambda c: parse_version(c['metadata']['version']), reverse=True) logger.debug("Candidates %s", [c['filename'] for c in candidates_sorted]) logger.debug("Choosing the latest of the remaining candidates.") chosen = candidates_sorted[0] logger.debug("Chosen %s", chosen) download_url, digest = chosen.get('downloadUrl'), chosen.get( 'sha256Digest') if not download_url: raise NoExtensionCandidatesError("No download url found.") return download_url, digest
def test_get_index_extensions(self): data = {'extensions': {}} with mock.patch('requests.get', side_effect=mock_index_get_generator(DEFAULT_INDEX_URL, data)): self.assertEqual(get_index_extensions(), {}) obj = object() data = {'extensions': {'myext': obj}} with mock.patch('requests.get', side_effect=mock_index_get_generator(DEFAULT_INDEX_URL, data)): self.assertEqual(get_index_extensions().get('myext'), obj) with mock.patch('azure.cli.core.extension._index.logger.warning', autospec=True) as logger_mock: with mock.patch('requests.get', side_effect=mock_index_get_generator(DEFAULT_INDEX_URL, {})): self.assertEqual(get_index_extensions(), None) logger_mock.assert_called_once_with(ERR_UNABLE_TO_GET_EXTENSIONS) with mock.patch('azure.cli.core.extension._index.logger.warning', autospec=True) as logger_mock: with mock.patch('requests.get', side_effect=mock_index_get_generator(DEFAULT_INDEX_URL, {'v2extensions': []})): self.assertEqual(get_index_extensions(), None) logger_mock.assert_called_once_with(ERR_UNABLE_TO_GET_EXTENSIONS)
def resolve_project_url_from_index(extension_name): """ Gets the project url of the matching extension from the index """ candidates = get_index_extensions().get(extension_name, []) if not candidates: raise NoExtensionCandidatesError("No extension found with name '{}'".format(extension_name)) try: return candidates[0]['metadata']['extensions']['python.details']['project_urls']['Home'] except KeyError as ex: logger.debug(ex) raise CLIError('Could not find project information for extension {}.'.format(extension_name))
def resolve_from_index(extension_name, cur_version=None, index_url=None, target_version=None): """ Gets the download Url and digest for the matching extension :param cur_version: threshold verssion to filter out extensions. """ candidates = get_index_extensions(index_url=index_url).get( extension_name, []) if not candidates: raise NoExtensionCandidatesError( "No extension found with name '{}'".format(extension_name)) filters = [ _is_not_platform_specific, _is_compatible_with_cli_version, _is_greater_than_cur_version(cur_version) ] for f in filters: logger.debug("Candidates %s", [c['filename'] for c in candidates]) candidates = list(filter(f, candidates)) if not candidates: raise NoExtensionCandidatesError("No suitable extensions found.") candidates_sorted = sorted( candidates, key=lambda c: parse_version(c['metadata']['version']), reverse=True) logger.debug("Candidates %s", [c['filename'] for c in candidates_sorted]) logger.debug("Choosing the latest of the remaining candidates.") if target_version: try: chosen = [ c for c in candidates_sorted if c['metadata']['version'] == target_version ][0] except IndexError: raise NoExtensionCandidatesError( 'Extension with version {} not found'.format(target_version)) else: chosen = candidates_sorted[0] logger.debug("Chosen %s", chosen) download_url, digest = chosen.get('downloadUrl'), chosen.get( 'sha256Digest') if not download_url: raise NoExtensionCandidatesError("No download url found.") return download_url, digest
def resolve_from_index(extension_name, cur_version=None, index_url=None, target_version=None, cli_ctx=None): """ Gets the download Url and digest for the matching extension :param cur_version: threshold verssion to filter out extensions. """ candidates = get_index_extensions(index_url=index_url, cli_ctx=cli_ctx).get(extension_name, []) if not candidates: raise NoExtensionCandidatesError("No extension found with name '{}'".format(extension_name)) filters = [_is_not_platform_specific, _is_compatible_with_cli_version] if not target_version: filters.append(_is_greater_than_cur_version(cur_version)) for f in filters: logger.debug("Candidates %s", [c['filename'] for c in candidates]) candidates = list(filter(f, candidates)) if not candidates: raise NoExtensionCandidatesError("No suitable extensions found.") candidates_sorted = sorted(candidates, key=lambda c: parse(c['metadata']['version']), reverse=True) logger.debug("Candidates %s", [c['filename'] for c in candidates_sorted]) if target_version: try: chosen = [c for c in candidates_sorted if c['metadata']['version'] == target_version][0] except IndexError: raise NoExtensionCandidatesError('Extension with version {} not found'.format(target_version)) else: logger.debug("Choosing the latest of the remaining candidates.") chosen = candidates_sorted[0] logger.debug("Chosen %s", chosen) download_url, digest = chosen.get('downloadUrl'), chosen.get('sha256Digest') if not download_url: raise NoExtensionCandidatesError("No download url found.") azmirror_endpoint = cli_ctx.cloud.endpoints.azmirror_storage_account_resource_id if cli_ctx and \ cli_ctx.cloud.endpoints.has_endpoint_set('azmirror_storage_account_resource_id') else None config_index_url = cli_ctx.config.get('extension', 'index_url', None) if cli_ctx else None if azmirror_endpoint and not config_index_url: # when extension index and wheels are mirrored in airgapped clouds from public cloud # the content of the index.json is not updated, so we need to modify the wheel url got # from the index.json here. import posixpath whl_name = download_url.split('/')[-1] download_url = posixpath.join(azmirror_endpoint, 'extensions', whl_name) return download_url, digest
def resolve_from_index(extension_name, cur_version=None, index_url=None): candidates = get_index_extensions(index_url=index_url).get(extension_name, []) if not candidates: raise NoExtensionCandidatesError("No extension found with name '{}'".format(extension_name)) filters = [_is_not_platform_specific, _is_compatible_with_cli_version, _is_greater_than_cur_version(cur_version)] for f in filters: logger.debug("Candidates %s", [c['filename'] for c in candidates]) candidates = list(filter(f, candidates)) if not candidates: raise NoExtensionCandidatesError("No suitable extensions found.") candidates_sorted = sorted(candidates, key=lambda c: parse_version(c['metadata']['version']), reverse=True) logger.debug("Candidates %s", [c['filename'] for c in candidates_sorted]) logger.debug("Choosing the latest of the remaining candidates.") chosen = candidates_sorted[0] logger.debug("Chosen %s", chosen) download_url, digest = chosen.get('downloadUrl'), chosen.get('sha256Digest') if not download_url: raise NoExtensionCandidatesError("No download url found.") return download_url, digest