From a18b1f42b4a02e2e9e14e20f3efc02b984f3ae07 Mon Sep 17 00:00:00 2001 From: djyou Date: Sat, 10 Sep 2016 21:25:00 -0700 Subject: [PATCH] Added "az acr" commands for Azure container registries 1. Added commands to manage Azure container registries (create/delete/show/list/update). 2. Integrated repository list and show-tags commands. 3. Added mgmt_acr SDK for Python. --- src/command_modules/azure-cli-acr/README.rst | 128 ++++++ .../azure-cli-acr/azure/__init__.py | 6 + .../azure-cli-acr/azure/cli/__init__.py | 6 + .../azure/cli/command_modules/__init__.py | 6 + .../azure/cli/command_modules/acr/__init__.py | 11 + .../cli/command_modules/acr/_arm_utils.py | 99 +++++ .../cli/command_modules/acr/_constants.py | 7 + .../azure/cli/command_modules/acr/_factory.py | 46 +++ .../azure/cli/command_modules/acr/_format.py | 115 ++++++ .../azure/cli/command_modules/acr/_help.py | 65 ++++ .../azure/cli/command_modules/acr/_params.py | 42 ++ .../azure/cli/command_modules/acr/_utils.py | 73 ++++ .../cli/command_modules/acr/_validators.py | 31 ++ .../azure/cli/command_modules/acr/custom.py | 97 +++++ .../command_modules/acr/mgmt_acr/__init__.py | 22 ++ .../acr/mgmt_acr/container_registry.py | 84 ++++ .../acr/mgmt_acr/credentials.py | 16 + .../acr/mgmt_acr/exceptions.py | 22 ++ .../acr/mgmt_acr/models/__init__.py | 23 ++ .../mgmt_acr/models/registry_parameters.py | 56 +++ .../mgmt_acr/models/registry_properties.py | 45 +++ .../resource_list_registry_parameters.py | 29 ++ .../models/storage_account_properties.py | 40 ++ .../acr/mgmt_acr/operations/__init__.py | 17 + .../acr/mgmt_acr/operations/registries.py | 366 ++++++++++++++++++ .../command_modules/acr/mgmt_acr/version.py | 14 + .../cli/command_modules/acr/repository.py | 77 ++++ .../cli/command_modules/acr/template.json | 77 ++++ .../azure-cli-acr/requirements.txt | 1 + src/command_modules/azure-cli-acr/setup.py | 56 +++ 30 files changed, 1677 insertions(+) create mode 100644 src/command_modules/azure-cli-acr/README.rst create mode 100644 src/command_modules/azure-cli-acr/azure/__init__.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/__init__.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/__init__.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/__init__.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_arm_utils.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_constants.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_factory.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_format.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_help.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_params.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_utils.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_validators.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/custom.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/__init__.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/container_registry.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/credentials.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/exceptions.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/__init__.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_parameters.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_properties.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/resource_list_registry_parameters.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/storage_account_properties.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/__init__.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/registries.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/version.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/repository.py create mode 100644 src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.json create mode 100644 src/command_modules/azure-cli-acr/requirements.txt create mode 100644 src/command_modules/azure-cli-acr/setup.py diff --git a/src/command_modules/azure-cli-acr/README.rst b/src/command_modules/azure-cli-acr/README.rst new file mode 100644 index 00000000000..cb6c72a1349 --- /dev/null +++ b/src/command_modules/azure-cli-acr/README.rst @@ -0,0 +1,128 @@ +Microsoft Azure CLI 'acr' Command Module +================================== + +Commands to manage Azure container registries +------------- +:: + + Group + az acr: Commands to manage Azure container registries. + + Subgroups: + repository + + Commands: + create : Create a container registry. + delete : Delete a container registry. + list : List container registries. + show : Get a container registry. + update : Update a container registry. + +Create a container registry +------------- +:: + + Command + az acr create: Create a container registry. + + Arguments + --location -l [Required]: Location. + --name -n [Required]: Name of container registry. + --resource-group -g [Required]: Name of resource group. + --storage-account-name -s : Name of storage account. + + Examples + Create a container registry with a new storage account + az acr create -n -g -l + Create a container registry with a new/existing storage account + az acr create -n -g -l -s + +Delete a container registry +------------- +:: + + Command + az acr delete: Delete a container registry. + + Arguments + --name -n [Required]: Name of container registry. + +List container registries +------------- +:: + + Command + az acr list: List container registries. + + Arguments + --resource-group -g: Name of resource group. + + Examples + List container registries and show result in a table + az acr list -o table + List container registries in a resource group and show result in a table + az acr list -g -o table + +Get a container registry +------------- +:: + + Command + az acr show: Get a container registry. + + Arguments + --name -n [Required]: Name of container registry. + +Update a container registry +------------- +:: + + Command + az acr update: Update a container registry. + + Arguments + --name -n [Required]: Name of container registry. + --tags : Multiple semicolon separated tags in 'key[=value]' format. Use "" to + clear existing tags. + Examples + Update tags of a container registry and show result in a table + az acr update -n --tags key1=value1;key2=value2 -o table + +List repositories in a given container registry +------------- +:: + + Command + az acr repository list: List repositories in a given container registry. + + Arguments + --login-server [Required]: The URL of a container registry login server. + --password : The password used to log into the container registry. + --username : The username used to log into the container registry. + + Examples + List repositories in a given container registry under the current subscription + az acr repository list --login-server + List repositories in a given container registry with credentials + az acr repository list --login-server --username --password + + +Show tags of a given repository in a given container registry +------------- +:: + + Command + az acr repository show-tags: Show tags of a given repository in a given container registry. + + Arguments + --login-server [Required]: The URL of a container registry login server. + --repository [Required]: The repository to obtain tags from. + --password : The password used to log into the container registry. + --username : The username used to log into the container registry. + + Examples + Show tags of a given repository in a given container registry under the current subscription + az acr repository show-tags --login-server --repository + Show tags of a given repository in a given container registry with credentials + az acr repository show-tags --login-server --repository + --username --password diff --git a/src/command_modules/azure-cli-acr/azure/__init__.py b/src/command_modules/azure-cli-acr/azure/__init__.py new file mode 100644 index 00000000000..e8f024a89a8 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/__init__.py @@ -0,0 +1,6 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/src/command_modules/azure-cli-acr/azure/cli/__init__.py b/src/command_modules/azure-cli-acr/azure/cli/__init__.py new file mode 100644 index 00000000000..e8f024a89a8 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/__init__.py @@ -0,0 +1,6 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/__init__.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/__init__.py new file mode 100644 index 00000000000..e8f024a89a8 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/__init__.py @@ -0,0 +1,6 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +import pkg_resources +pkg_resources.declare_namespace(__name__) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/__init__.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/__init__.py new file mode 100644 index 00000000000..5673500debc --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/__init__.py @@ -0,0 +1,11 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +#pylint: disable=unused-import + +import azure.cli.command_modules.acr._help +import azure.cli.command_modules.acr._params +import azure.cli.command_modules.acr.custom +import azure.cli.command_modules.acr.repository diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_arm_utils.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_arm_utils.py new file mode 100644 index 00000000000..9393bb1d056 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_arm_utils.py @@ -0,0 +1,99 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from azure.cli.command_modules.acr.mgmt_acr.models import RegistryParameters + +from ._constants import ( + RESOURCE_PROVIDER, + RESOURCE_TYPE +) +from ._factory import get_arm_service_client + +from azure.cli.command_modules.acr.mgmt_acr import VERSION + +def arm_get_registries_in_subscription(): + '''Returns the list of container registries in the current subscription. + ''' + client = get_arm_service_client() + filter_str = "resourceType eq '{}'".format(RESOURCE_TYPE) + result = list(client.resources.list(filter=filter_str)) + + return [RegistryParameters(item.id, item.name, item.location, item.tags) for item in result] + +def arm_get_registries_in_resource_group(resource_group_name): + '''Returns the list of container registries in the resource group. + :param str resource_group_name: The name of resource group + ''' + client = get_arm_service_client() + filter_str = "resourceType eq '{}'".format(RESOURCE_TYPE) + result = list(client.resource_groups.list_resources(resource_group_name, filter=filter_str)) + + return [RegistryParameters(item.id, item.name, item.location, item.tags) for item in result] + +def arm_get_registry_by_name(registry_name): + '''Returns the container registry that matches the registry name. + :param str registry_name: The name of container registry + ''' + registries = arm_get_registries_in_subscription() + elements = [item for item in registries if item.name.lower() == registry_name.lower()] + + if len(elements) == 0: + return None + elif len(elements) == 1: + return elements[0] + else: + raise ValueError('More than one container registries are found with name: ' + registry_name) + +def arm_deploy_template(resource_group_name, registry_name, location, storage_account_name): + '''Deploys ARM template to create a container registry. + :param str resource_group_name: The name of resource group + :param str registry_name: The name of container registry + :param str location: The name of location + :param str storage_account_name: The name of storage account + ''' + from azure.mgmt.resource.resources.models import DeploymentProperties + from azure.cli.core._util import get_file_json + import os + + file_path = os.path.join(os.path.dirname(__file__), 'template.json') + template = get_file_json(file_path) + parameters = _parameters(registry_name, location, storage_account_name) + properties = DeploymentProperties(template=template, parameters=parameters, mode='incremental') + + return _arm_deploy_template(resource_group_name, properties) + +def _arm_deploy_template(resource_group_name, properties, index=0): + '''Deploys ARM template to create a container registry. + :param str resource_group_name: The name of resource group + :param DeploymentProperties properties: The properties of a deployment + :param int index: The index added to deployment name to avoid conflict + ''' + if index == 0: + deployment_name = RESOURCE_PROVIDER + else: + deployment_name = RESOURCE_PROVIDER + '_' + str(index) + + client = get_arm_service_client() + + try: + client.deployments.validate(resource_group_name, deployment_name, properties) + return client.deployments.create_or_update(resource_group_name, deployment_name, properties) + except: #pylint: disable=W0702 + return _arm_deploy_template(resource_group_name, properties, index + 1) + +def _parameters(registry_name, location, storage_account_name): + '''Returns a dict of deployment parameters. + :param str registry_name: The name of container registry + :param str location: The name of location + :param str storage_account_name: The name of storage account + ''' + parameters = { + 'registryName': {'value': registry_name}, + 'registryLocation': {'value': location}, + 'registryApiVersion': {'value': VERSION}, + 'storageAccountName': {'value': storage_account_name}, + 'storageAccountApiVersion': {'value': '2015-05-01-preview'} + } + return parameters diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_constants.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_constants.py new file mode 100644 index 00000000000..89b8403d43d --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_constants.py @@ -0,0 +1,7 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +RESOURCE_PROVIDER = 'Microsoft.ContainerRegistry' +RESOURCE_TYPE = RESOURCE_PROVIDER + '/registries' diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_factory.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_factory.py new file mode 100644 index 00000000000..d33e927cd65 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_factory.py @@ -0,0 +1,46 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from azure.cli.core._profile import Profile +from azure.cli.core._config import az_config +from azure.mgmt.resource.resources import ResourceManagementClient + +from azure.cli.core.commands.client_factory import ( + configure_common_settings, + get_mgmt_service_client +) + +from azure.cli.command_modules.acr.mgmt_acr import ( + ContainerRegistry, + ContainerRegistryConfiguration, + VERSION +) + +import azure.cli.core._logging as _logging +logger = _logging.get_az_logger(__name__) + +def get_arm_service_client(): + '''Returns the client for managing ARM resources. + ''' + return get_mgmt_service_client(ResourceManagementClient) + +def get_registry_service_client(): + '''Returns the client for managing container registries. + ''' + profile = Profile() + credentials, subscription_id, _ = profile.get_login_credentials() + + customized_api_version = az_config.get('acr', 'apiversion', None) + if customized_api_version: + logger.warning('Customized api-version is used: ' + customized_api_version) + + api_version = customized_api_version or VERSION + + config = ContainerRegistryConfiguration(subscription_id, api_version, credentials) + client = ContainerRegistry(config) + + configure_common_settings(client) + + return client.registries diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_format.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_format.py new file mode 100644 index 00000000000..5420451c7f8 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_format.py @@ -0,0 +1,115 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from collections import OrderedDict + +from ._constants import RESOURCE_TYPE +from ._utils import get_resource_group_name_by_registry + +_basic_map = { + 'name': 'NAME', + 'resourceGroup': 'RESOURCE GROUP', + 'location': 'LOCATION', + 'tags': 'TAGS' +} + +_properties_map = { + 'loginServer': 'LOGIN SERVER', + 'username': 'USERNAME', + 'key': 'PASSWORD', + 'creationDate': 'CREATION DATE', +} + +_storage_account_map = { + 'name': 'STORAGE ACCOUNT NAME' +} + +_parameters_map = { + 'registryName': 'NAME', + 'location': 'LOCATION', + 'storageAccountName': 'STORAGE ACCOUNT NAME' +} + +_order_map = { + 'NAME': 1, + 'RESOURCE GROUP': 2, + 'LOCATION': 3, + 'TAGS': 4, + 'LOGIN SERVER': 11, + 'USERNAME': 12, + 'PASSWORD': 13, + 'CREATION DATE': 14, + 'STORAGE ACCOUNT NAME': 21 +} + +def output_format(result): + '''Returns the list of container registries each of which is an ordered dictionary. + :param list/dict result: The container registry object(s) or deployment result(s) + ''' + obj_list = result if isinstance(result, list) else [result] + return [_format(item) for item in obj_list] + +def _format(item): + '''Returns an ordered dictionary of the container registry or deployment result. + :param dict item: The container registry object or deployment result + ''' + if isinstance(item, dict) and \ + 'id' in item and \ + '/providers/Microsoft.Resources/deployments/' in item['id']: + return _format_deployment(item) + elif isinstance(item, dict) and \ + 'id' in item and \ + ('/providers/' + RESOURCE_TYPE + '/') in item['id']: + return _format_registry(item) + else: + raise ValueError('Unknown item: ' + str(item)) + +def _format_deployment(item): + '''Returns an ordered dictionary of the deployment result. + :param dict item: The deployment result + ''' + basic_info = {_basic_map[key]: str(item[key]) for key in item if key in _basic_map} + + parameters_info = {} + if 'properties' in item and \ + item['properties'] and \ + 'parameters' in item['properties'] and \ + item['properties']['parameters']: + parameters = item['properties']['parameters'] + parameters_info = {_parameters_map[key]: str(parameters[key]['value']) + for key in parameters if key in _parameters_map} + + all_info = basic_info.copy() + all_info.update(parameters_info) + + return OrderedDict(sorted(all_info.items(), key=lambda t: _order_map[t[0]])) + +def _format_registry(item): + '''Returns an ordered dictionary of the container registry. + :param dict item: The container registry object + ''' + basic_info = {_basic_map[key]: str(item[key]) for key in item if key in _basic_map} + + resource_group_name = get_resource_group_name_by_registry(item) + if resource_group_name: + basic_info['RESOURCE GROUP'] = resource_group_name + + properties_info = {} + storage_account_info = {} + if 'properties' in item and item['properties']: + properties = item['properties'] + properties_info = {_properties_map[key]: str(properties[key]) + for key in properties if key in _properties_map} + + if 'storageAccount' in properties and properties['storageAccount']: + storage_account = properties['storageAccount'] + storage_account_info = {_storage_account_map[key]: str(storage_account[key]) + for key in storage_account if key in _storage_account_map} + + all_info = basic_info.copy() + all_info.update(properties_info) + all_info.update(storage_account_info) + + return OrderedDict(sorted(all_info.items(), key=lambda t: _order_map[t[0]])) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_help.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_help.py new file mode 100644 index 00000000000..135690a0eb1 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_help.py @@ -0,0 +1,65 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from azure.cli.core.help_files import helps + +#pylint: disable=line-too-long + +helps['acr'] = """ + type: group + short-summary: Commands to manage Azure container registries. + """ + +helps['acr list'] = """ + type: command + examples: + - name: List container registries and show result in a table + text: + az acr list -o table + - name: List container registries in a resource group and show result in a table + text: + az acr list -g -o table + """ + +helps['acr create'] = """ + type: command + examples: + - name: Create a container registry with a new storage account + text: + az acr create -n -g -l + - name: Create a container registry with a new/existing storage account + text: + az acr create -n -g -l -s + """ + +helps['acr update'] = """ + type: command + examples: + - name: Update tags of a container registry and show result in a table + text: + az acr update -n --tags key1=value1;key2=value2 -o table + """ + +helps['acr repository list'] = """ + type: command + examples: + - name: List repositories in a given container registry under the current subscription + text: + az acr repository list --login-server + - name: List repositories in a given container registry with credentials + text: + az acr repository list --login-server --username --password + """ + +helps['acr repository show-tags'] = """ + type: command + examples: + - name: Show tags of a given repository in a given container registry under the current subscription + text: + az acr repository show-tags --login-server --repository + - name: Show tags of a given repository in a given container registry with credentials + text: + az acr repository show-tags --login-server --repository --username --password + """ diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_params.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_params.py new file mode 100644 index 00000000000..42ab394ab28 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_params.py @@ -0,0 +1,42 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from azure.cli.core.commands import ( + register_cli_argument, + CliArgumentType +) + +from azure.cli.core.commands.parameters import ( + resource_group_name_type, + location_type, + tags_type, + get_resource_name_completion_list +) + +from ._constants import RESOURCE_TYPE +from ._validators import ( + validate_registry_name, + validate_storage_account_name +) + +registry_name_type = CliArgumentType( + options_list=('--name', '-n'), + help='Name of container registry', + completer=get_resource_name_completion_list(RESOURCE_TYPE), + validator=validate_registry_name +) + +register_cli_argument('acr', 'registry_name', registry_name_type) +register_cli_argument('acr', 'resource_group_name', arg_type=resource_group_name_type) +register_cli_argument('acr', 'location', arg_type=location_type) +register_cli_argument('acr', 'tags', arg_type=tags_type) +register_cli_argument('acr', 'storage_account_name', + options_list=('--storage-account-name', '-s'), + help='Name of storage account.', + completer=get_resource_name_completion_list( + 'Microsoft.Storage/storageAccounts'), + validator=validate_storage_account_name) + +register_cli_argument('acr create', 'registry_name', registry_name_type, completer=None) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_utils.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_utils.py new file mode 100644 index 00000000000..6beceaf3a26 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_utils.py @@ -0,0 +1,73 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from azure.cli.command_modules.acr.mgmt_acr.models import RegistryParameters + +from ._factory import get_registry_service_client + +def _get_registries_in_subscription(): + '''Returns the list of container registries in the current subscription. + ''' + return get_registry_service_client().list().value #pylint: disable=E1101 + +def _get_registries_in_resource_group(resource_group): + '''Returns the list of container registries in the resource group. + :param str resource_group: The name of resource group + ''' + return get_registry_service_client().list_by_resource_group(resource_group).value #pylint: disable=E1101 + +def get_registry_by_name(registry_name): + '''Returns the container registry that matches the registry name. + :param str registry_name: The name of container registry + ''' + registries = _get_registries_in_subscription() + elements = [item for item in registries if item.name.lower() == registry_name.lower()] + + if len(elements) == 0: + return None + elif len(elements) == 1: + return elements[0] + else: + raise ValueError('More than one container registries are found with name: ' + registry_name) + +def _get_resource_id(registry): + '''Returns the resource id of a container registry. + :param RegistryParameters/dict registry: The container registry object + ''' + if isinstance(registry, RegistryParameters): + return registry.id + elif isinstance(registry, dict): + return registry['id'] + else: + raise ValueError('Unknown registry: ' + str(registry)) + +def get_subscription_id_by_registry(registry): + '''Returns the subscription id of a container registry. + :param RegistryParameters/dict registry: The container registry object + ''' + resource_id = _get_resource_id(registry) + resource_group_keyword = _get_resource_group_keyword(resource_id) + return resource_id[resource_id.index('/subscriptions/') + len('/subscriptions/'): + resource_id.index(resource_group_keyword)] + +def get_resource_group_name_by_registry(registry): + '''Returns the resource group of a container registry. + :param RegistryParameters/dict registry: The container registry object + ''' + resource_id = _get_resource_id(registry) + resource_group_keyword = _get_resource_group_keyword(resource_id) + return resource_id[resource_id.index(resource_group_keyword) + len(resource_group_keyword): + resource_id.index('/providers/')] + +def _get_resource_group_keyword(resource_id): + '''Returns the resource group keyword for parsing resource id. + :param str resource_id: The resource id of a container registry + ''' + if '/resourcegroups/' in resource_id: + return '/resourcegroups/' + elif '/resourceGroups/' in resource_id: + return '/resourceGroups/' + else: + raise ValueError('Invalid resource id: ' + resource_id) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_validators.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_validators.py new file mode 100644 index 00000000000..4c894e551e3 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/_validators.py @@ -0,0 +1,31 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +import re +import uuid + +from azure.cli.core._util import CLIError +from azure.cli.command_modules.storage._factory import storage_client_factory + +def validate_registry_name(namespace): + if namespace.registry_name: + registry_name = namespace.registry_name + if len(registry_name) < 5 or len(registry_name) > 60: + raise CLIError('The registry name must be between 5 and 60 characters.') + + p = re.compile('^([A-Za-z0-9]+)$') + + if not p.match(registry_name): + raise CLIError('The registry name can contain only letters and numbers.') + +def validate_storage_account_name(namespace): + client = storage_client_factory().storage_accounts + + if namespace.storage_account_name is None: + while True: + storage_account_name = str(uuid.uuid4()).replace('-', '')[:24] + if client.check_name_availability(storage_account_name).name_available is True: #pylint: disable=E1101 + namespace.storage_account_name = storage_account_name + break diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/custom.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/custom.py new file mode 100644 index 00000000000..d6cde67c495 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/custom.py @@ -0,0 +1,97 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from azure.cli.core.commands import cli_command +from azure.cli.core._util import CLIError + +from azure.cli.command_modules.acr.mgmt_acr.models import RegistryParameters + +from ._factory import get_registry_service_client + +from ._arm_utils import ( + arm_get_registries_in_subscription, + arm_get_registries_in_resource_group, + arm_get_registry_by_name, + arm_deploy_template +) + +from ._utils import ( + get_registry_by_name, + get_resource_group_name_by_registry +) + +from ._format import output_format + +def acr_list(resource_group_name=None): + '''List container registries. + :param str resource_group: The name of resource group + ''' + if resource_group_name: + return arm_get_registries_in_resource_group(resource_group_name) + else: + return arm_get_registries_in_subscription() + +def acr_create(resource_group_name, registry_name, location, storage_account_name=None): + '''Create a container registry. + :param str resource_group_name: The name of resource group + :param str registry_name: The name of container registry + :param str location: The name of location + :param str storage_account_name: The name of storage account + ''' + return arm_deploy_template(resource_group_name, registry_name, location, storage_account_name) + +def acr_delete(registry_name): + '''Delete a container registry. + :param str registry_name: The name of container registry + ''' + registry = arm_get_registry_by_name(registry_name) + if registry is None: + raise CLIError('No container registry can be found with name: ' + registry_name) + + resource_group_name = get_resource_group_name_by_registry(registry) + return get_registry_service_client().delete(resource_group_name, registry_name) + +def acr_show(registry_name): + '''Get a container registry. + :param str registry_name: The name of container registry + ''' + registry = arm_get_registry_by_name(registry_name) + if registry is None: + raise CLIError('No container registry can be found with name: ' + registry_name) + + resource_group_name = get_resource_group_name_by_registry(registry) + return get_registry_service_client().get_properties(resource_group_name, registry_name) + +def acr_update(registry_name, tags=None): + '''Update a container registry. + :param str registry_name: The name of container registry + ''' + registry = get_registry_by_name(registry_name) + if registry is None: + raise CLIError('No container registry can be found with name: ' + registry_name) + + resource_group_name = get_resource_group_name_by_registry(registry) + newTags = registry.tags + + if isinstance(tags, dict): + if tags: + for key in tags: + if tags[key]: + newTags[key] = tags[key] + elif key in newTags: + del newTags[key] + else: + newTags = {} + + return get_registry_service_client().update( + resource_group_name, registry_name, + RegistryParameters(location=registry.location, + tags=newTags)) + +cli_command('acr list', acr_list, table_transformer=output_format) +cli_command('acr create', acr_create, table_transformer=output_format) +cli_command('acr delete', acr_delete, table_transformer=output_format) +cli_command('acr show', acr_show, table_transformer=output_format) +cli_command('acr update', acr_update, table_transformer=output_format) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/__init__.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/__init__.py new file mode 100644 index 00000000000..ece5117909b --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/__init__.py @@ -0,0 +1,22 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from .container_registry import ContainerRegistry, ContainerRegistryConfiguration +from .version import VERSION + +__all__ = [ + 'ContainerRegistry', + 'ContainerRegistryConfiguration' +] + +__version__ = VERSION + diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/container_registry.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/container_registry.py new file mode 100644 index 00000000000..bb7337b70a3 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/container_registry.py @@ -0,0 +1,84 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.service_client import ServiceClient +from msrest import Configuration, Serializer, Deserializer +from .version import VERSION +from .operations.registries import Registries +from . import models + + +class ContainerRegistryConfiguration(Configuration): + """Configuration for ContainerRegistry + Note that all parameters used to create this instance are saved as instance + attributes. + + :param subscription_id: Gets subscription credentials which uniquely + identify Microsoft Azure subscription.The subscription ID forms part of + the URI for every service call. + :type subscription_id: str + :param api_version: Client Api Version. + :type api_version: str + :param credentials: Subscription credentials which uniquely identify + client subscription. + :type credentials: :mod:`A msrest Authentication + object` + :param str base_url: Service URL + :param str filepath: Existing config + """ + + def __init__( + self, subscription_id, api_version, credentials, base_url=None, filepath=None): + + if subscription_id is None: + raise ValueError("Parameter 'subscription_id' must not be None.") + if not isinstance(subscription_id, str): + raise TypeError("Parameter 'subscription_id' must be str.") + if api_version is None: + raise ValueError("Parameter 'api_version' must not be None.") + if not isinstance(api_version, str): + raise TypeError("Parameter 'api_version' must be str.") + if credentials is None: + raise ValueError("Parameter 'credentials' must not be None.") + if not base_url: + base_url = 'https://management.azure.com' + + super(ContainerRegistryConfiguration, self).__init__(base_url, filepath) + + self.add_user_agent('containerregistry/{}'.format(VERSION)) + + self.subscription_id = subscription_id + self.api_version = api_version + self.credentials = credentials + + +class ContainerRegistry(object): + """ContainerRegistry + + :param config: Configuration for client. + :type config: ContainerRegistryConfiguration + + :ivar registries: Registries operations + :vartype registries: .operations.Registries + """ + + def __init__(self, config): + + self._client = ServiceClient(config.credentials, config) + + client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)} + self._serialize = Serializer() + self._deserialize = Deserializer(client_models) + + self.config = config + self.registries = Registries( + self._client, self.config, self._serialize, self._deserialize) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/credentials.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/credentials.py new file mode 100644 index 00000000000..a3e369522aa --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/credentials.py @@ -0,0 +1,16 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.authentication import ( + BasicAuthentication, + BasicTokenAuthentication, + OAuthTokenAuthentication) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/exceptions.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/exceptions.py new file mode 100644 index 00000000000..63c04fade09 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/exceptions.py @@ -0,0 +1,22 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.exceptions import ( + ClientException, + SerializationError, + DeserializationError, + TokenExpiredError, + ClientRequestError, + AuthenticationError, + HttpOperationError, + ValidationError, +) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/__init__.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/__init__.py new file mode 100644 index 00000000000..b3a5ebe9a3d --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/__init__.py @@ -0,0 +1,23 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from .registry_parameters import RegistryParameters +from .registry_properties import RegistryProperties +from .storage_account_properties import StorageAccountProperties +from .resource_list_registry_parameters import ResourceListRegistryParameters + +__all__ = [ + 'RegistryParameters', + 'RegistryProperties', + 'StorageAccountProperties', + 'ResourceListRegistryParameters', +] diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_parameters.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_parameters.py new file mode 100644 index 00000000000..56f19523d1b --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_parameters.py @@ -0,0 +1,56 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.serialization import Model + + +class RegistryParameters(Model): + """RegistryParameters + + Variables are only populated by the server, and will be ignored when + sending a request. + + :param id: + :type id: str + :param name: + :type name: str + :param location: + :type location: str + :param tags: + :type tags: dict + :ivar type: + :vartype type: str + :param properties: + :type properties: :class:`RegistryProperties + ` + """ + + _validation = { + 'type': {'readonly': True}, + } + + _attribute_map = { + 'id': {'key': 'id', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, + 'location': {'key': 'location', 'type': 'str'}, + 'tags': {'key': 'tags', 'type': '{str}'}, + 'type': {'key': 'type', 'type': 'str'}, + 'properties': {'key': 'properties', 'type': 'RegistryProperties'}, + } + + def __init__(self, id=None, name=None, location=None, tags=None, properties=None): + self.id = id + self.name = name + self.location = location + self.tags = tags + self.type = None + self.properties = properties diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_properties.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_properties.py new file mode 100644 index 00000000000..7ac68462cba --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_properties.py @@ -0,0 +1,45 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.serialization import Model + + +class RegistryProperties(Model): + """RegistryProperties + + :param storage_account: + :type storage_account: :class:`StorageAccountProperties + ` + :param login_server: + :type login_server: str + :param username: + :type username: str + :param key: + :type key: str + :param creation_date: + :type creation_date: datetime + """ + + _attribute_map = { + 'storage_account': {'key': 'storageAccount', 'type': 'StorageAccountProperties'}, + 'login_server': {'key': 'loginServer', 'type': 'str'}, + 'username': {'key': 'username', 'type': 'str'}, + 'key': {'key': 'key', 'type': 'str'}, + 'creation_date': {'key': 'creationDate', 'type': 'iso-8601'}, + } + + def __init__(self, storage_account=None, login_server=None, username=None, key=None, creation_date=None): + self.storage_account = storage_account + self.login_server = login_server + self.username = username + self.key = key + self.creation_date = creation_date diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/resource_list_registry_parameters.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/resource_list_registry_parameters.py new file mode 100644 index 00000000000..39304ec8be8 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/resource_list_registry_parameters.py @@ -0,0 +1,29 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.serialization import Model + + +class ResourceListRegistryParameters(Model): + """ResourceListRegistryParameters + + :param value: + :type value: list of :class:`RegistryParameters + ` + """ + + _attribute_map = { + 'value': {'key': 'value', 'type': '[RegistryParameters]'}, + } + + def __init__(self, value=None): + self.value = value diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/storage_account_properties.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/storage_account_properties.py new file mode 100644 index 00000000000..276196e77f7 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/storage_account_properties.py @@ -0,0 +1,40 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.serialization import Model + + +class StorageAccountProperties(Model): + """StorageAccountProperties + + :param name: + :type name: str + :param access_key: + :type access_key: str + :param end_point_url: + :type end_point_url: str + :param endpoint_suffix: + :type endpoint_suffix: str + """ + + _attribute_map = { + 'name': {'key': 'name', 'type': 'str'}, + 'access_key': {'key': 'accessKey', 'type': 'str'}, + 'end_point_url': {'key': 'endPointUrl', 'type': 'str'}, + 'endpoint_suffix': {'key': 'endpointSuffix', 'type': 'str'}, + } + + def __init__(self, name=None, access_key=None, end_point_url=None, endpoint_suffix=None): + self.name = name + self.access_key = access_key + self.end_point_url = end_point_url + self.endpoint_suffix = endpoint_suffix diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/__init__.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/__init__.py new file mode 100644 index 00000000000..45581021ace --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/__init__.py @@ -0,0 +1,17 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from .registries import Registries + +__all__ = [ + 'Registries', +] diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/registries.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/registries.py new file mode 100644 index 00000000000..ee7d1e4ccd4 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/registries.py @@ -0,0 +1,366 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +from msrest.pipeline import ClientRawResponse +from msrest.exceptions import HttpOperationError + +from .. import models + + +class Registries(object): + """Registries operations. + + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An objec model deserializer. + """ + + def __init__(self, client, config, serializer, deserializer): + + self._client = client + self._serialize = serializer + self._deserialize = deserializer + + self.config = config + + def get_properties( + self, resource_group, registry_name, custom_headers={}, raw=False, **operation_config): + """ + + :param resource_group: + :type resource_group: str + :param registry_name: + :type registry_name: str + :param dict custom_headers: headers that will be added to the request + :param bool raw: returns the direct response alongside the + deserialized response + :param operation_config: :ref:`Operation configuration + overrides`. + :rtype: :class:`RegistryParameters + ` + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/providers/Microsoft.ContainerRegistry/registries/{registryName}' + path_format_arguments = { + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroup': self._serialize.url("resource_group", resource_group, 'str'), + 'registryName': self._serialize.url("registry_name", registry_name, 'str') + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} + query_parameters['api-version'] = self._serialize.query("self.config.api_version", self.config.api_version, 'str') + + # Construct headers + header_parameters = {} + header_parameters['Content-Type'] = 'application/json; charset=utf-8' + if custom_headers: + header_parameters.update(custom_headers) + + # Construct and send request + request = self._client.get(url, query_parameters) + response = self._client.send(request, header_parameters, **operation_config) + + if response.status_code not in [200]: + raise HttpOperationError(self._deserialize, response) + + deserialized = None + + if response.status_code == 200: + deserialized = self._deserialize('RegistryParameters', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized + + def create( + self, resource_group, registry_name, registry_parameters, custom_headers={}, raw=False, **operation_config): + """ + + :param resource_group: + :type resource_group: str + :param registry_name: + :type registry_name: str + :param registry_parameters: + :type registry_parameters: :class:`RegistryParameters + ` + :param dict custom_headers: headers that will be added to the request + :param bool raw: returns the direct response alongside the + deserialized response + :param operation_config: :ref:`Operation configuration + overrides`. + :rtype: object + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/providers/Microsoft.ContainerRegistry/registries/{registryName}' + path_format_arguments = { + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroup': self._serialize.url("resource_group", resource_group, 'str'), + 'registryName': self._serialize.url("registry_name", registry_name, 'str') + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} + query_parameters['api-version'] = self._serialize.query("self.config.api_version", self.config.api_version, 'str') + + # Construct headers + header_parameters = {} + header_parameters['Content-Type'] = 'application/json; charset=utf-8' + if custom_headers: + header_parameters.update(custom_headers) + + # Construct body + body_content = self._serialize.body(registry_parameters, 'RegistryParameters') + + # Construct and send request + request = self._client.put(url, query_parameters) + response = self._client.send( + request, header_parameters, body_content, **operation_config) + + if response.status_code not in [200]: + raise HttpOperationError(self._deserialize, response) + + deserialized = None + + if response.status_code == 200: + deserialized = self._deserialize('object', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized + + def delete( + self, resource_group, registry_name, custom_headers={}, raw=False, **operation_config): + """ + + :param resource_group: + :type resource_group: str + :param registry_name: + :type registry_name: str + :param dict custom_headers: headers that will be added to the request + :param bool raw: returns the direct response alongside the + deserialized response + :param operation_config: :ref:`Operation configuration + overrides`. + :rtype: object + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/providers/Microsoft.ContainerRegistry/registries/{registryName}' + path_format_arguments = { + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroup': self._serialize.url("resource_group", resource_group, 'str'), + 'registryName': self._serialize.url("registry_name", registry_name, 'str') + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} + query_parameters['api-version'] = self._serialize.query("self.config.api_version", self.config.api_version, 'str') + + # Construct headers + header_parameters = {} + header_parameters['Content-Type'] = 'application/json; charset=utf-8' + if custom_headers: + header_parameters.update(custom_headers) + + # Construct and send request + request = self._client.delete(url, query_parameters) + response = self._client.send(request, header_parameters, **operation_config) + + if response.status_code not in [200]: + raise HttpOperationError(self._deserialize, response) + + deserialized = None + + if response.status_code == 200: + deserialized = self._deserialize('object', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized + + def update( + self, resource_group, registry_name, registry_parameters, custom_headers={}, raw=False, **operation_config): + """ + + :param resource_group: + :type resource_group: str + :param registry_name: + :type registry_name: str + :param registry_parameters: + :type registry_parameters: :class:`RegistryParameters + ` + :param dict custom_headers: headers that will be added to the request + :param bool raw: returns the direct response alongside the + deserialized response + :param operation_config: :ref:`Operation configuration + overrides`. + :rtype: object + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/providers/Microsoft.ContainerRegistry/registries/{registryName}' + path_format_arguments = { + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroup': self._serialize.url("resource_group", resource_group, 'str'), + 'registryName': self._serialize.url("registry_name", registry_name, 'str') + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} + query_parameters['api-version'] = self._serialize.query("self.config.api_version", self.config.api_version, 'str') + + # Construct headers + header_parameters = {} + header_parameters['Content-Type'] = 'application/json; charset=utf-8' + if custom_headers: + header_parameters.update(custom_headers) + + # Construct body + body_content = self._serialize.body(registry_parameters, 'RegistryParameters') + + # Construct and send request + request = self._client.patch(url, query_parameters) + response = self._client.send( + request, header_parameters, body_content, **operation_config) + + if response.status_code not in [200]: + raise HttpOperationError(self._deserialize, response) + + deserialized = None + + if response.status_code == 200: + deserialized = self._deserialize('object', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized + + def list_by_resource_group( + self, resource_group, custom_headers={}, raw=False, **operation_config): + """ + + :param resource_group: + :type resource_group: str + :param dict custom_headers: headers that will be added to the request + :param bool raw: returns the direct response alongside the + deserialized response + :param operation_config: :ref:`Operation configuration + overrides`. + :rtype: :class:`ResourceListRegistryParameters + ` + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/providers/Microsoft.ContainerRegistry/registries' + path_format_arguments = { + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str'), + 'resourceGroup': self._serialize.url("resource_group", resource_group, 'str') + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} + query_parameters['api-version'] = self._serialize.query("self.config.api_version", self.config.api_version, 'str') + + # Construct headers + header_parameters = {} + header_parameters['Content-Type'] = 'application/json; charset=utf-8' + if custom_headers: + header_parameters.update(custom_headers) + + # Construct and send request + request = self._client.get(url, query_parameters) + response = self._client.send(request, header_parameters, **operation_config) + + if response.status_code not in [200]: + raise HttpOperationError(self._deserialize, response) + + deserialized = None + + if response.status_code == 200: + deserialized = self._deserialize('ResourceListRegistryParameters', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized + + def list( + self, custom_headers={}, raw=False, **operation_config): + """ + + :param dict custom_headers: headers that will be added to the request + :param bool raw: returns the direct response alongside the + deserialized response + :param operation_config: :ref:`Operation configuration + overrides`. + :rtype: :class:`ResourceListRegistryParameters + ` + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/providers/Microsoft.ContainerRegistry/registries' + path_format_arguments = { + 'subscriptionId': self._serialize.url("self.config.subscription_id", self.config.subscription_id, 'str') + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} + query_parameters['api-version'] = self._serialize.query("self.config.api_version", self.config.api_version, 'str') + + # Construct headers + header_parameters = {} + header_parameters['Content-Type'] = 'application/json; charset=utf-8' + if custom_headers: + header_parameters.update(custom_headers) + + # Construct and send request + request = self._client.get(url, query_parameters) + response = self._client.send(request, header_parameters, **operation_config) + + if response.status_code not in [200]: + raise HttpOperationError(self._deserialize, response) + + deserialized = None + + if response.status_code == 200: + deserialized = self._deserialize('ResourceListRegistryParameters', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/version.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/version.py new file mode 100644 index 00000000000..0a50b7028eb --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/version.py @@ -0,0 +1,14 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- +#pylint: skip-file +# coding=utf-8 +# -------------------------------------------------------------------------- +# Code generated by Microsoft (R) AutoRest Code Generator 0.16.0.0 +# Changes may cause incorrect behavior and will be lost if the code is +# regenerated. +# -------------------------------------------------------------------------- + +VERSION = "2016-06-27-preview" + diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/repository.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/repository.py new file mode 100644 index 00000000000..ff801e0f0da --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/repository.py @@ -0,0 +1,77 @@ +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +import requests + +from azure.cli.core.commands import cli_command +from azure.cli.core._util import CLIError + +from ._utils import get_registry_by_name + +def _obtain_data_from_registry(login_server, path, resultIndex, username, password): + registryEndpoint = 'https://' + login_server + resultList = [] + executeNextHttpCall = True + + while executeNextHttpCall: + executeNextHttpCall = False + response = requests.get( + registryEndpoint + path, + auth=requests.auth.HTTPBasicAuth( + username, + password + ) + ) + + if response.status_code == 200: + resultList += response.json()[resultIndex] + if 'link' in response.headers and response.headers['link']: + linkHeader = response.headers['link'] + # The registry is telling us there's more items in the list, + # and another call is needed. The link header looks something + # like `Link: ; rel="next"` + # we should follow the next path indicated in the link header + path = linkHeader[(linkHeader.index('<')+1):linkHeader.index('>')] + executeNextHttpCall = True + else: + response.raise_for_status() + + return {resultIndex: resultList} + +def _validate_user_credentials(login_server, path, resultIndex, username=None, password=None): + if username and password: + return _obtain_data_from_registry(login_server, path, resultIndex, username, password) + + try: + registry_name = login_server[0:login_server.index('.')] + registry = get_registry_by_name(registry_name) + username = registry.properties.username + password = registry.properties.key + return _obtain_data_from_registry(login_server, path, resultIndex, username, password) + except: #pylint: disable=W0702 + raise CLIError('No container registry can be found with name: ' + registry_name + + '\nPlease switch subscription or enter username/password') + +def acr_repository_list(login_server, username=None, password=None): + '''List repositories in a given container registry. + :param str login_server: The URL of a container registry login server + :param str username: The username used to log into the container registry + :param str password: The password used to log into the container registry + ''' + path = '/v2/_catalog' + return _validate_user_credentials(login_server, path, 'repositories', username, password) + +def acr_repository_show_tags(login_server, repository, username=None, password=None): + '''Show tags of a given repository in a given container registry. + :param str login_server: The URL of a container registry login server + :param str repository: The repository to obtain tags from + :param str username: The username used to log into the container registry + :param str password: The password used to log into the container registry + ''' + path = '/v2/' + repository + '/tags/list' + return _validate_user_credentials(login_server, path, 'tags', username, password) + +cli_command('acr repository list', acr_repository_list) +cli_command('acr repository show-tags', acr_repository_show_tags) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.json b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.json new file mode 100644 index 00000000000..c26aa404346 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.json @@ -0,0 +1,77 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "registryName": { + "type": "string", + "metadata": { + "description": "Name of the registry service" + } + }, + "registryLocation": { + "type": "string", + "metadata": { + "description": "Location of the registry service" + } + }, + "registryApiVersion": { + "type": "string", + "metadata": { + "description": "Api version of the registry service" + } + }, + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Name of the storage account" + } + }, + "storageAccountApiVersion": { + "type": "string", + "metadata": { + "description": "Api version of the storage account" + } + } + }, + "resources": [ + { + "comments": "# Storage Account", + "name": "[parameters('storageAccountName')]", + "type": "Microsoft.Storage/storageAccounts", + "location": "[parameters('registryLocation')]", + "apiVersion": "[parameters('storageAccountApiVersion')]", + "properties": { + "accountType": "Standard_LRS" + } + }, + { + "comments": "# Registry", + "name": "[parameters('registryName')]", + "type": "Microsoft.ContainerRegistry/registries", + "location": "[parameters('registryLocation')]", + "apiVersion": "[parameters('registryApiVersion')]", + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]" + ], + "properties": { + "storageAccount": { + "name": "[parameters('storageAccountName')]", + "accessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), parameters('storageAccountApiVersion')).key1]", + "endPointUrl": "[reference(concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName')), parameters('storageAccountApiVersion')).primaryEndpoints.blob]" + } + } + }, + { + "type": "Microsoft.ContainerRegistry/registries/providers/links", + "apiVersion": "2015-01-01", + "name": "[concat(parameters('registryName'),'/Microsoft.Resources/RegistryToStorage')]", + "dependsOn": [ + "[parameters('registryName')]" + ], + "properties": { + "targetId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]", + "notes": "This registry uses the storage account to store registry information." + } + } + ] +} \ No newline at end of file diff --git a/src/command_modules/azure-cli-acr/requirements.txt b/src/command_modules/azure-cli-acr/requirements.txt new file mode 100644 index 00000000000..525837d8ad6 --- /dev/null +++ b/src/command_modules/azure-cli-acr/requirements.txt @@ -0,0 +1 @@ +azure==2.0.0rc6 diff --git a/src/command_modules/azure-cli-acr/setup.py b/src/command_modules/azure-cli-acr/setup.py new file mode 100644 index 00000000000..ecb8e31cbde --- /dev/null +++ b/src/command_modules/azure-cli-acr/setup.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python + +#--------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +#--------------------------------------------------------------------------------------------- + +from codecs import open +from setuptools import setup + +VERSION = '0.0.5' + +CLASSIFIERS = [ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Developers', + 'Intended Audience :: System Administrators', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'License :: OSI Approved :: MIT License', +] + +DEPENDENCIES = [ + 'azure==2.0.0rc6', +] + +with open('README.rst', 'r', encoding='utf-8') as f: + README = f.read() + +setup( + name='azure-cli-acr', + version=VERSION, + description='Microsoft Azure Command-Line Tools', + long_description=README, + license='MIT', + author='Microsoft Corporation', + author_email='azpycli@microsoft.com', + url='https://github.com/Azure/azure-cli', + classifiers=CLASSIFIERS, + namespace_packages = [ + 'azure', + 'azure.cli', + 'azure.cli.command_modules', + ], + packages=[ + 'azure.cli.command_modules.acr', + 'azure.cli.command_modules.acr.mgmt_acr', + 'azure.cli.command_modules.acr.mgmt_acr.models', + 'azure.cli.command_modules.acr.mgmt_acr.operations', + ], + install_requires=DEPENDENCIES, + package_data={'azure.cli.command_modules.acr': ['template.json']}, +)