Skip to content

Commit

Permalink
[storage-blob-preview] Support blob immutability policy and legal hold (
Browse files Browse the repository at this point in the history
Azure#3868)

* Support blob immutability policy and legal hold

* help

* Update src/storage-blob-preview/azext_storage_blob_preview/_help.py
  • Loading branch information
evelyn-ys authored Sep 7, 2021
1 parent 9d2e1ce commit bce122b
Show file tree
Hide file tree
Showing 8 changed files with 475 additions and 3 deletions.
5 changes: 5 additions & 0 deletions src/storage-blob-preview/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Release History
===============
0.6.1
++++++
* `az storage blob immutability-policy set/delete`: Extend/Lock/Unlock/Delete blob's immutability policy
* `az storage blob set-legal-hold`: Configure/Clear blob legal hold

0.6.0
++++++
* Remove `az storage account blob-service-properties` since all the preview arguments are supported in main azure cli
Expand Down
35 changes: 34 additions & 1 deletion src/storage-blob-preview/azext_storage_blob_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

helps['storage blob copy start'] = """
type: command
short-summary: List blobs in a given container.
short-summary: Start a copy blob job.
parameters:
- name: --source-uri -u
type: string
Expand Down Expand Up @@ -183,3 +183,36 @@
- name: Enable users to select/project on blob by providing simple query expressions and an input format
text: az storage blob query -c mycontainer -n myblob --query-expression "SELECT _2 from BlobStorage" --input-format parquet
"""

helps['storage blob immutability-policy'] = """
type: group
short-summary: Manage blob immutability policy.
"""

helps['storage blob immutability-policy set'] = """
type: command
short-summary: Set blob's immutability policy.
examples:
- name: Set an unlocked immutability policy.
text: az storage blob immutability-policy set --expiry-time 2021-09-07T08:00:00Z --policy-mode Unlocked -c mycontainer -n myblob --account-name mystorageaccount
- name: Lock a immutability policy.
text: az storage blob immutability-policy set --policy-mode Locked -c mycontainer -n myblob --account-name mystorageaccount
"""

helps['storage blob immutability-policy delete'] = """
type: command
short-summary: Delete blob's immutability policy.
examples:
- name: Delete an unlocked immutability policy.
text: az storage blob immutability-policy delete -c mycontainer -n myblob --account-name mystorageaccount --account-key 0000-0000
"""

helps['storage blob set-legal-hold'] = """
type: command
short-summary: Set blob legal hold.
examples:
- name: Configure blob legal hold.
text: az storage blob set-legal-hold --legal-hold -c mycontainer -n myblob --account-name mystorageaccount --account-key 0000-0000
- name: Clear blob legal hold.
text: az storage blob set-legal-hold --legal-hold false -c mycontainer -n myblob --account-name mystorageaccount --account-key 0000-0000
"""
16 changes: 15 additions & 1 deletion src/storage-blob-preview/azext_storage_blob_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from azure.cli.core.commands.parameters import (file_type, get_enum_type, get_three_state_flag)

from ._validators import (validate_metadata, get_permission_validator, get_permission_help_string,
validate_blob_type, validate_included_datasets_v2,
validate_blob_type, validate_included_datasets_v2, get_datetime_type,
add_download_progress_callback, add_upload_progress_callback,
validate_storage_data_plane_list, as_user_validator, blob_tier_validator)

Expand Down Expand Up @@ -248,6 +248,20 @@ def load_arguments(self, _): # pylint: disable=too-many-locals, too-many-statem
with self.argument_context('storage blob exists') as c:
c.register_blob_arguments()

with self.argument_context('storage blob set-legal-hold') as c:
c.register_blob_arguments()
c.argument('legal_hold', arg_type=get_three_state_flag(),
help='Specified if a legal hold should be set on the blob.')

with self.argument_context('storage blob immutability-policy delete') as c:
c.register_blob_arguments()

with self.argument_context('storage blob immutability-policy set') as c:
c.register_blob_arguments()
c.argument('expiry_time', type=get_datetime_type(False),
help='expiration UTC datetime in (Y-m-d\'T\'H:M:S\'Z\')')
c.argument('policy_mode', arg_type=get_enum_type(['Locked', 'Unlocked']), help='Lock or Unlock the policy')

with self.argument_context('storage blob filter') as c:
c.argument('filter_expression', options_list=['--tag-filter'])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ def get_custom_sdk(custom_module, client_factory, resource_type=ResourceType.DAT
g.storage_custom_command_oauth('copy start-batch', 'storage_blob_copy_batch', client_factory=cf_blob_service)
g.storage_custom_command_oauth('query', 'query_blob',
is_preview=True, min_api='2020-10-02')
g.storage_command_oauth('set-legal-hold', 'set_legal_hold', min_api='2020-10-02', is_preview=True)
g.storage_custom_command_oauth('immutability-policy set', 'set_blob_immutability_policy',
min_api='2020-10-02', is_preview=True)
g.storage_command_oauth('immutability-policy delete', 'delete_immutability_policy',
min_api='2020-10-02', is_preview=True)

with self.command_group('storage blob', blob_service_sdk, resource_type=CUSTOM_DATA_STORAGE_BLOB,
min_api='2019-12-12',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ def set_service_properties(client, delete_retention=None, delete_retention_perio
return client.get_service_properties()


def set_blob_immutability_policy(cmd, client, expiry_time=None, policy_mode=None, **kwargs):
ImmutabilityPolicy = cmd.get_models("_models#ImmutabilityPolicy", resource_type=CUSTOM_DATA_STORAGE_BLOB)
if not expiry_time and not policy_mode:
from azure.cli.core.azclierror import InvalidArgumentValueError
raise InvalidArgumentValueError('Please specify --expiry-time | --policy-mode')
immutability_policy = ImmutabilityPolicy(expiry_time=expiry_time, policy_mode=policy_mode)
return client.set_immutability_policy(immutability_policy=immutability_policy, **kwargs)


def storage_blob_copy_batch(cmd, client, source_client, container_name=None,
destination_path=None, source_container=None, source_share=None,
source_sas=None, pattern=None, dryrun=False, source_account_name=None,
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,39 @@ def test_storage_blob_versioning(self, resource_group, storage_account):
self.storage_cmd('storage blob list -c {} --include v', account_info, container)\
.assert_with_checks(JMESPathCheck('length(@)', count - 1))

@ResourceGroupPreparer(name_prefix='clitest')
@StorageAccountPreparer(name_prefix='version', kind='StorageV2', location='centraluseuap')
def test_storage_blob_vlm(self, resource_group, storage_account_info):
container = self.create_random_name(prefix='container', length=18)
blob = self.create_random_name(prefix='blob', length=18)
self.kwargs.update({
'container': container,
'blob': blob
})
# Enable blob versioning
self.cmd('storage account blob-service-properties update -n {sa} -g {rg} --enable-versioning')
# Enable vlm on container creation
self.cmd('storage container-rm create -n {container} --storage-account {sa} -g {rg} --enable-vlw')
# Prepare blob resource
file = self.create_temp_file(10)
self.storage_cmd('storage blob upload -c {} -f "{}" -n {} ', storage_account_info, container, file, blob)

# Test set immutability policy
from datetime import datetime, timedelta
expiry = (datetime.utcnow() + timedelta(hours=1)).strftime('%Y-%m-%dT%H:%MZ')
result = self.storage_cmd('storage blob immutability-policy set -n {} -c {} '
'--expiry-time {} --policy-mode Unlocked',
storage_account_info, blob, container, expiry).get_output_in_json()
self.assertEqual(result.get('immutability_policy_mode'), 'unlocked')
self.assertIsNotNone(result.get('immutability_policy_until_date'))
# Test delete immutability policy
self.storage_cmd('storage blob immutability-policy delete -n {} -c {}', storage_account_info, blob, container)
# Test set legal hold
self.storage_cmd('storage blob set-legal-hold --legal-hold -n {} -c {}', storage_account_info, blob, container)\
.assert_with_checks(JMESPathCheck('legal_hold', True))
self.storage_cmd('storage blob set-legal-hold --legal-hold false -n {} -c {}', storage_account_info, blob, container) \
.assert_with_checks(JMESPathCheck('legal_hold', False))

@ResourceGroupPreparer(name_prefix='clitest')
@StorageAccountPreparer(name_prefix='blobtag', kind='StorageV2', location='eastus2euap')
def test_storage_blob_tags_scenario(self, resource_group, storage_account):
Expand Down
2 changes: 1 addition & 1 deletion src/storage-blob-preview/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# TODO: Confirm this is the right version number you want and it matches your
# HISTORY.rst entry.
VERSION = '0.6.0'
VERSION = '0.6.1'

# The full list of classifiers is available at
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
Expand Down

0 comments on commit bce122b

Please sign in to comment.