Skip to content

Commit

Permalink
[Storage]: Add a new command group az storage share-rm to use the M…
Browse files Browse the repository at this point in the history
…icrosoft.Storage resource provider for Azure file share management operations. (#11649)

[Storage]: Add a new command group `az storage share-rm` to use the Microsoft.Storage resource provider for Azure file share management operations.
  • Loading branch information
jsntcy authored Jan 19, 2020
1 parent b1cf183 commit 4051a36
Show file tree
Hide file tree
Showing 9 changed files with 1,303 additions and 3 deletions.
5 changes: 4 additions & 1 deletion src/azure-cli/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Release History

* Fix #6371: Support filename and environment variable completion in Bash

**Storage**

* Add a new command group `az storage share-rm` to use the Microsoft.Storage resource provider for Azure file share management operations.

2.0.80
++++++

Expand Down Expand Up @@ -98,7 +102,6 @@ Release History
* Update azure-mgmt-storage version to 7.0.0 to use api version 2019-06-01
* Add new parameters `--enable-delete-retention` and `--delete-retention-days` to support managing delete retention policy for storage account blob-service-properties.


2.0.78
++++++

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,9 @@ def cf_mgmt_blob_services(cli_ctx, _):
return storage_client_factory(cli_ctx).blob_services


def cf_mgmt_file_shares(cli_ctx, _):
return storage_client_factory(cli_ctx).file_shares


def cf_blob_data_gen_update(cli_ctx, kwargs):
return blob_data_service_factory(cli_ctx, kwargs.copy())
77 changes: 77 additions & 0 deletions src/azure-cli/azure/cli/command_modules/storage/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,83 @@
text: az storage remove -s MyShare --recursive
"""

helps['storage share-rm'] = """
type: group
short-summary: Manage Azure file shares using the Microsoft.Storage resource provider.
"""

helps['storage share-rm create'] = """
type: command
short-summary: Create a new Azure file share under the specified storage account.
examples:
- name: Create a new Azure file share 'myfileshare' with metadata and quota as 10 GB under the storage account 'mystorageaccount'(account name) in resource group 'MyResourceGroup'.
text: az storage share-rm create -g MyResourceGroup --storage-account mystorageaccount --name myfileshare --quota 10 --metadata key1=value1 key2=value2
- name: Create a new Azure file share 'myfileshare' with metadata and quota as 6000 GB under the storage account 'mystorageaccount'(account name) which enables large file share in resource group 'MyResourceGroup'.
text: |
az storage account update -g MyResourceGroup --name mystorageaccount --enable-large-file-share
az storage share-rm create -g MyResourceGroup --storage-account mystorageaccount --name myfileshare --quota 6000 --metadata key1=value1 key2=value2
- name: Create a new Azure file share 'myfileshare' with metadata and quota as 10 GB under the storage account 'mystorageaccount' (account id).
text: az storage share-rm create --storage-account mystorageaccount --name myfileshare --quota 10 --metadata key1=value1 key2=value2
"""

helps['storage share-rm delete'] = """
type: command
short-summary: Delete the specified Azure file share.
examples:
- name: Delete an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account name) in resource group 'MyResourceGroup'.
text: az storage share-rm delete -g MyResourceGroup --storage-account mystorageaccount --name myfileshare
- name: Delete an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account id).
text: az storage share-rm delete --storage-account mystorageaccount --name myfileshare
- name: Delete an Azure file share by resource id.
text: az storage share-rm delete --ids file-share-id
"""

helps['storage share-rm exists'] = """
type: command
short-summary: Check for the existence of an Azure file share.
examples:
- name: Check for the existence of an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account name) in resource group 'MyResourceGroup'.
text: az storage share-rm exists -g MyResourceGroup --storage-account mystorageaccount --name myfileshare
- name: Check for the existence of an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account id).
text: az storage share-rm exists --storage-account mystorageaccount --name myfileshare
- name: Check for the existence of an Azure file share by resource id.
text: az storage share-rm exists --ids file-share-id
"""

helps['storage share-rm list'] = """
type: command
short-summary: List the Azure file shares under the specified storage account.
examples:
- name: List the Azure file shares under the storage account 'mystorageaccount' (account name) in resource group 'MyResourceGroup'.
text: az storage share-rm list -g MyResourceGroup --storage-account mystorageaccount
- name: List the Azure file shares under the storage account 'mystorageaccount' (account id).
text: az storage share-rm list --storage-account mystorageaccount
"""

helps['storage share-rm show'] = """
type: command
short-summary: Show the properties for a specified Azure file share.
examples:
- name: Show the properties for an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account name) in resource group 'MyResourceGroup'.
text: az storage share-rm show -g MyResourceGroup --storage-account mystorageaccount --name myfileshare
- name: Show the properties for an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account id).
text: az storage share-rm show --storage-account mystorageaccount --name myfileshare
- name: Show the properties of an Azure file shares by resource id.
text: az storage share-rm show --ids file-share-id
"""

helps['storage share-rm update'] = """
type: command
short-summary: Update the properties for an Azure file share.
examples:
- name: Update the properties for an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account name) in resource group 'MyResourceGroup'.
text: az storage share-rm update -g MyResourceGroup --storage-account mystorageaccount --name myfileshare --quota 3 --metadata key1=value1 key2=value2
- name: Update the properties for an Azure file share 'myfileshare' under the storage account 'mystorageaccount' (account id).
text: az storage share-rm update --storage-account mystorageaccount --name myfileshare --quota 3 --metadata key1=value1 key2=value2
- name: Update the properties for an Azure file shares by resource id.
text: az storage share-rm update --ids file-share-id --quota 3 --metadata key1=value1 key2=value2
"""

helps['storage share'] = """
type: group
short-summary: Manage file shares.
Expand Down
21 changes: 20 additions & 1 deletion src/azure-cli/azure/cli/command_modules/storage/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
storage_account_key_options, process_file_download_namespace, process_metric_update_namespace,
get_char_options_validator, validate_bypass, validate_encryption_source, validate_marker,
validate_storage_data_plane_list, validate_azcopy_upload_destination_url,
validate_azcopy_remove_arguments, as_user_validator)
validate_azcopy_remove_arguments, as_user_validator, parse_storage_account)


def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statements
Expand All @@ -34,6 +34,10 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
t_queue_service = self.get_sdk('queue#QueueService')
t_table_service = get_table_data_type(self.cli_ctx, 'table', 'TableService')

storage_account_type = CLIArgumentType(options_list='--storage-account',
help='The name or ID of the storage account.',
validator=parse_storage_account, id_part='name')

acct_name_type = CLIArgumentType(options_list=['--account-name', '-n'], help='The storage account name.',
id_part='name',
completer=get_resource_name_completion_list('Microsoft.Storage/storageAccounts'))
Expand Down Expand Up @@ -635,6 +639,21 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
with self.argument_context('storage share') as c:
c.argument('share_name', share_name_type, options_list=('--name', '-n'))

for item in ['create', 'delete', 'exists', 'list', 'show', 'update']:
with self.argument_context('storage share-rm {}'.format(item), resource_type=ResourceType.MGMT_STORAGE) as c:
c.argument('resource_group_name', required=False)
c.argument('account_name', storage_account_type)
c.argument('share_name', share_name_type, options_list=('--name', '-n'), id_part='child_name_2')
c.argument('share_quota', type=int, options_list='--quota')
c.argument('metadata', nargs='+',
help='Metadata in space-separated key=value pairs that is associated with the share. '
'This overwrites any existing metadata',
validator=validate_metadata)
c.ignore('filter', 'maxpagesize', 'skip_token')

with self.argument_context('storage share-rm list', resource_type=ResourceType.MGMT_STORAGE) as c:
c.argument('account_name', storage_account_type, id_part=None)

with self.argument_context('storage share url') as c:
c.argument('unc', action='store_true', help='Output UNC network path.')
c.argument('protocol', arg_type=get_enum_type(['http', 'https'], 'https'), help='Protocol to use.')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ def _cancel_timer_event_handler(_, **__):


# region PARAMETER VALIDATORS
def parse_storage_account(namespace):
"""Parse storage account which can be either account name or account id"""
from msrestazure.tools import parse_resource_id, is_valid_resource_id

if namespace.account_name and is_valid_resource_id(namespace.account_name):
namespace.resource_group_name = parse_resource_id(namespace.account_name)['resource_group']
namespace.account_name = parse_resource_id(namespace.account_name)['name']


def process_resource_group(cmd, namespace):
"""Processes the resource group parameter from the account name"""
Expand Down
20 changes: 19 additions & 1 deletion src/azure-cli/azure/cli/command_modules/storage/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
multi_service_properties_factory,
cf_mgmt_policy,
cf_blob_data_gen_update, cf_sa_for_keys,
cf_mgmt_blob_services)
cf_mgmt_blob_services, cf_mgmt_file_shares)
from azure.cli.command_modules.storage.sdkutil import cosmosdb_table_exists
from azure.cli.command_modules.storage._format import transform_immutability_policy
from azure.cli.core.commands import CliCommandType
Expand All @@ -31,6 +31,12 @@ def load_command_table(self, _): # pylint: disable=too-many-locals, too-many-st
resource_type=ResourceType.MGMT_STORAGE
)

file_shares_mgmt_sdk = CliCommandType(
operations_tmpl='azure.mgmt.storage.operations#FileSharesOperations.{}',
client_factory=cf_mgmt_file_shares,
resource_type=ResourceType.MGMT_STORAGE
)

storage_account_sdk_keys = CliCommandType(
operations_tmpl='azure.mgmt.storage.operations#StorageAccountsOperations.{}',
client_factory=cf_sa_for_keys,
Expand Down Expand Up @@ -320,6 +326,18 @@ def get_custom_sdk(custom_module, client_factory, resource_type=ResourceType.DAT
client_factory=file_data_service_factory,
resource_type=ResourceType.DATA_STORAGE)

with self.command_group('storage share-rm', command_type=file_shares_mgmt_sdk,
custom_command_type=get_custom_sdk('file',
cf_mgmt_file_shares,
resource_type=ResourceType.MGMT_STORAGE),
resource_type=ResourceType.MGMT_STORAGE, min_api='2019-04-01', is_preview=True) as g:
g.command('create', 'create')
g.command('delete', 'delete', confirmation=True)
g.custom_command('exists', '_file_share_exists', transform=create_boolean_result_output_transformer('exists'))
g.command('list', 'list')
g.show_command('show', 'get')
g.command('update', 'update')

with self.command_group('storage share', command_type=file_sdk,
custom_command_type=get_custom_sdk('file', file_data_service_factory)) as g:
from ._format import (transform_share_list,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,12 @@ def _make_directory_in_files_share(file_service, file_share, directory_path, exi

if existing_dirs:
existing_dirs.add(directory_path)


def _file_share_exists(client, resource_group_name, account_name, share_name):
from msrestazure.azure_exceptions import CloudError
try:
file_share = client.get(resource_group_name, account_name, share_name)
return file_share is not None
except CloudError:
return False

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import os
from azure.cli.testsdk import (ScenarioTest, ResourceGroupPreparer, StorageAccountPreparer, api_version_constraint)
from azure.cli.core.profiles import ResourceType
from ..storage_test_util import StorageScenarioMixin


@api_version_constraint(ResourceType.MGMT_STORAGE, min_api='2019-04-01')
class StorageFileShareUsingResourceProviderScenarios(StorageScenarioMixin, ScenarioTest):
@ResourceGroupPreparer()
@StorageAccountPreparer()
def test_storage_file_using_rm_main_scenario(self):
# 1. Test create command.

# Create file share with storage account name and resource group.
share_name_1 = self.create_random_name('share', 24)
initial_quota = 5
self.kwargs.update({
'share_name_1': share_name_1,
'initial_quota': initial_quota
})

result = self.cmd('storage share-rm create --storage-account {sa} -g {rg} -n {share_name_1} --quota {initial_quota} --metadata key1=value1').get_output_in_json()
self.assertEqual(result['name'], share_name_1)
self.assertEqual(result['shareQuota'], initial_quota)
self.assertEqual(result['metadata']['key1'], 'value1')

share_id_1 = result['id']
self.kwargs.update({
'share_id_1': share_id_1
})

# Create file share with storage account id.
share_name_2 = self.create_random_name('share', 24)
storage_account = self.cmd('storage account show -n {sa}').get_output_in_json()
storage_account_id = storage_account['id']
self.kwargs.update({
'share_name_2': share_name_2,
'storage_account_id': storage_account_id
})

result = self.cmd('storage share-rm create --storage-account {storage_account_id} -n {share_name_2} --quota {initial_quota} --metadata key1=value1').get_output_in_json()
self.assertEqual(result['name'], share_name_2)
self.assertEqual(result['shareQuota'], initial_quota)
self.assertEqual(result['metadata']['key1'], 'value1')

share_id_2 = result['id']
self.kwargs.update({
'share_id_2': share_id_2
})

# 2. Test exists command (the file share exists).

# Check existence with storage account name and resource group.
result = self.cmd('storage share-rm exists --storage-account {sa} -g {rg} -n {share_name_1}').get_output_in_json()
self.assertEqual(result['exists'], True)

# Check existence with storage account id.
result = self.cmd('storage share-rm exists --storage-account {storage_account_id} -n {share_name_1}').get_output_in_json()
self.assertEqual(result['exists'], True)

# Check existence by file share resource id.
result = self.cmd('storage share-rm exists --ids {share_id_1}').get_output_in_json()
self.assertEqual(result['exists'], True)

# 3. Test show command (the file share exists).

# Show properties of a file share with storage account name and resource group.
result = self.cmd('storage share-rm show --storage-account {sa} -g {rg} -n {share_name_1}').get_output_in_json()
self.assertEqual(result['name'], share_name_1)

# Show properties of a file share with storage account id.
result = self.cmd('storage share-rm show --storage-account {storage_account_id} -n {share_name_1}').get_output_in_json()
self.assertEqual(result['name'], share_name_1)

# Show properties by file share resource id.
result = self.cmd('storage share-rm show --ids {share_id_1}').get_output_in_json()
self.assertEqual(result['name'], share_name_1)

# 4. Test show command (the file share doesn't exist).
non_exist_share_name = self.create_random_name('share', 24)
self.kwargs.update({
'non_exist_share_name': non_exist_share_name
})
with self.assertRaisesRegexp(SystemExit, '3'):
self.cmd('storage share-rm show --storage-account {sa} -g {rg} -n {non_exist_share_name}')

# 5. Test update command.
updated_quota = 10
self.kwargs.update({
'updated_quota': updated_quota
})

# Update file share with storage account name and resource group.
result = self.cmd(
'storage share-rm update --storage-account {sa} -g {rg} -n {share_name_1} --quota {updated_quota} --metadata key2=value2').get_output_in_json()
self.assertEqual(result['shareQuota'], updated_quota)
self.assertEqual(result['metadata']['key2'], 'value2')
self.assertNotIn('key1', result['metadata'])

# Update file share with storage account id.
result = self.cmd(
'storage share-rm update --storage-account {storage_account_id} -n {share_name_2} --quota {updated_quota} --metadata key2=value2').get_output_in_json()
self.assertEqual(result['shareQuota'], updated_quota)
self.assertEqual(result['metadata']['key2'], 'value2')
self.assertNotIn('key1', result['metadata'])

# Update file share by resource id
result = self.cmd(
'storage share-rm update --ids {share_id_1} --quota {updated_quota} --metadata key2=value2').get_output_in_json()
self.assertEqual(result['shareQuota'], updated_quota)
self.assertEqual(result['metadata']['key2'], 'value2')
self.assertNotIn('key1', result['metadata'])

# 6. Test list command.

# List file shares with storage account name and resource group.
self.assertIn(share_name_1,
self.cmd('storage share-rm list --storage-account {sa} -g {rg} --query "[].name"').get_output_in_json())

# List file shares with storage account id.
self.assertIn(share_name_1,
self.cmd('storage share-rm list --storage-account {storage_account_id} --query "[].name"').get_output_in_json())

# 7. Test delete command.

# Delete file shares with storage account name and resource group.
self.cmd('storage share-rm delete --storage-account {sa} -g {rg} -n {share_name_1} -y')

# Delete file share by resource id.
self.cmd('storage share-rm delete --ids {share_id_2} -y')

# 8. Test exists command (the file share doesn't exist).
result = self.cmd('storage share-rm exists --storage-account {sa} -g {rg} -n {share_name_1}').get_output_in_json()
self.assertEqual(result['exists'], False)

result = self.cmd('storage share-rm exists --ids {share_id_2}').get_output_in_json()
self.assertEqual(result['exists'], False)

0 comments on commit 4051a36

Please sign in to comment.