diff --git a/src/command_modules/azure-cli-acr/README.rst b/src/command_modules/azure-cli-acr/README.rst index cb6c72a1349..09843a0a0f2 100644 --- a/src/command_modules/azure-cli-acr/README.rst +++ b/src/command_modules/azure-cli-acr/README.rst @@ -9,7 +9,9 @@ Commands to manage Azure container registries az acr: Commands to manage Azure container registries. Subgroups: - repository + credential: Manage admin user credential for Azure container registries. + repository: Manage repositories for Azure container registries. + storage : Manage storage accounts for Azure container registries. Commands: create : Create a container registry. @@ -29,13 +31,25 @@ Create a container registry --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. + --app-id : The app id of an existing service principal. If provided, no + --new-sp or -p should be specified. + --disable-admin : Disable admin user. + --new-sp : Create a new service principal. If provided, no --app-id should + be specified. Optional: Use -p to specify a password. + --password -p : Password used to log into a container registry. + --role -r : Name of role. (Owner, Contributor, Reader). Default: Reader. + --storage-account-name -s : Name of new or existing storage account. If not provided, a + random storage account name will be generated. 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 + az acr create -n myRegistry -g myResourceGroup -l southus + Create a container registry with a specified new/existing storage account + az acr create -n myRegistry -g myResourceGroup -l southus -s myStorageAccount + Create a container registry with a new service principal + az acr create -n myRegistry -g myResourceGroup -l southus --new-sp -p myPassword -r Owner + Create a container registry with an existing service principal + az acr create -n myRegistry -g myResourceGroup -l southus --app-id myAppId -r Owner Delete a container registry ------------- @@ -46,6 +60,7 @@ Delete a container registry Arguments --name -n [Required]: Name of container registry. + --resource-group -g : Name of resource group. List container registries ------------- @@ -61,7 +76,7 @@ List container registries 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 + az acr list -g myResourceGroup -o table Get a container registry ------------- @@ -72,6 +87,7 @@ Get a container registry Arguments --name -n [Required]: Name of container registry. + --resource-group -g : Name of resource group. Update a container registry ------------- @@ -82,11 +98,50 @@ 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. + --app-id : The app id of an existing service principal. If provided, no --new-sp or + -p should be specified. + --disable-admin : Disable admin user. + --enable-admin : Enable admin user. + --new-sp : Create a new service principal. If provided, no --app-id should be + specified. Optional: Use -p to specify a password. + --password -p : Password used to log into a container registry. + --resource-group -g : Name of resource group. + --role -r : Name of role. (Owner, Contributor, Reader). Default: Reader. + --tags : Space separated tags in 'key[=value]' format. Use "" to clear existing + tags. + --tenant-id -t : Tenant id for service principal login. Warning: Changing tenant id will + invalidate assigned access of existing service principals. + Examples - Update tags of a container registry and show result in a table - az acr update -n --tags key1=value1;key2=value2 -o table + Update tags of a container registry + az acr update -n myRegistry --tags key1=value1;key2=value2 + Update a container registry with a new service principal + az acr update -n myRegistry --new-sp -p myPassword -r Owner + Update a container registry with an existing service principal + az acr update -n myRegistry --app-id myAppId -r Owner + +Update storage account for a container registry +------------- +:: + + Command + az acr storage update: Update storage account for a container registry. + + Arguments + --name -n [Required]: Name of container registry. + --storage-account-name -s [Required]: Name of new or existing storage account. + --resource-group -g : Name of resource group. + +Get admin username and password for a container registry +------------- +:: + + Command + az acr credential show: Get admin username and password for a container registry. + + Arguments + --name -n [Required]: Name of container registry. + --resource-group -g : Name of resource group. List repositories in a given container registry ------------- @@ -96,16 +151,15 @@ List repositories in a given container registry 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. + --name -n [Required]: Name of container registry. + --password -p : Password used to log into a container registry. + --username -u : Username used to log into a 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 if admin user is enabled + az acr repository list -n myRegistry List repositories in a given container registry with credentials - az acr repository list --login-server --username --password - + az acr repository list -n myRegistry -u myUsername -p myPassword Show tags of a given repository in a given container registry ------------- @@ -115,14 +169,14 @@ Show tags of a given repository in a given container registry 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. + --name -n [Required]: Name of container registry. + --repository [Required]: The repository to obtain tags from. + --password -p : Password used to log into a container registry. + --username -u : Username used to log into a 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 if admin user is enabled + az acr repository show-tags -n myRegistry --repository myRepository Show tags of a given repository in a given container registry with credentials - az acr repository show-tags --login-server --repository - --username --password + az acr repository show-tags -n myRegistry --repository myRepository -u myUsername -p + myPassword 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 index 5673500debc..231e89fa929 100644 --- 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 @@ -8,4 +8,6 @@ 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.storage +import azure.cli.command_modules.acr.credential 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 index 9393bb1d056..5fc7af7b05e 100644 --- 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 @@ -3,34 +3,37 @@ # 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 azure.cli.core._util import CLIError +from azure.cli.core.commands.parameters import ( + get_resources_in_subscription, + get_resources_in_resource_group +) + +from azure.cli.command_modules.acr.mgmt_acr.models import Registry from ._constants import ( RESOURCE_PROVIDER, RESOURCE_TYPE ) -from ._factory import get_arm_service_client - -from azure.cli.command_modules.acr.mgmt_acr import VERSION +from ._factory import ( + get_arm_service_client, + get_storage_service_client, + get_acr_api_version +) +from ._utils import get_resource_group_name_by_resource_id 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] + result = get_resources_in_subscription(RESOURCE_TYPE) + return [Registry(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] + result = get_resources_in_resource_group(resource_group_name, RESOURCE_TYPE) + return [Registry(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. @@ -44,56 +47,131 @@ def arm_get_registry_by_name(registry_name): 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. + raise CLIError( + 'More than one container registries are found with name: {}'.format(registry_name)) + +def arm_deploy_template(resource_group_name, + registry_name, + location, + storage_account_name, + admin_user_enabled): + '''Deploys ARM template to create/update 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 + :param bool admin_user_enabled: Enable admin user ''' 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') + parameters = _parameters(registry_name, location, storage_account_name, admin_user_enabled) + storage_account_resource_group, _ = _arm_get_storage_account(storage_account_name) + + if storage_account_resource_group: + file_path = os.path.join(os.path.dirname(__file__), 'template.existing.json') + parameters['storageAccountResourceGroup'] = {'value': storage_account_resource_group} + else: + file_path = os.path.join(os.path.dirname(__file__), 'template.new.json') + parameters['storageAccountType'] = {'value': 'Standard_LRS'} + 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) + return _arm_deploy_template( + get_arm_service_client().deployments, resource_group_name, properties) -def _arm_deploy_template(resource_group_name, properties, index=0): +def _arm_deploy_template(deployments_client, + resource_group_name, + properties, + index=0): '''Deploys ARM template to create a container registry. + :param obj deployments_client: ARM deployments service client :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 + elif index > 9: # Just a number to avoid infinite loops + raise CLIError( + 'The resource group {} has too many deployments'.format(resource_group_name)) 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) + deployments_client.validate( + resource_group_name, deployment_name, properties) + return deployments_client.create_or_update( + resource_group_name, deployment_name, properties) except: #pylint: disable=W0702 - return _arm_deploy_template(resource_group_name, properties, index + 1) + return _arm_deploy_template( + deployments_client, resource_group_name, properties, index + 1) -def _parameters(registry_name, location, storage_account_name): +def _parameters(registry_name, + location, + storage_account_name, + admin_user_enabled): '''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 + :param bool admin_user_enabled: Enable admin user ''' parameters = { 'registryName': {'value': registry_name}, 'registryLocation': {'value': location}, - 'registryApiVersion': {'value': VERSION}, + 'registryApiVersion': {'value': get_acr_api_version()}, 'storageAccountName': {'value': storage_account_name}, - 'storageAccountApiVersion': {'value': '2015-05-01-preview'} + 'adminUserEnabled': {'value': admin_user_enabled} } return parameters + +def _arm_get_storage_account(storage_account_name): + '''Returns the dict of tags in the storage account. + :param str storage_account_name: The name of storage account + ''' + result = get_resources_in_subscription('Microsoft.Storage/storageAccounts') + elements = [item for item in result if item.name.lower() == storage_account_name.lower()] + + if len(elements) == 0: + return None, None + elif len(elements) == 1: + storage_account_resource_group = get_resource_group_name_by_resource_id(elements[0].id) + return storage_account_resource_group, elements[0].tags + else: + raise CLIError( + 'More than one storage accounts are found with name: {}'.format(storage_account_name)) + +def add_tag_storage_account(storage_account_name, registry_name): + '''Add a new tag (key, value) to the storage account. + :param str storage_account_name: The name of storage account + :param str registry_name: The name of container registry + ''' + from azure.mgmt.storage.models import StorageAccountUpdateParameters + storage_account_resource_group, tags = _arm_get_storage_account(storage_account_name) + + tags[registry_name.lower()] = 'acr' + client = get_storage_service_client().storage_accounts + + return client.update(storage_account_resource_group, + storage_account_name, + StorageAccountUpdateParameters(tags=tags)) + +def delete_tag_storage_account(storage_account_name, registry_name): + '''Delete a tag (key, value) from the storage account, if value matches registry_name. + :param str storage_account_name: The name of storage account + :param str registry_name: The name of container registry + ''' + from azure.mgmt.storage.models import StorageAccountUpdateParameters + storage_account_resource_group, tags = _arm_get_storage_account(storage_account_name) + registry_name = registry_name.lower() + + if registry_name in tags and tags[registry_name] == 'acr': + del tags[registry_name] + client = get_storage_service_client().storage_accounts + + return client.update(storage_account_resource_group, + storage_account_name, + StorageAccountUpdateParameters(tags=tags)) 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 index 89b8403d43d..58fc04288a2 100644 --- 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 @@ -5,3 +5,11 @@ RESOURCE_PROVIDER = 'Microsoft.ContainerRegistry' RESOURCE_TYPE = RESOURCE_PROVIDER + '/registries' + +ALLOWED_ROLES = [ + 'owner', + 'contributor', + 'reader' +] + +DEFAULT_ROLE = 'Reader' 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 index d33e927cd65..4bb8fc679ce 100644 --- 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 @@ -6,6 +6,8 @@ from azure.cli.core._profile import Profile from azure.cli.core._config import az_config from azure.mgmt.resource.resources import ResourceManagementClient +from azure.mgmt.storage import StorageManagementClient +from azure.graphrbac import GraphRbacManagementClient from azure.cli.core.commands.client_factory import ( configure_common_settings, @@ -26,21 +28,39 @@ def get_arm_service_client(): ''' return get_mgmt_service_client(ResourceManagementClient) -def get_registry_service_client(): +def get_storage_service_client(): + '''Returns the client for managing storage accounts. + ''' + return get_mgmt_service_client(StorageManagementClient) + +def get_acr_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) + config = ContainerRegistryConfiguration(subscription_id, get_acr_api_version(), credentials) + client = ContainerRegistry(config) - api_version = customized_api_version or VERSION + configure_common_settings(client) - config = ContainerRegistryConfiguration(subscription_id, api_version, credentials) - client = ContainerRegistry(config) + return client + +def get_graph_mgmt_client(): + '''Returns the client for graph api. + ''' + profile = Profile() + credentials, _, tenant_id = profile.get_login_credentials(True) + client = GraphRbacManagementClient(credentials, tenant_id) configure_common_settings(client) - return client.registries + return client + +def get_acr_api_version(): + '''Returns the api version for container registry + ''' + customized_api_version = az_config.get('acr', 'apiversion', None) + if customized_api_version: + logger.warning('Customized api-version is used: %s', customized_api_version) + return customized_api_version or VERSION 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 index 5420451c7f8..b92402bed0e 100644 --- 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 @@ -5,8 +5,7 @@ from collections import OrderedDict -from ._constants import RESOURCE_TYPE -from ._utils import get_resource_group_name_by_registry +from ._utils import get_resource_group_name_by_resource_id _basic_map = { 'name': 'NAME', @@ -17,19 +16,17 @@ _properties_map = { 'loginServer': 'LOGIN SERVER', - 'username': 'USERNAME', - 'key': 'PASSWORD', 'creationDate': 'CREATION DATE', + 'adminUserEnabled': 'ADMIN USER ENABLED' } _storage_account_map = { 'name': 'STORAGE ACCOUNT NAME' } -_parameters_map = { - 'registryName': 'NAME', - 'location': 'LOCATION', - 'storageAccountName': 'STORAGE ACCOUNT NAME' +_admin_user_map = { + 'userName': 'USERNAME', + 'passWord': 'PASSWORD' } _order_map = { @@ -38,53 +35,19 @@ 'LOCATION': 3, 'TAGS': 4, 'LOGIN SERVER': 11, - 'USERNAME': 12, - 'PASSWORD': 13, - 'CREATION DATE': 14, - 'STORAGE ACCOUNT NAME': 21 + 'CREATION DATE': 12, + 'ADMIN USER ENABLED': 13, + 'STORAGE ACCOUNT NAME': 21, + 'USERNAME': 31, + 'PASSWORD': 32 } 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) + :param list/dict result: The (list of) container registry object(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]])) + return [_format_registry(item) for item in obj_list] def _format_registry(item): '''Returns an ordered dictionary of the container registry. @@ -92,8 +55,8 @@ def _format_registry(item): ''' 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: + if 'id' in item and item['id']: + resource_group_name = get_resource_group_name_by_resource_id(item['id']) basic_info['RESOURCE GROUP'] = resource_group_name properties_info = {} @@ -108,8 +71,12 @@ def _format_registry(item): storage_account_info = {_storage_account_map[key]: str(storage_account[key]) for key in storage_account if key in _storage_account_map} + admin_user_info = {_admin_user_map[key]: str(item[key]) + for key in item if key in _admin_user_map} + all_info = basic_info.copy() all_info.update(properties_info) all_info.update(storage_account_info) + all_info.update(admin_user_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 index 135690a0eb1..4a69ea0e94c 100644 --- 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 @@ -12,6 +12,21 @@ short-summary: Commands to manage Azure container registries. """ +helps['acr storage'] = """ + type: group + short-summary: Manage storage accounts for Azure container registries. + """ + +helps['acr credential'] = """ + type: group + short-summary: Manage admin user credential for Azure container registries. + """ + +helps['acr repository'] = """ + type: group + short-summary: Manage repositories for Azure container registries. + """ + helps['acr list'] = """ type: command examples: @@ -20,7 +35,7 @@ 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 + az acr list -g myResourceGroup -o table """ helps['acr create'] = """ @@ -28,38 +43,50 @@ 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 + az acr create -n myRegistry -g myResourceGroup -l southus + - name: Create a container registry with a specified new/existing storage account + text: + az acr create -n myRegistry -g myResourceGroup -l southus -s myStorageAccount + - name: Create a container registry with a new service principal text: - az acr create -n -g -l -s + az acr create -n myRegistry -g myResourceGroup -l southus --new-sp -p myPassword -r Owner + - name: Create a container registry with an existing service principal + text: + az acr create -n myRegistry -g myResourceGroup -l southus --app-id myAppId -r Owner """ helps['acr update'] = """ type: command examples: - - name: Update tags of a container registry and show result in a table + - name: Update tags of a container registry + text: + az acr update -n myRegistry --tags key1=value1;key2=value2 + - name: Update a container registry with a new service principal + text: + az acr update -n myRegistry --new-sp -p myPassword -r Owner + - name: Update a container registry with an existing service principal text: - az acr update -n --tags key1=value1;key2=value2 -o table + az acr update -n myRegistry --app-id myAppId -r Owner """ helps['acr repository list'] = """ type: command examples: - - name: List repositories in a given container registry under the current subscription + - name: List repositories in a given container registry if admin user is enabled text: - az acr repository list --login-server + az acr repository list -n myRegistry - name: List repositories in a given container registry with credentials text: - az acr repository list --login-server --username --password + az acr repository list -n myRegistry -u myUsername -p myPassword """ helps['acr repository show-tags'] = """ type: command examples: - - name: Show tags of a given repository in a given container registry under the current subscription + - name: Show tags of a given repository in a given container registry if admin user is enabled text: - az acr repository show-tags --login-server --repository + az acr repository show-tags -n myRegistry --repository myRepository - 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 + az acr repository show-tags -n myRegistry --repository myRepository -u myUsername -p myPassword """ 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 index 42ab394ab28..beca8846d5b 100644 --- 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 @@ -3,11 +3,7 @@ # 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 import register_cli_argument from azure.cli.core.commands.parameters import ( resource_group_name_type, location_type, @@ -17,26 +13,65 @@ from ._constants import RESOURCE_TYPE from ._validators import ( + validate_registry_name_create, validate_registry_name, - validate_storage_account_name + validate_storage_account_name, + validate_resource_group_name, + validate_password, + validate_role ) -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', + 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', 'resource_group_name', resource_group_name_type) +register_cli_argument('acr', 'location', location_type) +register_cli_argument('acr', 'tags', tags_type) -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.', + help='Name of new or existing 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) +register_cli_argument('acr', 'username', + options_list=('--username', '-u'), + help='Username used to log into a container registry') + +register_cli_argument('acr', 'password', + options_list=('--password', '-p'), + help='Password used to log into a container registry') + +register_cli_argument('acr', 'role', + options_list=('--role', '-r'), + help='Name of role. (Owner, Contributor, Reader)', + validator=validate_role) + +register_cli_argument('acr', 'new_sp', + help='Create a new service principal. ' +\ + 'If provided, no --app-id should be specified. ' +\ + 'Optional: Use -p to specify a password.') + +register_cli_argument('acr', 'app_id', + help='The app id of an existing service principal. ' +\ + 'If provided, no --new-sp or -p should be specified.') + +register_cli_argument('acr', 'tenant_id', + options_list=('--tenant-id', '-t'), + help='Tenant id for service principal login. ' +\ + 'Warning: Changing tenant id will invalidate ' +\ + 'assigned access of existing service principals.') + +register_cli_argument('acr create', 'registry_name', completer=None, + validator=validate_registry_name_create) +register_cli_argument('acr create', 'storage_account_name', + help='Name of new or existing storage account. ' +\ + 'If not provided, a random storage account name will be generated.') +register_cli_argument('acr create', 'password', validator=validate_password) +register_cli_argument('acr update', 'password', validator=validate_password) +register_cli_argument('acr create', 'resource_group_name', + validator=validate_resource_group_name) 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 index 6beceaf3a26..9f5b3606d23 100644 --- 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 @@ -3,20 +3,30 @@ # 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 +import uuid +import datetime -from ._factory import get_registry_service_client +from azure.graphrbac.models import ServicePrincipalCreateParameters +from azure.cli.core._util import CLIError +from azure.cli.command_modules.role.custom import create_application + +from ._factory import ( + get_acr_service_client, + get_graph_mgmt_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 + client = get_acr_service_client().registries + return client.list().value #pylint: disable=E1101 -def _get_registries_in_resource_group(resource_group): +def _get_registries_in_resource_group(resource_group_name): '''Returns the list of container registries in the resource group. - :param str resource_group: The name of resource group + :param str resource_group_name: The name of resource group ''' - return get_registry_service_client().list_by_resource_group(resource_group).value #pylint: disable=E1101 + client = get_acr_service_client().registries + return client.list_by_resource_group(resource_group_name).value #pylint: disable=E1101 def get_registry_by_name(registry_name): '''Returns the container registry that matches the registry name. @@ -32,42 +42,43 @@ def get_registry_by_name(registry_name): 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 +def get_resource_group_name_by_resource_id(resource_id): + '''Returns the resource group name from parsing the resource id. + :param str resource_id: The resource id ''' - 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) + resource_id = resource_id.lower() + resource_group_keyword = '/resourcegroups/' 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 +def create_service_principal(registry_name, password=None): + '''Creates an application and a service principal. + :param str registry_name: The name of container registry + :param str password: The password for container registry login ''' - if '/resourcegroups/' in resource_id: - return '/resourcegroups/' - elif '/resourceGroups/' in resource_id: - return '/resourceGroups/' - else: - raise ValueError('Invalid resource id: ' + resource_id) + client = get_graph_mgmt_client() + + start_date = datetime.datetime.now() + app_display_name = registry_name + '-' + start_date.strftime('%Y%m%d%H%M%S') + app_uri = 'http://' + app_display_name # just a valid uri, no need to exist + password_creds = password or str(uuid.uuid4()) + + application = create_application(client.applications, + display_name=app_display_name, + homepage=app_uri, + identifier_uris=[app_uri], + password=password_creds) + + app_id = application.app_id #pylint: disable=E1101 + service_principal = client.service_principals.create( + ServicePrincipalCreateParameters(app_id, True), raw=True) + session_key = service_principal.response.headers._store['ocp-aad-session-key'][1] #pylint: disable=W0212 + + return (app_id, + password_creds, + session_key) + +def registry_not_found(registry_name): + raise CLIError( + 'ERROR: Registry {} cannot be found in the current subscription.'\ + .format(registry_name)) 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 index 4c894e551e3..bb9bf8a5c5f 100644 --- 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 @@ -6,9 +6,22 @@ import re import uuid +from azure.mgmt.resource.resources.models.resource_group import ResourceGroup + +from azure.cli.command_modules.acr.mgmt_acr.models import RegistryNameCheckRequest + from azure.cli.core._util import CLIError from azure.cli.command_modules.storage._factory import storage_client_factory +from ._constants import ( + RESOURCE_TYPE, + ALLOWED_ROLES +) +from ._factory import ( + get_acr_service_client, + get_arm_service_client +) + def validate_registry_name(namespace): if namespace.registry_name: registry_name = namespace.registry_name @@ -20,6 +33,20 @@ def validate_registry_name(namespace): if not p.match(registry_name): raise CLIError('The registry name can contain only letters and numbers.') +def validate_registry_name_create(namespace): + if namespace.registry_name: + client = get_acr_service_client() + + result = client.operation.check_name_availability( + RegistryNameCheckRequest( + namespace.registry_name, + RESOURCE_TYPE + ) + ) + + if not result.name_available: #pylint: disable=E1101 + raise CLIError(result.message) #pylint: disable=E1101 + def validate_storage_account_name(namespace): client = storage_client_factory().storage_accounts @@ -29,3 +56,20 @@ def validate_storage_account_name(namespace): if client.check_name_availability(storage_account_name).name_available is True: #pylint: disable=E1101 namespace.storage_account_name = storage_account_name break + +def validate_resource_group_name(namespace): + client = get_arm_service_client() + + if namespace.resource_group_name: + if not client.resource_groups.check_existence(namespace.resource_group_name): + parameters = ResourceGroup(location=namespace.location) + client.resource_groups.create_or_update(namespace.resource_group_name, parameters) + +def validate_password(namespace): + if namespace.password and not namespace.new_sp: + raise CLIError('--password has to be used with --new-sp.') + +def validate_role(namespace): + if namespace.role and not namespace.role.lower() in ALLOWED_ROLES: + raise CLIError('The role {} is not allowed. Allowed roles (Owner, Contributor, Reader).'\ + .format(namespace.role)) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/credential.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/credential.py new file mode 100644 index 00000000000..46dedf23226 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/credential.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 cli_command +from azure.cli.core._util import CLIError + +from ._factory import get_acr_service_client + +from ._utils import ( + get_registry_by_name, + get_resource_group_name_by_resource_id, + registry_not_found +) + +from ._format import output_format + +import azure.cli.core._logging as _logging +logger = _logging.get_az_logger(__name__) + +def acr_credential_show(registry_name, resource_group_name=None): + '''Get admin username and password for a container registry. + :param str registry_name: The name of container registry + :param str resource_group_name: The name of resource group + ''' + registry = get_registry_by_name(registry_name) + if registry is None: + registry_not_found(registry_name) + + if resource_group_name is None: + resource_group_name = get_resource_group_name_by_resource_id(registry.id) + + client = get_acr_service_client().registries + if registry.properties.admin_user_enabled: + return client.get_credentials(resource_group_name, registry_name) + else: + raise CLIError( + 'Admin user is not enabled for the container registry with name: {}'\ + .format(registry_name)) + +cli_command('acr credential show', acr_credential_show, table_transformer=output_format) 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 index d6cde67c495..bd090a64557 100644 --- 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 @@ -5,76 +5,202 @@ from azure.cli.core.commands import cli_command from azure.cli.core._util import CLIError +from azure.cli.command_modules.role.custom import _create_role_assignment -from azure.cli.command_modules.acr.mgmt_acr.models import RegistryParameters - -from ._factory import get_registry_service_client +from azure.cli.command_modules.acr.mgmt_acr.models import ( + RegistryUpdateParameters, + RegistryPropertiesCreateParameters +) +from ._constants import ( + DEFAULT_ROLE +) +from ._factory import get_acr_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 + arm_deploy_template, + add_tag_storage_account, + delete_tag_storage_account ) - from ._utils import ( get_registry_by_name, - get_resource_group_name_by_registry + get_resource_group_name_by_resource_id, + create_service_principal, + registry_not_found ) from ._format import output_format +import azure.cli.core._logging as _logging +logger = _logging.get_az_logger(__name__) + def acr_list(resource_group_name=None): '''List container registries. - :param str resource_group: The name of resource group + :param str resource_group_name: 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): +def acr_create(registry_name, #pylint: disable=too-many-arguments + resource_group_name, + location, + storage_account_name=None, + new_sp=False, + app_id=None, + password=None, + role=DEFAULT_ROLE, + disable_admin=False): '''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 resource_group_name: The name of resource group :param str location: The name of location :param str storage_account_name: The name of storage account + :param bool new_sp: Create a new service principal + :param str app_id: The app id of an existing service principal + :param str password: The password used to log into the container registry + :param str role: The name of role + :param bool disable_admin: Disable admin user ''' - return arm_deploy_template(resource_group_name, registry_name, location, storage_account_name) - -def acr_delete(registry_name): + if new_sp and app_id: + raise CLIError('new-service-principal and app-id should not be specified together.') + + session_key = None + # Create a service principal + if new_sp: + (app_id, + password, + session_key) = create_service_principal(registry_name, password) + + # Create a container registry + arm_deploy_template(resource_group_name, + registry_name, + location, + storage_account_name, + not disable_admin).wait() # wait for the template deployment to finish + + client = get_acr_service_client().registries + registry = client.get_properties(resource_group_name, registry_name) + add_tag_storage_account(storage_account_name, registry_name) + + # Create role assignment + if app_id: + _create_role_assignment(role, + app_id, + scope=registry.id, #pylint: disable=E1101 + ocp_aad_session_key=session_key) + logger.warning("Service principal has been configured.") + logger.warning(" id(client_id): " + app_id) + if password: + logger.warning(" password(client_secret): " + password) + + return registry + +def acr_delete(registry_name, resource_group_name=None): '''Delete a container registry. :param str registry_name: The name of container registry + :param str resource_group_name: The name of resource group ''' registry = arm_get_registry_by_name(registry_name) if registry is None: - raise CLIError('No container registry can be found with name: ' + registry_name) + registry_not_found(registry_name) + + if resource_group_name is None: + resource_group_name = get_resource_group_name_by_resource_id(registry.id) - resource_group_name = get_resource_group_name_by_registry(registry) - return get_registry_service_client().delete(resource_group_name, registry_name) + client = get_acr_service_client().registries -def acr_show(registry_name): + storage_account_name = client.get_properties( #pylint: disable=E1101 + resource_group_name, registry_name).properties.storage_account.name + delete_tag_storage_account(storage_account_name, registry_name) + + return client.delete(resource_group_name, registry_name) + +def acr_show(registry_name, resource_group_name=None): '''Get a container registry. :param str registry_name: The name of container registry + :param str resource_group_name: The name of resource group ''' registry = arm_get_registry_by_name(registry_name) if registry is None: - raise CLIError('No container registry can be found with name: ' + registry_name) + registry_not_found(registry_name) + + if resource_group_name is None: + resource_group_name = get_resource_group_name_by_resource_id(registry.id) + + client = get_acr_service_client().registries - resource_group_name = get_resource_group_name_by_registry(registry) - return get_registry_service_client().get_properties(resource_group_name, registry_name) + return client.get_properties(resource_group_name, registry_name) -def acr_update(registry_name, tags=None): +def acr_update(registry_name, #pylint: disable=too-many-arguments + resource_group_name=None, + tags=None, + new_sp=False, + app_id=None, + password=None, + role=DEFAULT_ROLE, + disable_admin=False, + enable_admin=False, + tenant_id=None): '''Update a container registry. :param str registry_name: The name of container registry + :param str resource_group_name: The name of resource group + :param dict tags: The set of tags + :param bool new_sp: Create a new service principal + :param str app_id: The app id of an existing service principal + :param str password: The password used to log into the container registry + :param str role: The name of role + :param bool disable_admin: Disable admin user + :param bool enable_admin: Enable admin user + :param str tenant_id: Tenant id for service principal login ''' + if new_sp and app_id: + raise CLIError('new_sp and app-id should not be specified together.') + + if disable_admin and enable_admin: + raise CLIError('disable_admin and enable_admin should not be specified together.') + 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) + registry_not_found(registry_name) + + if resource_group_name is None: + resource_group_name = get_resource_group_name_by_resource_id(registry.id) + + client = get_acr_service_client().registries + + session_key = None + # Create a service principal + if new_sp: + (app_id, + password, + session_key) = create_service_principal(registry_name, password) + + # Create role assignment + if app_id: + _create_role_assignment(role, + app_id, + scope=registry.id, #pylint: disable=E1101 + ocp_aad_session_key=session_key) + logger.warning("Service principal has been configured.") + logger.warning(" id(client_id): " + app_id) + if password: + logger.warning(" password(client_secret): " + password) + + # Set admin_user_enabled + admin_user_enabled = None + if disable_admin: + admin_user_enabled = False + if enable_admin: + admin_user_enabled = True + if admin_user_enabled is None: + admin_user_enabled = registry.properties.admin_user_enabled + + # Set tags newTags = registry.tags - if isinstance(tags, dict): if tags: for key in tags: @@ -85,10 +211,16 @@ def acr_update(registry_name, tags=None): else: newTags = {} - return get_registry_service_client().update( + return client.update( resource_group_name, registry_name, - RegistryParameters(location=registry.location, - tags=newTags)) + RegistryUpdateParameters( + tags=newTags, + properties=RegistryPropertiesCreateParameters( + tenant_id=tenant_id, + admin_user_enabled=admin_user_enabled + ) + ) + ) cli_command('acr list', acr_list, table_transformer=output_format) cli_command('acr create', acr_create, table_transformer=output_format) 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 index bb7337b70a3..60cb6195786 100644 --- 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 @@ -13,7 +13,9 @@ from msrest.service_client import ServiceClient from msrest import Configuration, Serializer, Deserializer from .version import VERSION +from .operations.operation import Operation from .operations.registries import Registries +from .operations.subscriptions import Subscriptions from . import models @@ -67,8 +69,12 @@ class ContainerRegistry(object): :param config: Configuration for client. :type config: ContainerRegistryConfiguration + :ivar operation: Operation operations + :vartype operation: .operations.Operation :ivar registries: Registries operations :vartype registries: .operations.Registries + :ivar subscriptions: Subscriptions operations + :vartype subscriptions: .operations.Subscriptions """ def __init__(self, config): @@ -80,5 +86,9 @@ def __init__(self, config): self._deserialize = Deserializer(client_models) self.config = config + self.operation = Operation( + self._client, self.config, self._serialize, self._deserialize) self.registries = Registries( self._client, self.config, self._serialize, self._deserialize) + self.subscriptions = Subscriptions( + self._client, self.config, self._serialize, self._deserialize) 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 index b3a5ebe9a3d..0f7e4c4bc6d 100644 --- 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 @@ -10,14 +10,34 @@ # regenerated. # -------------------------------------------------------------------------- -from .registry_parameters import RegistryParameters +from .registry_name_check_request import RegistryNameCheckRequest +from .registry_name_status import RegistryNameStatus +from .registry_move_request import RegistryMoveRequest +from .registry import Registry from .registry_properties import RegistryProperties +from .storage_account_base_properties import StorageAccountBaseProperties +from .registry_create_parameters import RegistryCreateParameters +from .registry_properties_create_parameters import RegistryPropertiesCreateParameters from .storage_account_properties import StorageAccountProperties -from .resource_list_registry_parameters import ResourceListRegistryParameters +from .registry_update_parameters import RegistryUpdateParameters +from .resource_list_registry import ResourceListRegistry +from .registry_credentials import RegistryCredentials +from .subscription_notification import SubscriptionNotification +from .subscription_properties import SubscriptionProperties __all__ = [ - 'RegistryParameters', + 'RegistryNameCheckRequest', + 'RegistryNameStatus', + 'RegistryMoveRequest', + 'Registry', 'RegistryProperties', + 'StorageAccountBaseProperties', + 'RegistryCreateParameters', + 'RegistryPropertiesCreateParameters', 'StorageAccountProperties', - 'ResourceListRegistryParameters', + 'RegistryUpdateParameters', + 'ResourceListRegistry', + 'RegistryCredentials', + 'SubscriptionNotification', + 'SubscriptionProperties', ] 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.py similarity index 96% rename from src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_parameters.py rename to src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry.py index 56f19523d1b..12f9894e0e1 100644 --- 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.py @@ -13,8 +13,8 @@ from msrest.serialization import Model -class RegistryParameters(Model): - """RegistryParameters +class Registry(Model): + """Registry Variables are only populated by the server, and will be ignored when sending a request. diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_create_parameters.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_create_parameters.py new file mode 100644 index 00000000000..676cafc8570 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_create_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 RegistryCreateParameters(Model): + """RegistryCreateParameters + + 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:`RegistryPropertiesCreateParameters + ` + """ + + _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': 'RegistryPropertiesCreateParameters'}, + } + + 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_credentials.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_credentials.py new file mode 100644 index 00000000000..abb5423acf5 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_credentials.py @@ -0,0 +1,32 @@ +#--------------------------------------------------------------------------------------------- +# 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 RegistryCredentials(Model): + """RegistryCredentials + + :param user_name: + :type user_name: str + :param pass_word: + :type pass_word: str + """ + + _attribute_map = { + 'user_name': {'key': 'userName', 'type': 'str'}, + 'pass_word': {'key': 'passWord', 'type': 'str'}, + } + + def __init__(self, user_name=None, pass_word=None): + self.user_name = user_name + self.pass_word = pass_word diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_move_request.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_move_request.py new file mode 100644 index 00000000000..2e36f518931 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_move_request.py @@ -0,0 +1,32 @@ +#--------------------------------------------------------------------------------------------- +# 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 RegistryMoveRequest(Model): + """RegistryMoveRequest + + :param target_resource_group: + :type target_resource_group: str + :param resources: + :type resources: list of str + """ + + _attribute_map = { + 'target_resource_group': {'key': 'targetResourceGroup', 'type': 'str'}, + 'resources': {'key': 'resources', 'type': '[str]'}, + } + + def __init__(self, target_resource_group=None, resources=None): + self.target_resource_group = target_resource_group + self.resources = resources diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_name_check_request.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_name_check_request.py new file mode 100644 index 00000000000..c78bb196152 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_name_check_request.py @@ -0,0 +1,32 @@ +#--------------------------------------------------------------------------------------------- +# 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 RegistryNameCheckRequest(Model): + """RegistryNameCheckRequest + + :param name: + :type name: str + :param type: + :type type: str + """ + + _attribute_map = { + 'name': {'key': 'name', 'type': 'str'}, + 'type': {'key': 'type', 'type': 'str'}, + } + + def __init__(self, name=None, type=None): + self.name = name + self.type = type diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_name_status.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_name_status.py new file mode 100644 index 00000000000..e36611d0306 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_name_status.py @@ -0,0 +1,36 @@ +#--------------------------------------------------------------------------------------------- +# 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 RegistryNameStatus(Model): + """RegistryNameStatus + + :param name_available: + :type name_available: bool + :param reason: + :type reason: str + :param message: + :type message: str + """ + + _attribute_map = { + 'name_available': {'key': 'nameAvailable', 'type': 'bool'}, + 'reason': {'key': 'reason', 'type': 'str'}, + 'message': {'key': 'message', 'type': 'str'}, + } + + def __init__(self, name_available=None, reason=None, message=None): + self.name_available = name_available + self.reason = reason + self.message = message 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 index 7ac68462cba..cd4cf71982f 100644 --- 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 @@ -17,29 +17,25 @@ class RegistryProperties(Model): """RegistryProperties :param storage_account: - :type storage_account: :class:`StorageAccountProperties - ` + :type storage_account: :class:`StorageAccountBaseProperties + ` :param login_server: :type login_server: str - :param username: - :type username: str - :param key: - :type key: str :param creation_date: :type creation_date: datetime + :param admin_user_enabled: + :type admin_user_enabled: bool """ _attribute_map = { - 'storage_account': {'key': 'storageAccount', 'type': 'StorageAccountProperties'}, + 'storage_account': {'key': 'storageAccount', 'type': 'StorageAccountBaseProperties'}, 'login_server': {'key': 'loginServer', 'type': 'str'}, - 'username': {'key': 'username', 'type': 'str'}, - 'key': {'key': 'key', 'type': 'str'}, 'creation_date': {'key': 'creationDate', 'type': 'iso-8601'}, + 'admin_user_enabled': {'key': 'adminUserEnabled', 'type': 'bool'}, } - def __init__(self, storage_account=None, login_server=None, username=None, key=None, creation_date=None): + def __init__(self, storage_account=None, login_server=None, creation_date=None, admin_user_enabled=None): self.storage_account = storage_account self.login_server = login_server - self.username = username - self.key = key self.creation_date = creation_date + self.admin_user_enabled = admin_user_enabled diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_properties_create_parameters.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_properties_create_parameters.py new file mode 100644 index 00000000000..ba5a1a9c8ae --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_properties_create_parameters.py @@ -0,0 +1,37 @@ +#--------------------------------------------------------------------------------------------- +# 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 RegistryPropertiesCreateParameters(Model): + """RegistryPropertiesCreateParameters + + :param tenant_id: + :type tenant_id: str + :param admin_user_enabled: + :type admin_user_enabled: bool + :param storage_account: + :type storage_account: :class:`StorageAccountProperties + ` + """ + + _attribute_map = { + 'tenant_id': {'key': 'tenantId', 'type': 'str'}, + 'admin_user_enabled': {'key': 'adminUserEnabled', 'type': 'bool'}, + 'storage_account': {'key': 'storageAccount', 'type': 'StorageAccountProperties'}, + } + + def __init__(self, tenant_id=None, admin_user_enabled=None, storage_account=None): + self.tenant_id = tenant_id + self.admin_user_enabled = admin_user_enabled + self.storage_account = storage_account diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_update_parameters.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_update_parameters.py new file mode 100644 index 00000000000..8f4ef8e37fa --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/registry_update_parameters.py @@ -0,0 +1,33 @@ +#--------------------------------------------------------------------------------------------- +# 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 RegistryUpdateParameters(Model): + """RegistryUpdateParameters + + :param tags: + :type tags: dict + :param properties: + :type properties: :class:`RegistryPropertiesCreateParameters + ` + """ + + _attribute_map = { + 'tags': {'key': 'tags', 'type': '{str}'}, + 'properties': {'key': 'properties', 'type': 'RegistryPropertiesCreateParameters'}, + } + + def __init__(self, tags=None, properties=None): + self.tags = tags + self.properties = properties 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.py similarity index 76% rename from src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/resource_list_registry_parameters.py rename to src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/resource_list_registry.py index 39304ec8be8..6a213c46e37 100644 --- 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.py @@ -13,16 +13,15 @@ from msrest.serialization import Model -class ResourceListRegistryParameters(Model): - """ResourceListRegistryParameters +class ResourceListRegistry(Model): + """ResourceListRegistry :param value: - :type value: list of :class:`RegistryParameters - ` + :type value: list of :class:`Registry ` """ _attribute_map = { - 'value': {'key': 'value', 'type': '[RegistryParameters]'}, + 'value': {'key': 'value', 'type': '[Registry]'}, } def __init__(self, value=None): diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/storage_account_base_properties.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/storage_account_base_properties.py new file mode 100644 index 00000000000..c9d5bc7651a --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/storage_account_base_properties.py @@ -0,0 +1,28 @@ +#--------------------------------------------------------------------------------------------- +# 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 StorageAccountBaseProperties(Model): + """StorageAccountBaseProperties + + :param name: + :type name: str + """ + + _attribute_map = { + 'name': {'key': 'name', 'type': 'str'}, + } + + def __init__(self, name=None): + self.name = name 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 index 276196e77f7..7f9f554436c 100644 --- 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 @@ -16,25 +16,25 @@ 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 + :param location: + :type location: str + :param name: + :type name: 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'}, + 'location': {'key': 'location', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, } - def __init__(self, name=None, access_key=None, end_point_url=None, endpoint_suffix=None): - self.name = name + def __init__(self, access_key=None, end_point_url=None, location=None, name=None): self.access_key = access_key self.end_point_url = end_point_url - self.endpoint_suffix = endpoint_suffix + self.location = location + self.name = name diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/subscription_notification.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/subscription_notification.py new file mode 100644 index 00000000000..0b8073c313b --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/subscription_notification.py @@ -0,0 +1,38 @@ +#--------------------------------------------------------------------------------------------- +# 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 SubscriptionNotification(Model): + """SubscriptionNotification + + :param registration_date: + :type registration_date: datetime + :param state: Possible values include: 'NotDefined', 'Registered', + 'Unregistered', 'Warned', 'Suspended', 'Deleted' + :type state: str + :param properties: + :type properties: :class:`SubscriptionProperties + ` + """ + + _attribute_map = { + 'registration_date': {'key': 'registrationDate', 'type': 'iso-8601'}, + 'state': {'key': 'state', 'type': 'str'}, + 'properties': {'key': 'properties', 'type': 'SubscriptionProperties'}, + } + + def __init__(self, registration_date=None, state=None, properties=None): + self.registration_date = registration_date + self.state = state + self.properties = properties diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/subscription_properties.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/subscription_properties.py new file mode 100644 index 00000000000..d2227758a3a --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/models/subscription_properties.py @@ -0,0 +1,36 @@ +#--------------------------------------------------------------------------------------------- +# 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 SubscriptionProperties(Model): + """SubscriptionProperties + + :param tenant_id: + :type tenant_id: str + :param location_placement_id: + :type location_placement_id: str + :param quota_id: + :type quota_id: str + """ + + _attribute_map = { + 'tenant_id': {'key': 'tenantId', 'type': 'str'}, + 'location_placement_id': {'key': 'locationPlacementId', 'type': 'str'}, + 'quota_id': {'key': 'quotaId', 'type': 'str'}, + } + + def __init__(self, tenant_id=None, location_placement_id=None, quota_id=None): + self.tenant_id = tenant_id + self.location_placement_id = location_placement_id + self.quota_id = quota_id 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 index 45581021ace..dd08efaa7d8 100644 --- 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 @@ -10,8 +10,12 @@ # regenerated. # -------------------------------------------------------------------------- +from .operation import Operation from .registries import Registries +from .subscriptions import Subscriptions __all__ = [ + 'Operation', 'Registries', + 'Subscriptions', ] diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/operation.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/operation.py new file mode 100644 index 00000000000..21c31075397 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/operation.py @@ -0,0 +1,141 @@ +#--------------------------------------------------------------------------------------------- +# 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 Operation(object): + """Operation 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 check_name_availability( + self, name_check_request, custom_headers={}, raw=False, **operation_config): + """ + + :param name_check_request: + :type name_check_request: :class:`RegistryNameCheckRequest + ` + :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:`RegistryNameStatus + ` + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/providers/Microsoft.ContainerRegistry/checkNameAvailability' + 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 body + body_content = self._serialize.body(name_check_request, 'RegistryNameCheckRequest') + + # Construct and send request + request = self._client.post(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('RegistryNameStatus', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized + + def move_resources( + self, resource_group, move_request, custom_headers={}, raw=False, **operation_config): + """ + + :param resource_group: + :type resource_group: str + :param move_request: + :type move_request: :class:`RegistryMoveRequest + ` + :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: None + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/moveResources' + 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 body + body_content = self._serialize.body(move_request, 'RegistryMoveRequest') + + # Construct and send request + request = self._client.post(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) + + if raw: + client_raw_response = ClientRawResponse(None, response) + return client_raw_response 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 index ee7d1e4ccd4..945091678ff 100644 --- 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 @@ -46,8 +46,7 @@ def get_properties( deserialized response :param operation_config: :ref:`Operation configuration overrides`. - :rtype: :class:`RegistryParameters - ` + :rtype: :class:`Registry ` :rtype: :class:`ClientRawResponse` if raw=true """ @@ -80,7 +79,7 @@ def get_properties( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('RegistryParameters', response) + deserialized = self._deserialize('Registry', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) @@ -97,14 +96,15 @@ def create( :param registry_name: :type registry_name: str :param registry_parameters: - :type registry_parameters: :class:`RegistryParameters - ` + :type registry_parameters: :class:`RegistryCreateParameters + ` :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:`RegistryCreateParameters + ` :rtype: :class:`ClientRawResponse` if raw=true """ @@ -128,7 +128,7 @@ def create( header_parameters.update(custom_headers) # Construct body - body_content = self._serialize.body(registry_parameters, 'RegistryParameters') + body_content = self._serialize.body(registry_parameters, 'RegistryCreateParameters') # Construct and send request request = self._client.put(url, query_parameters) @@ -141,7 +141,7 @@ def create( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('object', response) + deserialized = self._deserialize('RegistryCreateParameters', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) @@ -162,7 +162,7 @@ def delete( deserialized response :param operation_config: :ref:`Operation configuration overrides`. - :rtype: object + :rtype: None :rtype: :class:`ClientRawResponse` if raw=true """ @@ -192,34 +192,27 @@ def delete( 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) + client_raw_response = ClientRawResponse(None, response) return client_raw_response - return deserialized - def update( - self, resource_group, registry_name, registry_parameters, custom_headers={}, raw=False, **operation_config): + self, resource_group, registry_name, registry_update_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 registry_update_parameters: + :type registry_update_parameters: :class:`RegistryUpdateParameters + ` :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:`Registry ` :rtype: :class:`ClientRawResponse` if raw=true """ @@ -243,7 +236,7 @@ def update( header_parameters.update(custom_headers) # Construct body - body_content = self._serialize.body(registry_parameters, 'RegistryParameters') + body_content = self._serialize.body(registry_update_parameters, 'RegistryUpdateParameters') # Construct and send request request = self._client.patch(url, query_parameters) @@ -256,7 +249,7 @@ def update( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('object', response) + deserialized = self._deserialize('Registry', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) @@ -275,8 +268,8 @@ def list_by_resource_group( deserialized response :param operation_config: :ref:`Operation configuration overrides`. - :rtype: :class:`ResourceListRegistryParameters - ` + :rtype: :class:`ResourceListRegistry + ` :rtype: :class:`ClientRawResponse` if raw=true """ @@ -308,7 +301,7 @@ def list_by_resource_group( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('ResourceListRegistryParameters', response) + deserialized = self._deserialize('ResourceListRegistry', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) @@ -325,8 +318,8 @@ def list( deserialized response :param operation_config: :ref:`Operation configuration overrides`. - :rtype: :class:`ResourceListRegistryParameters - ` + :rtype: :class:`ResourceListRegistry + ` :rtype: :class:`ClientRawResponse` if raw=true """ @@ -357,7 +350,62 @@ def list( deserialized = None if response.status_code == 200: - deserialized = self._deserialize('ResourceListRegistryParameters', response) + deserialized = self._deserialize('ResourceListRegistry', response) + + if raw: + client_raw_response = ClientRawResponse(deserialized, response) + return client_raw_response + + return deserialized + + def get_credentials( + 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:`RegistryCredentials + ` + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.ContainerRegistry/registries/{registryName}/GetCredentials' + 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.post(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('RegistryCredentials', response) if raw: client_raw_response = ClientRawResponse(deserialized, response) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/subscriptions.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/subscriptions.py new file mode 100644 index 00000000000..4cb592677f5 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/mgmt_acr/operations/subscriptions.py @@ -0,0 +1,90 @@ +#--------------------------------------------------------------------------------------------- +# 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 Subscriptions(object): + """Subscriptions 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 put_subscription( + self, notification, custom_headers={}, raw=False, **operation_config): + """ + + :param notification: + :type notification: :class:`SubscriptionNotification + ` + :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:`SubscriptionNotification + ` + :rtype: :class:`ClientRawResponse` + if raw=true + """ + # Construct URL + url = '/subscriptions/{subscriptionId}' + 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 body + body_content = self._serialize.body(notification, 'SubscriptionNotification') + + # 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('SubscriptionNotification', 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/repository.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/repository.py index ff801e0f0da..7e9139dc255 100644 --- 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 @@ -8,7 +8,11 @@ from azure.cli.core.commands import cli_command from azure.cli.core._util import CLIError -from ._utils import get_registry_by_name +from ._utils import ( + get_registry_by_name, + registry_not_found +) +from .credential import acr_credential_show def _obtain_data_from_registry(login_server, path, resultIndex, username, password): registryEndpoint = 'https://' + login_server @@ -40,38 +44,42 @@ def _obtain_data_from_registry(login_server, path, resultIndex, username, passwo return {resultIndex: resultList} -def _validate_user_credentials(login_server, path, resultIndex, username=None, password=None): +def _validate_user_credentials(registry_name, path, resultIndex, username=None, password=None): + registry = get_registry_by_name(registry_name) + if registry is None: + registry_not_found(registry_name) + + login_server = registry.properties.login_server + 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 + cred = acr_credential_show(registry_name) + username = cred.user_name + password = cred.pass_word 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') + raise CLIError('Login credentials cannot be obtained. Please enter username/password') -def acr_repository_list(login_server, username=None, password=None): +def acr_repository_list(registry_name, 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 registry_name: The name of container registry :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) + return _validate_user_credentials(registry_name, path, 'repositories', username, password) -def acr_repository_show_tags(login_server, repository, username=None, password=None): +def acr_repository_show_tags(registry_name, 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 registry_name: The name of container registry :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) + return _validate_user_credentials(registry_name, 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/storage.py b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/storage.py new file mode 100644 index 00000000000..9546ba01987 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/storage.py @@ -0,0 +1,58 @@ +#--------------------------------------------------------------------------------------------- +# 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 ._factory import get_acr_service_client +from ._arm_utils import ( + arm_deploy_template, + add_tag_storage_account, + delete_tag_storage_account +) +from ._utils import ( + get_registry_by_name, + get_resource_group_name_by_resource_id, + registry_not_found +) + +from ._format import output_format + +import azure.cli.core._logging as _logging +logger = _logging.get_az_logger(__name__) + +def acr_storage_update(registry_name, + storage_account_name, + resource_group_name=None): + '''Update storage account for a container registry. + :param str registry_name: The name of container registry + :param str storage_account_name: The name of storage account + :param str resource_group_name: The name of resource group + ''' + registry = get_registry_by_name(registry_name) + if registry is None: + registry_not_found(registry_name) + + if resource_group_name is None: + resource_group_name = get_resource_group_name_by_resource_id(registry.id) + + old_storage_account_name = registry.properties.storage_account.name + + # Create a container registry + arm_deploy_template(resource_group_name, + registry_name, + registry.location, + storage_account_name, + registry.properties.admin_user_enabled).wait() + # wait for the template deployment to finish + + client = get_acr_service_client().registries + registry = client.get_properties(resource_group_name, registry_name) + + delete_tag_storage_account(old_storage_account_name, registry_name) + add_tag_storage_account(storage_account_name, registry_name) + + return registry + +cli_command('acr storage update', acr_storage_update, table_transformer=output_format) diff --git a/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.existing.json b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.existing.json new file mode 100644 index 00000000000..aedd0047280 --- /dev/null +++ b/src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.existing.json @@ -0,0 +1,64 @@ +{ + "$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", + "defaultValue": "2016-06-27-preview", + "metadata": { + "description": "Api version of the registry service" + } + }, + "storageAccountName": { + "type": "string", + "metadata": { + "description": "Name of the storage account" + } + }, + "storageAccountResourceGroup": { + "type": "string", + "metadata": { + "description": "Resource group of the storage account" + } + }, + "adminUserEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Enable admin user" + } + } + }, + "resources": [ + { + "name": "[parameters('registryName')]", + "type": "Microsoft.ContainerRegistry/registries", + "location": "[parameters('registryLocation')]", + "apiVersion": "[parameters('registryApiVersion')]", + "tags": { + "storageaccount": "[parameters('storageAccountName')]" + }, + "properties": { + "tenantId": "[subscription().tenantId]", + "adminUserEnabled": "[parameters('adminUserEnabled')]", + "storageAccount": { + "name": "[parameters('storageAccountName')]", + "accessKey": "[listKeys(resourceId(parameters('storageAccountResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2016-01-01').keys[0].value]", + "endPointUrl": "[reference(resourceId(parameters('storageAccountResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2016-01-01').primaryEndpoints.blob]" + } + } + } + ] +} \ No newline at end of file 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.new.json similarity index 60% rename from src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.json rename to src/command_modules/azure-cli-acr/azure/cli/command_modules/acr/template.new.json index c26aa404346..60d73438583 100644 --- 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.new.json @@ -16,6 +16,7 @@ }, "registryApiVersion": { "type": "string", + "defaultValue": "2016-06-27-preview", "metadata": { "description": "Api version of the registry service" } @@ -26,52 +27,51 @@ "description": "Name of the storage account" } }, - "storageAccountApiVersion": { + "storageAccountType": { "type": "string", "metadata": { - "description": "Api version of the storage account" + "description": "Type of the storage account" + } + }, + "adminUserEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Enable admin user" } } }, "resources": [ { - "comments": "# Storage Account", "name": "[parameters('storageAccountName')]", "type": "Microsoft.Storage/storageAccounts", "location": "[parameters('registryLocation')]", - "apiVersion": "[parameters('storageAccountApiVersion')]", - "properties": { - "accountType": "Standard_LRS" - } + "apiVersion": "2016-01-01", + "sku": { + "name": "[parameters('storageAccountType')]" + }, + "kind": "Storage" }, { - "comments": "# Registry", "name": "[parameters('registryName')]", "type": "Microsoft.ContainerRegistry/registries", "location": "[parameters('registryLocation')]", "apiVersion": "[parameters('registryApiVersion')]", + "tags": { + "storageaccount": "[parameters('storageAccountName')]" + }, "dependsOn": [ "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]" ], "properties": { + "tenantId": "[subscription().tenantId]", + "adminUserEnabled": "[parameters('adminUserEnabled')]", "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]" + "accessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2016-01-01').keys[0].value]", + "endPointUrl": "[reference(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2016-01-01').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/setup.py b/src/command_modules/azure-cli-acr/setup.py index ecb8e31cbde..a99a43803ef 100644 --- a/src/command_modules/azure-cli-acr/setup.py +++ b/src/command_modules/azure-cli-acr/setup.py @@ -52,5 +52,5 @@ 'azure.cli.command_modules.acr.mgmt_acr.operations', ], install_requires=DEPENDENCIES, - package_data={'azure.cli.command_modules.acr': ['template.json']}, + package_data={'azure.cli.command_modules.acr': ['template.new.json', 'template.existing.json']}, )