From c4b7b6111f50f2f7fff89087f0f44777a2654acb Mon Sep 17 00:00:00 2001 From: zezha-msft Date: Tue, 2 Oct 2018 10:26:37 -0700 Subject: [PATCH 1/4] Added support for directory operations --- azure-storage-blob/ChangeLog.md | 5 + .../azure/storage/blob/_constants.py | 3 + .../azure/storage/blob/_deserialization.py | 5 + .../azure/storage/blob/_serialization.py | 9 + .../azure/storage/blob/baseblobservice.py | 273 +++++++++- tests/blob/test_directory.py | 393 ++++++++++++++ ...directory_with_hierarchical_namespace.yaml | 245 +++++++++ ...ectory_without_hierarchical_namespace.yaml | 499 ++++++++++++++++++ ...directory_with_hierarchical_namespace.yaml | 45 ++ ...ectory_without_hierarchical_namespace.yaml | 48 ++ tests/settings_fake.py | 3 + tests/testcase.py | 14 + 12 files changed, 1540 insertions(+), 2 deletions(-) create mode 100644 tests/blob/test_directory.py create mode 100644 tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml diff --git a/azure-storage-blob/ChangeLog.md b/azure-storage-blob/ChangeLog.md index 955aab5b..39e738d6 100644 --- a/azure-storage-blob/ChangeLog.md +++ b/azure-storage-blob/ChangeLog.md @@ -2,6 +2,10 @@ > See [BreakingChanges](BreakingChanges.md) for a detailed list of API breaks. +## Version XX.XX.XX + +- Added support for directory operations: create, rename, and delete. + ## Version 2.1.0: - Support for 2019-02-02 REST version. Please see our REST API documentation and blog for information about the related added features. @@ -15,6 +19,7 @@ - Updated dependency on azure-storage-common. ## Version 2.0.0: + - Support for 2018-11-09 REST version. Please see our REST API documentation and blog for information about the related added features. - Added support for append block from URL(synchronously) for append blobs. - Added support for update page from URL(synchronously) for page blobs. diff --git a/azure-storage-blob/azure/storage/blob/_constants.py b/azure-storage-blob/azure/storage/blob/_constants.py index f02e6d2a..b4232c26 100644 --- a/azure-storage-blob/azure/storage/blob/_constants.py +++ b/azure-storage-blob/azure/storage/blob/_constants.py @@ -12,3 +12,6 @@ # internal configurations, should not be changed _LARGE_BLOB_UPLOAD_MAX_READ_BUFFER_SIZE = 4 * 1024 * 1024 + +_BLOB_SERVICE_PUBLIC_CLOUD_HOST = 'blob.core.windows.net' +_DFS_SERVICE_PUBLIC_CLOUD_HOST = 'dfs.core.windows.net' diff --git a/azure-storage-blob/azure/storage/blob/_deserialization.py b/azure-storage-blob/azure/storage/blob/_deserialization.py index 8d243c46..7c35febb 100644 --- a/azure-storage-blob/azure/storage/blob/_deserialization.py +++ b/azure-storage-blob/azure/storage/blob/_deserialization.py @@ -648,3 +648,8 @@ def _parse_sub_response_to_http_response(sub_response): body_stream.close() return batch_http_sub_response + + +def _parse_continuation_token(response): + marker = response.headers.get('x-ms-continuation') + return marker if marker is not '' else None diff --git a/azure-storage-blob/azure/storage/blob/_serialization.py b/azure-storage-blob/azure/storage/blob/_serialization.py index 69b06013..c223673e 100644 --- a/azure-storage-blob/azure/storage/blob/_serialization.py +++ b/azure-storage-blob/azure/storage/blob/_serialization.py @@ -302,3 +302,12 @@ def _serialize_query(query): del serialized_query[-1] return ''.join(serialized_query) + + +# TODO to be removed after service update +def _add_file_or_directory_properties_header(properties_dict, request): + if properties_dict: + if not request.headers: + request.headers = {} + request.headers['x-ms-properties'] = \ + ",".join(["{}={}".format(str(name), _encode_base64(value)) for name, value in properties_dict.items()]) diff --git a/azure-storage-blob/azure/storage/blob/baseblobservice.py b/azure-storage-blob/azure/storage/blob/baseblobservice.py index 616ce1ad..0fcc765c 100644 --- a/azure-storage-blob/azure/storage/blob/baseblobservice.py +++ b/azure-storage-blob/azure/storage/blob/baseblobservice.py @@ -7,7 +7,10 @@ import uuid from abc import ABCMeta -from azure.common import AzureHttpError +from azure.common import ( + AzureHttpError, + AzureMissingResourceHttpError, +) from azure.storage.common._auth import ( _StorageSASAuthentication, @@ -51,6 +54,7 @@ Services, ListGenerator, _OperationContext, + LocationMode, ) from .sharedaccesssignature import ( BlobSharedAccessSignature, @@ -68,7 +72,9 @@ _parse_base_properties, _parse_account_information, _convert_xml_to_user_delegation_key, - _ingest_batch_response) + _ingest_batch_response, + _parse_continuation_token, +) from ._download_chunking import _download_blob_chunks from ._error import ( _ERROR_INVALID_LEASE_DURATION, @@ -81,6 +87,7 @@ _get_batch_request_delimiter, _serialize_batch_body, _validate_and_add_cpk_headers, + _add_file_or_directory_properties_header, ) from .models import ( BlobProperties, @@ -92,11 +99,14 @@ from ._constants import ( X_MS_VERSION, __version__ as package_version, + _BLOB_SERVICE_PUBLIC_CLOUD_HOST, + _DFS_SERVICE_PUBLIC_CLOUD_HOST, ) _CONTAINER_ALREADY_EXISTS_ERROR_CODE = 'ContainerAlreadyExists' _BLOB_NOT_FOUND_ERROR_CODE = 'BlobNotFound' _CONTAINER_NOT_FOUND_ERROR_CODE = 'ContainerNotFound' +_PATH_NOT_FOUND_ERROR_CODE = 'PathNotFound' if sys.version_info >= (3,): from io import BytesIO @@ -3567,3 +3577,262 @@ def undelete_blob(self, container_name, blob_name, timeout=None): } self._perform_request(request) + + # ----------------------------Methods related to directory manipulations---------------------------- # + + def create_directory(self, container_name, directory_path, proposed_lease_id=None, lease_id=None, metadata=None, + posix_permissions=None, posix_umask=None, timeout=None): + """ + Create a directory which can contain other directories or blobs. + + :param str container_name: + Name of existing container. + :param str directory_path: + Path of the directory to be created. Ex: 'dirfoo/dirbar'. + :param str proposed_lease_id: + Proposed lease ID, in a GUID string format. The Blob service + returns 400 (Invalid request) if the proposed lease ID is not + in the correct format. + :param str lease_id: + Required if the directory to be overwritten has an active lease. + :param metadata: + A dict with name_value pairs to associate with the + container as metadata. Example:{'Category':'test'} + :type metadata: dict(str, str) + :param str posix_permissions: + Optional and only valid if Hierarchical Namespace is enabled for the account. + Sets POSIX access permissions for the file owner, the file owning group, and others. + Each class may be granted read, write, or execute permission. + The sticky bit is also supported. + Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are supported. + :param str posix_umask: + Optional and only valid if Hierarchical Namespace is enabled for the account. + This umask restricts permission settings for file and directory, + and will only be applied when default Acl does not exist in parent directory. + If the umask bit has set, it means that the corresponding permission will be disabled. + Otherwise the corresponding permission will be determined by the permission. + A 4-digit octal notation (e.g. 0022) is supported here. + If no umask was specified, a default umask - 0027 will be used. + :param int timeout: + The timeout parameter is expressed in seconds. + :return: ETag and last modified time of the new directory. + :rtype: :class:`~azure.storage.blob.models.ResourceProperties` + """ + + _validate_not_none('container_name', container_name) + _validate_not_none('directory_path', directory_path) + + request = HTTPRequest() + # TODO remove endpoint swapping after service update + request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) + request.method = 'PUT' + request.path = _get_path(container_name, directory_path) + request.query = { + 'resource': 'directory', + 'timeout': _int_to_str(timeout), + } + request.headers = { + 'x-ms-proposed-lease-id': _to_str(proposed_lease_id), + 'x-ms-lease-id': _to_str(lease_id), + 'x-ms-permissions': _to_str(posix_permissions), + 'x-ms-umask': _to_str(posix_umask), + } + # TODO add test cases for lease and metadata + _add_file_or_directory_properties_header(metadata, request) + return self._perform_request(request, parser=_parse_base_properties) + + def delete_directory(self, container_name, directory_path, fail_not_exist=False, recursive=True, marker=None, + lease_id=None, if_modified_since=None, if_unmodified_since=None, if_match=None, + if_none_match=None, timeout=None): + """ + Delete a directory. This operation's behavior is different depending on whether Hierarchical Namespace + is enabled; if yes, then the delete operation can be atomic and instantaneous; + if not, the operation is performed in batches and a continuation token could be returned. + + :param str container_name: + Name of existing container. + :param str directory_path: + Path of the directory to be deleted. Ex: 'dirfoo/dirbar'. + :param fail_not_exist: + Specify whether to throw an exception when the directory doesn't exist. + :param recursive: + If "true", all paths beneath the directory will be deleted. + If "false" and the directory is non-empty, an error occurs. + :param marker: + Optional. When deleting a directory without the Hierarchical Namespace, + the number of paths that are deleted with each invocation is limited. + If the number of paths to be deleted exceeds this limit, + a continuation token is returned. When a continuation token is returned, + it must be specified in a subsequent invocation of the delete operation to continue deleting the directory. + :param str lease_id: + Required if the directory has an active lease. + :param datetime if_modified_since: + A DateTime value. Azure expects the date value passed in to be UTC. + If timezone is included, any non-UTC datetimes will be converted to UTC. + If a date is passed in without timezone info, it is assumed to be UTC. + Specify this header to perform the operation only + if the resource has been modified since the specified time. + :param datetime if_unmodified_since: + A DateTime value. Azure expects the date value passed in to be UTC. + If timezone is included, any non-UTC datetimes will be converted to UTC. + If a date is passed in without timezone info, it is assumed to be UTC. + Specify this header to perform the operation only if + the resource has not been modified since the specified date/time. + :param str if_match: + An ETag value, or the wildcard character (*). Specify this header to perform + the operation only if the resource's ETag matches the value specified. + :param str if_none_match: + An ETag value, or the wildcard character (*). Specify this header + to perform the operation only if the resource's ETag does not match + the value specified. + :param int timeout: + The timeout parameter is expressed in seconds. + :return: + (True, marker) if the directory is successfully deleted. Otherwise return (False, None). + :rtype: (bool, str) + """ + _validate_not_none('container_name', container_name) + _validate_not_none('directory_path', directory_path) + + request = HTTPRequest() + # TODO remove endpoint swapping after service update + request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) + request.method = 'DELETE' + request.path = _get_path(container_name, directory_path) + request.query = { + 'recursive': _to_str(recursive), + 'continuation': _to_str(marker), + 'timeout': _int_to_str(timeout), + } + request.headers = { + 'x-ms-lease-id': _to_str(lease_id), + 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), + 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), + 'If-Match': _to_str(if_match), + 'If-None-Match': _to_str(if_none_match), + } + # TODO add test cases for lease + if not fail_not_exist: + try: + return True, self._perform_request(request, expected_errors=[_PATH_NOT_FOUND_ERROR_CODE], + parser=_parse_continuation_token) + except AzureMissingResourceHttpError as ex: + _dont_fail_not_exist(ex) + return False, None + else: + return True, self._perform_request(request, parser=_parse_continuation_token) + + def rename_directory(self, container_name, new_directory_path, source_directory_path, + mode=None, marker=None, lease_id=None, source_lease_id=None, + metadata=None, source_if_modified_since=None, source_if_unmodified_since=None, + source_if_match=None, source_if_none_match=None, timeout=None): + """ + Rename a directory which can contain other directories or blobs. + + :param str container_name: + Name of existing container. + :param str new_directory_path: + New path for source_directory_path. Ex: 'dirfoo/dirsubfoo'. + :param str source_directory_path: + Directory to be renamed. Ex: 'dirfoo/dirbar'. + :param mode: + Optional. Valid only when namespace is enabled. + This parameter determines the behavior of the rename operation. + The value must be "legacy" or "posix", and the default value will be "posix". + A "posix" rename is done atomically; a "legacy" rename is done in batches and could return a marker. + :param marker: + Optional. When renaming a directory, the number of paths that are renamed with each invocation is limited. + If the number of paths to be renamed exceeds this limit, + a continuation token is returned. When a continuation token is returned, + it must be specified in a subsequent invocation of the rename operation to continue renaming the directory. + :param str lease_id: + Optional. A lease ID for the new_directory_path. + The new_directory_path must have an active lease and the lease ID must match. + :param str source_lease_id: + Optional. A lease ID for the source_directory_path. + The source_directory_path must have an active lease and the lease ID must match. + :param metadata: + Optional. A dict with name_value pairs to associate with the directory as metadata. + Example:{'Category':'test'}. + If metadata is specified, it will overwrite the existing metadata; + otherwise, the existing metadata will be preserved. + :type metadata: dict(str, str) + :param datetime source_if_modified_since: + Optional. A date and time value. Specify this header to perform the rename operation + only if the source has been modified since the specified date and time. + :param datetime source_if_unmodified_since: + Optional. A date and time value. Specify this header to perform the rename operation + only if the source has not been modified since the specified date and time. + :param str source_if_match: + Optional. An ETag value. Specify this header to perform the rename operation + only if the source's ETag matches the value specified. + :param str source_if_none_match: + Optional. An ETag value or the special wildcard ("*") value. + Specify this header to perform the rename operation + only if the source's ETag does not match the value specified. + :param int timeout: + The timeout parameter is expressed in seconds. + :return: + A continuation marker if applicable. Otherwise return None. + :rtype: str + """ + _validate_not_none('source_directory_path', source_directory_path) + _validate_not_none('new_directory_path', new_directory_path) + + request = HTTPRequest() + # TODO remove endpoint swapping after service update + request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) + request.method = 'PUT' + request.path = _get_path(container_name, new_directory_path) + request.query = { + 'mode': mode, + 'continuation': _to_str(marker), + 'timeout': _int_to_str(timeout), + } + request.headers = { + 'x-ms-rename-source': _get_path(container_name, source_directory_path), + 'x-ms-lease-id': _to_str(lease_id), + 'x-ms-source-lease-id': _to_str(source_lease_id), + 'x-ms-source-if-modified-since': _datetime_to_utc_string(source_if_modified_since), + 'x-ms-source-if-unmodified-since': _datetime_to_utc_string(source_if_unmodified_since), + 'x-ms-source-if-match': _to_str(source_if_match), + 'x-ms-source-if-none-match': _to_str(source_if_none_match), + } + # TODO add test cases for lease and metadata + _add_file_or_directory_properties_header(metadata, request) + return self._perform_request(request, parser=_parse_continuation_token) + + # ----------------------------Helpers for directory manipulations---------------------------- # + @staticmethod + def _swap_blob_endpoints(host_locations): + # Note that only the primary endpoint is supported for the DFS endpoint + return {LocationMode.PRIMARY: host_locations[LocationMode.PRIMARY].replace(_BLOB_SERVICE_PUBLIC_CLOUD_HOST, + _DFS_SERVICE_PUBLIC_CLOUD_HOST, 1)} + + # TODO remove after service update, needed for testing against HN-enabled account for the moment + def _create_file_system(self, filesystem_name, timeout=None): + _validate_not_none('filesystem_name', filesystem_name) + request = HTTPRequest() + request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) + request.method = 'PUT' + request.path = _get_path(filesystem_name) + request.query = { + 'resource': 'filesystem', + 'timeout': _int_to_str(timeout), + } + self._perform_request(request) + return True + + # TODO remove after service update, needed for testing against HN-enabled account for the moment + def _delete_file_system(self, filesystem_name, timeout=None): + _validate_not_none('filesystem_name', filesystem_name) + request = HTTPRequest() + request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) + request.method = 'DELETE' + request.path = _get_path(filesystem_name) + request.query = { + 'resource': 'filesystem', + 'timeout': _int_to_str(timeout), + } + self._perform_request(request) + return True diff --git a/tests/blob/test_directory.py b/tests/blob/test_directory.py new file mode 100644 index 00000000..6992c6e2 --- /dev/null +++ b/tests/blob/test_directory.py @@ -0,0 +1,393 @@ +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +import datetime + +from azure.common import ( + AzureHttpError, + AzureMissingResourceHttpError, + AzureConflictHttpError, +) + +from azure.storage.blob import ( + BlockBlobService, +) +from azure.storage.blob.baseblobservice import ( + BaseBlobService, +) +from azure.storage.common import ( + LocationMode, + ExponentialRetry, +) +from tests.testcase import ( + StorageTestCase, + TestMode, + record, +) + + +class StorageDirectoryTest(StorageTestCase): + def setUp(self): + super(StorageDirectoryTest, self).setUp() + self.bs = self._create_storage_service(BlockBlobService, self.settings) + self.bs_namespace = self._create_storage_service_with_hierarchical_namespace(BlockBlobService, self.settings) + + # shorten retries for faster failures + self.bs.retry = ExponentialRetry(initial_backoff=1, increment_base=2, max_attempts=3).retry + self.bs_namespace.retry = ExponentialRetry(initial_backoff=1, increment_base=2, max_attempts=3).retry + + self.container_name = self.get_resource_name('utcontainer') + if not self.is_playback(): + self.bs.create_container(self.container_name) + self.bs_namespace._create_file_system(self.container_name) + + def tearDown(self): + if not self.is_playback(): + self.bs.delete_container(self.container_name) + self.bs_namespace._delete_file_system(self.container_name) + return super(StorageDirectoryTest, self).tearDown() + + def _get_directory_reference(self, suffix=""): + return self.get_resource_name("directorytest" + suffix) + + def _get_blob_reference(self, directory_path): + return "{}/{}".format(directory_path, self.get_resource_name("blob")) + + def _create_sub_dirs(self, blob_service, directory_name, num_of_sub_dir): + import concurrent.futures + import itertools + # Use a thread pool because it is too slow otherwise + with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: + def create_sub_dir(): + blob_service.create_directory(self.container_name, + "{}/{}".format(directory_name, self._get_directory_reference())) + + futures = {executor.submit(create_sub_dir) for _ in itertools.repeat(None, num_of_sub_dir)} + concurrent.futures.wait(futures) + + def test_host_swapping(self): + # Arrange + example_blob_hosts = {LocationMode.PRIMARY: "account.blob.core.windows.net", + LocationMode.SECONDARY: "account-secondary.blob.core.windows.net"} + + # Act + swapped_hosts = BaseBlobService._swap_blob_endpoints(example_blob_hosts) + + # Assert + # DFS only supports the primary endpoint + self.assertEqual(len(swapped_hosts), 1) + self.assertEqual(swapped_hosts[LocationMode.PRIMARY], "account.dfs.core.windows.net") + + @record + def test_create_delete_directory_without_hierarchical_namespace(self): + self.create_delete_directory_simple_test_implementation(self.bs) + self.create_directory_with_permission_implementation(self.bs, hierarchical_namespace_enabled=False) + self.delete_directory_marker_test_implementation(self.bs) + self.delete_directory_recursive_test_implementation(self.bs) + self.delete_directory_access_conditions_test_implementation(self.bs) + + @record + def test_create_delete_directory_with_hierarchical_namespace(self): + self.create_delete_directory_simple_test_implementation(self.bs_namespace) + self.create_directory_with_permission_implementation(self.bs_namespace, hierarchical_namespace_enabled=True) + self.delete_directory_recursive_test_implementation(self.bs_namespace) + + # TODO encountering error 500 for if_match and if_none_match condition, uncomment after service fix + # self.delete_directory_access_conditions_test_implementation(self.bs_namespace) + + def create_delete_directory_simple_test_implementation(self, blob_service): + # Arrange + directory_name = self._get_directory_reference() + metadata = {"foo": "bar", "mama": "mia"} + + # Act + props = blob_service.create_directory(self.container_name, directory_name, metadata=metadata) + + # Assert + self.assertIsNotNone(props) + self.assertIsNotNone(props.etag) + self.assertIsNotNone(props.last_modified) + + # Act + # Creating the same directory again + self.sleep(1) + props2 = blob_service.create_directory(self.container_name, directory_name) + + # Assert + self.assertIsNotNone(props2) + self.assertNotEqual(props.etag, props2.etag) + self.assertNotEqual(props.last_modified, props2.last_modified) + + # Act + deleted, marker = blob_service.delete_directory(self.container_name, directory_name) + + # Assert + self.assertTrue(deleted) + + # Act + # Delete an already non-existing directory + deleted, marker = blob_service.delete_directory(self.container_name, directory_name) + + # Assert + self.assertFalse(deleted) + + # Act + # Delete an already non-existing directory, but with let it throw an error + with self.assertRaises(AzureMissingResourceHttpError): + blob_service.delete_directory(self.container_name, directory_name, fail_not_exist=True) + + def create_directory_with_permission_implementation(self, blob_service, hierarchical_namespace_enabled): + # Arrange + directory_name = self._get_directory_reference() + + if not hierarchical_namespace_enabled: + # Act + # Create with permission and umask is expected to fail due to the lack of namespace service + with self.assertRaises(AzureHttpError): + blob_service.create_directory(self.container_name, directory_name, + posix_permissions='rwxrw-rw-', posix_umask='0022') + else: + # Act + # Create with permission and umask + props = blob_service.create_directory(self.container_name, directory_name, + posix_permissions='rwxrw-rw-', posix_umask='0022') + + # Assert + self.assertIsNotNone(props) + self.assertIsNotNone(props.etag) + self.assertIsNotNone(props.last_modified) + + # Cleanup + blob_service.delete_directory(self.container_name, directory_name) + + def delete_directory_marker_test_implementation(self, blob_service): + # this test is too costly(too many requests to the service) and should only run in live mode + if TestMode.need_recording_file(self.test_mode): + return + + # Arrange + directory_name = self._get_directory_reference() + blob_service.create_directory(self.container_name, directory_name) + + # Create enough sub-directories to trigger the service to return a marker + self._create_sub_dirs(blob_service, directory_name, num_of_sub_dir=1000) + + # Act + deleted, marker = blob_service.delete_directory(self.container_name, directory_name) + + # Assert + self.assertTrue(deleted) + self.assertIsNotNone(marker) + + # Act + # Continue the delete + count = 0 + while marker is not None: + deleted, new_marker = blob_service.delete_directory(self.container_name, directory_name, marker=marker) + + # Assert + self.assertTrue(deleted) + self.assertNotEqual(marker, new_marker) + marker = new_marker + count += 1 + + self.logger.info("Took {} calls to finish deleting.".format(count)) + + def delete_directory_recursive_test_implementation(self, blob_service): + # Arrange + directory_name = self._get_directory_reference() + sub_directory_name = self._get_directory_reference() + blob_service.create_directory(self.container_name, directory_name) + blob_service.create_directory(self.container_name, "{}/{}".format(directory_name, sub_directory_name)) + + # Act + with self.assertRaises(AzureConflictHttpError): + blob_service.delete_directory(self.container_name, directory_name, recursive=False) + + deleted, marker = blob_service.delete_directory(self.container_name, directory_name, recursive=True) + self.assertTrue(deleted) + self.assertIsNone(marker) + + def delete_directory_access_conditions_test_implementation(self, blob_service): + # Arrange + directory_name = self._get_directory_reference() + props = blob_service.create_directory(self.container_name, directory_name) + + # if_match fails + with self.assertRaises(AzureHttpError): + blob_service.delete_directory(self.container_name, directory_name, if_match='0x111111111111111') + + # if_match succeeds + deleted, marker = blob_service.delete_directory(self.container_name, directory_name, + if_match=props.etag) + self.assertTrue(deleted) + self.assertIsNone(marker) + + # Arrange + props = blob_service.create_directory(self.container_name, directory_name) + + # if_none_match fails + with self.assertRaises(AzureHttpError): + blob_service.delete_directory(self.container_name, directory_name, if_none_match=props.etag) + + # if_none_match succeeds + deleted, marker = blob_service.delete_directory(self.container_name, directory_name, + if_none_match='0x111111111111111') + self.assertTrue(deleted) + self.assertIsNone(marker) + + # Arrange + props = blob_service.create_directory(self.container_name, directory_name) + + # if_modified_since fails + with self.assertRaises(AzureHttpError): + blob_service.delete_directory(self.container_name, directory_name, if_modified_since=props.last_modified) + + # if_modified_since succeeds + deleted, marker = blob_service.delete_directory(self.container_name, directory_name, + if_modified_since=props.last_modified - datetime.timedelta( + minutes=1)) + self.assertTrue(deleted) + self.assertIsNone(marker) + + # Arrange + props = blob_service.create_directory(self.container_name, directory_name) + + # if_unmodified_since fails + with self.assertRaises(AzureHttpError): + blob_service.delete_directory(self.container_name, directory_name, + if_unmodified_since=props.last_modified - datetime.timedelta( + minutes=1)) + + # if_unmodified_since succeeds + deleted, marker = blob_service.delete_directory(self.container_name, directory_name, + if_unmodified_since=props.last_modified) + self.assertTrue(deleted) + self.assertIsNone(marker) + + @record + def test_rename_directory_without_hierarchical_namespace(self): + self.rename_directory_simple_test_implementation(self.bs) + self.rename_directory_marker_test_implementation(self.bs) + + # TODO error 500s get thrown for precondition fail, uncomment after service fix + # self.rename_directory_access_conditions_test_implementation(self.bs) + + @record + def test_rename_directory_with_hierarchical_namespace(self): + self.rename_directory_simple_test_implementation(self.bs_namespace) + + # TODO access conditions get ignored, uncomment after service fix + # self.rename_directory_access_conditions_test_implementation(self.bs_namespace) + + def rename_directory_simple_test_implementation(self, blob_service): + # Arrange + directory_name = self._get_directory_reference() + + # Act + props = blob_service.create_directory(self.container_name, directory_name) + + # Assert + self.assertIsNotNone(props) + self.assertIsNotNone(props.etag) + self.assertIsNotNone(props.last_modified) + + # Arrange + new_directory_name = self._get_directory_reference("new") + + # Act + marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name) + + # Assert + self.assertIsNone(marker) + + def rename_directory_marker_test_implementation(self, blob_service): + # this test is too costly(too many requests to the service) and should only run in live mode + if TestMode.need_recording_file(self.test_mode): + return + + # Arrange + directory_name = self._get_directory_reference() + new_directory_name = self._get_directory_reference("new") + blob_service.create_directory(self.container_name, directory_name) + + # Create enough sub-directories to trigger the service to return a marker + self._create_sub_dirs(blob_service, directory_name, num_of_sub_dir=1000) + + # Act + marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name) + + # Assert + self.assertIsNotNone(marker) + + # Act + # Continue the rename + count = 0 + while marker is not None: + new_marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + marker=marker) + self.assertNotEqual(marker, new_marker) + marker = new_marker + count += 1 + + self.logger.info("Took {} calls to finish renaming.".format(count)) + + def rename_directory_access_conditions_test_implementation(self, blob_service): + # Arrange + directory_name = self._get_directory_reference() + new_directory_name = self._get_directory_reference("new") + props = blob_service.create_directory(self.container_name, directory_name) + + # if_match fails + with self.assertRaises(AzureHttpError): + blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_match='0x111111111111111') + + # if_match succeeds + marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_match=props.etag) + self.assertIsNone(marker) + + # Arrange + props = blob_service.create_directory(self.container_name, directory_name) + + # if_none_match fails + with self.assertRaises(AzureHttpError): + blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_none_match=props.etag) + + # if_none_match succeeds + marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_none_match='0x111111111111111') + self.assertIsNone(marker) + + # Arrange + props = blob_service.create_directory(self.container_name, directory_name) + + # if_modified_since fails + with self.assertRaises(AzureHttpError): + blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_modified_since=props.last_modified) + + # if_modified_since succeeds + marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_modified_since=props.last_modified - datetime.timedelta( + minutes=1)) + self.assertIsNone(marker) + + # Arrange + props = blob_service.create_directory(self.container_name, directory_name) + + # if_unmodified_since fails + with self.assertRaises(AzureHttpError): + blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_unmodified_since=props.last_modified - datetime.timedelta( + minutes=1)) + + # if_unmodified_since succeeds + marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, + source_if_unmodified_since=props.last_modified) + self.assertIsNone(marker) diff --git a/tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml new file mode 100644 index 00000000..b3aa214c --- /dev/null +++ b/tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml @@ -0,0 +1,245 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8d17ae72-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:10 GMT'] + x-ms-properties: ['foo=YmFy,mama=bWlh'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:11 GMT'] + ETag: ['"0x8D6297571A4A833"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:11 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff34-001f-00a9-0c5e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e0badec-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + ETag: ['"0x8D62975724499BF"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff35-001f-00a9-0d5e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e123e46-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff36-001f-00a9-0e5e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e17878e-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True + response: + body: {string: '{"error":{"code":"PathNotFound","message":"The specified path + does not exist.\nRequestId:3e5fff37-001f-00a9-0f5e-5b38ea000000\nTime:2018-10-03T21:16:12.5240091Z"}}'} + headers: + Content-Length: ['163'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [3e5fff37-001f-00a9-0f5e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e1ccd7a-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True + response: + body: {string: '{"error":{"code":"PathNotFound","message":"The specified path + does not exist.\nRequestId:3e5fff38-001f-00a9-105e-5b38ea000000\nTime:2018-10-03T21:16:12.5570393Z"}}'} + headers: + Content-Length: ['163'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [3e5fff38-001f-00a9-105e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e21d572-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-permissions: [rwxrw-rw-] + x-ms-umask: ['0022'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + ETag: ['"0x8D6297572596435"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff39-001f-00a9-115e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e270466-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff3a-001f-00a9-125e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e2c548e-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + ETag: ['"0x8D629757263E4A5"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff3b-001f-00a9-135e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e316122-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21/directorytest1c491d21?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + ETag: ['"0x8D6297572694BF7"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff3c-001f-00a9-145e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e36d1ca-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=False + response: + body: {string: '{"error":{"code":"DirectoryNotEmpty","message":"The recursive + query parameter value must be true to delete a non-empty directory.\nRequestId:3e5fff3d-001f-00a9-155e-5b38ea000000\nTime:2018-10-03T21:16:12.7272015Z"}}'} + headers: + Content-Length: ['215'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [DirectoryNotEmpty] + x-ms-request-id: [3e5fff3d-001f-00a9-155e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 409, message: The recursive query parameter value must be true + to delete a non-empty directory.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [8e3bee80-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3e5fff3e-001f-00a9-165e-5b38ea000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml new file mode 100644 index 00000000..8a583703 --- /dev/null +++ b/tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml @@ -0,0 +1,499 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [953e54a2-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:24 GMT'] + x-ms-properties: ['foo=YmFy,mama=bWlh'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:23 GMT'] + ETag: ['"0x8D6297579AE2EAC"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:24 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cb7-201f-0001-2f5e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [961ac356-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:25 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + ETag: ['"0x8D629757A58510E"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cb8-201f-0001-305e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [962c08aa-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cb9-201f-0001-315e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [964aecfc-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: '{"error":{"code":"PathNotFound","message":"The specified path + does not exist.\nRequestId:695e3cba-201f-0001-325e-5bcde7000000\nTime:2018-10-03T21:16:26.3077942Z"}}'} + headers: + Content-Length: ['163'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [695e3cba-201f-0001-325e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [965ad63a-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: '{"error":{"code":"PathNotFound","message":"The specified path + does not exist.\nRequestId:695e3cbb-201f-0001-335e-5bcde7000000\nTime:2018-10-03T21:16:26.4138003Z"}}'} + headers: + Content-Length: ['163'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [695e3cbb-201f-0001-335e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96697be0-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-permissions: [rwxrw-rw-] + x-ms-umask: ['0022'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: '{"error":{"code":"UnsupportedHeader","message":"One of the headers + specified in the request is not supported.\nRequestId:695e3cbc-201f-0001-345e-5bcde7000000\nTime:2018-10-03T21:16:26.5047893Z"}}'} + headers: + Content-Length: ['195'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [UnsupportedHeader] + x-ms-request-id: [695e3cbc-201f-0001-345e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 400, message: One of the headers specified in the request is not + supported.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96775490-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + ETag: ['"0x8D629757AB39149"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cbd-201f-0001-355e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [968777e4-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + ETag: ['"0x8D629757AC40B29"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cbe-201f-0001-365e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [969728b0-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=False + response: + body: {string: '{"error":{"code":"DirectoryNotEmpty","message":"The recursive + query parameter value must be true to delete a non-empty directory.\nRequestId:695e3cbf-201f-0001-375e-5bcde7000000\nTime:2018-10-03T21:16:26.8158344Z"}}'} + headers: + Content-Length: ['215'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [DirectoryNotEmpty] + x-ms-request-id: [695e3cbf-201f-0001-375e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 409, message: The recursive query parameter value must be true + to delete a non-empty directory.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96a6d558-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cc0-201f-0001-385e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96b62332-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + ETag: ['"0x8D629757AF29517"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cc1-201f-0001-395e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Match: ['0x111111111111111'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96c5ac6c-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified + using HTTP conditional header(s) is not met.\nRequestId:695e3cc2-201f-0001-3a5e-5bcde7000000\nTime:2018-10-03T21:16:27.1268204Z"}}'} + headers: + Content-Length: ['200'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [695e3cc2-201f-0001-3a5e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Match: ['"0x8D629757AF29517"'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96d6955e-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cc3-201f-0001-3b5e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96e6129a-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + ETag: ['"0x8D629757B227FC4"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cc4-201f-0001-3c5e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-None-Match: ['"0x8D629757B227FC4"'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [96f59f6c-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified + using HTTP conditional header(s) is not met.\nRequestId:695e3cc5-201f-0001-3d5e-5bcde7000000\nTime:2018-10-03T21:16:27.4248079Z"}}'} + headers: + Content-Length: ['200'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [695e3cc5-201f-0001-3d5e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-None-Match: ['0x111111111111111'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [97039d2e-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cc6-201f-0001-3e5e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [9712af30-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + ETag: ['"0x8D629757B4EE606"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cc7-201f-0001-3f5e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Modified-Since: ['Wed, 03 Oct 2018 21:16:27 GMT'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [9721ff76-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified + using HTTP conditional header(s) is not met.\nRequestId:695e3cc8-201f-0001-405e-5bcde7000000\nTime:2018-10-03T21:16:27.7207932Z"}}'} + headers: + Content-Length: ['200'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [695e3cc8-201f-0001-405e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Modified-Since: ['Wed, 03 Oct 2018 21:15:27 GMT'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [9730eaa4-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cc9-201f-0001-415e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [973ffe9a-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + ETag: ['"0x8D629757B7C3750"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3cca-201f-0001-425e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Unmodified-Since: ['Wed, 03 Oct 2018 21:15:27 GMT'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [974f369e-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified + using HTTP conditional header(s) is not met.\nRequestId:695e3ccb-201f-0001-435e-5bcde7000000\nTime:2018-10-03T21:16:28.0117962Z"}}'} + headers: + Content-Length: ['200'] + Content-Type: [application/json;charset=utf-8] + Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [695e3ccb-201f-0001-435e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Unmodified-Since: ['Wed, 03 Oct 2018 21:16:27 GMT'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [975d2fb0-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:28 GMT'] + x-ms-version: ['2018-06-17'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:28 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [695e3ccc-201f-0001-445e-5bcde7000000] + x-ms-version: ['2018-06-17'] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml new file mode 100644 index 00000000..309c41c7 --- /dev/null +++ b/tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml @@ -0,0 +1,45 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [98df3342-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:30 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5bc51a53/directorytest5bc51a53?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:30 GMT'] + ETag: ['"0x8D629757D814599"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:31 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a041ac47-901f-0006-5d5e-5b1a7a000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [995bcb6e-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:31 GMT'] + x-ms-rename-source: [/utcontainer5bc51a53/directorytest5bc51a53] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5bc51a53/directorytestnew5bc51a53 + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:30 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a041ac48-901f-0006-5e5e-5b1a7a000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +version: 1 diff --git a/tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml new file mode 100644 index 00000000..dd00e27b --- /dev/null +++ b/tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml @@ -0,0 +1,48 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [9a2dee50-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:32 GMT'] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerb0731bab/directorytestb0731bab?resource=directory + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:32 GMT'] + ETag: ['"0x8D629757E92ED44"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:33 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [3eb87f4f-301f-0022-685e-5b5724000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] + x-ms-client-request-id: [9a65caf0-c751-11e8-a389-f218981b70f8] + x-ms-date: ['Wed, 03 Oct 2018 21:16:33 GMT'] + x-ms-rename-source: [/utcontainerb0731bab/directorytestb0731bab] + x-ms-version: ['2018-06-17'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerb0731bab/directorytestnewb0731bab + response: + body: {string: ''} + headers: + Content-Length: ['0'] + Date: ['Wed, 03 Oct 2018 21:16:32 GMT'] + ETag: ['"0x8D629757EA31AA2"'] + Last-Modified: ['Wed, 03 Oct 2018 21:16:33 GMT'] + Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-continuation: [''] + x-ms-request-id: [3eb87f50-301f-0022-695e-5b5724000000] + x-ms-version: ['2018-06-17'] + status: {code: 201, message: Created} +version: 1 diff --git a/tests/settings_fake.py b/tests/settings_fake.py index ce0833aa..b7dcac22 100644 --- a/tests/settings_fake.py +++ b/tests/settings_fake.py @@ -9,6 +9,8 @@ STORAGE_ACCOUNT_NAME = "storagename" STORAGE_ACCOUNT_KEY = "NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==" +HIERARCHICAL_NAMESPACE_ACCOUNT_NAME = "hierarchicalnamespacestoragename" +HIERARCHICAL_NAMESPACE_ACCOUNT_KEY = "NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==" BLOB_STORAGE_ACCOUNT_NAME = "blobstoragename" BLOB_STORAGE_ACCOUNT_KEY = "NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==" REMOTE_STORAGE_ACCOUNT_NAME = "remotestoragename" @@ -26,6 +28,7 @@ CONNECTION_STRING = "" BLOB_CONNECTION_STRING = "" PREMIUM_CONNECTION_STRING = "" +HIERARCHICAL_NAMESPACE_CONNECTION_STRING = "" # Use 'https' or 'http' protocol for sending requests, 'https' highly recommended PROTOCOL = "https" diff --git a/tests/testcase.py b/tests/testcase.py index 7b61755a..216b86bd 100644 --- a/tests/testcase.py +++ b/tests/testcase.py @@ -172,6 +172,18 @@ def _create_storage_service(self, service_class, settings): self._set_test_proxy(service, settings) return service + def _create_storage_service_with_hierarchical_namespace(self, service_class, settings): + if settings.HIERARCHICAL_NAMESPACE_CONNECTION_STRING: + service = service_class(connection_string=settings.HIERARCHICAL_NAMESPACE_CONNECTION_STRING) + else: + service = service_class( + settings.HIERARCHICAL_NAMESPACE_ACCOUNT_NAME, + settings.HIERARCHICAL_NAMESPACE_ACCOUNT_KEY, + protocol=settings.PROTOCOL, + ) + self._set_test_proxy(service, settings) + return service + # for blob storage account def _create_storage_service_for_blob_storage_account(self, service_class, settings): if hasattr(settings, 'BLOB_CONNECTION_STRING') and settings.BLOB_CONNECTION_STRING != "": @@ -304,6 +316,8 @@ def _scrub(self, val): old_to_new_dict = { self.settings.STORAGE_ACCOUNT_NAME: self.fake_settings.STORAGE_ACCOUNT_NAME, self.settings.STORAGE_ACCOUNT_KEY: self.fake_settings.STORAGE_ACCOUNT_KEY, + self.settings.HIERARCHICAL_NAMESPACE_ACCOUNT_NAME: self.fake_settings.HIERARCHICAL_NAMESPACE_ACCOUNT_NAME, + self.settings.HIERARCHICAL_NAMESPACE_ACCOUNT_KEY: self.fake_settings.HIERARCHICAL_NAMESPACE_ACCOUNT_KEY, self.settings.BLOB_STORAGE_ACCOUNT_NAME: self.fake_settings.BLOB_STORAGE_ACCOUNT_NAME, self.settings.BLOB_STORAGE_ACCOUNT_KEY: self.fake_settings.BLOB_STORAGE_ACCOUNT_KEY, self.settings.REMOTE_STORAGE_ACCOUNT_KEY: self.fake_settings.REMOTE_STORAGE_ACCOUNT_KEY, From 612ac23bada6aa09e083770fb92362629ef70c09 Mon Sep 17 00:00:00 2001 From: zezha-msft Date: Fri, 7 Jun 2019 00:51:19 -0700 Subject: [PATCH 2/4] Added APIs to set and get access control properties for paths --- azure-storage-blob/ChangeLog.md | 2 +- .../azure/storage/blob/_deserialization.py | 14 +- .../azure/storage/blob/baseblobservice.py | 206 +++++-- .../azure/storage/blob/models.py | 21 + .../blob/{test_directory.py => test_path.py} | 212 +++++-- ...directory_with_hierarchical_namespace.yaml | 245 -------- ...ectory_without_hierarchical_namespace.yaml | 499 --------------- ...directory_with_hierarchical_namespace.yaml | 45 -- ...ectory_without_hierarchical_namespace.yaml | 48 -- ...directory_with_hierarchical_namespace.yaml | 575 ++++++++++++++++++ ...ectory_without_hierarchical_namespace.yaml | 534 ++++++++++++++++ ...s_control_with_hierarchical_namespace.yaml | 297 +++++++++ ...name_path_with_hierarchical_namespace.yaml | 541 ++++++++++++++++ ...e_path_without_hierarchical_namespace.yaml | 471 ++++++++++++++ 14 files changed, 2784 insertions(+), 926 deletions(-) rename tests/blob/{test_directory.py => test_path.py} (60%) delete mode 100644 tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml delete mode 100644 tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml delete mode 100644 tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml delete mode 100644 tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_path.test_create_delete_directory_with_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_path.test_create_delete_directory_without_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_path.test_get_set_access_control_with_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_path.test_rename_path_with_hierarchical_namespace.yaml create mode 100644 tests/recordings/test_path.test_rename_path_without_hierarchical_namespace.yaml diff --git a/azure-storage-blob/ChangeLog.md b/azure-storage-blob/ChangeLog.md index 39e738d6..7ed784f4 100644 --- a/azure-storage-blob/ChangeLog.md +++ b/azure-storage-blob/ChangeLog.md @@ -4,7 +4,7 @@ ## Version XX.XX.XX -- Added support for directory operations: create, rename, and delete. +- Added support for path operations(only available for accounts with ADLS Gen2 Inter-op enabled): create and delete directory, rename path, get and set path access control. ## Version 2.1.0: diff --git a/azure-storage-blob/azure/storage/blob/_deserialization.py b/azure-storage-blob/azure/storage/blob/_deserialization.py index 7c35febb..99919516 100644 --- a/azure-storage-blob/azure/storage/blob/_deserialization.py +++ b/azure-storage-blob/azure/storage/blob/_deserialization.py @@ -38,7 +38,10 @@ ResourceProperties, BlobPrefix, AccountInformation, - UserDelegationKey, BatchSubResponse) + BatchSubResponse, + UserDelegationKey, + PathProperties, +) from ._encryption import _decrypt_blob from azure.storage.common.models import _list from azure.storage.common._error import ( @@ -653,3 +656,12 @@ def _parse_sub_response_to_http_response(sub_response): def _parse_continuation_token(response): marker = response.headers.get('x-ms-continuation') return marker if marker is not '' else None + + +def _parse_path_permission_and_acl(response): + props = PathProperties() + props.owner = response.headers.get('x-ms-owner') + props.group = response.headers.get('x-ms-group') + props.permissions = response.headers.get('x-ms-permissions') + props.acl = response.headers.get('x-ms-acl') + return props diff --git a/azure-storage-blob/azure/storage/blob/baseblobservice.py b/azure-storage-blob/azure/storage/blob/baseblobservice.py index 0fcc765c..0e4f10cd 100644 --- a/azure-storage-blob/azure/storage/blob/baseblobservice.py +++ b/azure-storage-blob/azure/storage/blob/baseblobservice.py @@ -74,6 +74,7 @@ _convert_xml_to_user_delegation_key, _ingest_batch_response, _parse_continuation_token, + _parse_path_permission_and_acl, ) from ._download_chunking import _download_blob_chunks from ._error import ( @@ -1554,7 +1555,6 @@ def set_blob_service_properties( ''' if all(parameter is None for parameter in [logging, hour_metrics, minute_metrics, cors, target_version, delete_retention_policy, static_website]): - raise ValueError("set_blob_service_properties should be called with at least one parameter") request = HTTPRequest() @@ -3580,7 +3580,7 @@ def undelete_blob(self, container_name, blob_name, timeout=None): # ----------------------------Methods related to directory manipulations---------------------------- # - def create_directory(self, container_name, directory_path, proposed_lease_id=None, lease_id=None, metadata=None, + def create_directory(self, container_name, directory_path, lease_id=None, metadata=None, posix_permissions=None, posix_umask=None, timeout=None): """ Create a directory which can contain other directories or blobs. @@ -3589,10 +3589,7 @@ def create_directory(self, container_name, directory_path, proposed_lease_id=Non Name of existing container. :param str directory_path: Path of the directory to be created. Ex: 'dirfoo/dirbar'. - :param str proposed_lease_id: - Proposed lease ID, in a GUID string format. The Blob service - returns 400 (Invalid request) if the proposed lease ID is not - in the correct format. + The service will create parent directories if they do not exist yet. :param str lease_id: Required if the directory to be overwritten has an active lease. :param metadata: @@ -3632,16 +3629,15 @@ def create_directory(self, container_name, directory_path, proposed_lease_id=Non 'timeout': _int_to_str(timeout), } request.headers = { - 'x-ms-proposed-lease-id': _to_str(proposed_lease_id), 'x-ms-lease-id': _to_str(lease_id), 'x-ms-permissions': _to_str(posix_permissions), 'x-ms-umask': _to_str(posix_umask), } - # TODO add test cases for lease and metadata + # TODO add test cases for lease _add_file_or_directory_properties_header(metadata, request) return self._perform_request(request, parser=_parse_base_properties) - def delete_directory(self, container_name, directory_path, fail_not_exist=False, recursive=True, marker=None, + def delete_directory(self, container_name, directory_path, fail_not_exist=False, recursive=False, marker=None, lease_id=None, if_modified_since=None, if_unmodified_since=None, if_match=None, if_none_match=None, timeout=None): """ @@ -3722,41 +3718,41 @@ def delete_directory(self, container_name, directory_path, fail_not_exist=False, else: return True, self._perform_request(request, parser=_parse_continuation_token) - def rename_directory(self, container_name, new_directory_path, source_directory_path, - mode=None, marker=None, lease_id=None, source_lease_id=None, - metadata=None, source_if_modified_since=None, source_if_unmodified_since=None, - source_if_match=None, source_if_none_match=None, timeout=None): + def rename_path(self, container_name, new_path, source_path, + mode=None, marker=None, lease_id=None, source_lease_id=None, + source_if_modified_since=None, source_if_unmodified_since=None, + source_if_match=None, source_if_none_match=None, timeout=None): """ - Rename a directory which can contain other directories or blobs. + Rename a blob or directory(which can contain other directories or blobs). :param str container_name: Name of existing container. - :param str new_directory_path: - New path for source_directory_path. Ex: 'dirfoo/dirsubfoo'. - :param str source_directory_path: - Directory to be renamed. Ex: 'dirfoo/dirbar'. + :param str new_path: + New path for source_path. Ex: 'topdir1/dirsubfoo'. + Note that the path should be an absolute path under the container. + :param str source_path: + Path to be renamed. Ex: 'topdir1/dirbar'. + Note that the path should be an absolute path under the container. :param mode: Optional. Valid only when namespace is enabled. This parameter determines the behavior of the rename operation. The value must be "legacy" or "posix", and the default value will be "posix". - A "posix" rename is done atomically; a "legacy" rename is done in batches and could return a marker. + Legacy: if the destination of the move is an existing directory and that directory is empty, + the source will overwrite the destination. If the directory is not empty, the move will fail. + Posix: if the destination of the move is an existing empty directory, + destination will be overwritten. Otherwise, the source will be moved into the destination directory. + If the destination is an existing file, the file will be overwritten. :param marker: Optional. When renaming a directory, the number of paths that are renamed with each invocation is limited. If the number of paths to be renamed exceeds this limit, a continuation token is returned. When a continuation token is returned, it must be specified in a subsequent invocation of the rename operation to continue renaming the directory. :param str lease_id: - Optional. A lease ID for the new_directory_path. - The new_directory_path must have an active lease and the lease ID must match. + Optional. A lease ID for the new_path. + The new_path must have an active lease and the lease ID must match. :param str source_lease_id: - Optional. A lease ID for the source_directory_path. - The source_directory_path must have an active lease and the lease ID must match. - :param metadata: - Optional. A dict with name_value pairs to associate with the directory as metadata. - Example:{'Category':'test'}. - If metadata is specified, it will overwrite the existing metadata; - otherwise, the existing metadata will be preserved. - :type metadata: dict(str, str) + Optional. A lease ID for the source_path. + The source_path must have an active lease and the lease ID must match. :param datetime source_if_modified_since: Optional. A date and time value. Specify this header to perform the rename operation only if the source has been modified since the specified date and time. @@ -3776,21 +3772,21 @@ def rename_directory(self, container_name, new_directory_path, source_directory_ A continuation marker if applicable. Otherwise return None. :rtype: str """ - _validate_not_none('source_directory_path', source_directory_path) - _validate_not_none('new_directory_path', new_directory_path) + _validate_not_none('source_path', source_path) + _validate_not_none('new_path', new_path) request = HTTPRequest() # TODO remove endpoint swapping after service update request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) request.method = 'PUT' - request.path = _get_path(container_name, new_directory_path) + request.path = _get_path(container_name, new_path) request.query = { 'mode': mode, 'continuation': _to_str(marker), 'timeout': _int_to_str(timeout), } request.headers = { - 'x-ms-rename-source': _get_path(container_name, source_directory_path), + 'x-ms-rename-source': _get_path(container_name, source_path), 'x-ms-lease-id': _to_str(lease_id), 'x-ms-source-lease-id': _to_str(source_lease_id), 'x-ms-source-if-modified-since': _datetime_to_utc_string(source_if_modified_since), @@ -3798,10 +3794,150 @@ def rename_directory(self, container_name, new_directory_path, source_directory_ 'x-ms-source-if-match': _to_str(source_if_match), 'x-ms-source-if-none-match': _to_str(source_if_none_match), } - # TODO add test cases for lease and metadata - _add_file_or_directory_properties_header(metadata, request) return self._perform_request(request, parser=_parse_continuation_token) + def get_path_access_control(self, container_name, path, user_principle_names=False, + lease_id=None, if_modified_since=None, if_unmodified_since=None, + if_match=None, if_none_match=None, timeout=None): + """ + Retrieve the access control properties of a path(directory or blob). + + :param str container_name: + Name of existing container. + :param str path: + Path of the directory/blob. + :param user_principle_names: + Valid only when Hierarchical Namespace is enabled for the account. + If "true", the user identity values returned for owner, group, and acl will be transformed + from Azure Active Directory Object IDs to User Principal Names. + If "false", the values will be returned as Azure Active Directory Object IDs. + The default value is false. Note that group and application Object IDs are not translated + because they do not have unique friendly names. + :param str lease_id: + Required if the path has an active lease. + :param datetime if_modified_since: + A date and time value. Specify this header to perform the operation only if the resource + has been modified since the specified date and time. + :param datetime if_unmodified_since: + A date and time value. Specify this header to perform the operation only if the resource + has not been modified since the specified date and time. + :param datetime if_match: + An ETag value. Specify this header to perform the operation + only if the resource's ETag matches the value specified. The ETag must be specified in quotes. + :param datetime if_none_match: + An ETag value or the special wildcard ("*") value. + Specify this header to perform the operation only if the resource's ETag + does not match the value specified. The ETag must be specified in quotes. + :param int timeout: + The timeout parameter is expressed in seconds. + :return: ETag and last modified time of the new directory. + :rtype: :class:`~azure.storage.blob.models.ResourceProperties` + """ + _validate_not_none('path', path) + + request = HTTPRequest() + # TODO remove endpoint swapping after service update + request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) + request.method = 'HEAD' + request.path = _get_path(container_name, path) + request.query = { + 'action': 'getAccessControl', + 'upn': _to_str(user_principle_names), + 'timeout': _int_to_str(timeout), + } + request.headers = { + 'x-ms-lease-id': _to_str(lease_id), + 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), + 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), + 'If-Match': _to_str(if_match), + 'If-None-Match': _to_str(if_none_match), + } + return self._perform_request(request, parser=_parse_path_permission_and_acl) + + def set_path_access_control(self, container_name, path, owner=None, group=None, permissions=None, + acl=None, lease_id=None, if_modified_since=None, if_unmodified_since=None, + if_match=None, if_none_match=None, timeout=None): + """ + Set the access control properties of a path(directory or blob). + + :param str container_name: + Name of existing container. + :param str path: + Path of the directory/blob. + :param str owner: + Sets the owner of the file or directory. + :param str group: + Sets the owning group of the file or directory. + :param str permissions: + Invalid in conjunction with acl. + Sets POSIX access permissions for the file owner, the file owning group, and others. + Each class may be granted read, write, or execute permission. + The sticky bit is also supported. Both symbolic (rwxrw-rw-) + and 4-digit octal notation (e.g. 0766) are supported. + :param str acl: + Invalid in conjunction with permissions. + Sets POSIX access control rights on files and directories. + The value is a comma-separated list of access control entries that fully replaces the existing + access control list (ACL). Each access control entry (ACE) consists of a scope, a type, + a user or group identifier, and permissions in the format "[scope:][type]:[id]:[permissions]". + The scope must be "default" to indicate the ACE belongs to the default ACL for a directory; + otherwise scope is implicit and the ACE belongs to the access ACL. + There are four ACE types: "user" grants rights to the owner or a named user, + "group" grants rights to the owning group or a named group, + "mask" restricts rights granted to named users and the members of groups, + and "other" grants rights to all users not found in any of the other entries. + The user or group identifier is omitted for entries of type "mask" and "other". + The user or group identifier is also omitted for the owner and owning group. + The permission field is a 3-character sequence where the first character is 'r' to grant read access, + the second character is 'w' to grant write access, and the third character is 'x' + to grant execute permission. If access is not granted, the '-' character is used to denote + that the permission is denied. For example, the following ACL grants read, write, and execute rights to + the file owner and john.doe@contoso, the read right to the owning group, + and nothing to everyone else: "user::rwx,user:john.doe@contoso:rwx,group::r--,other::---,mask=rwx". + :param str lease_id: + Required if the path has an active lease. + :param datetime if_modified_since: + A date and time value. Specify this header to perform the operation only if the resource + has been modified since the specified date and time. + :param datetime if_unmodified_since: + A date and time value. Specify this header to perform the operation only if the resource + has not been modified since the specified date and time. + :param datetime if_match: + An ETag value. Specify this header to perform the operation + only if the resource's ETag matches the value specified. The ETag must be specified in quotes. + :param datetime if_none_match: + An ETag value or the special wildcard ("*") value. + Specify this header to perform the operation only if the resource's ETag + does not match the value specified. The ETag must be specified in quotes. + :param int timeout: + The timeout parameter is expressed in seconds. + :return: ETag and last modified time of the new directory. + :rtype: :class:`~azure.storage.blob.models.ResourceProperties` + """ + _validate_not_none('path', path) + + request = HTTPRequest() + # TODO remove endpoint swapping after service update + request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) + request.method = 'PATCH' + request.path = _get_path(container_name, path) + request.query = { + 'action': 'setAccessControl', + 'timeout': _int_to_str(timeout), + } + request.headers = { + 'x-ms-owner': _to_str(owner), + 'x-ms-group': _to_str(group), + 'x-ms-permissions': _to_str(permissions), + 'x-ms-acl': _to_str(acl), + 'x-ms-lease-id': _to_str(lease_id), + 'If-Modified-Since': _datetime_to_utc_string(if_modified_since), + 'If-Unmodified-Since': _datetime_to_utc_string(if_unmodified_since), + 'If-Match': _to_str(if_match), + 'If-None-Match': _to_str(if_none_match), + } + return self._perform_request(request, parser=_parse_base_properties) + # ----------------------------Helpers for directory manipulations---------------------------- # @staticmethod def _swap_blob_endpoints(host_locations): diff --git a/azure-storage-blob/azure/storage/blob/models.py b/azure-storage-blob/azure/storage/blob/models.py index fe42e256..7f124707 100644 --- a/azure-storage-blob/azure/storage/blob/models.py +++ b/azure-storage-blob/azure/storage/blob/models.py @@ -975,3 +975,24 @@ def __init__(self, key_value, key_hash): self.key_value = key_value self.key_hash = key_hash self.algorithm = 'AES256' + +class PathProperties(object): + """ + Represent a path's properties(only permissions and acl at the moment). + The path can be either a directory or a file. + + :ivar string owner: + Represents the owner of the path. + :ivar string group: + Represents the group of the path. + :ivar string permissions: + Represents the permissions of the path. + :ivar string acl: + Represents the acl of the path. + """ + + def __init__(self): + self.owner = None + self.group = None + self.permissions = None + self.acl = None diff --git a/tests/blob/test_directory.py b/tests/blob/test_path.py similarity index 60% rename from tests/blob/test_directory.py rename to tests/blob/test_path.py index 6992c6e2..70dd0cbb 100644 --- a/tests/blob/test_directory.py +++ b/tests/blob/test_path.py @@ -29,9 +29,9 @@ ) -class StorageDirectoryTest(StorageTestCase): +class StoragePathTest(StorageTestCase): def setUp(self): - super(StorageDirectoryTest, self).setUp() + super(StoragePathTest, self).setUp() self.bs = self._create_storage_service(BlockBlobService, self.settings) self.bs_namespace = self._create_storage_service_with_hierarchical_namespace(BlockBlobService, self.settings) @@ -42,13 +42,13 @@ def setUp(self): self.container_name = self.get_resource_name('utcontainer') if not self.is_playback(): self.bs.create_container(self.container_name) - self.bs_namespace._create_file_system(self.container_name) + self.bs_namespace.create_container(self.container_name) def tearDown(self): if not self.is_playback(): self.bs.delete_container(self.container_name) - self.bs_namespace._delete_file_system(self.container_name) - return super(StorageDirectoryTest, self).tearDown() + self.bs_namespace.delete_container(self.container_name) + return super(StoragePathTest, self).tearDown() def _get_directory_reference(self, suffix=""): return self.get_resource_name("directorytest" + suffix) @@ -56,16 +56,20 @@ def _get_directory_reference(self, suffix=""): def _get_blob_reference(self, directory_path): return "{}/{}".format(directory_path, self.get_resource_name("blob")) - def _create_sub_dirs(self, blob_service, directory_name, num_of_sub_dir): + def _create_sub_dirs_and_blobs(self, blob_service, directory_name, num_of_sub_dir): import concurrent.futures import itertools # Use a thread pool because it is too slow otherwise with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: - def create_sub_dir(): - blob_service.create_directory(self.container_name, - "{}/{}".format(directory_name, self._get_directory_reference())) + def create_sub_dir_and_file(): + sub_dir_name = "{}/{}".format(directory_name, self._get_directory_reference()) + blob_service.create_directory(self.container_name, sub_dir_name) - futures = {executor.submit(create_sub_dir) for _ in itertools.repeat(None, num_of_sub_dir)} + # create a blob under the sub dir + blob_service.create_blob_from_bytes(self.container_name, + self._get_blob_reference(sub_dir_name), b"test") + + futures = {executor.submit(create_sub_dir_and_file) for _ in itertools.repeat(None, num_of_sub_dir)} concurrent.futures.wait(futures) def test_host_swapping(self): @@ -94,13 +98,11 @@ def test_create_delete_directory_with_hierarchical_namespace(self): self.create_delete_directory_simple_test_implementation(self.bs_namespace) self.create_directory_with_permission_implementation(self.bs_namespace, hierarchical_namespace_enabled=True) self.delete_directory_recursive_test_implementation(self.bs_namespace) - - # TODO encountering error 500 for if_match and if_none_match condition, uncomment after service fix - # self.delete_directory_access_conditions_test_implementation(self.bs_namespace) + self.delete_directory_access_conditions_test_implementation(self.bs_namespace) def create_delete_directory_simple_test_implementation(self, blob_service): # Arrange - directory_name = self._get_directory_reference() + directory_name = self._get_directory_reference(suffix="/foo/bar") metadata = {"foo": "bar", "mama": "mia"} # Act @@ -111,6 +113,11 @@ def create_delete_directory_simple_test_implementation(self, blob_service): self.assertIsNotNone(props.etag) self.assertIsNotNone(props.last_modified) + # Verify metadata + dir_props = blob_service.get_blob_properties(self.container_name, directory_name) + for key, value in metadata.items(): + self.assertEqual(value, dir_props.metadata[key]) + # Act # Creating the same directory again self.sleep(1) @@ -122,7 +129,7 @@ def create_delete_directory_simple_test_implementation(self, blob_service): self.assertNotEqual(props.last_modified, props2.last_modified) # Act - deleted, marker = blob_service.delete_directory(self.container_name, directory_name) + deleted, marker = blob_service.delete_directory(self.container_name, directory_name, recursive=True) # Assert self.assertTrue(deleted) @@ -141,6 +148,8 @@ def create_delete_directory_simple_test_implementation(self, blob_service): def create_directory_with_permission_implementation(self, blob_service, hierarchical_namespace_enabled): # Arrange + test_permissions = 'rwxrw-rw-' + test_umask = '0000' directory_name = self._get_directory_reference() if not hierarchical_namespace_enabled: @@ -148,18 +157,23 @@ def create_directory_with_permission_implementation(self, blob_service, hierarch # Create with permission and umask is expected to fail due to the lack of namespace service with self.assertRaises(AzureHttpError): blob_service.create_directory(self.container_name, directory_name, - posix_permissions='rwxrw-rw-', posix_umask='0022') + posix_permissions=test_permissions, posix_umask=test_umask) else: # Act # Create with permission and umask props = blob_service.create_directory(self.container_name, directory_name, - posix_permissions='rwxrw-rw-', posix_umask='0022') + posix_permissions=test_permissions, posix_umask=test_umask) # Assert self.assertIsNotNone(props) self.assertIsNotNone(props.etag) self.assertIsNotNone(props.last_modified) + # Verify if permissions are set + props = blob_service.get_path_access_control(self.container_name, directory_name) + self.assertIsNotNone(props) + self.assertEqual(props.permissions, test_permissions) + # Cleanup blob_service.delete_directory(self.container_name, directory_name) @@ -173,10 +187,10 @@ def delete_directory_marker_test_implementation(self, blob_service): blob_service.create_directory(self.container_name, directory_name) # Create enough sub-directories to trigger the service to return a marker - self._create_sub_dirs(blob_service, directory_name, num_of_sub_dir=1000) + self._create_sub_dirs_and_blobs(blob_service, directory_name, num_of_sub_dir=500) # Act - deleted, marker = blob_service.delete_directory(self.container_name, directory_name) + deleted, marker = blob_service.delete_directory(self.container_name, directory_name, recursive=True) # Assert self.assertTrue(deleted) @@ -186,7 +200,8 @@ def delete_directory_marker_test_implementation(self, blob_service): # Continue the delete count = 0 while marker is not None: - deleted, new_marker = blob_service.delete_directory(self.container_name, directory_name, marker=marker) + deleted, new_marker = blob_service.delete_directory(self.container_name, directory_name, + marker=marker, recursive=True) # Assert self.assertTrue(deleted) @@ -269,19 +284,18 @@ def delete_directory_access_conditions_test_implementation(self, blob_service): self.assertIsNone(marker) @record - def test_rename_directory_without_hierarchical_namespace(self): + def test_rename_path_without_hierarchical_namespace(self): self.rename_directory_simple_test_implementation(self.bs) self.rename_directory_marker_test_implementation(self.bs) - - # TODO error 500s get thrown for precondition fail, uncomment after service fix - # self.rename_directory_access_conditions_test_implementation(self.bs) + self.rename_directory_access_conditions_test_implementation(self.bs) + self.rename_blob_simple_test_implementation(self.bs) @record - def test_rename_directory_with_hierarchical_namespace(self): + def test_rename_path_with_hierarchical_namespace(self): self.rename_directory_simple_test_implementation(self.bs_namespace) - - # TODO access conditions get ignored, uncomment after service fix - # self.rename_directory_access_conditions_test_implementation(self.bs_namespace) + self.rename_directory_access_conditions_test_implementation(self.bs_namespace) + self.rename_directory_with_legacy_mode_test_implementation(self.bs_namespace) + self.rename_blob_simple_test_implementation(self.bs_namespace) def rename_directory_simple_test_implementation(self, blob_service): # Arrange @@ -296,14 +310,31 @@ def rename_directory_simple_test_implementation(self, blob_service): self.assertIsNotNone(props.last_modified) # Arrange - new_directory_name = self._get_directory_reference("new") + new_directory_parent = self._get_directory_reference("parent") + blob_service.create_directory(self.container_name, new_directory_parent) + new_directory_name = "{}/{}".format(new_directory_parent, self._get_directory_reference("new")) # Act - marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name) + marker = blob_service.rename_path(self.container_name, new_directory_name, directory_name) # Assert self.assertIsNone(marker) + def rename_directory_with_legacy_mode_test_implementation(self, blob_service): + # Arrange old directory + old_directory_name = self._get_directory_reference() + blob_service.create_directory(self.container_name, old_directory_name) + + # Arrange new directory with a blob + new_directory_name = self._get_directory_reference("new") + blob_service.create_directory(self.container_name, new_directory_name) + blob_service.create_blob_from_bytes(self.container_name, self._get_blob_reference(new_directory_name), b"test") + + # Act + # make sure the mode parameter is reaching the service properly + with self.assertRaises(AzureHttpError): + blob_service.rename_path(self.container_name, new_directory_name, old_directory_name, mode='legacy') + def rename_directory_marker_test_implementation(self, blob_service): # this test is too costly(too many requests to the service) and should only run in live mode if TestMode.need_recording_file(self.test_mode): @@ -315,10 +346,10 @@ def rename_directory_marker_test_implementation(self, blob_service): blob_service.create_directory(self.container_name, directory_name) # Create enough sub-directories to trigger the service to return a marker - self._create_sub_dirs(blob_service, directory_name, num_of_sub_dir=1000) + self._create_sub_dirs_and_blobs(blob_service, directory_name, num_of_sub_dir=500) # Act - marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name) + marker = blob_service.rename_path(self.container_name, new_directory_name, directory_name) # Assert self.assertIsNotNone(marker) @@ -327,8 +358,8 @@ def rename_directory_marker_test_implementation(self, blob_service): # Continue the rename count = 0 while marker is not None: - new_marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - marker=marker) + new_marker = blob_service.rename_path(self.container_name, new_directory_name, directory_name, + marker=marker) self.assertNotEqual(marker, new_marker) marker = new_marker count += 1 @@ -343,12 +374,12 @@ def rename_directory_access_conditions_test_implementation(self, blob_service): # if_match fails with self.assertRaises(AzureHttpError): - blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_match='0x111111111111111') + blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_match='0x111111111111111') # if_match succeeds - marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_match=props.etag) + marker = blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_match=props.etag) self.assertIsNone(marker) # Arrange @@ -356,12 +387,12 @@ def rename_directory_access_conditions_test_implementation(self, blob_service): # if_none_match fails with self.assertRaises(AzureHttpError): - blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_none_match=props.etag) + blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_none_match=props.etag) # if_none_match succeeds - marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_none_match='0x111111111111111') + marker = blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_none_match='0x111111111111111') self.assertIsNone(marker) # Arrange @@ -369,13 +400,13 @@ def rename_directory_access_conditions_test_implementation(self, blob_service): # if_modified_since fails with self.assertRaises(AzureHttpError): - blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_modified_since=props.last_modified) + blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_modified_since=props.last_modified) # if_modified_since succeeds - marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_modified_since=props.last_modified - datetime.timedelta( - minutes=1)) + marker = blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_modified_since=props.last_modified - datetime.timedelta( + minutes=1)) self.assertIsNone(marker) # Arrange @@ -383,11 +414,88 @@ def rename_directory_access_conditions_test_implementation(self, blob_service): # if_unmodified_since fails with self.assertRaises(AzureHttpError): - blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_unmodified_since=props.last_modified - datetime.timedelta( - minutes=1)) + blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_unmodified_since=props.last_modified - datetime.timedelta( + minutes=1)) # if_unmodified_since succeeds - marker = blob_service.rename_directory(self.container_name, new_directory_name, directory_name, - source_if_unmodified_since=props.last_modified) + marker = blob_service.rename_path(self.container_name, new_directory_name, directory_name, + source_if_unmodified_since=props.last_modified) + self.assertIsNone(marker) + + def rename_blob_simple_test_implementation(self, blob_service): + # Arrange old blob path + old_blob_name = self._get_blob_reference(self._get_directory_reference()) + "old" + blob_service.create_blob_from_bytes(self.container_name, old_blob_name, b"test") + + # Arrange new blob path + new_blob_parent = self._get_directory_reference() + blob_service.create_directory(self.container_name, new_blob_parent) + new_blob_name = self._get_blob_reference(new_blob_parent) + "new" + + # Act + marker = blob_service.rename_path(self.container_name, new_blob_name, old_blob_name) + + # Assert blob is moved self.assertIsNone(marker) + props = blob_service.get_blob_properties(self.container_name, new_blob_name) + self.assertIsNotNone(props) + + @record + def test_get_set_access_control_with_hierarchical_namespace(self): + # Arrange a directory + directory_name = self._get_directory_reference() + props = self.bs_namespace.create_directory(self.container_name, directory_name) + self.assertIsNotNone(props.etag) + self.assertIsNotNone(props.last_modified) + + # Arrange a blob + blob_name = self._get_blob_reference(self._get_directory_reference()) + props = self.bs_namespace.create_blob_from_bytes(self.container_name, blob_name, b"test") + self.assertIsNotNone(props.etag) + self.assertIsNotNone(props.last_modified) + + for path_name in [directory_name, blob_name]: + # Act: get acl + props = self.bs_namespace.get_path_access_control( + self.container_name, path_name, user_principle_names=True) + # validate the default values are being returned + self.assertIsNotNone(props) + self.assertIsNotNone(props.owner) + self.assertIsNotNone(props.permissions) + self.assertIsNotNone(props.group) + self.assertIsNotNone(props.acl) + + # Act: set acl + test_owner = self.settings.ACTIVE_DIRECTORY_APPLICATION_ID + test_group = self.settings.ACTIVE_DIRECTORY_APPLICATION_ID + test_acl = 'user::rwx,group::r--,other::r--' + props = self.bs_namespace.set_path_access_control(self.container_name, path_name, + owner=test_owner, group=test_group, acl=test_acl) + self.assertIsNotNone(props.etag) + self.assertIsNotNone(props.last_modified) + + # Assert + props = self.bs_namespace.get_path_access_control(self.container_name, path_name, + user_principle_names=True) + self.assertIsNotNone(props) + self.assertEqual(props.owner, test_owner) + self.assertEqual(props.group, test_group) + self.assertEqual(props.acl, test_acl) + + # Act: set permissions + test_owner = self.settings.ACTIVE_DIRECTORY_APPLICATION_ID + test_group = self.settings.ACTIVE_DIRECTORY_APPLICATION_ID + test_permissions = 'rwxrw-rw-' + props = self.bs_namespace.set_path_access_control(self.container_name, path_name, + owner=test_owner, group=test_group, + permissions=test_permissions) + self.assertIsNotNone(props.etag) + self.assertIsNotNone(props.last_modified) + + # Assert + props = self.bs_namespace.get_path_access_control(self.container_name, path_name) + self.assertIsNotNone(props) + self.assertEqual(props.owner, test_owner) + self.assertEqual(props.group, test_group) + self.assertEqual(props.permissions, test_permissions) diff --git a/tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml deleted file mode 100644 index b3aa214c..00000000 --- a/tests/recordings/test_directory.test_create_delete_directory_with_hierarchical_namespace.yaml +++ /dev/null @@ -1,245 +0,0 @@ -interactions: -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8d17ae72-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:10 GMT'] - x-ms-properties: ['foo=YmFy,mama=bWlh'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:11 GMT'] - ETag: ['"0x8D6297571A4A833"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:11 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff34-001f-00a9-0c5e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e0badec-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - ETag: ['"0x8D62975724499BF"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff35-001f-00a9-0d5e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e123e46-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff36-001f-00a9-0e5e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e17878e-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True - response: - body: {string: '{"error":{"code":"PathNotFound","message":"The specified path - does not exist.\nRequestId:3e5fff37-001f-00a9-0f5e-5b38ea000000\nTime:2018-10-03T21:16:12.5240091Z"}}'} - headers: - Content-Length: ['163'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [PathNotFound] - x-ms-request-id: [3e5fff37-001f-00a9-0f5e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 404, message: The specified path does not exist.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e1ccd7a-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True - response: - body: {string: '{"error":{"code":"PathNotFound","message":"The specified path - does not exist.\nRequestId:3e5fff38-001f-00a9-105e-5b38ea000000\nTime:2018-10-03T21:16:12.5570393Z"}}'} - headers: - Content-Length: ['163'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [PathNotFound] - x-ms-request-id: [3e5fff38-001f-00a9-105e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 404, message: The specified path does not exist.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e21d572-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-permissions: [rwxrw-rw-] - x-ms-umask: ['0022'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - ETag: ['"0x8D6297572596435"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff39-001f-00a9-115e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e270466-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff3a-001f-00a9-125e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e2c548e-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - ETag: ['"0x8D629757263E4A5"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff3b-001f-00a9-135e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e316122-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21/directorytest1c491d21?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - ETag: ['"0x8D6297572694BF7"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff3c-001f-00a9-145e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e36d1ca-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=False - response: - body: {string: '{"error":{"code":"DirectoryNotEmpty","message":"The recursive - query parameter value must be true to delete a non-empty directory.\nRequestId:3e5fff3d-001f-00a9-155e-5b38ea000000\nTime:2018-10-03T21:16:12.7272015Z"}}'} - headers: - Content-Length: ['215'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [DirectoryNotEmpty] - x-ms-request-id: [3e5fff3d-001f-00a9-155e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 409, message: The recursive query parameter value must be true - to delete a non-empty directory.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [8e3bee80-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer1c491d21/directorytest1c491d21?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:12 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3e5fff3e-001f-00a9-165e-5b38ea000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -version: 1 diff --git a/tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml deleted file mode 100644 index 8a583703..00000000 --- a/tests/recordings/test_directory.test_create_delete_directory_without_hierarchical_namespace.yaml +++ /dev/null @@ -1,499 +0,0 @@ -interactions: -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [953e54a2-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:24 GMT'] - x-ms-properties: ['foo=YmFy,mama=bWlh'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:23 GMT'] - ETag: ['"0x8D6297579AE2EAC"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:24 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cb7-201f-0001-2f5e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [961ac356-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:25 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - ETag: ['"0x8D629757A58510E"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cb8-201f-0001-305e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [962c08aa-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cb9-201f-0001-315e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [964aecfc-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: '{"error":{"code":"PathNotFound","message":"The specified path - does not exist.\nRequestId:695e3cba-201f-0001-325e-5bcde7000000\nTime:2018-10-03T21:16:26.3077942Z"}}'} - headers: - Content-Length: ['163'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [PathNotFound] - x-ms-request-id: [695e3cba-201f-0001-325e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 404, message: The specified path does not exist.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [965ad63a-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: '{"error":{"code":"PathNotFound","message":"The specified path - does not exist.\nRequestId:695e3cbb-201f-0001-335e-5bcde7000000\nTime:2018-10-03T21:16:26.4138003Z"}}'} - headers: - Content-Length: ['163'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [PathNotFound] - x-ms-request-id: [695e3cbb-201f-0001-335e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 404, message: The specified path does not exist.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96697be0-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-permissions: [rwxrw-rw-] - x-ms-umask: ['0022'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: '{"error":{"code":"UnsupportedHeader","message":"One of the headers - specified in the request is not supported.\nRequestId:695e3cbc-201f-0001-345e-5bcde7000000\nTime:2018-10-03T21:16:26.5047893Z"}}'} - headers: - Content-Length: ['195'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [UnsupportedHeader] - x-ms-request-id: [695e3cbc-201f-0001-345e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 400, message: One of the headers specified in the request is not - supported.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96775490-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - ETag: ['"0x8D629757AB39149"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cbd-201f-0001-355e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [968777e4-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - ETag: ['"0x8D629757AC40B29"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cbe-201f-0001-365e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [969728b0-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=False - response: - body: {string: '{"error":{"code":"DirectoryNotEmpty","message":"The recursive - query parameter value must be true to delete a non-empty directory.\nRequestId:695e3cbf-201f-0001-375e-5bcde7000000\nTime:2018-10-03T21:16:26.8158344Z"}}'} - headers: - Content-Length: ['215'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [DirectoryNotEmpty] - x-ms-request-id: [695e3cbf-201f-0001-375e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 409, message: The recursive query parameter value must be true - to delete a non-empty directory.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96a6d558-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cc0-201f-0001-385e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96b62332-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:26 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - ETag: ['"0x8D629757AF29517"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cc1-201f-0001-395e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-Match: ['0x111111111111111'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96c5ac6c-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified - using HTTP conditional header(s) is not met.\nRequestId:695e3cc2-201f-0001-3a5e-5bcde7000000\nTime:2018-10-03T21:16:27.1268204Z"}}'} - headers: - Content-Length: ['200'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [ConditionNotMet] - x-ms-request-id: [695e3cc2-201f-0001-3a5e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 412, message: The condition specified using HTTP conditional header(s) - is not met.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-Match: ['"0x8D629757AF29517"'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96d6955e-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cc3-201f-0001-3b5e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96e6129a-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - ETag: ['"0x8D629757B227FC4"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cc4-201f-0001-3c5e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-None-Match: ['"0x8D629757B227FC4"'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [96f59f6c-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified - using HTTP conditional header(s) is not met.\nRequestId:695e3cc5-201f-0001-3d5e-5bcde7000000\nTime:2018-10-03T21:16:27.4248079Z"}}'} - headers: - Content-Length: ['200'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [ConditionNotMet] - x-ms-request-id: [695e3cc5-201f-0001-3d5e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 412, message: The condition specified using HTTP conditional header(s) - is not met.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-None-Match: ['0x111111111111111'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [97039d2e-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cc6-201f-0001-3e5e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [9712af30-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - ETag: ['"0x8D629757B4EE606"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cc7-201f-0001-3f5e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-Modified-Since: ['Wed, 03 Oct 2018 21:16:27 GMT'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [9721ff76-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified - using HTTP conditional header(s) is not met.\nRequestId:695e3cc8-201f-0001-405e-5bcde7000000\nTime:2018-10-03T21:16:27.7207932Z"}}'} - headers: - Content-Length: ['200'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [ConditionNotMet] - x-ms-request-id: [695e3cc8-201f-0001-405e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 412, message: The condition specified using HTTP conditional header(s) - is not met.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-Modified-Since: ['Wed, 03 Oct 2018 21:15:27 GMT'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [9730eaa4-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cc9-201f-0001-415e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [973ffe9a-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - ETag: ['"0x8D629757B7C3750"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3cca-201f-0001-425e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-Unmodified-Since: ['Wed, 03 Oct 2018 21:15:27 GMT'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [974f369e-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: '{"error":{"code":"ConditionNotMet","message":"The condition specified - using HTTP conditional header(s) is not met.\nRequestId:695e3ccb-201f-0001-435e-5bcde7000000\nTime:2018-10-03T21:16:28.0117962Z"}}'} - headers: - Content-Length: ['200'] - Content-Type: [application/json;charset=utf-8] - Date: ['Wed, 03 Oct 2018 21:16:27 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-error-code: [ConditionNotMet] - x-ms-request-id: [695e3ccb-201f-0001-435e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 412, message: The condition specified using HTTP conditional header(s) - is not met.} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - If-Unmodified-Since: ['Wed, 03 Oct 2018 21:16:27 GMT'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [975d2fb0-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:28 GMT'] - x-ms-version: ['2018-06-17'] - method: DELETE - uri: https://storagename.dfs.core.windows.net/utcontainer79611e79/directorytest79611e79?recursive=True - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:28 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [695e3ccc-201f-0001-445e-5bcde7000000] - x-ms-version: ['2018-06-17'] - status: {code: 200, message: OK} -version: 1 diff --git a/tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml deleted file mode 100644 index 309c41c7..00000000 --- a/tests/recordings/test_directory.test_rename_directory_with_hierarchical_namespace.yaml +++ /dev/null @@ -1,45 +0,0 @@ -interactions: -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [98df3342-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:30 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5bc51a53/directorytest5bc51a53?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:30 GMT'] - ETag: ['"0x8D629757D814599"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:31 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [a041ac47-901f-0006-5d5e-5b1a7a000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [995bcb6e-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:31 GMT'] - x-ms-rename-source: [/utcontainer5bc51a53/directorytest5bc51a53] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5bc51a53/directorytestnew5bc51a53 - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:30 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [a041ac48-901f-0006-5e5e-5b1a7a000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -version: 1 diff --git a/tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml b/tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml deleted file mode 100644 index dd00e27b..00000000 --- a/tests/recordings/test_directory.test_rename_directory_without_hierarchical_namespace.yaml +++ /dev/null @@ -1,48 +0,0 @@ -interactions: -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [9a2dee50-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:32 GMT'] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainerb0731bab/directorytestb0731bab?resource=directory - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:32 GMT'] - ETag: ['"0x8D629757E92ED44"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:33 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-request-id: [3eb87f4f-301f-0022-685e-5b5724000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -- request: - body: null - headers: - Connection: [keep-alive] - Content-Length: ['0'] - User-Agent: [Azure-Storage/1.3.0-1.3.1 (Python CPython 3.7.0; Darwin 17.7.0)] - x-ms-client-request-id: [9a65caf0-c751-11e8-a389-f218981b70f8] - x-ms-date: ['Wed, 03 Oct 2018 21:16:33 GMT'] - x-ms-rename-source: [/utcontainerb0731bab/directorytestb0731bab] - x-ms-version: ['2018-06-17'] - method: PUT - uri: https://storagename.dfs.core.windows.net/utcontainerb0731bab/directorytestnewb0731bab - response: - body: {string: ''} - headers: - Content-Length: ['0'] - Date: ['Wed, 03 Oct 2018 21:16:32 GMT'] - ETag: ['"0x8D629757EA31AA2"'] - Last-Modified: ['Wed, 03 Oct 2018 21:16:33 GMT'] - Server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] - x-ms-continuation: [''] - x-ms-request-id: [3eb87f50-301f-0022-695e-5b5724000000] - x-ms-version: ['2018-06-17'] - status: {code: 201, message: Created} -version: 1 diff --git a/tests/recordings/test_path.test_create_delete_directory_with_hierarchical_namespace.yaml b/tests/recordings/test_path.test_create_delete_directory_with_hierarchical_namespace.yaml new file mode 100644 index 00000000..bdb6db51 --- /dev/null +++ b/tests/recordings/test_path.test_create_delete_directory_with_hierarchical_namespace.yaml @@ -0,0 +1,575 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [8f970973-9729-11e9-a72c-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:57 GMT'] + x-ms-properties: ['mama=bWlh,foo=YmFy'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest/foo/bar88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:56 GMT'] + etag: ['"0x8D6F94D741C8A15"'] + last-modified: ['Tue, 25 Jun 2019 09:13:57 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891def-d01f-0015-4536-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [8ff1ddb8-9729-11e9-98c8-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:57 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.blob.core.windows.net/utcontainer88341af9/directorytest/foo/bar88341af9 + response: + body: {string: !!python/unicode ''} + headers: + accept-ranges: [bytes] + content-length: ['0'] + content-type: [application/octet-stream] + date: ['Tue, 25 Jun 2019 09:13:57 GMT'] + etag: ['"0x8D6F94D741C8A15"'] + last-modified: ['Tue, 25 Jun 2019 09:13:57 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + x-ms-access-tier: [Hot] + x-ms-access-tier-inferred: ['true'] + x-ms-blob-type: [BlockBlob] + x-ms-creation-time: ['Mon, 01 Jan 1601 00:00:00 GMT'] + x-ms-lease-state: [available] + x-ms-lease-status: [unlocked] + x-ms-meta-foo: [bar] + x-ms-meta-hdi_isfolder: ['true'] + x-ms-meta-mama: [mia] + x-ms-request-id: [599ef910-201e-003e-6f36-2b0544000000] + x-ms-server-encrypted: ['true'] + x-ms-tag-count: ['0'] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [90cd99e8-9729-11e9-be7d-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest/foo/bar88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:58 GMT'] + etag: ['"0x8D6F94D750A7669"'] + last-modified: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891df0-d01f-0015-4636-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [90dfc8d1-9729-11e9-92e2-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest/foo/bar88341af9?recursive=True + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:58 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891df1-d01f-0015-4736-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [90f0a9eb-9729-11e9-b706-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest/foo/bar88341af9?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"PathNotFound","message":"The + specified path does not exist.\nRequestId:51891df2-d01f-0015-4836-2b8588000000\nTime:2019-06-25T09:13:59.3193803Z"}}'} + headers: + content-length: ['163'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:13:58 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [51891df2-d01f-0015-4836-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [91019963-9729-11e9-aeca-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest/foo/bar88341af9?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"PathNotFound","message":"The + specified path does not exist.\nRequestId:51891df3-d01f-0015-4936-2b8588000000\nTime:2019-06-25T09:13:59.4234720Z"}}'} + headers: + content-length: ['163'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:13:58 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [51891df3-d01f-0015-4936-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9111968f-9729-11e9-b083-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-permissions: [rwxrw-rw-] + x-ms-umask: ['0000'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:58 GMT'] + etag: ['"0x8D6F94D754F5A90"'] + last-modified: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891df4-d01f-0015-4a36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9124bec5-9729-11e9-8f62-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?action=getAccessControl&upn=False + response: + body: {string: !!python/unicode ''} + headers: + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + etag: ['"0x8D6F94D754F5A90"'] + last-modified: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-acl: ['user::rwx,group::rw-,other::rw-'] + x-ms-group: [$superuser] + x-ms-owner: [$superuser] + x-ms-permissions: [rwxrw-rw-] + x-ms-request-id: [51891df5-d01f-0015-4b36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9134d02b-9729-11e9-b882-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891df6-d01f-0015-4c36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9145c530-9729-11e9-81b3-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + etag: ['"0x8D6F94D75825AD6"'] + last-modified: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891df7-d01f-0015-4d36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [915852ae-9729-11e9-95f9-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9/directorytest88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + etag: ['"0x8D6F94D75954762"'] + last-modified: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891df8-d01f-0015-4e36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [916a8173-9729-11e9-9244-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"DirectoryNotEmpty","message":"The + recursive query parameter value must be true to delete a non-empty directory.\nRequestId:51891df9-d01f-0015-4f36-2b8588000000\nTime:2019-06-25T09:14:00.1126077Z"}}'} + headers: + content-length: ['215'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [DirectoryNotEmpty] + x-ms-request-id: [51891df9-d01f-0015-4f36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 409, message: The recursive query parameter value must be true + to delete a non-empty directory.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [917ab130-9729-11e9-957b-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=True + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891dfa-d01f-0015-5036-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [918b974a-9729-11e9-8bd6-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + etag: ['"0x8D6F94D75C837C3"'] + last-modified: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891dfb-d01f-0015-5136-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Match: ['0x111111111111111'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [919d5c59-9729-11e9-b710-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:51891dfc-d01f-0015-5236-2b8588000000\nTime:2019-06-25T09:14:00.4687518Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [51891dfc-d01f-0015-5236-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Match: ['"0x8D6F94D75C837C3"'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [91b20e02-9729-11e9-a3f9-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:13:59 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891dfd-d01f-0015-5336-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [91c2bf54-9729-11e9-9eb4-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + etag: ['"0x8D6F94D75FFACB4"'] + last-modified: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891dfe-d01f-0015-5436-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-None-Match: ['"0x8D6F94D75FFACB4"'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [91d50ca3-9729-11e9-8fea-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:51891dff-d01f-0015-5536-2b8588000000\nTime:2019-06-25T09:14:00.8128457Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [51891dff-d01f-0015-5536-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-None-Match: ['0x111111111111111'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [91e5b463-9729-11e9-a7c1-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891e00-d01f-0015-5636-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [91f660a1-9729-11e9-91d3-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + etag: ['"0x8D6F94D7633563B"'] + last-modified: ['Tue, 25 Jun 2019 09:14:01 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891e02-d01f-0015-5836-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Modified-Since: ['Tue, 25 Jun 2019 09:14:01 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9208934c-9729-11e9-b80d-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:01 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:51891e04-d01f-0015-5a36-2b8588000000\nTime:2019-06-25T09:14:01.1529075Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [51891e04-d01f-0015-5a36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Modified-Since: ['Tue, 25 Jun 2019 09:13:01 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9219815e-9729-11e9-8edb-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:01 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891e05-d01f-0015-5b36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [922a211c-9729-11e9-8afe-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:01 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + etag: ['"0x8D6F94D7666E686"'] + last-modified: ['Tue, 25 Jun 2019 09:14:01 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891e06-d01f-0015-5c36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Unmodified-Since: ['Tue, 25 Jun 2019 09:13:01 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [923c515c-9729-11e9-a36c-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:01 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:51891e07-d01f-0015-5d36-2b8588000000\nTime:2019-06-25T09:14:01.4890053Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [51891e07-d01f-0015-5d36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Unmodified-Since: ['Tue, 25 Jun 2019 09:14:01 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [924c9530-9729-11e9-af92-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:01 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer88341af9/directorytest88341af9?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:00 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [51891e08-d01f-0015-5e36-2b8588000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/recordings/test_path.test_create_delete_directory_without_hierarchical_namespace.yaml b/tests/recordings/test_path.test_create_delete_directory_without_hierarchical_namespace.yaml new file mode 100644 index 00000000..7ef65ac3 --- /dev/null +++ b/tests/recordings/test_path.test_create_delete_directory_without_hierarchical_namespace.yaml @@ -0,0 +1,534 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [931133c0-9729-11e9-86c9-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:02 GMT'] + x-ms-properties: ['mama=bWlh,foo=YmFy'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytest/foo/barded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:03 GMT'] + etag: ['"0x8D6F94D776D343A"'] + last-modified: ['Tue, 25 Jun 2019 09:14:03 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd708c-401f-0044-5736-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [933cf26e-9729-11e9-aeab-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:03 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerded41c51/directorytest/foo/barded41c51 + response: + body: {string: !!python/unicode ''} + headers: + accept-ranges: [bytes] + content-length: ['0'] + content-type: [application/octet-stream] + date: ['Tue, 25 Jun 2019 09:14:03 GMT'] + etag: ['"0x8D6F94D776D343A"'] + last-modified: ['Tue, 25 Jun 2019 09:14:03 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + vary: [Origin] + x-ms-access-tier: [Hot] + x-ms-access-tier-inferred: ['true'] + x-ms-blob-type: [BlockBlob] + x-ms-creation-time: ['Tue, 25 Jun 2019 09:14:03 GMT'] + x-ms-lease-state: [available] + x-ms-lease-status: [unlocked] + x-ms-meta-foo: [bar] + x-ms-meta-hdi_isfolder: ['true'] + x-ms-meta-mama: [mia] + x-ms-request-id: [828ab7d6-801e-0059-7936-2bcaad000000] + x-ms-server-encrypted: ['true'] + x-ms-tag-count: ['0'] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [93f25ecf-9729-11e9-9912-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytest/foo/barded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + etag: ['"0x8D6F94D782B5B1A"'] + last-modified: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd708d-401f-0044-5836-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [93fb2430-9729-11e9-94cd-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytest/foo/barded41c51?recursive=True + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd708e-401f-0044-5936-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [940d6840-9729-11e9-8ff7-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytest/foo/barded41c51?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"PathNotFound","message":"The + specified path does not exist.\nRequestId:b5cd708f-401f-0044-5a36-2b1347000000\nTime:2019-06-25T09:14:04.5133082Z"}}'} + headers: + content-length: ['163'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [b5cd708f-401f-0044-5a36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [941521b5-9729-11e9-9f8f-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytest/foo/barded41c51?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"PathNotFound","message":"The + specified path does not exist.\nRequestId:b5cd7090-401f-0044-5b36-2b1347000000\nTime:2019-06-25T09:14:04.5593519Z"}}'} + headers: + content-length: ['163'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [PathNotFound] + x-ms-request-id: [b5cd7090-401f-0044-5b36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 404, message: The specified path does not exist.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [941c3597-9729-11e9-a81a-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-permissions: [rwxrw-rw-] + x-ms-umask: ['0000'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?resource=directory + response: + body: {string: !!python/unicode '{"error":{"code":"UnsupportedHeader","message":"One + of the headers specified in the request is not supported.\nRequestId:b5cd7091-401f-0044-5c36-2b1347000000\nTime:2019-06-25T09:14:04.5993899Z"}}'} + headers: + content-length: ['195'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [UnsupportedHeader] + x-ms-request-id: [b5cd7091-401f-0044-5c36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 400, message: One of the headers specified in the request is not + supported.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [942267a3-9729-11e9-af77-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + etag: ['"0x8D6F94D785A65C4"'] + last-modified: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd7092-401f-0044-5d36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [942a76b0-9729-11e9-9471-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51/directorytestded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + etag: ['"0x8D6F94D78631A70"'] + last-modified: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd7093-401f-0044-5e36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9432c2ca-9729-11e9-8f91-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"DirectoryNotEmpty","message":"The + recursive query parameter value must be true to delete a non-empty directory.\nRequestId:b5cd7094-401f-0044-5f36-2b1347000000\nTime:2019-06-25T09:14:04.7545396Z"}}'} + headers: + content-length: ['215'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [DirectoryNotEmpty] + x-ms-request-id: [b5cd7094-401f-0044-5f36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 409, message: The recursive query parameter value must be true + to delete a non-empty directory.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [943c5100-9729-11e9-b159-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=True + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd7095-401f-0044-6036-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9442cf26-9729-11e9-8058-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + etag: ['"0x8D6F94D787B150B"'] + last-modified: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd7096-401f-0044-6136-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Match: ['0x111111111111111'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [944ab16e-9729-11e9-9252-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:b5cd7097-401f-0044-6236-2b1347000000\nTime:2019-06-25T09:14:04.9106889Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [b5cd7097-401f-0044-6236-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Match: ['"0x8D6F94D787B150B"'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9451f8f0-9729-11e9-a7d9-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd7098-401f-0044-6336-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [94597bb8-9729-11e9-9499-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:04 GMT'] + etag: ['"0x8D6F94D7890EC49"'] + last-modified: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd7099-401f-0044-6436-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-None-Match: ['"0x8D6F94D7890EC49"'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [94606afd-9729-11e9-8fd4-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:b5cd709a-401f-0044-6536-2b1347000000\nTime:2019-06-25T09:14:05.0548276Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [b5cd709a-401f-0044-6536-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-None-Match: ['0x111111111111111'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9467bd05-9729-11e9-8f39-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd709b-401f-0044-6636-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [946edbab-9729-11e9-8303-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + etag: ['"0x8D6F94D78A60000"'] + last-modified: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd709c-401f-0044-6736-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Modified-Since: ['Tue, 25 Jun 2019 09:14:05 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [94759851-9729-11e9-ba80-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:b5cd709d-401f-0044-6836-2b1347000000\nTime:2019-06-25T09:14:05.1849519Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [b5cd709d-401f-0044-6836-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Modified-Since: ['Tue, 25 Jun 2019 09:13:05 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [947ba65c-9729-11e9-af80-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd709e-401f-0044-6936-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [94835f14-9729-11e9-93c0-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + etag: ['"0x8D6F94D78BAC588"'] + last-modified: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd709f-401f-0044-6a36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Unmodified-Since: ['Tue, 25 Jun 2019 09:13:05 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [948a4338-9729-11e9-a28c-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode '{"error":{"code":"ConditionNotMet","message":"The + condition specified using HTTP conditional header(s) is not met.\nRequestId:b5cd70a0-401f-0044-6b36-2b1347000000\nTime:2019-06-25T09:14:05.3210829Z"}}'} + headers: + content-length: ['200'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [ConditionNotMet] + x-ms-request-id: [b5cd70a0-401f-0044-6b36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The condition specified using HTTP conditional header(s) + is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + If-Unmodified-Since: ['Tue, 25 Jun 2019 09:14:05 GMT'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [94906acf-9729-11e9-b18c-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + x-ms-version: ['2018-11-09'] + method: DELETE + uri: https://storagename.dfs.core.windows.net/utcontainerded41c51/directorytestded41c51?recursive=False + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:05 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b5cd70a1-401f-0044-6c36-2b1347000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/recordings/test_path.test_get_set_access_control_with_hierarchical_namespace.yaml b/tests/recordings/test_path.test_get_set_access_control_with_hierarchical_namespace.yaml new file mode 100644 index 00000000..86c0eb81 --- /dev/null +++ b/tests/recordings/test_path.test_get_set_access_control_with_hierarchical_namespace.yaml @@ -0,0 +1,297 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [952b497d-9729-11e9-bc47-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:06 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:06 GMT'] + etag: ['"0x8D6F94D7997CE0F"'] + last-modified: ['Tue, 25 Jun 2019 09:14:06 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [5610e77d-c01f-0026-0f36-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: !!python/unicode 'test' + headers: + Connection: [keep-alive] + Content-Length: ['4'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-blob-type: [BlockBlob] + x-ms-client-request-id: [956d2278-9729-11e9-8972-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:06 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.blob.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b/blob6f6f1a9b + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + content-md5: [CY9rzUYh03PK3k6DJie09g==] + date: ['Tue, 25 Jun 2019 09:14:06 GMT'] + etag: ['"0x8D6F94D79DB996B"'] + last-modified: ['Tue, 25 Jun 2019 09:14:07 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b3d93763-401e-0028-6636-2bf393000000] + x-ms-request-server-encrypted: ['true'] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [95b1342e-9729-11e9-a006-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b?action=getAccessControl&upn=True + response: + body: {string: !!python/unicode ''} + headers: + date: ['Tue, 25 Jun 2019 09:14:06 GMT'] + etag: ['"0x8D6F94D7997CE0F"'] + last-modified: ['Tue, 25 Jun 2019 09:14:06 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-acl: ['user::rwx,group::r-x,other::---'] + x-ms-group: [$superuser] + x-ms-owner: [$superuser] + x-ms-permissions: [rwxr-x---] + x-ms-request-id: [5610e77e-c01f-0026-1036-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-acl: ['user::rwx,group::r--,other::r--'] + x-ms-client-request-id: [95c3c48f-9729-11e9-836b-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + x-ms-group: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-owner: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-version: ['2018-11-09'] + method: PATCH + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b?action=setAccessControl + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:06 GMT'] + etag: ['"0x8D6F94D7A0575D6"'] + last-modified: ['Tue, 25 Jun 2019 09:14:07 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-namespace-enabled: ['true'] + x-ms-request-id: [5610e77f-c01f-0026-1136-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [95dabc7a-9729-11e9-a346-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b?action=getAccessControl&upn=True + response: + body: {string: !!python/unicode ''} + headers: + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D7A0575D6"'] + last-modified: ['Tue, 25 Jun 2019 09:14:07 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-acl: ['user::rwx,group::r--,other::r--'] + x-ms-group: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-owner: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-permissions: [rwxr--r--] + x-ms-request-id: [5610e780-c01f-0026-1236-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [960c7bcc-9729-11e9-b1e4-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + x-ms-group: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-owner: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-permissions: [rwxrw-rw-] + x-ms-version: ['2018-11-09'] + method: PATCH + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b?action=setAccessControl + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D7A48F4F6"'] + last-modified: ['Tue, 25 Jun 2019 09:14:07 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-namespace-enabled: ['true'] + x-ms-request-id: [5610e781-c01f-0026-1336-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [961e4d66-9729-11e9-9e55-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b?action=getAccessControl&upn=False + response: + body: {string: !!python/unicode ''} + headers: + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D7A48F4F6"'] + last-modified: ['Tue, 25 Jun 2019 09:14:07 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-acl: ['user::rwx,group::rw-,other::rw-'] + x-ms-group: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-owner: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-permissions: [rwxrw-rw-] + x-ms-request-id: [5610e782-c01f-0026-1436-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [962e2e5c-9729-11e9-b108-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:08 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b/blob6f6f1a9b?action=getAccessControl&upn=True + response: + body: {string: !!python/unicode ''} + headers: + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D79DB996B"'] + last-modified: ['Tue, 25 Jun 2019 09:14:07 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-acl: ['user::rw-,group::r--,other::---'] + x-ms-group: [$superuser] + x-ms-owner: [$superuser] + x-ms-permissions: [rw-r-----] + x-ms-request-id: [5610e783-c01f-0026-1536-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-acl: ['user::rwx,group::r--,other::r--'] + x-ms-client-request-id: [963e204f-9729-11e9-b234-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:08 GMT'] + x-ms-group: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-owner: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-version: ['2018-11-09'] + method: PATCH + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b/blob6f6f1a9b?action=setAccessControl + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D7A7B4415"'] + last-modified: ['Tue, 25 Jun 2019 09:14:08 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-namespace-enabled: ['true'] + x-ms-request-id: [5610e784-c01f-0026-1636-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [96508505-9729-11e9-8b14-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:08 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b/blob6f6f1a9b?action=getAccessControl&upn=True + response: + body: {string: !!python/unicode ''} + headers: + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D7A7B4415"'] + last-modified: ['Tue, 25 Jun 2019 09:14:08 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-acl: ['user::rwx,group::r--,other::r--'] + x-ms-group: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-owner: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-permissions: [rwxr--r--] + x-ms-request-id: [5610e785-c01f-0026-1736-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [96709454-9729-11e9-80b0-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:08 GMT'] + x-ms-group: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-owner: [68390a19-a643-458b-b726-408abf67b4fc] + x-ms-permissions: [rwxrw-rw-] + x-ms-version: ['2018-11-09'] + method: PATCH + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b/blob6f6f1a9b?action=setAccessControl + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D7AAD5B9B"'] + last-modified: ['Tue, 25 Jun 2019 09:14:08 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-namespace-enabled: ['true'] + x-ms-request-id: [5610e786-c01f-0026-1836-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9682ad6b-9729-11e9-8ed9-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:08 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer6f6f1a9b/directorytest6f6f1a9b/blob6f6f1a9b?action=getAccessControl&upn=False + response: + body: {string: !!python/unicode ''} + headers: + date: ['Tue, 25 Jun 2019 09:14:07 GMT'] + etag: ['"0x8D6F94D7AAD5B9B"'] + last-modified: ['Tue, 25 Jun 2019 09:14:08 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-acl: ['user::rwx,group::rw-,other::rw-'] + x-ms-group: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-owner: [68390a19-a897-236b-b453-488abf67b4fc] + x-ms-permissions: [rwxrw-rw-] + x-ms-request-id: [5610e787-c01f-0026-1936-2bda23000000] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/recordings/test_path.test_rename_path_with_hierarchical_namespace.yaml b/tests/recordings/test_path.test_rename_path_with_hierarchical_namespace.yaml new file mode 100644 index 00000000..1881de1f --- /dev/null +++ b/tests/recordings/test_path.test_rename_path_with_hierarchical_namespace.yaml @@ -0,0 +1,541 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [97bc53d4-9729-11e9-8ece-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:10 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:10 GMT'] + etag: ['"0x8D6F94D7C29D635"'] + last-modified: ['Tue, 25 Jun 2019 09:14:11 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1e3-d01f-003a-2f36-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [97ff2aba-9729-11e9-a4bb-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestparent5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + etag: ['"0x8D6F94D7C3C3E75"'] + last-modified: ['Tue, 25 Jun 2019 09:14:11 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1e4-d01f-003a-3036-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9811e600-9729-11e9-97e7-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestparent5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1e5-d01f-003a-3136-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [982ae478-9729-11e9-99b4-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + etag: ['"0x8D6F94D7C67A270"'] + last-modified: ['Tue, 25 Jun 2019 09:14:11 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1e6-d01f-003a-3236-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [983cdc3d-9729-11e9-a7a2-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-match: ['0x111111111111111'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:a3a9b1e7-d01f-003a-3336-2b8843000000\nTime:2019-06-25T09:14:11.8416655Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [a3a9b1e7-d01f-003a-3336-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [987ee96b-9729-11e9-add4-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-match: ['"0x8D6F94D7C67A270"'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:11 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1e8-d01f-003a-3436-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9896cd5c-9729-11e9-97dc-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + etag: ['"0x8D6F94D7CD37E18"'] + last-modified: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1e9-d01f-003a-3536-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [98a8e514-9729-11e9-8f05-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-none-match: ['"0x8D6F94D7CD37E18"'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:a3a9b1ea-d01f-003a-3636-2b8843000000\nTime:2019-06-25T09:14:12.2841087Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [a3a9b1ea-d01f-003a-3636-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [98bc4f28-9729-11e9-ad15-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-none-match: ['0x111111111111111'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1eb-d01f-003a-3736-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [98d55cfa-9729-11e9-bf1e-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + etag: ['"0x8D6F94D7D11C1D2"'] + last-modified: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1ec-d01f-003a-3836-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [98e716f3-9729-11e9-82a4-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-modified-since: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:a3a9b1ed-d01f-003a-3936-2b8843000000\nTime:2019-06-25T09:14:12.6934347Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [a3a9b1ed-d01f-003a-3936-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [98fa9df0-9729-11e9-a8d7-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-modified-since: ['Tue, 25 Jun 2019 09:13:12 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1f0-d01f-003a-3c36-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [99125e70-9729-11e9-aa01-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + etag: ['"0x8D6F94D7D4F3FB7"'] + last-modified: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1f1-d01f-003a-3d36-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [99248711-9729-11e9-8aca-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-unmodified-since: ['Tue, 25 Jun 2019 09:13:12 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:a3a9b1f2-d01f-003a-3e36-2b8843000000\nTime:2019-06-25T09:14:13.1008400Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:12 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [a3a9b1f2-d01f-003a-3e36-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9938c742-9729-11e9-a572-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-source-if-unmodified-since: ['Tue, 25 Jun 2019 09:14:12 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603 + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1f3-d01f-003a-3f36-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [99545cb3-9729-11e9-b703-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + etag: ['"0x8D6F94D7D926DE7"'] + last-modified: ['Tue, 25 Jun 2019 09:14:13 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1f4-d01f-003a-4036-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9967b41c-9729-11e9-95e1-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + etag: ['"0x8D6F94D7DA4D79A"'] + last-modified: ['Tue, 25 Jun 2019 09:14:13 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1f5-d01f-003a-4136-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: !!python/unicode 'test' + headers: + Connection: [keep-alive] + Content-Length: ['4'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-blob-type: [BlockBlob] + x-ms-client-request-id: [997a106b-9729-11e9-9726-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.blob.core.windows.net/utcontainer5f351603/directorytestnew5f351603/blob5f351603 + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + content-md5: [CY9rzUYh03PK3k6DJie09g==] + date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + etag: ['"0x8D6F94D7DE7297F"'] + last-modified: ['Tue, 25 Jun 2019 09:14:13 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [1f1e1b51-501e-0024-1136-2b649b000000] + x-ms-request-server-encrypted: ['true'] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [99bc73a6-9729-11e9-b44d-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytestnew5f351603?mode=legacy + response: + body: {string: !!python/unicode '{"error":{"code":"InternalOperationAbortError","message":"This + operation is aborted because there is another conflicting operation in progress.\nRequestId:a3a9b1f6-d01f-003a-4236-2b8843000000\nTime:2019-06-25T09:14:14.0726744Z"}}'} + headers: + content-length: ['229'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:13 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [InternalOperationAbortError] + x-ms-request-id: [a3a9b1f6-d01f-003a-4236-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 409, message: This operation is aborted because there is another + conflicting operation in progress.} +- request: + body: !!python/unicode 'test' + headers: + Connection: [keep-alive] + Content-Length: ['4'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-blob-type: [BlockBlob] + x-ms-client-request-id: [99ccef4f-9729-11e9-b253-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.blob.core.windows.net/utcontainer5f351603/directorytest5f351603/blob5f351603old + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + content-md5: [CY9rzUYh03PK3k6DJie09g==] + date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + etag: ['"0x8D6F94D7E0B1113"'] + last-modified: ['Tue, 25 Jun 2019 09:14:14 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [1f1e1b5c-501e-0024-1a36-2b649b000000] + x-ms-request-server-encrypted: ['true'] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [99e10194-9729-11e9-89d6-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + etag: ['"0x8D6F94D7E1DE62E"'] + last-modified: ['Tue, 25 Jun 2019 09:14:14 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b1f8-d01f-003a-4436-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [99f332a6-9729-11e9-9e61-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + x-ms-rename-source: [/utcontainer5f351603/directorytest5f351603/blob5f351603old] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://hierarchicalnamespacestoragename.dfs.core.windows.net/utcontainer5f351603/directorytest5f351603/blob5f351603new + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [a3a9b200-d01f-003a-4c36-2b8843000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9a0b3ee8-9729-11e9-a7d9-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://hierarchicalnamespacestoragename.blob.core.windows.net/utcontainer5f351603/directorytest5f351603/blob5f351603new + response: + body: {string: !!python/unicode ''} + headers: + accept-ranges: [bytes] + content-length: ['4'] + content-md5: [CY9rzUYh03PK3k6DJie09g==] + content-type: [application/octet-stream] + date: ['Tue, 25 Jun 2019 09:14:14 GMT'] + etag: ['"0x8D6F94D7E325B6D"'] + last-modified: ['Tue, 25 Jun 2019 09:14:14 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + x-ms-access-tier: [Hot] + x-ms-access-tier-inferred: ['true'] + x-ms-blob-type: [BlockBlob] + x-ms-creation-time: ['Mon, 01 Jan 1601 00:00:00 GMT'] + x-ms-lease-state: [available] + x-ms-lease-status: [unlocked] + x-ms-request-id: [1f1e1b61-501e-0024-1c36-2b649b000000] + x-ms-server-encrypted: ['true'] + x-ms-tag-count: ['0'] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +version: 1 diff --git a/tests/recordings/test_path.test_rename_path_without_hierarchical_namespace.yaml b/tests/recordings/test_path.test_rename_path_without_hierarchical_namespace.yaml new file mode 100644 index 00000000..0cf6ac1d --- /dev/null +++ b/tests/recordings/test_path.test_rename_path_without_hierarchical_namespace.yaml @@ -0,0 +1,471 @@ +interactions: +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9ad54fee-9729-11e9-b5ff-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:15 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:15 GMT'] + etag: ['"0x8D6F94D7F1EFE3D"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b66b55b2-601f-001c-1136-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9aeebe02-9729-11e9-99c7-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestparenta6f3175b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:15 GMT'] + etag: ['"0x8D6F94D7F25DDB3"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b66b55b3-601f-001c-1236-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9af57a07-9729-11e9-bd11-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestparenta6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:15 GMT'] + etag: ['"0x8D6F94D7F2E6B45"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-continuation: [''] + x-ms-request-id: [b66b55b4-601f-001c-1336-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9afec728-9729-11e9-96f8-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:15 GMT'] + etag: ['"0x8D6F94D7F360E3F"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b66b55b5-601f-001c-1436-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b05c19c-9729-11e9-8fdf-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-match: ['0x111111111111111'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:b66b55b6-601f-001c-1536-2b173c000000\nTime:2019-06-25T09:14:16.1995625Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [b66b55b6-601f-001c-1536-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b166c02-9729-11e9-bb62-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-match: ['"0x8D6F94D7F360E3F"'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7F4EA544"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-continuation: [''] + x-ms-request-id: [b66b55b7-601f-001c-1636-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b1fea68-9729-11e9-8f87-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7F570BC1"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b66b55b8-601f-001c-1736-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b26b302-9729-11e9-8313-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-none-match: ['"0x8D6F94D7F570BC1"'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:b66b55b9-601f-001c-1836-2b173c000000\nTime:2019-06-25T09:14:16.4127675Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [b66b55b9-601f-001c-1836-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b2cad02-9729-11e9-9dbe-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-none-match: ['0x111111111111111'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7F64CAB5"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-continuation: [''] + x-ms-request-id: [b66b55ba-601f-001c-1936-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b3509fd-9729-11e9-84c1-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7F6C6DAF"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b66b55bb-601f-001c-1a36-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b3c1628-9729-11e9-9cde-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-modified-since: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:b66b55bc-601f-001c-1b36-2b173c000000\nTime:2019-06-25T09:14:16.5589077Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [b66b55bc-601f-001c-1b36-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b42e3b0-9729-11e9-95c6-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-modified-since: ['Tue, 25 Jun 2019 09:13:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7F7C7722"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-continuation: [''] + x-ms-request-id: [b66b55bd-601f-001c-1c36-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b4cc038-9729-11e9-980a-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7F83CBE8"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b66b55be-601f-001c-1d36-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b536c80-9729-11e9-944f-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-unmodified-since: ['Tue, 25 Jun 2019 09:13:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode '{"error":{"code":"SourceConditionNotMet","message":"The + source condition specified using HTTP conditional header(s) is not met.\nRequestId:b66b55bf-601f-001c-1e36-2b173c000000\nTime:2019-06-25T09:14:16.7130552Z"}}'} + headers: + content-length: ['213'] + content-type: [application/json;charset=utf-8] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-error-code: [SourceConditionNotMet] + x-ms-request-id: [b66b55bf-601f-001c-1e36-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 412, message: The source condition specified using HTTP conditional + header(s) is not met.} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b5a541e-9729-11e9-8226-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b] + x-ms-source-if-unmodified-since: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytestnewa6f3175b + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7F929C93"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-continuation: [''] + x-ms-request-id: [b66b55c0-601f-001c-1f36-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: !!python/unicode 'test' + headers: + Connection: [keep-alive] + Content-Length: ['4'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-blob-type: [BlockBlob] + x-ms-client-request-id: [9b62d300-9729-11e9-ad1b-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainera6f3175b/directorytesta6f3175b/bloba6f3175bold + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + content-md5: [CY9rzUYh03PK3k6DJie09g==] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7FAB81C7"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [023befbb-d01e-0063-4c36-2b890e000000] + x-ms-request-server-encrypted: ['true'] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b7b394a-9729-11e9-bed0-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b?resource=directory + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7FB2AF70"'] + last-modified: ['Tue, 25 Jun 2019 09:14:16 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-request-id: [b66b55c1-601f-001c-2036-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + Content-Length: ['0'] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b8283ee-9729-11e9-97ef-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + x-ms-rename-source: [/utcontainera6f3175b/directorytesta6f3175b/bloba6f3175bold] + x-ms-version: ['2018-11-09'] + method: PUT + uri: https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b/bloba6f3175bnew + response: + body: {string: !!python/unicode ''} + headers: + content-length: ['0'] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7FBB8B35"'] + last-modified: ['Tue, 25 Jun 2019 09:14:17 GMT'] + server: [Windows-Azure-HDFS/1.0 Microsoft-HTTPAPI/2.0] + x-ms-continuation: [''] + x-ms-request-id: [b66b55c2-601f-001c-2136-2b173c000000] + x-ms-version: ['2018-11-09'] + status: {code: 201, message: Created} +- request: + body: null + headers: + Connection: [keep-alive] + User-Agent: [Azure-Storage/2.0.0-2.0.1 (Python CPython 2.7.15; Darwin 18.6.0)] + x-ms-client-request-id: [9b8bf0a8-9729-11e9-904b-acde48001122] + x-ms-date: ['Tue, 25 Jun 2019 09:14:17 GMT'] + x-ms-version: ['2018-11-09'] + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainera6f3175b/directorytesta6f3175b/bloba6f3175bnew + response: + body: {string: !!python/unicode ''} + headers: + accept-ranges: [bytes] + content-length: ['4'] + content-md5: [CY9rzUYh03PK3k6DJie09g==] + content-type: [application/octet-stream] + date: ['Tue, 25 Jun 2019 09:14:16 GMT'] + etag: ['"0x8D6F94D7FBB8B35"'] + last-modified: ['Tue, 25 Jun 2019 09:14:17 GMT'] + server: [Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0] + vary: [Origin] + x-ms-access-tier: [Hot] + x-ms-access-tier-inferred: ['true'] + x-ms-blob-type: [BlockBlob] + x-ms-copy-completion-time: ['Tue, 25 Jun 2019 09:14:17 GMT'] + x-ms-copy-id: [8ca9f7c5-66d5-43ab-a993-86ab7874050f] + x-ms-copy-progress: [4/4] + x-ms-copy-source: ['https://storagename.dfs.core.windows.net/utcontainera6f3175b/directorytesta6f3175b/bloba6f3175bold'] + x-ms-copy-status: [success] + x-ms-creation-time: ['Tue, 25 Jun 2019 09:14:17 GMT'] + x-ms-lease-state: [available] + x-ms-lease-status: [unlocked] + x-ms-request-id: [023befef-d01e-0063-7b36-2b890e000000] + x-ms-server-encrypted: ['true'] + x-ms-tag-count: ['0'] + x-ms-version: ['2018-11-09'] + status: {code: 200, message: OK} +version: 1 From 8bfa7b4b2f7636b04d65833ac595e2b2c54acadd Mon Sep 17 00:00:00 2001 From: zezha-msft Date: Wed, 26 Jun 2019 17:48:38 -0700 Subject: [PATCH 3/4] ADLSGen2: remove filesystem APIs and bump version --- .../azure/storage/blob/baseblobservice.py | 28 ------------------- azure-storage-blob/setup.py | 2 +- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/azure-storage-blob/azure/storage/blob/baseblobservice.py b/azure-storage-blob/azure/storage/blob/baseblobservice.py index 0e4f10cd..90468e4f 100644 --- a/azure-storage-blob/azure/storage/blob/baseblobservice.py +++ b/azure-storage-blob/azure/storage/blob/baseblobservice.py @@ -3944,31 +3944,3 @@ def _swap_blob_endpoints(host_locations): # Note that only the primary endpoint is supported for the DFS endpoint return {LocationMode.PRIMARY: host_locations[LocationMode.PRIMARY].replace(_BLOB_SERVICE_PUBLIC_CLOUD_HOST, _DFS_SERVICE_PUBLIC_CLOUD_HOST, 1)} - - # TODO remove after service update, needed for testing against HN-enabled account for the moment - def _create_file_system(self, filesystem_name, timeout=None): - _validate_not_none('filesystem_name', filesystem_name) - request = HTTPRequest() - request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) - request.method = 'PUT' - request.path = _get_path(filesystem_name) - request.query = { - 'resource': 'filesystem', - 'timeout': _int_to_str(timeout), - } - self._perform_request(request) - return True - - # TODO remove after service update, needed for testing against HN-enabled account for the moment - def _delete_file_system(self, filesystem_name, timeout=None): - _validate_not_none('filesystem_name', filesystem_name) - request = HTTPRequest() - request.host_locations = self._swap_blob_endpoints(self._get_host_locations()) - request.method = 'DELETE' - request.path = _get_path(filesystem_name) - request.query = { - 'resource': 'filesystem', - 'timeout': _int_to_str(timeout), - } - self._perform_request(request) - return True diff --git a/azure-storage-blob/setup.py b/azure-storage-blob/setup.py index aae07efd..d07fbf1d 100644 --- a/azure-storage-blob/setup.py +++ b/azure-storage-blob/setup.py @@ -44,7 +44,7 @@ setup( name='azure-storage-blob', - version='2.1.0', + version='2.2.0b1', description='Microsoft Azure Storage Blob Client Library for Python', long_description=open('README.rst', 'r').read(), license='MIT License', From c1eb9755f0c3f30950c56729e20045b0a37d420c Mon Sep 17 00:00:00 2001 From: zezha-msft Date: Tue, 16 Jul 2019 16:49:41 -0700 Subject: [PATCH 4/4] Added sample for directory usage --- samples/blob/directory_usage.py | 129 ++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 samples/blob/directory_usage.py diff --git a/samples/blob/directory_usage.py b/samples/blob/directory_usage.py new file mode 100644 index 00000000..17c0a49c --- /dev/null +++ b/samples/blob/directory_usage.py @@ -0,0 +1,129 @@ +import uuid + +from tests.settings_real import ( + STORAGE_ACCOUNT_NAME, + STORAGE_ACCOUNT_KEY, + HIERARCHICAL_NAMESPACE_ACCOUNT_NAME, + HIERARCHICAL_NAMESPACE_ACCOUNT_KEY, + ACTIVE_DIRECTORY_APPLICATION_ID +) +from azure.storage.blob import ( + BlockBlobService +) + +# toggle this constant to see different behaviors +# when HNS is enabled: +# - get/set access control operations are supported +# - rename/delete operations are atomic +IS_HNS_ENABLED = False + + +def run(): + # swap in your test accounts + if IS_HNS_ENABLED: + blob_service = BlockBlobService(HIERARCHICAL_NAMESPACE_ACCOUNT_NAME, HIERARCHICAL_NAMESPACE_ACCOUNT_KEY) + else: + blob_service = BlockBlobService(STORAGE_ACCOUNT_NAME, STORAGE_ACCOUNT_KEY, protocol="http") + + # set up a test container + container_name = "testcontainer" + blob_service.create_container(container_name) + + try: + demonstrate_directory_usage(blob_service, container_name) + finally: + # clean up the test container + blob_service.delete_container(container_name) + + +def demonstrate_directory_usage(blob_service, container_name): + directory_name = "dir" + + # usage 1: create a directory with metadata inside the container + props = blob_service.create_directory(container_name, directory_path=directory_name, metadata={"test": "value"}) + + # show the etag and lmt of the newly created directory + print("Etag: {}".format(props.etag)) + print("Lmt: {}".format(props.last_modified)) + + # populate the created directory with some blobs + _create_blobs(blob_service, container_name, directory_name, num_of_blobs=200) + + # these APIs only work against an account where HNS is enabled + if IS_HNS_ENABLED: + # usage 2: set the access control properties on the directory + test_owner = ACTIVE_DIRECTORY_APPLICATION_ID + test_group = ACTIVE_DIRECTORY_APPLICATION_ID + test_permissions = 'rwxrw-rw-' + blob_service.set_path_access_control(container_name, directory_name, owner=test_owner, group=test_group, + permissions=test_permissions) + + # usage 3: fetch the access control information on the directory + access_control_props = blob_service.get_path_access_control( + container_name, directory_name, user_principle_names=True) + + # print out values + print("Owner: {}".format(access_control_props.owner)) + print("Permissions: {}".format(access_control_props.permissions)) + print("Group: {}".format(access_control_props.group)) + print("Acl: {}".format(access_control_props.acl)) + + # usage 4: rename directory, see method for more details + new_directory_name = "dir2" + rename_directory(blob_service, container_name, new_directory_name, directory_name) + + # usage 5: delete the directory, see method for more details + delete_directory(blob_service, container_name, new_directory_name) + + +def rename_directory(blob_service, container_name, new_directory_name, old_directory_name): + marker = blob_service.rename_path(container_name, new_directory_name, old_directory_name) + + # if HNS is enabled, the rename operation is atomic and no marker is returned + # if HNS is not enabled, and there are too more files/subdirectories in the directories to be renamed + # in a single call, the service returns a marker, so that we can follow it and finish renaming + # the rest of the files/subdirectories + count = 1 + while marker is not None: + marker = blob_service.rename_path(container_name, new_directory_name, old_directory_name, marker=marker) + count += 1 + + print("Took {} call(s) to finish renaming.".format(count)) + + +def delete_directory(blob_service, container_name, directory_name): + deleted, marker = blob_service.delete_directory(container_name, directory_name, recursive=True) + + # if HNS is enabled, the delete operation is atomic and no marker is returned + # if HNS is not enabled, and there are too more files/subdirectories in the directories to be deleted + # in a single call, the service returns a marker, so that we can follow it and finish deleting + # the rest of the files/subdirectories + count = 1 + while marker is not None: + deleted, marker = blob_service.delete_directory(container_name, directory_name, + marker=marker, recursive=True) + count += 1 + + print("Took {} calls(s) to finish deleting.".format(count)) + + +def _create_blobs(blob_service, container_name, directory_name, num_of_blobs): + import concurrent.futures + import itertools + # Use a thread pool because it is too slow otherwise + with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: + def create_blob(): + # generate a random name + blob_name = "{}/{}".format(directory_name, str(uuid.uuid4()).replace('-', '')) + + # create a blob under the directory + # blob_service.create_blob_from_bytes(container_name, blob_name, b"test") + blob_service.create_directory(container_name, blob_name) + + futures = {executor.submit(create_blob) for _ in itertools.repeat(None, num_of_blobs)} + concurrent.futures.wait(futures) + print("Created {} blobs under the directory: {}".format(num_of_blobs, directory_name)) + + +if __name__ == '__main__': + run()