diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py index db4273e7ee3a..3390840d9203 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.py @@ -18,6 +18,7 @@ import six from azure.core.tracing.decorator import distributed_trace +from azure.core.exceptions import ResourceNotFoundError from ._shared import encode_base64 from ._shared.base_client import StorageAccountHostsMixin, parse_connection_str, parse_query @@ -929,6 +930,31 @@ def undelete_blob(self, **kwargs): except StorageErrorException as error: process_storage_error(error) + @distributed_trace() + def exists(self, **kwargs): + # type: (**Any) -> bool + """ + Returns True if a blob exists with the defined parameters, and returns + False otherwise. + + :param str version_id: + The version id parameter is an opaque DateTime + value that, when present, specifies the version of the blob to check if it exists. + :param int timeout: + The timeout parameter is expressed in seconds. + :returns: boolean + """ + try: + self._client.blob.get_properties( + snapshot=self.snapshot, + **kwargs) + return True + except StorageErrorException as error: + try: + process_storage_error(error) + except ResourceNotFoundError: + return False + @distributed_trace def get_blob_properties(self, **kwargs): # type: (**Any) -> BlobProperties diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_blob_client_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_blob_client_async.py index d88075ae87b9..49674227f6de 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_blob_client_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_blob_client_async.py @@ -11,6 +11,7 @@ ) from azure.core.tracing.decorator_async import distributed_trace_async +from azure.core.exceptions import ResourceNotFoundError from .._shared.base_client_async import AsyncStorageAccountHostsMixin from .._shared.policies_async import ExponentialRetry @@ -30,6 +31,7 @@ from ._lease_async import BlobLeaseClient from ._download_async import StorageStreamDownloader + if TYPE_CHECKING: from datetime import datetime from .._models import ( # pylint: disable=unused-import @@ -459,6 +461,31 @@ async def undelete_blob(self, **kwargs): except StorageErrorException as error: process_storage_error(error) + @distributed_trace_async + async def exists(self, **kwargs): + # type: (**Any) -> bool + """ + Returns True if a blob exists with the defined parameters, and returns + False otherwise. + + :param str version_id: + The version id parameter is an opaque DateTime + value that, when present, specifies the version of the blob to check if it exists. + :param int timeout: + The timeout parameter is expressed in seconds. + :returns: boolean + """ + try: + await self._client.blob.get_properties( + snapshot=self.snapshot, + **kwargs) + return True + except StorageErrorException as error: + try: + process_storage_error(error) + except ResourceNotFoundError: + return False + @distributed_trace_async async def get_blob_properties(self, **kwargs): # type: (Any) -> BlobProperties diff --git a/sdk/storage/azure-storage-blob/tests/recordings/test_blob_access_conditions.test_if_blob_exists.yaml b/sdk/storage/azure-storage-blob/tests/recordings/test_blob_access_conditions.test_if_blob_exists.yaml new file mode 100644 index 000000000000..4cd261819afe --- /dev/null +++ b/sdk/storage/azure-storage-blob/tests/recordings/test_blob_access_conditions.test_if_blob_exists.yaml @@ -0,0 +1,730 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:53 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainerccc51342?restype=container + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 04 Sep 2020 18:46:52 GMT + etag: + - '"0x8D85102E4833C1D"' + last-modified: + - Fri, 04 Sep 2020 18:46:53 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-version: + - '2019-12-12' + status: + code: 201 + message: Created +- request: + body: hello world + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '11' + Content-Type: + - application/octet-stream + If-None-Match: + - '*' + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-blob-type: + - BlockBlob + x-ms-date: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1 + response: + body: + string: '' + headers: + content-length: + - '0' + content-md5: + - XrY7u+Ae7tCTyyK7j1rNww== + date: + - Fri, 04 Sep 2020 18:46:54 GMT + etag: + - '"0x8D85102E49BFD6D"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: + - vo7q9sPVKY0= + x-ms-request-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:54.0137837Z' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1 + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '11' + content-md5: + - XrY7u+Ae7tCTyyK7j1rNww== + content-type: + - application/octet-stream + date: + - Fri, 04 Sep 2020 18:46:54 GMT + etag: + - '"0x8D85102E49BFD6D"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 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: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-is-current-version: + - 'true' + x-ms-lease-state: + - available + x-ms-lease-status: + - unlocked + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:54.0137837Z' + status: + code: 200 + message: OK +- request: + body: this is test content + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '20' + Content-Type: + - application/octet-stream + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?blockid=MQ%3D%3D&comp=block + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 04 Sep 2020 18:46:54 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: + - wae/Ns62JRA= + x-ms-request-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + status: + code: 201 + message: Created +- request: + body: ' + + MQ==' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '83' + Content-Type: + - application/xml; charset=utf-8 + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?comp=blocklist + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 04 Sep 2020 18:46:54 GMT + etag: + - '"0x8D85102E4E26222"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: + - iEgKfcNWGmY= + x-ms-request-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:54.4761138Z' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1 + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '20' + content-type: + - application/octet-stream + date: + - Fri, 04 Sep 2020 18:46:54 GMT + etag: + - '"0x8D85102E4E26222"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 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: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-is-current-version: + - 'true' + x-ms-lease-state: + - available + x-ms-lease-status: + - unlocked + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:54.4761138Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:55 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?versionid=2020-09-04T18%3A46%3A54.0137837Z + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '11' + content-md5: + - XrY7u+Ae7tCTyyK7j1rNww== + content-type: + - application/octet-stream + date: + - Fri, 04 Sep 2020 18:46:54 GMT + etag: + - '"0x8D85102E49BFD6D"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 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: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:54.0137837Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:55 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?versionid=2020-09-04T18%3A46%3A54.4761138Z + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '20' + content-type: + - application/octet-stream + date: + - Fri, 04 Sep 2020 18:46:54 GMT + etag: + - '"0x8D85102E4E26222"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 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: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-is-current-version: + - 'true' + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:54.4761138Z' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:55 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?versionid=2020-08-21T21%3A24%3A15.3585832Z + response: + body: + string: '' + headers: + date: + - Fri, 04 Sep 2020 18:46:55 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + transfer-encoding: + - chunked + x-ms-error-code: + - BlobNotFound + x-ms-version: + - '2019-12-12' + status: + code: 404 + message: The specified blob does not exist. +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:55 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?comp=snapshot + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 04 Sep 2020 18:46:55 GMT + etag: + - '"0x8D85102E4E26222"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-request-server-encrypted: + - 'false' + x-ms-snapshot: + - '2020-09-04T18:46:55.2236480Z' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:55.2246480Z' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:55 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?snapshot=2020-09-04T18:46:55.2236480Z + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '20' + content-type: + - application/octet-stream + date: + - Fri, 04 Sep 2020 18:46:55 GMT + etag: + - '"0x8D85102E4E26222"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 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: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + status: + code: 200 + message: OK +- request: + body: this is additional test content + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '31' + Content-Type: + - application/octet-stream + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:55 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?blockid=MQ%3D%3D&comp=block + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 04 Sep 2020 18:46:55 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: + - npKkArwnhSg= + x-ms-request-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + status: + code: 201 + message: Created +- request: + body: ' + + MQ==' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '83' + Content-Type: + - application/xml; charset=utf-8 + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:56 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?comp=blocklist + response: + body: + string: '' + headers: + content-length: + - '0' + date: + - Fri, 04 Sep 2020 18:46:55 GMT + etag: + - '"0x8D85102E599C5B2"' + last-modified: + - Fri, 04 Sep 2020 18:46:55 GMT + server: + - Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: + - iEgKfcNWGmY= + x-ms-request-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:55.6789721Z' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:56 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1?snapshot=2020-09-04T18:46:55.2236480Z + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '20' + content-type: + - application/octet-stream + date: + - Fri, 04 Sep 2020 18:46:55 GMT + etag: + - '"0x8D85102E4E26222"' + last-modified: + - Fri, 04 Sep 2020 18:46:54 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: + - Fri, 04 Sep 2020 18:46:54 GMT + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:56 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainerccc51342/blob1 + response: + body: + string: '' + headers: + accept-ranges: + - bytes + content-length: + - '31' + content-type: + - application/octet-stream + date: + - Fri, 04 Sep 2020 18:46:55 GMT + etag: + - '"0x8D85102E599C5B2"' + last-modified: + - Fri, 04 Sep 2020 18:46:55 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: + - Fri, 04 Sep 2020 18:46:55 GMT + x-ms-is-current-version: + - 'true' + x-ms-lease-state: + - available + x-ms-lease-status: + - unlocked + x-ms-server-encrypted: + - 'true' + x-ms-version: + - '2019-12-12' + x-ms-version-id: + - '2020-09-04T18:46:55.6789721Z' + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/storage/azure-storage-blob/tests/recordings/test_blob_access_conditions_async.test_if_blob_exists.yaml b/sdk/storage/azure-storage-blob/tests/recordings/test_blob_access_conditions_async.test_if_blob_exists.yaml new file mode 100644 index 000000000000..1efaa06c1971 --- /dev/null +++ b/sdk/storage/azure-storage-blob/tests/recordings/test_blob_access_conditions_async.test_if_blob_exists.yaml @@ -0,0 +1,483 @@ +interactions: +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:41 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf?restype=container + response: + body: + string: '' + headers: + content-length: '0' + date: Fri, 04 Sep 2020 18:46:40 GMT + etag: '"0x8D85102DCED6139"' + last-modified: Fri, 04 Sep 2020 18:46:41 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-version: '2019-12-12' + status: + code: 201 + message: Created + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf?restype=container +- request: + body: hello world + headers: + Content-Length: + - '11' + Content-Type: + - application/octet-stream + If-None-Match: + - '*' + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-blob-type: + - BlockBlob + x-ms-date: + - Fri, 04 Sep 2020 18:46:41 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1 + response: + body: + string: '' + headers: + content-length: '0' + content-md5: XrY7u+Ae7tCTyyK7j1rNww== + date: Fri, 04 Sep 2020 18:46:40 GMT + etag: '"0x8D85102DCFA8B6D"' + last-modified: Fri, 04 Sep 2020 18:46:41 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: vo7q9sPVKY0= + x-ms-request-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:41.2126852Z' + status: + code: 201 + message: Created + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1 +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:41 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1 + response: + body: + string: '' + headers: + accept-ranges: bytes + content-length: '11' + content-md5: XrY7u+Ae7tCTyyK7j1rNww== + content-type: application/octet-stream + date: Fri, 04 Sep 2020 18:46:40 GMT + etag: '"0x8D85102DCFA8B6D"' + last-modified: Fri, 04 Sep 2020 18:46:41 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: Fri, 04 Sep 2020 18:46:41 GMT + x-ms-is-current-version: 'true' + x-ms-lease-state: available + x-ms-lease-status: unlocked + x-ms-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:41.2126852Z' + status: + code: 200 + message: OK + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1 +- request: + body: this is test content + headers: + Content-Length: + - '20' + Content-Type: + - application/octet-stream + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:41 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?blockid=MQ%3D%3D&comp=block + response: + body: + string: '' + headers: + content-length: '0' + date: Fri, 04 Sep 2020 18:46:41 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: wae/Ns62JRA= + x-ms-request-server-encrypted: 'true' + x-ms-version: '2019-12-12' + status: + code: 201 + message: Created + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?blockid=MQ%3D%3D&comp=block +- request: + body: ' + + MQ==' + headers: + Content-Length: + - '83' + Content-Type: + - application/xml; charset=utf-8 + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:42 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?comp=blocklist + response: + body: + string: '' + headers: + content-length: '0' + date: Fri, 04 Sep 2020 18:46:41 GMT + etag: '"0x8D85102DD486B76"' + last-modified: Fri, 04 Sep 2020 18:46:41 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: iEgKfcNWGmY= + x-ms-request-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:41.7230470Z' + status: + code: 201 + message: Created + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?comp=blocklist +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:42 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1 + response: + body: + string: '' + headers: + accept-ranges: bytes + content-length: '20' + content-type: application/octet-stream + date: Fri, 04 Sep 2020 18:46:41 GMT + etag: '"0x8D85102DD486B76"' + last-modified: Fri, 04 Sep 2020 18:46:41 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: Fri, 04 Sep 2020 18:46:41 GMT + x-ms-is-current-version: 'true' + x-ms-lease-state: available + x-ms-lease-status: unlocked + x-ms-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:41.7230470Z' + status: + code: 200 + message: OK + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1 +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:42 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?versionid=2020-09-04T18:46:41.2126852Z + response: + body: + string: '' + headers: + accept-ranges: bytes + content-length: '11' + content-md5: XrY7u+Ae7tCTyyK7j1rNww== + content-type: application/octet-stream + date: Fri, 04 Sep 2020 18:46:41 GMT + etag: '"0x8D85102DCFA8B6D"' + last-modified: Fri, 04 Sep 2020 18:46:41 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: Fri, 04 Sep 2020 18:46:41 GMT + x-ms-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:41.2126852Z' + status: + code: 200 + message: OK + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?versionid=2020-09-04T18:46:41.2126852Z +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:42 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?versionid=2020-09-04T18:46:41.7230470Z + response: + body: + string: '' + headers: + accept-ranges: bytes + content-length: '20' + content-type: application/octet-stream + date: Fri, 04 Sep 2020 18:46:42 GMT + etag: '"0x8D85102DD486B76"' + last-modified: Fri, 04 Sep 2020 18:46:41 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: Fri, 04 Sep 2020 18:46:41 GMT + x-ms-is-current-version: 'true' + x-ms-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:41.7230470Z' + status: + code: 200 + message: OK + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?versionid=2020-09-04T18:46:41.7230470Z +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:42 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?versionid=2020-08-21T21:24:15.3585832Z + response: + body: + string: '' + headers: + date: Fri, 04 Sep 2020 18:46:42 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + transfer-encoding: chunked + x-ms-error-code: BlobNotFound + x-ms-version: '2019-12-12' + status: + code: 404 + message: The specified blob does not exist. + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?versionid=2020-08-21T21:24:15.3585832Z +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:43 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?comp=snapshot + response: + body: + string: '' + headers: + content-length: '0' + date: Fri, 04 Sep 2020 18:46:42 GMT + etag: '"0x8D85102DD486B76"' + last-modified: Fri, 04 Sep 2020 18:46:41 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-request-server-encrypted: 'false' + x-ms-snapshot: '2020-09-04T18:46:43.1560641Z' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:43.1570641Z' + status: + code: 201 + message: Created + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?comp=snapshot +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:43 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?snapshot=2020-09-04T18:46:43.1560641Z + response: + body: + string: '' + headers: + accept-ranges: bytes + content-length: '20' + content-type: application/octet-stream + date: Fri, 04 Sep 2020 18:46:42 GMT + etag: '"0x8D85102DD486B76"' + last-modified: Fri, 04 Sep 2020 18:46:41 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: Fri, 04 Sep 2020 18:46:41 GMT + x-ms-server-encrypted: 'true' + x-ms-version: '2019-12-12' + status: + code: 200 + message: OK + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?snapshot=2020-09-04T18:46:43.1560641Z +- request: + body: this is additional test content + headers: + Content-Length: + - '31' + Content-Type: + - application/octet-stream + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:43 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?blockid=MQ%3D%3D&comp=block + response: + body: + string: '' + headers: + content-length: '0' + date: Fri, 04 Sep 2020 18:46:42 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: npKkArwnhSg= + x-ms-request-server-encrypted: 'true' + x-ms-version: '2019-12-12' + status: + code: 201 + message: Created + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?blockid=MQ%3D%3D&comp=block +- request: + body: ' + + MQ==' + headers: + Content-Length: + - '83' + Content-Type: + - application/xml; charset=utf-8 + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:44 GMT + x-ms-version: + - '2019-12-12' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?comp=blocklist + response: + body: + string: '' + headers: + content-length: '0' + date: Fri, 04 Sep 2020 18:46:42 GMT + etag: '"0x8D85102DE756263"' + last-modified: Fri, 04 Sep 2020 18:46:43 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: iEgKfcNWGmY= + x-ms-request-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:43.6954483Z' + status: + code: 201 + message: Created + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?comp=blocklist +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:44 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1?snapshot=2020-09-04T18:46:43.1560641Z + response: + body: + string: '' + headers: + accept-ranges: bytes + content-length: '20' + content-type: application/octet-stream + date: Fri, 04 Sep 2020 18:46:42 GMT + etag: '"0x8D85102DD486B76"' + last-modified: Fri, 04 Sep 2020 18:46:41 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: Fri, 04 Sep 2020 18:46:41 GMT + x-ms-server-encrypted: 'true' + x-ms-version: '2019-12-12' + status: + code: 200 + message: OK + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1?snapshot=2020-09-04T18:46:43.1560641Z +- request: + body: null + headers: + User-Agent: + - azsdk-python-storage-blob/12.4.0 Python/3.8.5 (Windows-10-10.0.18362-SP0) + x-ms-date: + - Fri, 04 Sep 2020 18:46:44 GMT + x-ms-version: + - '2019-12-12' + method: HEAD + uri: https://storagename.blob.core.windows.net/utcontainer4a2315bf/blob1 + response: + body: + string: '' + headers: + accept-ranges: bytes + content-length: '31' + content-type: application/octet-stream + date: Fri, 04 Sep 2020 18:46:43 GMT + etag: '"0x8D85102DE756263"' + last-modified: Fri, 04 Sep 2020 18:46:43 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: Fri, 04 Sep 2020 18:46:43 GMT + x-ms-is-current-version: 'true' + x-ms-lease-state: available + x-ms-lease-status: unlocked + x-ms-server-encrypted: 'true' + x-ms-version: '2019-12-12' + x-ms-version-id: '2020-09-04T18:46:43.6954483Z' + status: + code: 200 + message: OK + url: https://tamerdevtest.blob.core.windows.net/utcontainer4a2315bf/blob1 +version: 1 diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions.py b/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions.py index 876c8bb55849..5721447f62c5 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions.py @@ -715,6 +715,36 @@ def test_get_blob_properties_with_if_modified(self, resource_group, location, st self.assertEqual(properties.size, 11) self.assertEqual(properties.lease.status, 'unlocked') + @GlobalStorageAccountPreparer() + def test_if_blob_exists(self, resource_group, location, storage_account, storage_account_key): + bsc = BlobServiceClient(self.account_url(storage_account, "blob"), storage_account_key, connection_data_block_size=4 * 1024) + self._setup() + self._create_container_and_block_blob( + self.container_name, 'blob1', b'hello world', bsc) + # Act + blob = bsc.get_blob_client(self.container_name, 'blob1') + old_blob_version_id = blob.get_blob_properties().get("version_id") + self.assertIsNotNone(old_blob_version_id) + blob.stage_block(block_id='1', data="this is test content") + blob.commit_block_list(['1']) + new_blob_version_id = blob.get_blob_properties().get("version_id") + + # Assert + self.assertEqual(blob.exists(version_id=old_blob_version_id), True) + self.assertEqual(blob.exists(version_id=new_blob_version_id), True) + self.assertEqual(blob.exists(version_id="2020-08-21T21:24:15.3585832Z"), False) + + # Act + test_snapshot = blob.create_snapshot() + blob_snapshot = bsc.get_blob_client(self.container_name, 'blob1', snapshot=test_snapshot) + self.assertEqual(blob_snapshot.exists(), True) + blob.stage_block(block_id='1', data="this is additional test content") + blob.commit_block_list(['1']) + + # Assert + self.assertEqual(blob_snapshot.exists(), True) + self.assertEqual(blob.exists(), True) + @GlobalStorageAccountPreparer() def test_get_blob_properties_with_if_modified_fail(self, resource_group, location, storage_account, storage_account_key): bsc = BlobServiceClient(self.account_url(storage_account, "blob"), storage_account_key, connection_data_block_size=4 * 1024) diff --git a/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions_async.py b/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions_async.py index c7cb1af7b692..b353b5fa0b16 100644 --- a/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_blob_access_conditions_async.py @@ -744,6 +744,39 @@ async def test_set_blob_props_with_if_none_match_fail(self, resource_group, loca # Assert self.assertEqual(StorageErrorCode.condition_not_met, e.exception.error_code) + @GlobalStorageAccountPreparer() + @AsyncStorageTestCase.await_prepared_test + async def test_if_blob_exists(self, resource_group, location, storage_account, storage_account_key): + bsc = BlobServiceClient(self.account_url(storage_account, "blob"), storage_account_key, connection_data_block_size=4 * 1024) + self._setup() + await self._create_container_and_block_blob( + self.container_name, 'blob1', b'hello world', bsc) + # Act + blob = bsc.get_blob_client(self.container_name, 'blob1') + old_blob_props = await blob.get_blob_properties() + old_blob_version_id = old_blob_props.get("version_id") + self.assertIsNotNone(old_blob_version_id) + await blob.stage_block(block_id='1', data="this is test content") + await blob.commit_block_list(['1']) + new_blob_props = await blob.get_blob_properties() + new_blob_version_id = new_blob_props.get("version_id") + + # Assert + self.assertEqual(await blob.exists(version_id=old_blob_version_id), True) + self.assertEqual(await blob.exists(version_id=new_blob_version_id), True) + self.assertEqual(await blob.exists(version_id="2020-08-21T21:24:15.3585832Z"), False) + + # Act + test_snapshot = await blob.create_snapshot() + blob_snapshot = bsc.get_blob_client(self.container_name, 'blob1', snapshot=test_snapshot) + self.assertEqual(await blob_snapshot.exists(), True) + await blob.stage_block(block_id='1', data="this is additional test content") + await blob.commit_block_list(['1']) + + # Assert + self.assertEqual(await blob_snapshot.exists(), True) + self.assertEqual(await blob.exists(), True) + @GlobalStorageAccountPreparer() @AsyncStorageTestCase.await_prepared_test async def test_get_blob_properties_with_if_modified(self, resource_group, location, storage_account, storage_account_key):