Skip to content

Commit

Permalink
Add file share snapshot support
Browse files Browse the repository at this point in the history
Update storage multiapi package
  • Loading branch information
troydai committed Oct 5, 2017
1 parent bc50a23 commit e79852b
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 114 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ pyOpenSSL==16.2.0
pyyaml==3.11
requests==2.18.4
setuptools==30.4.0
six==1.10.0
six==1.11.0
vcrpy==1.10.3
wheel==0.29.0
3 changes: 1 addition & 2 deletions src/azure-cli-core/azure/cli/core/commands/client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ def get_data_service_client(service_type, account_name, account_key, connection_
client_kwargs['endpoint_suffix'] = endpoint_suffix
client = service_type(**client_kwargs)
except ValueError as exc:
_ERROR_STORAGE_MISSING_INFO = \
get_sdk(ResourceType.DATA_STORAGE, '_error#_ERROR_STORAGE_MISSING_INFO')
_ERROR_STORAGE_MISSING_INFO = get_sdk(ResourceType.DATA_STORAGE, 'common._error#_ERROR_STORAGE_MISSING_INFO')
if _ERROR_STORAGE_MISSING_INFO in str(exc):
raise ValueError(exc)
else:
Expand Down
31 changes: 12 additions & 19 deletions src/azure-cli-core/azure/cli/core/profiles/_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,17 @@ def __str__(self):

class ResourceType(Enum): # pylint: disable=too-few-public-methods

MGMT_STORAGE = ('azure.mgmt.storage',
'StorageManagementClient')
MGMT_COMPUTE = ('azure.mgmt.compute',
'ComputeManagementClient')
MGMT_NETWORK = ('azure.mgmt.network',
'NetworkManagementClient')
MGMT_RESOURCE_FEATURES = ('azure.mgmt.resource.features',
'FeatureClient')
MGMT_RESOURCE_LINKS = ('azure.mgmt.resource.links',
'ManagementLinkClient')
MGMT_RESOURCE_LOCKS = ('azure.mgmt.resource.locks',
'ManagementLockClient')
MGMT_RESOURCE_POLICY = ('azure.mgmt.resource.policy',
'PolicyClient')
MGMT_RESOURCE_RESOURCES = ('azure.mgmt.resource.resources',
'ResourceManagementClient')
MGMT_RESOURCE_SUBSCRIPTIONS = ('azure.mgmt.resource.subscriptions',
'SubscriptionClient')
MGMT_STORAGE = ('azure.mgmt.storage', 'StorageManagementClient')
MGMT_COMPUTE = ('azure.mgmt.compute', 'ComputeManagementClient')
MGMT_NETWORK = ('azure.mgmt.network', 'NetworkManagementClient')
MGMT_RESOURCE_FEATURES = ('azure.mgmt.resource.features', 'FeatureClient')
MGMT_RESOURCE_LINKS = ('azure.mgmt.resource.links', 'ManagementLinkClient')
MGMT_RESOURCE_LOCKS = ('azure.mgmt.resource.locks', 'ManagementLockClient')
MGMT_RESOURCE_POLICY = ('azure.mgmt.resource.policy', 'PolicyClient')
MGMT_RESOURCE_RESOURCES = ('azure.mgmt.resource.resources', 'ResourceManagementClient')
MGMT_RESOURCE_SUBSCRIPTIONS = ('azure.mgmt.resource.subscriptions', 'SubscriptionClient')
DATA_STORAGE = ('azure.multiapi.storage', None)
DATA_COSMOS_TABLE = ('azure.multiapi.cosmosdb', None)

def __init__(self, import_prefix, client_name):
"""Constructor.
Expand All @@ -69,7 +61,8 @@ def __init__(self, import_prefix, client_name):
ResourceType.MGMT_RESOURCE_POLICY: '2017-06-01-preview',
ResourceType.MGMT_RESOURCE_RESOURCES: '2017-05-10',
ResourceType.MGMT_RESOURCE_SUBSCRIPTIONS: '2016-06-01',
ResourceType.DATA_STORAGE: '2017-04-17'
ResourceType.DATA_STORAGE: '2017-04-17',
ResourceType.DATA_COSMOS_TABLE: '2017-04-17'
},
'2017-03-09-profile': {
ResourceType.MGMT_STORAGE: '2015-06-15',
Expand Down
6 changes: 4 additions & 2 deletions src/command_modules/azure-cli-storage/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
Release History
===============

unreleased
++++++++++
* File share snapshot

2.0.16 (2017-09-22)
+++++++++++++++++++
* `storage account network-rule`: Fixed issue where commands may fail after updating the SDK.


2.0.15 (2017-09-11)
+++++++++++++++++++
* minor fixes
Expand All @@ -27,7 +30,6 @@ Release History
* Breaking change: rename --encryption option to --encryption-services for az storage account create and az storage account update command.
* Fix #4220: az storage account update encryption - syntax mismatch


2.0.12 (2017-08-11)
+++++++++++++++++++
* Enable create storage account with system assigned identity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from azure.cli.core.commands import CLIError
from azure.cli.core._profile import CLOUD
from azure.cli.core.profiles import get_sdk, ResourceType
from .sdkutil import get_table_data_type

NO_CREDENTIALS_ERROR_MESSAGE = """
No credentials specified to access storage service. Please provide any of the following:
Expand All @@ -33,7 +34,7 @@ def generic_data_service_factory(service, name=None, key=None, connection_string
try:
return get_storage_data_service_client(service, name, key, connection_string, sas_token)
except ValueError as val_exception:
_ERROR_STORAGE_MISSING_INFO = get_sdk(ResourceType.DATA_STORAGE, '_error#_ERROR_STORAGE_MISSING_INFO')
_ERROR_STORAGE_MISSING_INFO = get_sdk(ResourceType.DATA_STORAGE, 'common._error#_ERROR_STORAGE_MISSING_INFO')
message = str(val_exception)
if message == _ERROR_STORAGE_MISSING_INFO:
message = NO_CREDENTIALS_ERROR_MESSAGE
Expand All @@ -55,8 +56,7 @@ def file_data_service_factory(kwargs):


def page_blob_service_factory(kwargs):
PageBlobService = get_sdk(ResourceType.DATA_STORAGE,
'blob.pageblobservice#PageBlobService')
PageBlobService = get_sdk(ResourceType.DATA_STORAGE, 'blob.pageblobservice#PageBlobService')
return generic_data_service_factory(
PageBlobService,
kwargs.pop('account_name', None),
Expand All @@ -79,7 +79,7 @@ def blob_data_service_factory(kwargs):


def table_data_service_factory(kwargs):
TableService = get_sdk(ResourceType.DATA_STORAGE, 'table#TableService')
TableService = get_table_data_type('table', 'TableService')
return generic_data_service_factory(
TableService,
kwargs.pop('account_name', None),
Expand All @@ -99,7 +99,7 @@ def queue_data_service_factory(kwargs):


def cloud_storage_account_service_factory(kwargs):
CloudStorageAccount = get_sdk(ResourceType.DATA_STORAGE, '#CloudStorageAccount')
CloudStorageAccount = get_sdk(ResourceType.DATA_STORAGE, 'common#CloudStorageAccount')
account_name = kwargs.pop('account_name', None)
account_key = kwargs.pop('account_key', None)
sas_token = kwargs.pop('sas_token', None)
Expand All @@ -111,9 +111,11 @@ def multi_service_properties_factory(kwargs):
"""Create multiple data services properties instance based on the services option"""
from .services_wrapper import ServiceProperties

BaseBlobService, FileService, TableService, QueueService, = \
BaseBlobService, FileService, QueueService, = \
get_sdk(ResourceType.DATA_STORAGE,
'blob.baseblobservice#BaseBlobService', 'file#FileService', 'table#TableService', 'queue#QueueService')
'blob.baseblobservice#BaseBlobService', 'file#FileService', 'queue#QueueService')

TableService = get_table_data_type('table', 'TableService')

account_name = kwargs.pop('account_name', None)
account_key = kwargs.pop('account_key', None)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from azure.cli.core.profiles import get_sdk, ResourceType, supported_api_version

from .sdkutil import get_table_data_type
from ._factory import get_storage_data_service_client
from ._validators import \
(get_datetime_type, get_file_path_validator, validate_metadata,
Expand All @@ -37,44 +38,35 @@
get_source_file_or_blob_service_client, process_blob_source_uri,
get_char_options_validator, validate_bypass, validate_subnet, page_blob_tier_validator, blob_tier_validator)

DeleteSnapshot, BlockBlobService, PageBlobService, AppendBlobService = get_sdk(ResourceType.DATA_STORAGE,
'DeleteSnapshot',
'BlockBlobService',
'PageBlobService',
'AppendBlobService',
mod='blob')

DeleteSnapshot, BlockBlobService, \
PageBlobService, AppendBlobService = get_sdk(ResourceType.DATA_STORAGE,
'DeleteSnapshot',
'BlockBlobService',
'PageBlobService',
'AppendBlobService',
mod='blob')


BlobContentSettings, ContainerPermissions, \
BlobPermissions, PublicAccess = get_sdk(ResourceType.DATA_STORAGE,
'ContentSettings',
'ContainerPermissions',
'BlobPermissions',
'PublicAccess',
mod='blob.models')

FileContentSettings, SharePermissions, \
FilePermissions = get_sdk(ResourceType.DATA_STORAGE,
'ContentSettings',
'SharePermissions',
'FilePermissions',
mod='file.models')

TableService, TablePayloadFormat = get_sdk(ResourceType.DATA_STORAGE,
'TableService',
'TablePayloadFormat',
mod='table')

AccountPermissions, BaseBlobService, \
FileService, QueueService, QueuePermissions = get_sdk(ResourceType.DATA_STORAGE,
'models#AccountPermissions',
'blob.baseblobservice#BaseBlobService',
'file#FileService',
'queue#QueueService',
'queue.models#QueuePermissions')
BlobContentSettings, ContainerPermissions, BlobPermissions, PublicAccess = get_sdk(ResourceType.DATA_STORAGE,
'ContentSettings',
'ContainerPermissions',
'BlobPermissions',
'PublicAccess',
mod='blob.models')

FileContentSettings, SharePermissions, FilePermissions = get_sdk(ResourceType.DATA_STORAGE,
'ContentSettings',
'SharePermissions',
'FilePermissions',
mod='file.models')

TableService, TablePayloadFormat = get_table_data_type('table', 'TableService', 'TablePayloadFormat')

AccountPermissions = get_sdk(ResourceType.DATA_STORAGE, 'common.models#AccountPermissions')

BaseBlobService, FileService, QueueService, QueuePermissions = get_sdk(ResourceType.DATA_STORAGE,
'blob.baseblobservice#BaseBlobService',
'file#FileService',
'queue#QueueService',
'queue.models#QueuePermissions')

# UTILITY

Expand Down Expand Up @@ -572,6 +564,9 @@ def register_common_storage_account_options(context):
register_cli_argument('storage share policy', 'policy_name', options_list=('--name', '-n'), help='The stored access policy name.', completer=get_storage_acl_name_completion_list(FileService, 'container_name', 'get_share_acl'))

register_cli_argument('storage share list', 'marker', ignore_type) # https://github.com/Azure/azure-cli/issues/3745
register_cli_argument('storage share delete', 'delete_snapshots',
help='Specify the deletion strategy when the share has snapshots.',
**enum_choice_list(list(delete_snapshot_types.keys())))

register_cli_argument('storage directory', 'directory_name', directory_type, options_list=('--name', '-n'))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
from azure.cli.core.util import CLIError
from azure.cli.core._profile import CLOUD
from azure.cli.core._config import az_config
from azure.cli.core.profiles import get_sdk, ResourceType
from azure.cli.core.profiles import get_sdk, ResourceType, supported_api_version
from azure.cli.core.commands.client_factory import get_mgmt_service_client
from azure.cli.core.commands.validators import validate_key_value_pairs

from ._factory import get_storage_data_service_client
from .util import glob_files_locally, guess_content_type
from .sdkutil import get_table_data_type

storage_account_key_options = {'primary': 'key1', 'secondary': 'key2'}

Expand Down Expand Up @@ -44,21 +45,28 @@ def _query_account_key(account_name):


def _create_short_lived_blob_sas(account_name, account_key, container, blob):
SharedAccessSignature, BlobPermissions = \
get_sdk(ResourceType.DATA_STORAGE,
'sharedaccesssignature#SharedAccessSignature',
'blob.models#BlobPermissions')
if supported_api_version(ResourceType.DATA_STORAGE, min_api='2017-04-17'):
SharedAccessSignature = get_sdk(ResourceType.DATA_STORAGE, 'BlobSharedAccessSignature',
mod='blob.sharedaccesssignature')
else:
SharedAccessSignature = get_sdk(ResourceType.DATA_STORAGE, 'SharedAccessSignature',
mod='sharedaccesssignature')

BlobPermissions = get_sdk(ResourceType.DATA_STORAGE, 'blob.models#BlobPermissions')
expiry = (datetime.utcnow() + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%SZ')
sas = SharedAccessSignature(account_name, account_key)
return sas.generate_blob(container, blob, permission=BlobPermissions(read=True), expiry=expiry,
protocol='https')


def _create_short_lived_file_sas(account_name, account_key, share, directory_name, file_name):
SharedAccessSignature, BlobPermissions = \
get_sdk(ResourceType.DATA_STORAGE,
'sharedaccesssignature#SharedAccessSignature',
'blob.models#BlobPermissions')
if supported_api_version(ResourceType.DATA_STORAGE, min_api='2017-04-17'):
SharedAccessSignature = get_sdk(ResourceType.DATA_STORAGE, 'FileSharedAccessSignature',
mod='file.sharedaccesssignature')
else:
SharedAccessSignature = get_sdk(ResourceType.DATA_STORAGE, 'SharedAccessSignature',
mod='sharedaccesssignature')
BlobPermissions = get_sdk(ResourceType.DATA_STORAGE, 'blob.models#BlobPermissions')
# if dir is empty string change it to None
directory_name = directory_name if directory_name else None
expiry = (datetime.utcnow() + timedelta(days=1)).strftime('%Y-%m-%dT%H:%M:%SZ')
Expand All @@ -70,7 +78,7 @@ def _create_short_lived_file_sas(account_name, account_key, share, directory_nam
# region PARAMETER VALIDATORS

def validate_accept(namespace):
TablePayloadFormat = get_sdk(ResourceType.DATA_STORAGE, 'table#TablePayloadFormat')
TablePayloadFormat = get_table_data_type('table', 'TablePayloadFormat')
if namespace.accept:
formats = {
'none': TablePayloadFormat.JSON_NO_METADATA,
Expand Down Expand Up @@ -521,7 +529,7 @@ def validator(namespace):

def table_permission_validator(namespace):
""" A special case for table because the SDK associates the QUERY permission with 'r' """
TablePermissions = get_sdk(ResourceType.DATA_STORAGE, 'table#TablePermissions')
TablePermissions = get_table_data_type('table', 'TablePermissions')
if namespace.permission:
if set(namespace.permission) - set('raud'):
help_string = '(r)ead/query (a)dd (u)pdate (d)elete'
Expand Down Expand Up @@ -849,7 +857,7 @@ def ipv4_range_type(string):
def resource_type_type(string):
''' Validates that resource types string contains only a combination
of (s)ervice, (c)ontainer, (o)bject '''
ResourceTypes = get_sdk(ResourceType.DATA_STORAGE, 'models#ResourceTypes')
ResourceTypes = get_sdk(ResourceType.DATA_STORAGE, 'common.models#ResourceTypes')
if set(string) - set("sco"):
raise ValueError
return ResourceTypes(_str=''.join(set(string)))
Expand All @@ -858,7 +866,7 @@ def resource_type_type(string):
def services_type(string):
''' Validates that services string contains only a combination
of (b)lob, (q)ueue, (t)able, (f)ile '''
Services = get_sdk(ResourceType.DATA_STORAGE, 'models#Services')
Services = get_sdk(ResourceType.DATA_STORAGE, 'common.models#Services')
if set(string) - set("bqtf"):
raise ValueError
return Services(_str=''.join(set(string)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,25 @@
from azure.cli.core.commands import cli_command, VersionConstraint
from azure.cli.core.commands.arm import cli_generic_update_command
from azure.cli.core.util import empty_on_404
from azure.cli.core.profiles import supported_api_version, get_sdk, ResourceType
from azure.cli.core.profiles import supported_api_version, ResourceType, get_sdk
from .sdkutil import cosmosdb_table_exists

mgmt_path = 'azure.mgmt.storage.operations.storage_accounts_operations#StorageAccountsOperations.'
custom_path = 'azure.cli.command_modules.storage.custom#'
file_service_path = 'azure.multiapi.storage.file.fileservice#FileService.'
block_blob_path = 'azure.multiapi.storage.blob.blockblobservice#BlockBlobService.'
page_blob_path = 'azure.multiapi.storage.blob.pageblobservice#PageBlobService.'
base_blob_path = 'azure.multiapi.storage.blob.baseblobservice#BaseBlobService.'
table_path = 'azure.multiapi.storage.table.tableservice#TableService.'
queue_path = 'azure.multiapi.storage.queue.queueservice#QueueService.'

if cosmosdb_table_exists():
table_path = 'azure.multiapi.cosmosdb.table.tableservice#TableService.'
else:
table_path = 'azure.multiapi.storage.table.tableservice#TableService.'


def _dont_fail_not_exist(ex):
AzureMissingResourceHttpError = \
get_sdk(ResourceType.DATA_STORAGE, '_error#AzureMissingResourceHttpError')
AzureMissingResourceHttpError = get_sdk(ResourceType.DATA_STORAGE, 'common._error#AzureMissingResourceHttpError')
if isinstance(ex, AzureMissingResourceHttpError):
return None
else:
Expand Down Expand Up @@ -75,7 +79,7 @@ def _dont_fail_not_exist(ex):
mgmt_path + 'update', factory,
custom_function_op=custom_path + 'update_storage_account')

cli_storage_data_plane_command('storage account generate-sas', 'azure.multiapi.storage.cloudstorageaccount#CloudStorageAccount.generate_shared_access_signature', cloud_storage_account_service_factory)
cli_storage_data_plane_command('storage account generate-sas', 'azure.multiapi.storage.common#CloudStorageAccount.generate_shared_access_signature', cloud_storage_account_service_factory)

# container commands
factory = blob_data_service_factory
Expand Down Expand Up @@ -150,6 +154,7 @@ def _dont_fail_not_exist(ex):
cli_storage_data_plane_command('storage share policy show', custom_path + 'get_acl_policy', factory)
cli_storage_data_plane_command('storage share policy list', custom_path + 'list_acl_policies', factory, table_transformer=transform_acl_list_output)
cli_storage_data_plane_command('storage share policy update', custom_path + 'set_acl_policy', factory)
cli_storage_data_plane_command('storage share snapshot', file_service_path + 'snapshot_share', factory, resource_type=ResourceType.DATA_STORAGE, min_api='2017-04-17')

# directory commands
cli_storage_data_plane_command('storage directory create', file_service_path + 'create_directory', factory, transform=create_boolean_result_output_transformer('created'), table_transformer=transform_boolean_for_table)
Expand Down
Loading

0 comments on commit e79852b

Please sign in to comment.