From 5e854e6e6674cb2f7c78291a8e0c64c4473c5f32 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Feb 2021 14:43:11 -0500 Subject: [PATCH 01/86] generated code from swagger --- .../containerregistry/_generated/__init__.py | 19 + .../_generated/_azure_container_registry.py | 96 ++ .../_generated/_configuration.py | 71 + .../containerregistry/_generated/_version.py | 9 + .../_generated/aio/__init__.py | 10 + .../aio/_azure_container_registry.py | 90 ++ .../_generated/aio/_configuration.py | 67 + .../_generated/aio/operations/__init__.py | 25 + .../operations/_access_tokens_operations.py | 165 ++ .../aio/operations/_blob_operations.py | 711 +++++++++ .../aio/operations/_manifests_operations.py | 422 +++++ .../operations/_refresh_tokens_operations.py | 112 ++ .../aio/operations/_repository_operations.py | 269 ++++ .../aio/operations/_tag_operations.py | 290 ++++ .../aio/operations/_v2_support_operations.py | 86 ++ .../_generated/models/__init__.py | 129 ++ .../models/_azure_container_registry_enums.py | 35 + .../_generated/models/_models.py | 1177 ++++++++++++++ .../_generated/models/_models_py3.py | 1363 +++++++++++++++++ .../_generated/operations/__init__.py | 25 + .../operations/_access_tokens_operations.py | 171 +++ .../_generated/operations/_blob_operations.py | 726 +++++++++ .../operations/_manifests_operations.py | 432 ++++++ .../operations/_refresh_tokens_operations.py | 117 ++ .../operations/_repository_operations.py | 277 ++++ .../_generated/operations/_tag_operations.py | 298 ++++ .../operations/_v2_support_operations.py | 91 ++ .../containerregistry/_generated/py.typed | 1 + 28 files changed, 7284 insertions(+) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_azure_container_registry.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_azure_container_registry.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_blob_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_manifests_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_repository_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_azure_container_registry_enums.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_blob_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_manifests_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_repository_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/py.typed diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py new file mode 100644 index 000000000000..89894c5e7034 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py @@ -0,0 +1,19 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._azure_container_registry import AzureContainerRegistry +from ._version import VERSION + +__version__ = VERSION +__all__ = ['AzureContainerRegistry'] + +try: + from ._patch import patch_sdk # type: ignore + patch_sdk() +except ImportError: + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_azure_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_azure_container_registry.py new file mode 100644 index 000000000000..65c20111ba47 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_azure_container_registry.py @@ -0,0 +1,96 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from typing import TYPE_CHECKING + +from azure.core import PipelineClient +from msrest import Deserializer, Serializer + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any + + from azure.core.credentials import TokenCredential + +from ._configuration import AzureContainerRegistryConfiguration +from .operations import V2SupportOperations +from .operations import ManifestsOperations +from .operations import BlobOperations +from .operations import RepositoryOperations +from .operations import TagOperations +from .operations import RefreshTokensOperations +from .operations import AccessTokensOperations +from . import models + + +class AzureContainerRegistry(object): + """Metadata API definition for the Azure Container Registry runtime. + + :ivar v2_support: V2SupportOperations operations + :vartype v2_support: azure.containerregistry.operations.V2SupportOperations + :ivar manifests: ManifestsOperations operations + :vartype manifests: azure.containerregistry.operations.ManifestsOperations + :ivar blob: BlobOperations operations + :vartype blob: azure.containerregistry.operations.BlobOperations + :ivar repository: RepositoryOperations operations + :vartype repository: azure.containerregistry.operations.RepositoryOperations + :ivar tag: TagOperations operations + :vartype tag: azure.containerregistry.operations.TagOperations + :ivar refresh_tokens: RefreshTokensOperations operations + :vartype refresh_tokens: azure.containerregistry.operations.RefreshTokensOperations + :ivar access_tokens: AccessTokensOperations operations + :vartype access_tokens: azure.containerregistry.operations.AccessTokensOperations + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials.TokenCredential + :param url: Registry login URL. + :type url: str + """ + + def __init__( + self, + credential, # type: "TokenCredential" + url, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + base_url = '{url}' + self._config = AzureContainerRegistryConfiguration(credential, url, **kwargs) + self._client = PipelineClient(base_url=base_url, config=self._config, **kwargs) + + client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)} + self._serialize = Serializer(client_models) + self._serialize.client_side_validation = False + self._deserialize = Deserializer(client_models) + + self.v2_support = V2SupportOperations( + self._client, self._config, self._serialize, self._deserialize) + self.manifests = ManifestsOperations( + self._client, self._config, self._serialize, self._deserialize) + self.blob = BlobOperations( + self._client, self._config, self._serialize, self._deserialize) + self.repository = RepositoryOperations( + self._client, self._config, self._serialize, self._deserialize) + self.tag = TagOperations( + self._client, self._config, self._serialize, self._deserialize) + self.refresh_tokens = RefreshTokensOperations( + self._client, self._config, self._serialize, self._deserialize) + self.access_tokens = AccessTokensOperations( + self._client, self._config, self._serialize, self._deserialize) + + def close(self): + # type: () -> None + self._client.close() + + def __enter__(self): + # type: () -> AzureContainerRegistry + self._client.__enter__() + return self + + def __exit__(self, *exc_details): + # type: (Any) -> None + self._client.__exit__(*exc_details) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py new file mode 100644 index 000000000000..760fb1df0b03 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py @@ -0,0 +1,71 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from typing import TYPE_CHECKING + +from azure.core.configuration import Configuration +from azure.core.pipeline import policies + +from ._version import VERSION + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any + + from azure.core.credentials import TokenCredential + + +class AzureContainerRegistryConfiguration(Configuration): + """Configuration for AzureContainerRegistry. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials.TokenCredential + :param url: Registry login URL. + :type url: str + """ + + def __init__( + self, + credential, # type: "TokenCredential" + url, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + if url is None: + raise ValueError("Parameter 'url' must not be None.") + super(AzureContainerRegistryConfiguration, self).__init__(**kwargs) + + self.credential = credential + self.url = url + self.credential_scopes = kwargs.pop('credential_scopes', []) + kwargs.setdefault('sdk_moniker', 'containerregistry/{}'.format(VERSION)) + self._configure(**kwargs) + + def _configure( + self, + **kwargs # type: Any + ): + # type: (...) -> None + self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs) + self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs) + self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs) + self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs) + self.http_logging_policy = kwargs.get('http_logging_policy') or policies.HttpLoggingPolicy(**kwargs) + self.retry_policy = kwargs.get('retry_policy') or policies.RetryPolicy(**kwargs) + self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs) + self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs) + self.authentication_policy = kwargs.get('authentication_policy') + if not self.credential_scopes and not self.authentication_policy: + raise ValueError("You must provide either credential_scopes or authentication_policy as kwargs") + if self.credential and not self.authentication_policy: + self.authentication_policy = policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py new file mode 100644 index 000000000000..eae7c95b6fbd --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py @@ -0,0 +1,9 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +VERSION = "0.1.0" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py new file mode 100644 index 000000000000..eebca06c77c9 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py @@ -0,0 +1,10 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._azure_container_registry import AzureContainerRegistry +__all__ = ['AzureContainerRegistry'] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_azure_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_azure_container_registry.py new file mode 100644 index 000000000000..bdf6c1d1e6c3 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_azure_container_registry.py @@ -0,0 +1,90 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from typing import Any, TYPE_CHECKING + +from azure.core import AsyncPipelineClient +from msrest import Deserializer, Serializer + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from azure.core.credentials_async import AsyncTokenCredential + +from ._configuration import AzureContainerRegistryConfiguration +from .operations import V2SupportOperations +from .operations import ManifestsOperations +from .operations import BlobOperations +from .operations import RepositoryOperations +from .operations import TagOperations +from .operations import RefreshTokensOperations +from .operations import AccessTokensOperations +from .. import models + + +class AzureContainerRegistry(object): + """Metadata API definition for the Azure Container Registry runtime. + + :ivar v2_support: V2SupportOperations operations + :vartype v2_support: azure.containerregistry.aio.operations.V2SupportOperations + :ivar manifests: ManifestsOperations operations + :vartype manifests: azure.containerregistry.aio.operations.ManifestsOperations + :ivar blob: BlobOperations operations + :vartype blob: azure.containerregistry.aio.operations.BlobOperations + :ivar repository: RepositoryOperations operations + :vartype repository: azure.containerregistry.aio.operations.RepositoryOperations + :ivar tag: TagOperations operations + :vartype tag: azure.containerregistry.aio.operations.TagOperations + :ivar refresh_tokens: RefreshTokensOperations operations + :vartype refresh_tokens: azure.containerregistry.aio.operations.RefreshTokensOperations + :ivar access_tokens: AccessTokensOperations operations + :vartype access_tokens: azure.containerregistry.aio.operations.AccessTokensOperations + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential + :param url: Registry login URL. + :type url: str + """ + + def __init__( + self, + credential: "AsyncTokenCredential", + url: str, + **kwargs: Any + ) -> None: + base_url = '{url}' + self._config = AzureContainerRegistryConfiguration(credential, url, **kwargs) + self._client = AsyncPipelineClient(base_url=base_url, config=self._config, **kwargs) + + client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)} + self._serialize = Serializer(client_models) + self._serialize.client_side_validation = False + self._deserialize = Deserializer(client_models) + + self.v2_support = V2SupportOperations( + self._client, self._config, self._serialize, self._deserialize) + self.manifests = ManifestsOperations( + self._client, self._config, self._serialize, self._deserialize) + self.blob = BlobOperations( + self._client, self._config, self._serialize, self._deserialize) + self.repository = RepositoryOperations( + self._client, self._config, self._serialize, self._deserialize) + self.tag = TagOperations( + self._client, self._config, self._serialize, self._deserialize) + self.refresh_tokens = RefreshTokensOperations( + self._client, self._config, self._serialize, self._deserialize) + self.access_tokens = AccessTokensOperations( + self._client, self._config, self._serialize, self._deserialize) + + async def close(self) -> None: + await self._client.close() + + async def __aenter__(self) -> "AzureContainerRegistry": + await self._client.__aenter__() + return self + + async def __aexit__(self, *exc_details) -> None: + await self._client.__aexit__(*exc_details) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py new file mode 100644 index 000000000000..73b8600479b8 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py @@ -0,0 +1,67 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from typing import Any, TYPE_CHECKING + +from azure.core.configuration import Configuration +from azure.core.pipeline import policies + +from .._version import VERSION + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from azure.core.credentials_async import AsyncTokenCredential + + +class AzureContainerRegistryConfiguration(Configuration): + """Configuration for AzureContainerRegistry. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param credential: Credential needed for the client to connect to Azure. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential + :param url: Registry login URL. + :type url: str + """ + + def __init__( + self, + credential: "AsyncTokenCredential", + url: str, + **kwargs: Any + ) -> None: + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + if url is None: + raise ValueError("Parameter 'url' must not be None.") + super(AzureContainerRegistryConfiguration, self).__init__(**kwargs) + + self.credential = credential + self.url = url + self.credential_scopes = kwargs.pop('credential_scopes', []) + kwargs.setdefault('sdk_moniker', 'containerregistry/{}'.format(VERSION)) + self._configure(**kwargs) + + def _configure( + self, + **kwargs: Any + ) -> None: + self.user_agent_policy = kwargs.get('user_agent_policy') or policies.UserAgentPolicy(**kwargs) + self.headers_policy = kwargs.get('headers_policy') or policies.HeadersPolicy(**kwargs) + self.proxy_policy = kwargs.get('proxy_policy') or policies.ProxyPolicy(**kwargs) + self.logging_policy = kwargs.get('logging_policy') or policies.NetworkTraceLoggingPolicy(**kwargs) + self.http_logging_policy = kwargs.get('http_logging_policy') or policies.HttpLoggingPolicy(**kwargs) + self.retry_policy = kwargs.get('retry_policy') or policies.AsyncRetryPolicy(**kwargs) + self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs) + self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs) + self.authentication_policy = kwargs.get('authentication_policy') + if not self.credential_scopes and not self.authentication_policy: + raise ValueError("You must provide either credential_scopes or authentication_policy as kwargs") + if self.credential and not self.authentication_policy: + self.authentication_policy = policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py new file mode 100644 index 000000000000..d6560dfe7906 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py @@ -0,0 +1,25 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._v2_support_operations import V2SupportOperations +from ._manifests_operations import ManifestsOperations +from ._blob_operations import BlobOperations +from ._repository_operations import RepositoryOperations +from ._tag_operations import TagOperations +from ._refresh_tokens_operations import RefreshTokensOperations +from ._access_tokens_operations import AccessTokensOperations + +__all__ = [ + 'V2SupportOperations', + 'ManifestsOperations', + 'BlobOperations', + 'RepositoryOperations', + 'TagOperations', + 'RefreshTokensOperations', + 'AccessTokensOperations', +] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py new file mode 100644 index 000000000000..edf931e348cb --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py @@ -0,0 +1,165 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, Optional, TypeVar +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class AccessTokensOperations: + """AccessTokensOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def get( + self, + service: str, + scope: str, + refresh_token: str, + **kwargs + ) -> "_models.AccessToken": + """Exchange ACR Refresh token for an ACR Access Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Which is expected to be a valid scope, and can be specified more than once for + multiple scope requests. You obtained this from the Www-Authenticate response header from the + challenge. + :type scope: str + :param refresh_token: Must be a valid ACR refresh token. + :type refresh_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AccessToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AccessToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "refresh_token" + accept = "application/json" + + # Construct URL + url = self.get.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AccessToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get.metadata = {'url': '/oauth2/token'} # type: ignore + + async def get_from_login( + self, + service: str, + scope: str, + **kwargs + ) -> "_models.AccessToken": + """Exchange Username, Password, and Scope for an ACR Access Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Expected to be a valid scope, and can be specified more than once for multiple + scope requests. You can obtain this from the Www-Authenticate response header from the + challenge. + :type scope: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AccessToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AccessToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_from_login.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + query_parameters['service'] = self._serialize.query("service", service, 'str') + query_parameters['scope'] = self._serialize.query("scope", scope, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AccessToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_from_login.metadata = {'url': '/oauth2/token'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_blob_operations.py new file mode 100644 index 000000000000..d7079ed69af2 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_blob_operations.py @@ -0,0 +1,711 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, IO, Optional, TypeVar +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class BlobOperations: + """BlobOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def get( + self, + name: str, + digest: str, + **kwargs + ) -> Optional[IO]: + """Retrieve the blob from the registry identified by digest. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: IO, or the result of cls(response) + :rtype: IO or None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[Optional[IO]] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/octet-stream" + + # Construct URL + url = self.get.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 307]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + deserialized = None + if response.status_code == 200: + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + deserialized = response.stream_download(self._client._pipeline) + + if response.status_code == 307: + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + get.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + async def check( + self, + name: str, + digest: str, + **kwargs + ) -> None: + """Same as GET, except only the headers are returned. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.head(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 307]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + if response.status_code == 200: + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + + if response.status_code == 307: + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + + if cls: + return cls(pipeline_response, None, response_headers) + + check.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + async def delete( + self, + name: str, + digest: str, + **kwargs + ) -> IO: + """Removes an already uploaded blob. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: IO, or the result of cls(response) + :rtype: IO + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[IO] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/octet-stream" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + deserialized = response.stream_download(self._client._pipeline) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + delete.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + async def mount( + self, + name: str, + from_parameter: str, + mount: str, + **kwargs + ) -> None: + """Mount a blob identified by the ``mount`` parameter from another repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param from_parameter: Name of the source repository. + :type from_parameter: str + :param mount: Digest of blob to mount from the source repository. + :type mount: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.mount.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + query_parameters['from'] = self._serialize.query("from_parameter", from_parameter, 'str') + query_parameters['mount'] = self._serialize.query("mount", mount, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.post(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [201]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + + if cls: + return cls(pipeline_response, None, response_headers) + + mount.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore + + async def get_status( + self, + location: str, + **kwargs + ) -> None: + """Retrieve status of upload identified by uuid. The primary purpose of this endpoint is to + resolve the current status of a resumable upload. + + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_status.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + + if cls: + return cls(pipeline_response, None, response_headers) + + get_status.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + async def upload( + self, + location: str, + value: IO, + **kwargs + ) -> None: + """Upload a stream of data without completing the upload. + + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :param value: Raw data of blob. + :type value: IO + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/octet-stream") + accept = "application/json" + + # Construct URL + url = self.upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content_kwargs['stream_content'] = value + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + + if cls: + return cls(pipeline_response, None, response_headers) + + upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + async def end_upload( + self, + digest: str, + location: str, + value: Optional[IO] = None, + **kwargs + ) -> None: + """Complete the upload, providing all the data in the body, if necessary. A request without a body + will just complete the upload with previously uploaded content. + + :param digest: Digest of a BLOB. + :type digest: str + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :param value: Optional raw data of blob. + :type value: IO + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/octet-stream") + accept = "application/json" + + # Construct URL + url = self.end_upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content_kwargs['stream_content'] = value + request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [201]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + + if cls: + return cls(pipeline_response, None, response_headers) + + end_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + async def cancel_upload( + self, + location: str, + **kwargs + ) -> None: + """Cancel outstanding upload processes, releasing associated resources. If this is not called, the + unfinished uploads will eventually timeout. + + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.cancel_upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + cancel_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + async def start_upload( + self, + name: str, + **kwargs + ) -> None: + """Initiate a resumable blob upload with an empty request body. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.start_upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.post(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + + if cls: + return cls(pipeline_response, None, response_headers) + + start_upload.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore + + async def get_chunk( + self, + name: str, + digest: str, + range: str, + **kwargs + ) -> IO: + """Retrieve the blob from the registry identified by ``digest``. This endpoint may also support + RFC7233 compliant range requests. Support can be detected by issuing a HEAD request. If the + header ``Accept-Range: bytes`` is returned, range requests can be used to fetch partial + content. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :param range: Format : bytes=:code:``-:code:``, HTTP Range header specifying blob + chunk. + :type range: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: IO, or the result of cls(response) + :rtype: IO + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[IO] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/octet-stream" + + # Construct URL + url = self.get_chunk.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Range'] = self._serialize.header("range", range, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [206]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Content-Range']=self._deserialize('str', response.headers.get('Content-Range')) + deserialized = response.stream_download(self._client._pipeline) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + get_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + async def check_chunk( + self, + name: str, + digest: str, + range: str, + **kwargs + ) -> None: + """Same as GET, except only the headers are returned. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :param range: Format : bytes=:code:``-:code:``, HTTP Range header specifying blob + chunk. + :type range: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check_chunk.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Range'] = self._serialize.header("range", range, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.head(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Content-Range']=self._deserialize('str', response.headers.get('Content-Range')) + + if cls: + return cls(pipeline_response, None, response_headers) + + check_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_manifests_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_manifests_operations.py new file mode 100644 index 000000000000..ab4dd318ba23 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_manifests_operations.py @@ -0,0 +1,422 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, Optional, TypeVar +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class ManifestsOperations: + """ManifestsOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def get( + self, + name: str, + reference: str, + accept: Optional[str] = None, + **kwargs + ) -> "_models.ManifestWrapper": + """Get the manifest identified by ``name`` and ``reference`` where ``reference`` can be a tag or + digest. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :param accept: Accept header string delimited by comma. For example, + application/vnd.docker.distribution.manifest.v2+json. + :type accept: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: ManifestWrapper, or the result of cls(response) + :rtype: ~azure.containerregistry.models.ManifestWrapper + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestWrapper"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + if accept is not None: + header_parameters['accept'] = self._serialize.header("accept", accept, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('ManifestWrapper', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + + async def create( + self, + name: str, + reference: str, + schema_version: Optional[int] = None, + **kwargs + ) -> object: + """Put the manifest identified by ``name`` and ``reference`` where ``reference`` can be a tag or + digest. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :param schema_version: Schema version. + :type schema_version: int + :keyword callable cls: A custom type or function that will be passed the direct response + :return: object, or the result of cls(response) + :rtype: object + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[object] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + _payload = _models.Manifest(schema_version=schema_version) + content_type = kwargs.pop("content_type", "application/vnd.docker.distribution.manifest.v2+json") + accept = "application/json" + + # Construct URL + url = self.create.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(_payload, 'Manifest') + body_content_kwargs['content'] = body_content + request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [201]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + deserialized = self._deserialize('object', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + create.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + + async def delete( + self, + name: str, + reference: str, + **kwargs + ) -> None: + """Delete the manifest identified by ``name`` and ``reference``. Note that a manifest can *only* + be deleted by ``digest``. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + delete.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + + async def get_list( + self, + name: str, + last: Optional[str] = None, + n: Optional[int] = None, + orderby: Optional[str] = None, + **kwargs + ) -> "_models.AcrManifests": + """List manifests of a repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :param orderby: orderby query parameter. + :type orderby: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AcrManifests, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AcrManifests + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrManifests"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_list.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AcrManifests', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_list.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore + + async def get_attributes( + self, + name: str, + reference: str, + **kwargs + ) -> "_models.ManifestAttributes": + """Get manifest attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: ManifestAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.ManifestAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('ManifestAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + + async def update_attributes( + self, + name: str, + reference: str, + value: Optional["_models.ChangeableAttributes"] = None, + **kwargs + ) -> None: + """Update attributes of a manifest. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py new file mode 100644 index 000000000000..4f599817601f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py @@ -0,0 +1,112 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, Optional, TypeVar, Union +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class RefreshTokensOperations: + """RefreshTokensOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def get_from_exchange( + self, + grant_type: Union[str, "_models.PostContentSchemaGrantType"], + service: str, + tenant: Optional[str] = None, + refresh_token: Optional[str] = None, + access_token: Optional[str] = None, + **kwargs + ) -> "_models.RefreshToken": + """Exchange AAD tokens for an ACR refresh Token. + + :param grant_type: Can take a value of access_token_refresh_token, or access_token, or + refresh_token. + :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType + :param service: Indicates the name of your Azure container registry. + :type service: str + :param tenant: AAD tenant associated to the AAD credentials. + :type tenant: str + :param refresh_token: AAD refresh token, mandatory when grant_type is + access_token_refresh_token or refresh_token. + :type refresh_token: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: RefreshToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RefreshToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.RefreshToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + accept = "application/json" + + # Construct URL + url = self.get_from_exchange.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('RefreshToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_from_exchange.metadata = {'url': '/oauth2/exchange'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_repository_operations.py new file mode 100644 index 000000000000..b0200ad8469b --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_repository_operations.py @@ -0,0 +1,269 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, Optional, TypeVar +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class RepositoryOperations: + """RepositoryOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def get_list( + self, + last: Optional[str] = None, + n: Optional[int] = None, + **kwargs + ) -> "_models.Repositories": + """List repositories. + + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :keyword callable cls: A custom type or function that will be passed the direct response + :return: Repositories, or the result of cls(response) + :rtype: ~azure.containerregistry.models.Repositories + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.Repositories"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_list.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Link']=self._deserialize('str', response.headers.get('Link')) + deserialized = self._deserialize('Repositories', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + get_list.metadata = {'url': '/acr/v1/_catalog'} # type: ignore + + async def get_attributes( + self, + name: str, + **kwargs + ) -> "_models.RepositoryAttributes": + """Get repository attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: RepositoryAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RepositoryAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('RepositoryAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore + + async def delete( + self, + name: str, + **kwargs + ) -> "_models.DeletedRepository": + """Delete the repository identified by ``name``. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: DeletedRepository, or the result of cls(response) + :rtype: ~azure.containerregistry.models.DeletedRepository + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepository"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('DeletedRepository', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + delete.metadata = {'url': '/acr/v1/{name}'} # type: ignore + + async def update_attributes( + self, + name: str, + value: Optional["_models.ChangeableAttributes"] = None, + **kwargs + ) -> None: + """Update the attribute identified by ``name`` where ``reference`` is the name of the repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py new file mode 100644 index 000000000000..2fb3ee4d65cf --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py @@ -0,0 +1,290 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, Optional, TypeVar +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class TagOperations: + """TagOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def get_list( + self, + name: str, + last: Optional[str] = None, + n: Optional[int] = None, + orderby: Optional[str] = None, + digest: Optional[str] = None, + **kwargs + ) -> "_models.TagList": + """List tags of a repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :param orderby: orderby query parameter. + :type orderby: str + :param digest: filter by digest. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagList, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagList + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_list.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + if digest is not None: + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagList', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_list.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore + + async def get_attributes( + self, + name: str, + reference: str, + **kwargs + ) -> "_models.TagAttributes": + """Get tag attributes by tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + async def update_attributes( + self, + name: str, + reference: str, + value: Optional["_models.ChangeableAttributes"] = None, + **kwargs + ) -> None: + """Update tag attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + async def delete( + self, + name: str, + reference: str, + **kwargs + ) -> None: + """Delete tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + delete.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py new file mode 100644 index 000000000000..cbe93d0a48a2 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py @@ -0,0 +1,86 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, Optional, TypeVar +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class V2SupportOperations: + """V2SupportOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def check( + self, + **kwargs + ) -> None: + """Tells whether this Docker Registry instance supports Docker Registry HTTP API v2. + + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + check.metadata = {'url': '/v2/'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py new file mode 100644 index 000000000000..13c72aec8b41 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py @@ -0,0 +1,129 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +try: + from ._models_py3 import AccessToken + from ._models_py3 import AcrErrorInfo + from ._models_py3 import AcrErrors + from ._models_py3 import AcrManifests + from ._models_py3 import Annotations + from ._models_py3 import ChangeableAttributes + from ._models_py3 import DeletedRepository + from ._models_py3 import Descriptor + from ._models_py3 import FsLayer + from ._models_py3 import History + from ._models_py3 import ImageSignature + from ._models_py3 import JWK + from ._models_py3 import JWKHeader + from ._models_py3 import Manifest + from ._models_py3 import ManifestAttributes + from ._models_py3 import ManifestAttributesBase + from ._models_py3 import ManifestAttributesManifest + from ._models_py3 import ManifestAttributesManifestReferences + from ._models_py3 import ManifestChangeableAttributes + from ._models_py3 import ManifestList + from ._models_py3 import ManifestListAttributes + from ._models_py3 import ManifestWrapper + from ._models_py3 import OCIIndex + from ._models_py3 import OCIManifest + from ._models_py3 import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema + from ._models_py3 import PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema + from ._models_py3 import Platform + from ._models_py3 import RefreshToken + from ._models_py3 import Repositories + from ._models_py3 import RepositoryAttributes + from ._models_py3 import RepositoryTags + from ._models_py3 import TagAttributes + from ._models_py3 import TagAttributesBase + from ._models_py3 import TagAttributesTag + from ._models_py3 import TagList + from ._models_py3 import V1Manifest + from ._models_py3 import V2Manifest +except (SyntaxError, ImportError): + from ._models import AccessToken # type: ignore + from ._models import AcrErrorInfo # type: ignore + from ._models import AcrErrors # type: ignore + from ._models import AcrManifests # type: ignore + from ._models import Annotations # type: ignore + from ._models import ChangeableAttributes # type: ignore + from ._models import DeletedRepository # type: ignore + from ._models import Descriptor # type: ignore + from ._models import FsLayer # type: ignore + from ._models import History # type: ignore + from ._models import ImageSignature # type: ignore + from ._models import JWK # type: ignore + from ._models import JWKHeader # type: ignore + from ._models import Manifest # type: ignore + from ._models import ManifestAttributes # type: ignore + from ._models import ManifestAttributesBase # type: ignore + from ._models import ManifestAttributesManifest # type: ignore + from ._models import ManifestAttributesManifestReferences # type: ignore + from ._models import ManifestChangeableAttributes # type: ignore + from ._models import ManifestList # type: ignore + from ._models import ManifestListAttributes # type: ignore + from ._models import ManifestWrapper # type: ignore + from ._models import OCIIndex # type: ignore + from ._models import OCIManifest # type: ignore + from ._models import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema # type: ignore + from ._models import PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema # type: ignore + from ._models import Platform # type: ignore + from ._models import RefreshToken # type: ignore + from ._models import Repositories # type: ignore + from ._models import RepositoryAttributes # type: ignore + from ._models import RepositoryTags # type: ignore + from ._models import TagAttributes # type: ignore + from ._models import TagAttributesBase # type: ignore + from ._models import TagAttributesTag # type: ignore + from ._models import TagList # type: ignore + from ._models import V1Manifest # type: ignore + from ._models import V2Manifest # type: ignore + +from ._azure_container_registry_enums import ( + PostContentSchemaGrantType, +) + +__all__ = [ + 'AccessToken', + 'AcrErrorInfo', + 'AcrErrors', + 'AcrManifests', + 'Annotations', + 'ChangeableAttributes', + 'DeletedRepository', + 'Descriptor', + 'FsLayer', + 'History', + 'ImageSignature', + 'JWK', + 'JWKHeader', + 'Manifest', + 'ManifestAttributes', + 'ManifestAttributesBase', + 'ManifestAttributesManifest', + 'ManifestAttributesManifestReferences', + 'ManifestChangeableAttributes', + 'ManifestList', + 'ManifestListAttributes', + 'ManifestWrapper', + 'OCIIndex', + 'OCIManifest', + 'Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema', + 'PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema', + 'Platform', + 'RefreshToken', + 'Repositories', + 'RepositoryAttributes', + 'RepositoryTags', + 'TagAttributes', + 'TagAttributesBase', + 'TagAttributesTag', + 'TagList', + 'V1Manifest', + 'V2Manifest', + 'PostContentSchemaGrantType', +] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_azure_container_registry_enums.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_azure_container_registry_enums.py new file mode 100644 index 000000000000..4f9b6bfb490f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_azure_container_registry_enums.py @@ -0,0 +1,35 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from enum import Enum, EnumMeta +from six import with_metaclass + +class _CaseInsensitiveEnumMeta(EnumMeta): + def __getitem__(self, name): + return super().__getitem__(name.upper()) + + def __getattr__(cls, name): + """Return the enum member matching `name` + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + """ + try: + return cls._member_map_[name.upper()] + except KeyError: + raise AttributeError(name) + + +class PostContentSchemaGrantType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + """Can take a value of access_token_refresh_token, or access_token, or refresh_token + """ + + ACCESS_TOKEN_REFRESH_TOKEN = "access_token_refresh_token" + ACCESS_TOKEN = "access_token" + REFRESH_TOKEN = "refresh_token" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py new file mode 100644 index 000000000000..1d5a605ea4a1 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -0,0 +1,1177 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.core.exceptions import HttpResponseError +import msrest.serialization + + +class AccessToken(msrest.serialization.Model): + """AccessToken. + + :param access_token: The access token for performing authenticated requests. + :type access_token: str + """ + + _attribute_map = { + 'access_token': {'key': 'access_token', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(AccessToken, self).__init__(**kwargs) + self.access_token = kwargs.get('access_token', None) + + +class AcrErrorInfo(msrest.serialization.Model): + """Error information. + + :param code: Error code. + :type code: str + :param message: Error message. + :type message: str + :param detail: Error details. + :type detail: object + """ + + _attribute_map = { + 'code': {'key': 'code', 'type': 'str'}, + 'message': {'key': 'message', 'type': 'str'}, + 'detail': {'key': 'detail', 'type': 'object'}, + } + + def __init__( + self, + **kwargs + ): + super(AcrErrorInfo, self).__init__(**kwargs) + self.code = kwargs.get('code', None) + self.message = kwargs.get('message', None) + self.detail = kwargs.get('detail', None) + + +class AcrErrors(msrest.serialization.Model): + """Acr error response describing why the operation failed. + + :param errors: Array of detailed error. + :type errors: list[~azure.containerregistry.models.AcrErrorInfo] + """ + + _attribute_map = { + 'errors': {'key': 'errors', 'type': '[AcrErrorInfo]'}, + } + + def __init__( + self, + **kwargs + ): + super(AcrErrors, self).__init__(**kwargs) + self.errors = kwargs.get('errors', None) + + +class AcrManifests(msrest.serialization.Model): + """Manifest attributes. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param manifests_attributes: List of manifests. + :type manifests_attributes: list[~azure.containerregistry.models.ManifestAttributesBase] + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'manifests_attributes': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, + } + + def __init__( + self, + **kwargs + ): + super(AcrManifests, self).__init__(**kwargs) + self.registry = kwargs.get('registry', None) + self.image_name = kwargs.get('image_name', None) + self.manifests_attributes = kwargs.get('manifests_attributes', None) + + +class Annotations(msrest.serialization.Model): + """Additional information provided through arbitrary metadata. + + :param additional_properties: Unmatched properties from the message are deserialized to this + collection. + :type additional_properties: dict[str, object] + :param created: Date and time on which the image was built (string, date-time as defined by + https://tools.ietf.org/html/rfc3339#section-5.6). + :type created: ~datetime.datetime + :param authors: Contact details of the people or organization responsible for the image. + :type authors: str + :param url: URL to find more information on the image. + :type url: str + :param documentation: URL to get documentation on the image. + :type documentation: str + :param source: URL to get source code for building the image. + :type source: str + :param version: Version of the packaged software. The version MAY match a label or tag in the + source code repository, may also be Semantic versioning-compatible. + :type version: str + :param revision: Source control revision identifier for the packaged software. + :type revision: str + :param vendor: Name of the distributing entity, organization or individual. + :type vendor: str + :param licenses: License(s) under which contained software is distributed as an SPDX License + Expression. + :type licenses: str + :param name: Name of the reference for a target. + :type name: str + :param title: Human-readable title of the image. + :type title: str + :param description: Human-readable description of the software packaged in the image. + :type description: str + """ + + _attribute_map = { + 'additional_properties': {'key': '', 'type': '{object}'}, + 'created': {'key': 'org\\.opencontainers\\.image\\.created', 'type': 'iso-8601'}, + 'authors': {'key': 'org\\.opencontainers\\.image\\.authors', 'type': 'str'}, + 'url': {'key': 'org\\.opencontainers\\.image\\.url', 'type': 'str'}, + 'documentation': {'key': 'org\\.opencontainers\\.image\\.documentation', 'type': 'str'}, + 'source': {'key': 'org\\.opencontainers\\.image\\.source', 'type': 'str'}, + 'version': {'key': 'org\\.opencontainers\\.image\\.version', 'type': 'str'}, + 'revision': {'key': 'org\\.opencontainers\\.image\\.revision', 'type': 'str'}, + 'vendor': {'key': 'org\\.opencontainers\\.image\\.vendor', 'type': 'str'}, + 'licenses': {'key': 'org\\.opencontainers\\.image\\.licenses', 'type': 'str'}, + 'name': {'key': 'org\\.opencontainers\\.image\\.ref\\.name', 'type': 'str'}, + 'title': {'key': 'org\\.opencontainers\\.image\\.title', 'type': 'str'}, + 'description': {'key': 'org\\.opencontainers\\.image\\.description', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(Annotations, self).__init__(**kwargs) + self.additional_properties = kwargs.get('additional_properties', None) + self.created = kwargs.get('created', None) + self.authors = kwargs.get('authors', None) + self.url = kwargs.get('url', None) + self.documentation = kwargs.get('documentation', None) + self.source = kwargs.get('source', None) + self.version = kwargs.get('version', None) + self.revision = kwargs.get('revision', None) + self.vendor = kwargs.get('vendor', None) + self.licenses = kwargs.get('licenses', None) + self.name = kwargs.get('name', None) + self.title = kwargs.get('title', None) + self.description = kwargs.get('description', None) + + +class ChangeableAttributes(msrest.serialization.Model): + """ChangeableAttributes. + + :param delete_enabled: Delete enabled. + :type delete_enabled: bool + :param write_enabled: Write enabled. + :type write_enabled: bool + :param list_enabled: List enabled. + :type list_enabled: bool + :param read_enabled: Read enabled. + :type read_enabled: bool + """ + + _attribute_map = { + 'delete_enabled': {'key': 'deleteEnabled', 'type': 'bool'}, + 'write_enabled': {'key': 'writeEnabled', 'type': 'bool'}, + 'list_enabled': {'key': 'listEnabled', 'type': 'bool'}, + 'read_enabled': {'key': 'readEnabled', 'type': 'bool'}, + } + + def __init__( + self, + **kwargs + ): + super(ChangeableAttributes, self).__init__(**kwargs) + self.delete_enabled = kwargs.get('delete_enabled', None) + self.write_enabled = kwargs.get('write_enabled', None) + self.list_enabled = kwargs.get('list_enabled', None) + self.read_enabled = kwargs.get('read_enabled', None) + + +class DeletedRepository(msrest.serialization.Model): + """Deleted repository. + + :param manifests_deleted: SHA of the deleted image. + :type manifests_deleted: list[str] + :param tags_deleted: Tag of the deleted image. + :type tags_deleted: list[str] + """ + + _attribute_map = { + 'manifests_deleted': {'key': 'manifestsDeleted', 'type': '[str]'}, + 'tags_deleted': {'key': 'tagsDeleted', 'type': '[str]'}, + } + + def __init__( + self, + **kwargs + ): + super(DeletedRepository, self).__init__(**kwargs) + self.manifests_deleted = kwargs.get('manifests_deleted', None) + self.tags_deleted = kwargs.get('tags_deleted', None) + + +class Descriptor(msrest.serialization.Model): + """Docker V2 image layer descriptor including config and layers. + + :param media_type: Layer media type. + :type media_type: str + :param size: Layer size. + :type size: long + :param digest: Layer digest. + :type digest: str + :param urls: Specifies a list of URIs from which this object may be downloaded. + :type urls: list[str] + :param annotations: Additional information provided through arbitrary metadata. + :type annotations: ~azure.containerregistry.models.Annotations + """ + + _attribute_map = { + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'size': {'key': 'size', 'type': 'long'}, + 'digest': {'key': 'digest', 'type': 'str'}, + 'urls': {'key': 'urls', 'type': '[str]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + } + + def __init__( + self, + **kwargs + ): + super(Descriptor, self).__init__(**kwargs) + self.media_type = kwargs.get('media_type', None) + self.size = kwargs.get('size', None) + self.digest = kwargs.get('digest', None) + self.urls = kwargs.get('urls', None) + self.annotations = kwargs.get('annotations', None) + + +class FsLayer(msrest.serialization.Model): + """Image layer information. + + :param blob_sum: SHA of an image layer. + :type blob_sum: str + """ + + _attribute_map = { + 'blob_sum': {'key': 'blobSum', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(FsLayer, self).__init__(**kwargs) + self.blob_sum = kwargs.get('blob_sum', None) + + +class History(msrest.serialization.Model): + """A list of unstructured historical data for v1 compatibility. + + :param v1_compatibility: The raw v1 compatibility information. + :type v1_compatibility: str + """ + + _attribute_map = { + 'v1_compatibility': {'key': 'v1Compatibility', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(History, self).__init__(**kwargs) + self.v1_compatibility = kwargs.get('v1_compatibility', None) + + +class ImageSignature(msrest.serialization.Model): + """Signature of a signed manifest. + + :param header: A JSON web signature. + :type header: ~azure.containerregistry.models.JWK + :param signature: A signature for the image manifest, signed by a libtrust private key. + :type signature: str + :param protected: The signed protected header. + :type protected: str + """ + + _attribute_map = { + 'header': {'key': 'header', 'type': 'JWK'}, + 'signature': {'key': 'signature', 'type': 'str'}, + 'protected': {'key': 'protected', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(ImageSignature, self).__init__(**kwargs) + self.header = kwargs.get('header', None) + self.signature = kwargs.get('signature', None) + self.protected = kwargs.get('protected', None) + + +class JWK(msrest.serialization.Model): + """A JSON web signature. + + :param jwk: JSON web key parameter. + :type jwk: ~azure.containerregistry.models.JWKHeader + :param alg: The algorithm used to sign or encrypt the JWT. + :type alg: str + """ + + _attribute_map = { + 'jwk': {'key': 'jwk', 'type': 'JWKHeader'}, + 'alg': {'key': 'alg', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(JWK, self).__init__(**kwargs) + self.jwk = kwargs.get('jwk', None) + self.alg = kwargs.get('alg', None) + + +class JWKHeader(msrest.serialization.Model): + """JSON web key parameter. + + :param crv: crv value. + :type crv: str + :param kid: kid value. + :type kid: str + :param kty: kty value. + :type kty: str + :param x: x value. + :type x: str + :param y: y value. + :type y: str + """ + + _attribute_map = { + 'crv': {'key': 'crv', 'type': 'str'}, + 'kid': {'key': 'kid', 'type': 'str'}, + 'kty': {'key': 'kty', 'type': 'str'}, + 'x': {'key': 'x', 'type': 'str'}, + 'y': {'key': 'y', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(JWKHeader, self).__init__(**kwargs) + self.crv = kwargs.get('crv', None) + self.kid = kwargs.get('kid', None) + self.kty = kwargs.get('kty', None) + self.x = kwargs.get('x', None) + self.y = kwargs.get('y', None) + + +class Manifest(msrest.serialization.Model): + """Returns the requested manifest file. + + :param schema_version: Schema version. + :type schema_version: int + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + } + + def __init__( + self, + **kwargs + ): + super(Manifest, self).__init__(**kwargs) + self.schema_version = kwargs.get('schema_version', None) + + +class ManifestAttributes(msrest.serialization.Model): + """Manifest attributes details. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param attributes: Manifest attributes. + :type attributes: ~azure.containerregistry.models.ManifestAttributesBase + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'attributes': {'key': 'manifest', 'type': 'ManifestAttributesBase'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestAttributes, self).__init__(**kwargs) + self.registry = kwargs.get('registry', None) + self.image_name = kwargs.get('image_name', None) + self.attributes = kwargs.get('attributes', None) + + +class ManifestAttributesBase(msrest.serialization.Model): + """Manifest details. + + :param digest: Manifest. + :type digest: str + :param image_size: Image size. + :type image_size: long + :param created_time: Created time. + :type created_time: str + :param last_update_time: Last update time. + :type last_update_time: str + :param architecture: CPU architecture. + :type architecture: str + :param os: Operating system. + :type os: str + :param media_type: Media type. + :type media_type: str + :param config_media_type: Config blob media type. + :type config_media_type: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + :param changeable_attributes: Changeable attributes. + :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + """ + + _attribute_map = { + 'digest': {'key': 'digest', 'type': 'str'}, + 'image_size': {'key': 'imageSize', 'type': 'long'}, + 'created_time': {'key': 'createdTime', 'type': 'str'}, + 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'os': {'key': 'os', 'type': 'str'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, + 'tags': {'key': 'tags', 'type': '[str]'}, + 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestAttributesBase, self).__init__(**kwargs) + self.digest = kwargs.get('digest', None) + self.image_size = kwargs.get('image_size', None) + self.created_time = kwargs.get('created_time', None) + self.last_update_time = kwargs.get('last_update_time', None) + self.architecture = kwargs.get('architecture', None) + self.os = kwargs.get('os', None) + self.media_type = kwargs.get('media_type', None) + self.config_media_type = kwargs.get('config_media_type', None) + self.tags = kwargs.get('tags', None) + self.changeable_attributes = kwargs.get('changeable_attributes', None) + + +class ManifestAttributesManifest(msrest.serialization.Model): + """List of manifest attributes. + + :param references: List of manifest attributes details. + :type references: list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :param quarantine_tag: Quarantine tag name. + :type quarantine_tag: str + """ + + _attribute_map = { + 'references': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, + 'quarantine_tag': {'key': 'quarantineTag', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestAttributesManifest, self).__init__(**kwargs) + self.references = kwargs.get('references', None) + self.quarantine_tag = kwargs.get('quarantine_tag', None) + + +class ManifestAttributesManifestReferences(msrest.serialization.Model): + """Manifest attributes details. + + :param digest: Manifest digest. + :type digest: str + :param architecture: CPU architecture. + :type architecture: str + :param os: Operating system. + :type os: str + """ + + _attribute_map = { + 'digest': {'key': 'digest', 'type': 'str'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'os': {'key': 'os', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestAttributesManifestReferences, self).__init__(**kwargs) + self.digest = kwargs.get('digest', None) + self.architecture = kwargs.get('architecture', None) + self.os = kwargs.get('os', None) + + +class ManifestChangeableAttributes(msrest.serialization.Model): + """Changeable attributes. + + :param delete_enabled: Delete enabled. + :type delete_enabled: bool + :param write_enabled: Write enabled. + :type write_enabled: bool + :param list_enabled: List enabled. + :type list_enabled: bool + :param read_enabled: Read enabled. + :type read_enabled: bool + :param quarantine_state: Quarantine state. + :type quarantine_state: str + :param quarantine_details: Quarantine details. + :type quarantine_details: str + """ + + _attribute_map = { + 'delete_enabled': {'key': 'deleteEnabled', 'type': 'bool'}, + 'write_enabled': {'key': 'writeEnabled', 'type': 'bool'}, + 'list_enabled': {'key': 'listEnabled', 'type': 'bool'}, + 'read_enabled': {'key': 'readEnabled', 'type': 'bool'}, + 'quarantine_state': {'key': 'quarantineState', 'type': 'str'}, + 'quarantine_details': {'key': 'quarantineDetails', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestChangeableAttributes, self).__init__(**kwargs) + self.delete_enabled = kwargs.get('delete_enabled', None) + self.write_enabled = kwargs.get('write_enabled', None) + self.list_enabled = kwargs.get('list_enabled', None) + self.read_enabled = kwargs.get('read_enabled', None) + self.quarantine_state = kwargs.get('quarantine_state', None) + self.quarantine_details = kwargs.get('quarantine_details', None) + + +class ManifestList(Manifest): + """Returns the requested Docker multi-arch-manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param media_type: Media type for this Manifest. + :type media_type: str + :param manifests: List of V2 image layer information. + :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestListAttributes]'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestList, self).__init__(**kwargs) + self.media_type = kwargs.get('media_type', None) + self.manifests = kwargs.get('manifests', None) + + +class ManifestListAttributes(msrest.serialization.Model): + """ManifestListAttributes. + + :param media_type: The MIME type of the referenced object. This will generally be + application/vnd.docker.image.manifest.v2+json, but it could also be + application/vnd.docker.image.manifest.v1+json. + :type media_type: str + :param size: The size in bytes of the object. + :type size: long + :param digest: The digest of the content, as defined by the Registry V2 HTTP API Specification. + :type digest: str + :param platform: The platform object describes the platform which the image in the manifest + runs on. A full list of valid operating system and architecture values are listed in the Go + language documentation for $GOOS and $GOARCH. + :type platform: ~azure.containerregistry.models.Platform + """ + + _attribute_map = { + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'size': {'key': 'size', 'type': 'long'}, + 'digest': {'key': 'digest', 'type': 'str'}, + 'platform': {'key': 'platform', 'type': 'Platform'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestListAttributes, self).__init__(**kwargs) + self.media_type = kwargs.get('media_type', None) + self.size = kwargs.get('size', None) + self.digest = kwargs.get('digest', None) + self.platform = kwargs.get('platform', None) + + +class ManifestWrapper(Manifest): + """Returns the requested manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param media_type: Media type for this Manifest. + :type media_type: str + :param manifests: (ManifestList, OCIIndex) List of V2 image layer information. + :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :param config: (V2, OCI) Image config descriptor. + :type config: ~azure.containerregistry.models.Descriptor + :param layers: (V2, OCI) List of V2 image layer information. + :type layers: list[~azure.containerregistry.models.Descriptor] + :param annotations: (OCI, OCIIndex) Additional metadata. + :type annotations: ~azure.containerregistry.models.Annotations + :param architecture: (V1) CPU architecture. + :type architecture: str + :param name: (V1) Image name. + :type name: str + :param tag: (V1) Image tag. + :type tag: str + :param fs_layers: (V1) List of layer information. + :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :param history: (V1) Image history. + :type history: list[~azure.containerregistry.models.History] + :param signatures: (V1) Image signature. + :type signatures: list[~azure.containerregistry.models.ImageSignature] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestListAttributes]'}, + 'config': {'key': 'config', 'type': 'Descriptor'}, + 'layers': {'key': 'layers', 'type': '[Descriptor]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, + 'tag': {'key': 'tag', 'type': 'str'}, + 'fs_layers': {'key': 'fsLayers', 'type': '[FsLayer]'}, + 'history': {'key': 'history', 'type': '[History]'}, + 'signatures': {'key': 'signatures', 'type': '[ImageSignature]'}, + } + + def __init__( + self, + **kwargs + ): + super(ManifestWrapper, self).__init__(**kwargs) + self.media_type = kwargs.get('media_type', None) + self.manifests = kwargs.get('manifests', None) + self.config = kwargs.get('config', None) + self.layers = kwargs.get('layers', None) + self.annotations = kwargs.get('annotations', None) + self.architecture = kwargs.get('architecture', None) + self.name = kwargs.get('name', None) + self.tag = kwargs.get('tag', None) + self.fs_layers = kwargs.get('fs_layers', None) + self.history = kwargs.get('history', None) + self.signatures = kwargs.get('signatures', None) + + +class OCIIndex(Manifest): + """Returns the requested OCI index file. + + :param schema_version: Schema version. + :type schema_version: int + :param manifests: List of OCI image layer information. + :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :param annotations: Additional information provided through arbitrary metadata. + :type annotations: ~azure.containerregistry.models.Annotations + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestListAttributes]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + } + + def __init__( + self, + **kwargs + ): + super(OCIIndex, self).__init__(**kwargs) + self.manifests = kwargs.get('manifests', None) + self.annotations = kwargs.get('annotations', None) + + +class OCIManifest(Manifest): + """Returns the requested OCI Manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param config: V2 image config descriptor. + :type config: ~azure.containerregistry.models.Descriptor + :param layers: List of V2 image layer information. + :type layers: list[~azure.containerregistry.models.Descriptor] + :param annotations: Additional information provided through arbitrary metadata. + :type annotations: ~azure.containerregistry.models.Annotations + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'config': {'key': 'config', 'type': 'Descriptor'}, + 'layers': {'key': 'layers', 'type': '[Descriptor]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + } + + def __init__( + self, + **kwargs + ): + super(OCIManifest, self).__init__(**kwargs) + self.config = kwargs.get('config', None) + self.layers = kwargs.get('layers', None) + self.annotations = kwargs.get('annotations', None) + + +class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): + """Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema. + + All required parameters must be populated in order to send to Azure. + + :param grant_type: Required. Can take a value of access_token_refresh_token, or access_token, + or refresh_token. Possible values include: "access_token_refresh_token", "access_token", + "refresh_token". + :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType + :param service: Required. Indicates the name of your Azure container registry. + :type service: str + :param tenant: AAD tenant associated to the AAD credentials. + :type tenant: str + :param refresh_token: AAD refresh token, mandatory when grant_type is + access_token_refresh_token or refresh_token. + :type refresh_token: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str + """ + + _validation = { + 'grant_type': {'required': True}, + 'service': {'required': True}, + } + + _attribute_map = { + 'grant_type': {'key': 'grant_type', 'type': 'str'}, + 'service': {'key': 'service', 'type': 'str'}, + 'tenant': {'key': 'tenant', 'type': 'str'}, + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + 'access_token': {'key': 'access_token', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) + self.grant_type = kwargs['grant_type'] + self.service = kwargs['service'] + self.tenant = kwargs.get('tenant', None) + self.refresh_token = kwargs.get('refresh_token', None) + self.access_token = kwargs.get('access_token', None) + + +class PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): + """PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema. + + Variables are only populated by the server, and will be ignored when sending a request. + + All required parameters must be populated in order to send to Azure. + + :ivar grant_type: Required. Grant type is expected to be refresh_token. Default value: + "refresh_token". + :vartype grant_type: str + :param service: Required. Indicates the name of your Azure container registry. + :type service: str + :param scope: Required. Which is expected to be a valid scope, and can be specified more than + once for multiple scope requests. You obtained this from the Www-Authenticate response header + from the challenge. + :type scope: str + :param refresh_token: Required. Must be a valid ACR refresh token. + :type refresh_token: str + """ + + _validation = { + 'grant_type': {'required': True, 'constant': True}, + 'service': {'required': True}, + 'scope': {'required': True}, + 'refresh_token': {'required': True}, + } + + _attribute_map = { + 'grant_type': {'key': 'grant_type', 'type': 'str'}, + 'service': {'key': 'service', 'type': 'str'}, + 'scope': {'key': 'scope', 'type': 'str'}, + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + } + + grant_type = "refresh_token" + + def __init__( + self, + **kwargs + ): + super(PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) + self.service = kwargs['service'] + self.scope = kwargs['scope'] + self.refresh_token = kwargs['refresh_token'] + + +class Platform(msrest.serialization.Model): + """The platform object describes the platform which the image in the manifest runs on. A full list of valid operating system and architecture values are listed in the Go language documentation for $GOOS and $GOARCH. + + :param architecture: Specifies the CPU architecture, for example amd64 or ppc64le. + :type architecture: str + :param os: The os field specifies the operating system, for example linux or windows. + :type os: str + :param os_version: The optional os.version field specifies the operating system version, for + example 10.0.10586. + :type os_version: str + :param os_features: The optional os.features field specifies an array of strings, each listing + a required OS feature (for example on Windows win32k. + :type os_features: list[str] + :param variant: The optional variant field specifies a variant of the CPU, for example armv6l + to specify a particular CPU variant of the ARM CPU. + :type variant: str + :param features: The optional features field specifies an array of strings, each listing a + required CPU feature (for example sse4 or aes. + :type features: list[str] + """ + + _attribute_map = { + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'os': {'key': 'os', 'type': 'str'}, + 'os_version': {'key': 'os\\.version', 'type': 'str'}, + 'os_features': {'key': 'os\\.features', 'type': '[str]'}, + 'variant': {'key': 'variant', 'type': 'str'}, + 'features': {'key': 'features', 'type': '[str]'}, + } + + def __init__( + self, + **kwargs + ): + super(Platform, self).__init__(**kwargs) + self.architecture = kwargs.get('architecture', None) + self.os = kwargs.get('os', None) + self.os_version = kwargs.get('os_version', None) + self.os_features = kwargs.get('os_features', None) + self.variant = kwargs.get('variant', None) + self.features = kwargs.get('features', None) + + +class RefreshToken(msrest.serialization.Model): + """RefreshToken. + + :param refresh_token: The refresh token to be used for generating access tokens. + :type refresh_token: str + """ + + _attribute_map = { + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(RefreshToken, self).__init__(**kwargs) + self.refresh_token = kwargs.get('refresh_token', None) + + +class Repositories(msrest.serialization.Model): + """List of repositories. + + :param names: Repository names. + :type names: list[str] + """ + + _attribute_map = { + 'names': {'key': 'repositories', 'type': '[str]'}, + } + + def __init__( + self, + **kwargs + ): + super(Repositories, self).__init__(**kwargs) + self.names = kwargs.get('names', None) + + +class RepositoryAttributes(msrest.serialization.Model): + """Repository attributes. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param created_time: Image created time. + :type created_time: str + :param last_update_time: Image last update time. + :type last_update_time: str + :param manifest_count: Number of the manifests. + :type manifest_count: int + :param tag_count: Number of the tags. + :type tag_count: int + :param changeable_attributes: Changeable attributes. + :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'created_time': {'key': 'createdTime', 'type': 'str'}, + 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, + 'manifest_count': {'key': 'manifestCount', 'type': 'int'}, + 'tag_count': {'key': 'tagCount', 'type': 'int'}, + 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + } + + def __init__( + self, + **kwargs + ): + super(RepositoryAttributes, self).__init__(**kwargs) + self.registry = kwargs.get('registry', None) + self.image_name = kwargs.get('image_name', None) + self.created_time = kwargs.get('created_time', None) + self.last_update_time = kwargs.get('last_update_time', None) + self.manifest_count = kwargs.get('manifest_count', None) + self.tag_count = kwargs.get('tag_count', None) + self.changeable_attributes = kwargs.get('changeable_attributes', None) + + +class RepositoryTags(msrest.serialization.Model): + """Result of the request to list tags of the image. + + :param name: Name of the image. + :type name: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + """ + + _attribute_map = { + 'name': {'key': 'name', 'type': 'str'}, + 'tags': {'key': 'tags', 'type': '[str]'}, + } + + def __init__( + self, + **kwargs + ): + super(RepositoryTags, self).__init__(**kwargs) + self.name = kwargs.get('name', None) + self.tags = kwargs.get('tags', None) + + +class TagAttributes(msrest.serialization.Model): + """Tag attributes. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param attributes: List of tag attribute details. + :type attributes: ~azure.containerregistry.models.TagAttributesBase + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'attributes': {'key': 'tag', 'type': 'TagAttributesBase'}, + } + + def __init__( + self, + **kwargs + ): + super(TagAttributes, self).__init__(**kwargs) + self.registry = kwargs.get('registry', None) + self.image_name = kwargs.get('image_name', None) + self.attributes = kwargs.get('attributes', None) + + +class TagAttributesBase(msrest.serialization.Model): + """Tag attribute details. + + :param name: Tag name. + :type name: str + :param digest: Tag digest. + :type digest: str + :param created_time: Tag created time. + :type created_time: str + :param last_update_time: Tag last update time. + :type last_update_time: str + :param signed: Is signed. + :type signed: bool + :param changeable_attributes: Changeable attributes. + :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + """ + + _attribute_map = { + 'name': {'key': 'name', 'type': 'str'}, + 'digest': {'key': 'digest', 'type': 'str'}, + 'created_time': {'key': 'createdTime', 'type': 'str'}, + 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, + 'signed': {'key': 'signed', 'type': 'bool'}, + 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + } + + def __init__( + self, + **kwargs + ): + super(TagAttributesBase, self).__init__(**kwargs) + self.name = kwargs.get('name', None) + self.digest = kwargs.get('digest', None) + self.created_time = kwargs.get('created_time', None) + self.last_update_time = kwargs.get('last_update_time', None) + self.signed = kwargs.get('signed', None) + self.changeable_attributes = kwargs.get('changeable_attributes', None) + + +class TagAttributesTag(msrest.serialization.Model): + """Tag. + + :param signature_record: SignatureRecord value. + :type signature_record: str + """ + + _attribute_map = { + 'signature_record': {'key': 'signatureRecord', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(TagAttributesTag, self).__init__(**kwargs) + self.signature_record = kwargs.get('signature_record', None) + + +class TagList(msrest.serialization.Model): + """List of tag details. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param tags: A set of tags. List of tag attribute details. + :type tags: list[~azure.containerregistry.models.TagAttributesBase] + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, + } + + def __init__( + self, + **kwargs + ): + super(TagList, self).__init__(**kwargs) + self.registry = kwargs.get('registry', None) + self.image_name = kwargs.get('image_name', None) + self.tags = kwargs.get('tags', None) + + +class V1Manifest(Manifest): + """Returns the requested V1 manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param architecture: CPU architecture. + :type architecture: str + :param name: Image name. + :type name: str + :param tag: Image tag. + :type tag: str + :param fs_layers: List of layer information. + :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :param history: Image history. + :type history: list[~azure.containerregistry.models.History] + :param signatures: Image signature. + :type signatures: list[~azure.containerregistry.models.ImageSignature] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, + 'tag': {'key': 'tag', 'type': 'str'}, + 'fs_layers': {'key': 'fsLayers', 'type': '[FsLayer]'}, + 'history': {'key': 'history', 'type': '[History]'}, + 'signatures': {'key': 'signatures', 'type': '[ImageSignature]'}, + } + + def __init__( + self, + **kwargs + ): + super(V1Manifest, self).__init__(**kwargs) + self.architecture = kwargs.get('architecture', None) + self.name = kwargs.get('name', None) + self.tag = kwargs.get('tag', None) + self.fs_layers = kwargs.get('fs_layers', None) + self.history = kwargs.get('history', None) + self.signatures = kwargs.get('signatures', None) + + +class V2Manifest(Manifest): + """Returns the requested Docker V2 Manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param media_type: Media type for this Manifest. + :type media_type: str + :param config: V2 image config descriptor. + :type config: ~azure.containerregistry.models.Descriptor + :param layers: List of V2 image layer information. + :type layers: list[~azure.containerregistry.models.Descriptor] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'config': {'key': 'config', 'type': 'Descriptor'}, + 'layers': {'key': 'layers', 'type': '[Descriptor]'}, + } + + def __init__( + self, + **kwargs + ): + super(V2Manifest, self).__init__(**kwargs) + self.media_type = kwargs.get('media_type', None) + self.config = kwargs.get('config', None) + self.layers = kwargs.get('layers', None) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py new file mode 100644 index 000000000000..5da6ec963853 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -0,0 +1,1363 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +import datetime +from typing import Dict, List, Optional, Union + +from azure.core.exceptions import HttpResponseError +import msrest.serialization + +from ._azure_container_registry_enums import * + + +class AccessToken(msrest.serialization.Model): + """AccessToken. + + :param access_token: The access token for performing authenticated requests. + :type access_token: str + """ + + _attribute_map = { + 'access_token': {'key': 'access_token', 'type': 'str'}, + } + + def __init__( + self, + *, + access_token: Optional[str] = None, + **kwargs + ): + super(AccessToken, self).__init__(**kwargs) + self.access_token = access_token + + +class AcrErrorInfo(msrest.serialization.Model): + """Error information. + + :param code: Error code. + :type code: str + :param message: Error message. + :type message: str + :param detail: Error details. + :type detail: object + """ + + _attribute_map = { + 'code': {'key': 'code', 'type': 'str'}, + 'message': {'key': 'message', 'type': 'str'}, + 'detail': {'key': 'detail', 'type': 'object'}, + } + + def __init__( + self, + *, + code: Optional[str] = None, + message: Optional[str] = None, + detail: Optional[object] = None, + **kwargs + ): + super(AcrErrorInfo, self).__init__(**kwargs) + self.code = code + self.message = message + self.detail = detail + + +class AcrErrors(msrest.serialization.Model): + """Acr error response describing why the operation failed. + + :param errors: Array of detailed error. + :type errors: list[~azure.containerregistry.models.AcrErrorInfo] + """ + + _attribute_map = { + 'errors': {'key': 'errors', 'type': '[AcrErrorInfo]'}, + } + + def __init__( + self, + *, + errors: Optional[List["AcrErrorInfo"]] = None, + **kwargs + ): + super(AcrErrors, self).__init__(**kwargs) + self.errors = errors + + +class AcrManifests(msrest.serialization.Model): + """Manifest attributes. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param manifests_attributes: List of manifests. + :type manifests_attributes: list[~azure.containerregistry.models.ManifestAttributesBase] + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'manifests_attributes': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, + } + + def __init__( + self, + *, + registry: Optional[str] = None, + image_name: Optional[str] = None, + manifests_attributes: Optional[List["ManifestAttributesBase"]] = None, + **kwargs + ): + super(AcrManifests, self).__init__(**kwargs) + self.registry = registry + self.image_name = image_name + self.manifests_attributes = manifests_attributes + + +class Annotations(msrest.serialization.Model): + """Additional information provided through arbitrary metadata. + + :param additional_properties: Unmatched properties from the message are deserialized to this + collection. + :type additional_properties: dict[str, object] + :param created: Date and time on which the image was built (string, date-time as defined by + https://tools.ietf.org/html/rfc3339#section-5.6). + :type created: ~datetime.datetime + :param authors: Contact details of the people or organization responsible for the image. + :type authors: str + :param url: URL to find more information on the image. + :type url: str + :param documentation: URL to get documentation on the image. + :type documentation: str + :param source: URL to get source code for building the image. + :type source: str + :param version: Version of the packaged software. The version MAY match a label or tag in the + source code repository, may also be Semantic versioning-compatible. + :type version: str + :param revision: Source control revision identifier for the packaged software. + :type revision: str + :param vendor: Name of the distributing entity, organization or individual. + :type vendor: str + :param licenses: License(s) under which contained software is distributed as an SPDX License + Expression. + :type licenses: str + :param name: Name of the reference for a target. + :type name: str + :param title: Human-readable title of the image. + :type title: str + :param description: Human-readable description of the software packaged in the image. + :type description: str + """ + + _attribute_map = { + 'additional_properties': {'key': '', 'type': '{object}'}, + 'created': {'key': 'org\\.opencontainers\\.image\\.created', 'type': 'iso-8601'}, + 'authors': {'key': 'org\\.opencontainers\\.image\\.authors', 'type': 'str'}, + 'url': {'key': 'org\\.opencontainers\\.image\\.url', 'type': 'str'}, + 'documentation': {'key': 'org\\.opencontainers\\.image\\.documentation', 'type': 'str'}, + 'source': {'key': 'org\\.opencontainers\\.image\\.source', 'type': 'str'}, + 'version': {'key': 'org\\.opencontainers\\.image\\.version', 'type': 'str'}, + 'revision': {'key': 'org\\.opencontainers\\.image\\.revision', 'type': 'str'}, + 'vendor': {'key': 'org\\.opencontainers\\.image\\.vendor', 'type': 'str'}, + 'licenses': {'key': 'org\\.opencontainers\\.image\\.licenses', 'type': 'str'}, + 'name': {'key': 'org\\.opencontainers\\.image\\.ref\\.name', 'type': 'str'}, + 'title': {'key': 'org\\.opencontainers\\.image\\.title', 'type': 'str'}, + 'description': {'key': 'org\\.opencontainers\\.image\\.description', 'type': 'str'}, + } + + def __init__( + self, + *, + additional_properties: Optional[Dict[str, object]] = None, + created: Optional[datetime.datetime] = None, + authors: Optional[str] = None, + url: Optional[str] = None, + documentation: Optional[str] = None, + source: Optional[str] = None, + version: Optional[str] = None, + revision: Optional[str] = None, + vendor: Optional[str] = None, + licenses: Optional[str] = None, + name: Optional[str] = None, + title: Optional[str] = None, + description: Optional[str] = None, + **kwargs + ): + super(Annotations, self).__init__(**kwargs) + self.additional_properties = additional_properties + self.created = created + self.authors = authors + self.url = url + self.documentation = documentation + self.source = source + self.version = version + self.revision = revision + self.vendor = vendor + self.licenses = licenses + self.name = name + self.title = title + self.description = description + + +class ChangeableAttributes(msrest.serialization.Model): + """ChangeableAttributes. + + :param delete_enabled: Delete enabled. + :type delete_enabled: bool + :param write_enabled: Write enabled. + :type write_enabled: bool + :param list_enabled: List enabled. + :type list_enabled: bool + :param read_enabled: Read enabled. + :type read_enabled: bool + """ + + _attribute_map = { + 'delete_enabled': {'key': 'deleteEnabled', 'type': 'bool'}, + 'write_enabled': {'key': 'writeEnabled', 'type': 'bool'}, + 'list_enabled': {'key': 'listEnabled', 'type': 'bool'}, + 'read_enabled': {'key': 'readEnabled', 'type': 'bool'}, + } + + def __init__( + self, + *, + delete_enabled: Optional[bool] = None, + write_enabled: Optional[bool] = None, + list_enabled: Optional[bool] = None, + read_enabled: Optional[bool] = None, + **kwargs + ): + super(ChangeableAttributes, self).__init__(**kwargs) + self.delete_enabled = delete_enabled + self.write_enabled = write_enabled + self.list_enabled = list_enabled + self.read_enabled = read_enabled + + +class DeletedRepository(msrest.serialization.Model): + """Deleted repository. + + :param manifests_deleted: SHA of the deleted image. + :type manifests_deleted: list[str] + :param tags_deleted: Tag of the deleted image. + :type tags_deleted: list[str] + """ + + _attribute_map = { + 'manifests_deleted': {'key': 'manifestsDeleted', 'type': '[str]'}, + 'tags_deleted': {'key': 'tagsDeleted', 'type': '[str]'}, + } + + def __init__( + self, + *, + manifests_deleted: Optional[List[str]] = None, + tags_deleted: Optional[List[str]] = None, + **kwargs + ): + super(DeletedRepository, self).__init__(**kwargs) + self.manifests_deleted = manifests_deleted + self.tags_deleted = tags_deleted + + +class Descriptor(msrest.serialization.Model): + """Docker V2 image layer descriptor including config and layers. + + :param media_type: Layer media type. + :type media_type: str + :param size: Layer size. + :type size: long + :param digest: Layer digest. + :type digest: str + :param urls: Specifies a list of URIs from which this object may be downloaded. + :type urls: list[str] + :param annotations: Additional information provided through arbitrary metadata. + :type annotations: ~azure.containerregistry.models.Annotations + """ + + _attribute_map = { + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'size': {'key': 'size', 'type': 'long'}, + 'digest': {'key': 'digest', 'type': 'str'}, + 'urls': {'key': 'urls', 'type': '[str]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + } + + def __init__( + self, + *, + media_type: Optional[str] = None, + size: Optional[int] = None, + digest: Optional[str] = None, + urls: Optional[List[str]] = None, + annotations: Optional["Annotations"] = None, + **kwargs + ): + super(Descriptor, self).__init__(**kwargs) + self.media_type = media_type + self.size = size + self.digest = digest + self.urls = urls + self.annotations = annotations + + +class FsLayer(msrest.serialization.Model): + """Image layer information. + + :param blob_sum: SHA of an image layer. + :type blob_sum: str + """ + + _attribute_map = { + 'blob_sum': {'key': 'blobSum', 'type': 'str'}, + } + + def __init__( + self, + *, + blob_sum: Optional[str] = None, + **kwargs + ): + super(FsLayer, self).__init__(**kwargs) + self.blob_sum = blob_sum + + +class History(msrest.serialization.Model): + """A list of unstructured historical data for v1 compatibility. + + :param v1_compatibility: The raw v1 compatibility information. + :type v1_compatibility: str + """ + + _attribute_map = { + 'v1_compatibility': {'key': 'v1Compatibility', 'type': 'str'}, + } + + def __init__( + self, + *, + v1_compatibility: Optional[str] = None, + **kwargs + ): + super(History, self).__init__(**kwargs) + self.v1_compatibility = v1_compatibility + + +class ImageSignature(msrest.serialization.Model): + """Signature of a signed manifest. + + :param header: A JSON web signature. + :type header: ~azure.containerregistry.models.JWK + :param signature: A signature for the image manifest, signed by a libtrust private key. + :type signature: str + :param protected: The signed protected header. + :type protected: str + """ + + _attribute_map = { + 'header': {'key': 'header', 'type': 'JWK'}, + 'signature': {'key': 'signature', 'type': 'str'}, + 'protected': {'key': 'protected', 'type': 'str'}, + } + + def __init__( + self, + *, + header: Optional["JWK"] = None, + signature: Optional[str] = None, + protected: Optional[str] = None, + **kwargs + ): + super(ImageSignature, self).__init__(**kwargs) + self.header = header + self.signature = signature + self.protected = protected + + +class JWK(msrest.serialization.Model): + """A JSON web signature. + + :param jwk: JSON web key parameter. + :type jwk: ~azure.containerregistry.models.JWKHeader + :param alg: The algorithm used to sign or encrypt the JWT. + :type alg: str + """ + + _attribute_map = { + 'jwk': {'key': 'jwk', 'type': 'JWKHeader'}, + 'alg': {'key': 'alg', 'type': 'str'}, + } + + def __init__( + self, + *, + jwk: Optional["JWKHeader"] = None, + alg: Optional[str] = None, + **kwargs + ): + super(JWK, self).__init__(**kwargs) + self.jwk = jwk + self.alg = alg + + +class JWKHeader(msrest.serialization.Model): + """JSON web key parameter. + + :param crv: crv value. + :type crv: str + :param kid: kid value. + :type kid: str + :param kty: kty value. + :type kty: str + :param x: x value. + :type x: str + :param y: y value. + :type y: str + """ + + _attribute_map = { + 'crv': {'key': 'crv', 'type': 'str'}, + 'kid': {'key': 'kid', 'type': 'str'}, + 'kty': {'key': 'kty', 'type': 'str'}, + 'x': {'key': 'x', 'type': 'str'}, + 'y': {'key': 'y', 'type': 'str'}, + } + + def __init__( + self, + *, + crv: Optional[str] = None, + kid: Optional[str] = None, + kty: Optional[str] = None, + x: Optional[str] = None, + y: Optional[str] = None, + **kwargs + ): + super(JWKHeader, self).__init__(**kwargs) + self.crv = crv + self.kid = kid + self.kty = kty + self.x = x + self.y = y + + +class Manifest(msrest.serialization.Model): + """Returns the requested manifest file. + + :param schema_version: Schema version. + :type schema_version: int + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + } + + def __init__( + self, + *, + schema_version: Optional[int] = None, + **kwargs + ): + super(Manifest, self).__init__(**kwargs) + self.schema_version = schema_version + + +class ManifestAttributes(msrest.serialization.Model): + """Manifest attributes details. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param attributes: Manifest attributes. + :type attributes: ~azure.containerregistry.models.ManifestAttributesBase + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'attributes': {'key': 'manifest', 'type': 'ManifestAttributesBase'}, + } + + def __init__( + self, + *, + registry: Optional[str] = None, + image_name: Optional[str] = None, + attributes: Optional["ManifestAttributesBase"] = None, + **kwargs + ): + super(ManifestAttributes, self).__init__(**kwargs) + self.registry = registry + self.image_name = image_name + self.attributes = attributes + + +class ManifestAttributesBase(msrest.serialization.Model): + """Manifest details. + + :param digest: Manifest. + :type digest: str + :param image_size: Image size. + :type image_size: long + :param created_time: Created time. + :type created_time: str + :param last_update_time: Last update time. + :type last_update_time: str + :param architecture: CPU architecture. + :type architecture: str + :param os: Operating system. + :type os: str + :param media_type: Media type. + :type media_type: str + :param config_media_type: Config blob media type. + :type config_media_type: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + :param changeable_attributes: Changeable attributes. + :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + """ + + _attribute_map = { + 'digest': {'key': 'digest', 'type': 'str'}, + 'image_size': {'key': 'imageSize', 'type': 'long'}, + 'created_time': {'key': 'createdTime', 'type': 'str'}, + 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'os': {'key': 'os', 'type': 'str'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, + 'tags': {'key': 'tags', 'type': '[str]'}, + 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + } + + def __init__( + self, + *, + digest: Optional[str] = None, + image_size: Optional[int] = None, + created_time: Optional[str] = None, + last_update_time: Optional[str] = None, + architecture: Optional[str] = None, + os: Optional[str] = None, + media_type: Optional[str] = None, + config_media_type: Optional[str] = None, + tags: Optional[List[str]] = None, + changeable_attributes: Optional["ChangeableAttributes"] = None, + **kwargs + ): + super(ManifestAttributesBase, self).__init__(**kwargs) + self.digest = digest + self.image_size = image_size + self.created_time = created_time + self.last_update_time = last_update_time + self.architecture = architecture + self.os = os + self.media_type = media_type + self.config_media_type = config_media_type + self.tags = tags + self.changeable_attributes = changeable_attributes + + +class ManifestAttributesManifest(msrest.serialization.Model): + """List of manifest attributes. + + :param references: List of manifest attributes details. + :type references: list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :param quarantine_tag: Quarantine tag name. + :type quarantine_tag: str + """ + + _attribute_map = { + 'references': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, + 'quarantine_tag': {'key': 'quarantineTag', 'type': 'str'}, + } + + def __init__( + self, + *, + references: Optional[List["ManifestAttributesManifestReferences"]] = None, + quarantine_tag: Optional[str] = None, + **kwargs + ): + super(ManifestAttributesManifest, self).__init__(**kwargs) + self.references = references + self.quarantine_tag = quarantine_tag + + +class ManifestAttributesManifestReferences(msrest.serialization.Model): + """Manifest attributes details. + + :param digest: Manifest digest. + :type digest: str + :param architecture: CPU architecture. + :type architecture: str + :param os: Operating system. + :type os: str + """ + + _attribute_map = { + 'digest': {'key': 'digest', 'type': 'str'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'os': {'key': 'os', 'type': 'str'}, + } + + def __init__( + self, + *, + digest: Optional[str] = None, + architecture: Optional[str] = None, + os: Optional[str] = None, + **kwargs + ): + super(ManifestAttributesManifestReferences, self).__init__(**kwargs) + self.digest = digest + self.architecture = architecture + self.os = os + + +class ManifestChangeableAttributes(msrest.serialization.Model): + """Changeable attributes. + + :param delete_enabled: Delete enabled. + :type delete_enabled: bool + :param write_enabled: Write enabled. + :type write_enabled: bool + :param list_enabled: List enabled. + :type list_enabled: bool + :param read_enabled: Read enabled. + :type read_enabled: bool + :param quarantine_state: Quarantine state. + :type quarantine_state: str + :param quarantine_details: Quarantine details. + :type quarantine_details: str + """ + + _attribute_map = { + 'delete_enabled': {'key': 'deleteEnabled', 'type': 'bool'}, + 'write_enabled': {'key': 'writeEnabled', 'type': 'bool'}, + 'list_enabled': {'key': 'listEnabled', 'type': 'bool'}, + 'read_enabled': {'key': 'readEnabled', 'type': 'bool'}, + 'quarantine_state': {'key': 'quarantineState', 'type': 'str'}, + 'quarantine_details': {'key': 'quarantineDetails', 'type': 'str'}, + } + + def __init__( + self, + *, + delete_enabled: Optional[bool] = None, + write_enabled: Optional[bool] = None, + list_enabled: Optional[bool] = None, + read_enabled: Optional[bool] = None, + quarantine_state: Optional[str] = None, + quarantine_details: Optional[str] = None, + **kwargs + ): + super(ManifestChangeableAttributes, self).__init__(**kwargs) + self.delete_enabled = delete_enabled + self.write_enabled = write_enabled + self.list_enabled = list_enabled + self.read_enabled = read_enabled + self.quarantine_state = quarantine_state + self.quarantine_details = quarantine_details + + +class ManifestList(Manifest): + """Returns the requested Docker multi-arch-manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param media_type: Media type for this Manifest. + :type media_type: str + :param manifests: List of V2 image layer information. + :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestListAttributes]'}, + } + + def __init__( + self, + *, + schema_version: Optional[int] = None, + media_type: Optional[str] = None, + manifests: Optional[List["ManifestListAttributes"]] = None, + **kwargs + ): + super(ManifestList, self).__init__(schema_version=schema_version, **kwargs) + self.media_type = media_type + self.manifests = manifests + + +class ManifestListAttributes(msrest.serialization.Model): + """ManifestListAttributes. + + :param media_type: The MIME type of the referenced object. This will generally be + application/vnd.docker.image.manifest.v2+json, but it could also be + application/vnd.docker.image.manifest.v1+json. + :type media_type: str + :param size: The size in bytes of the object. + :type size: long + :param digest: The digest of the content, as defined by the Registry V2 HTTP API Specification. + :type digest: str + :param platform: The platform object describes the platform which the image in the manifest + runs on. A full list of valid operating system and architecture values are listed in the Go + language documentation for $GOOS and $GOARCH. + :type platform: ~azure.containerregistry.models.Platform + """ + + _attribute_map = { + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'size': {'key': 'size', 'type': 'long'}, + 'digest': {'key': 'digest', 'type': 'str'}, + 'platform': {'key': 'platform', 'type': 'Platform'}, + } + + def __init__( + self, + *, + media_type: Optional[str] = None, + size: Optional[int] = None, + digest: Optional[str] = None, + platform: Optional["Platform"] = None, + **kwargs + ): + super(ManifestListAttributes, self).__init__(**kwargs) + self.media_type = media_type + self.size = size + self.digest = digest + self.platform = platform + + +class ManifestWrapper(Manifest): + """Returns the requested manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param media_type: Media type for this Manifest. + :type media_type: str + :param manifests: (ManifestList, OCIIndex) List of V2 image layer information. + :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :param config: (V2, OCI) Image config descriptor. + :type config: ~azure.containerregistry.models.Descriptor + :param layers: (V2, OCI) List of V2 image layer information. + :type layers: list[~azure.containerregistry.models.Descriptor] + :param annotations: (OCI, OCIIndex) Additional metadata. + :type annotations: ~azure.containerregistry.models.Annotations + :param architecture: (V1) CPU architecture. + :type architecture: str + :param name: (V1) Image name. + :type name: str + :param tag: (V1) Image tag. + :type tag: str + :param fs_layers: (V1) List of layer information. + :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :param history: (V1) Image history. + :type history: list[~azure.containerregistry.models.History] + :param signatures: (V1) Image signature. + :type signatures: list[~azure.containerregistry.models.ImageSignature] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestListAttributes]'}, + 'config': {'key': 'config', 'type': 'Descriptor'}, + 'layers': {'key': 'layers', 'type': '[Descriptor]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, + 'tag': {'key': 'tag', 'type': 'str'}, + 'fs_layers': {'key': 'fsLayers', 'type': '[FsLayer]'}, + 'history': {'key': 'history', 'type': '[History]'}, + 'signatures': {'key': 'signatures', 'type': '[ImageSignature]'}, + } + + def __init__( + self, + *, + schema_version: Optional[int] = None, + media_type: Optional[str] = None, + manifests: Optional[List["ManifestListAttributes"]] = None, + config: Optional["Descriptor"] = None, + layers: Optional[List["Descriptor"]] = None, + annotations: Optional["Annotations"] = None, + architecture: Optional[str] = None, + name: Optional[str] = None, + tag: Optional[str] = None, + fs_layers: Optional[List["FsLayer"]] = None, + history: Optional[List["History"]] = None, + signatures: Optional[List["ImageSignature"]] = None, + **kwargs + ): + super(ManifestWrapper, self).__init__(schema_version=schema_version, **kwargs) + self.media_type = media_type + self.manifests = manifests + self.config = config + self.layers = layers + self.annotations = annotations + self.architecture = architecture + self.name = name + self.tag = tag + self.fs_layers = fs_layers + self.history = history + self.signatures = signatures + + +class OCIIndex(Manifest): + """Returns the requested OCI index file. + + :param schema_version: Schema version. + :type schema_version: int + :param manifests: List of OCI image layer information. + :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :param annotations: Additional information provided through arbitrary metadata. + :type annotations: ~azure.containerregistry.models.Annotations + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestListAttributes]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + } + + def __init__( + self, + *, + schema_version: Optional[int] = None, + manifests: Optional[List["ManifestListAttributes"]] = None, + annotations: Optional["Annotations"] = None, + **kwargs + ): + super(OCIIndex, self).__init__(schema_version=schema_version, **kwargs) + self.manifests = manifests + self.annotations = annotations + + +class OCIManifest(Manifest): + """Returns the requested OCI Manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param config: V2 image config descriptor. + :type config: ~azure.containerregistry.models.Descriptor + :param layers: List of V2 image layer information. + :type layers: list[~azure.containerregistry.models.Descriptor] + :param annotations: Additional information provided through arbitrary metadata. + :type annotations: ~azure.containerregistry.models.Annotations + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'config': {'key': 'config', 'type': 'Descriptor'}, + 'layers': {'key': 'layers', 'type': '[Descriptor]'}, + 'annotations': {'key': 'annotations', 'type': 'Annotations'}, + } + + def __init__( + self, + *, + schema_version: Optional[int] = None, + config: Optional["Descriptor"] = None, + layers: Optional[List["Descriptor"]] = None, + annotations: Optional["Annotations"] = None, + **kwargs + ): + super(OCIManifest, self).__init__(schema_version=schema_version, **kwargs) + self.config = config + self.layers = layers + self.annotations = annotations + + +class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): + """Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema. + + All required parameters must be populated in order to send to Azure. + + :param grant_type: Required. Can take a value of access_token_refresh_token, or access_token, + or refresh_token. Possible values include: "access_token_refresh_token", "access_token", + "refresh_token". + :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType + :param service: Required. Indicates the name of your Azure container registry. + :type service: str + :param tenant: AAD tenant associated to the AAD credentials. + :type tenant: str + :param refresh_token: AAD refresh token, mandatory when grant_type is + access_token_refresh_token or refresh_token. + :type refresh_token: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str + """ + + _validation = { + 'grant_type': {'required': True}, + 'service': {'required': True}, + } + + _attribute_map = { + 'grant_type': {'key': 'grant_type', 'type': 'str'}, + 'service': {'key': 'service', 'type': 'str'}, + 'tenant': {'key': 'tenant', 'type': 'str'}, + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + 'access_token': {'key': 'access_token', 'type': 'str'}, + } + + def __init__( + self, + *, + grant_type: Union[str, "PostContentSchemaGrantType"], + service: str, + tenant: Optional[str] = None, + refresh_token: Optional[str] = None, + access_token: Optional[str] = None, + **kwargs + ): + super(Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) + self.grant_type = grant_type + self.service = service + self.tenant = tenant + self.refresh_token = refresh_token + self.access_token = access_token + + +class PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): + """PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema. + + Variables are only populated by the server, and will be ignored when sending a request. + + All required parameters must be populated in order to send to Azure. + + :ivar grant_type: Required. Grant type is expected to be refresh_token. Default value: + "refresh_token". + :vartype grant_type: str + :param service: Required. Indicates the name of your Azure container registry. + :type service: str + :param scope: Required. Which is expected to be a valid scope, and can be specified more than + once for multiple scope requests. You obtained this from the Www-Authenticate response header + from the challenge. + :type scope: str + :param refresh_token: Required. Must be a valid ACR refresh token. + :type refresh_token: str + """ + + _validation = { + 'grant_type': {'required': True, 'constant': True}, + 'service': {'required': True}, + 'scope': {'required': True}, + 'refresh_token': {'required': True}, + } + + _attribute_map = { + 'grant_type': {'key': 'grant_type', 'type': 'str'}, + 'service': {'key': 'service', 'type': 'str'}, + 'scope': {'key': 'scope', 'type': 'str'}, + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + } + + grant_type = "refresh_token" + + def __init__( + self, + *, + service: str, + scope: str, + refresh_token: str, + **kwargs + ): + super(PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) + self.service = service + self.scope = scope + self.refresh_token = refresh_token + + +class Platform(msrest.serialization.Model): + """The platform object describes the platform which the image in the manifest runs on. A full list of valid operating system and architecture values are listed in the Go language documentation for $GOOS and $GOARCH. + + :param architecture: Specifies the CPU architecture, for example amd64 or ppc64le. + :type architecture: str + :param os: The os field specifies the operating system, for example linux or windows. + :type os: str + :param os_version: The optional os.version field specifies the operating system version, for + example 10.0.10586. + :type os_version: str + :param os_features: The optional os.features field specifies an array of strings, each listing + a required OS feature (for example on Windows win32k. + :type os_features: list[str] + :param variant: The optional variant field specifies a variant of the CPU, for example armv6l + to specify a particular CPU variant of the ARM CPU. + :type variant: str + :param features: The optional features field specifies an array of strings, each listing a + required CPU feature (for example sse4 or aes. + :type features: list[str] + """ + + _attribute_map = { + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'os': {'key': 'os', 'type': 'str'}, + 'os_version': {'key': 'os\\.version', 'type': 'str'}, + 'os_features': {'key': 'os\\.features', 'type': '[str]'}, + 'variant': {'key': 'variant', 'type': 'str'}, + 'features': {'key': 'features', 'type': '[str]'}, + } + + def __init__( + self, + *, + architecture: Optional[str] = None, + os: Optional[str] = None, + os_version: Optional[str] = None, + os_features: Optional[List[str]] = None, + variant: Optional[str] = None, + features: Optional[List[str]] = None, + **kwargs + ): + super(Platform, self).__init__(**kwargs) + self.architecture = architecture + self.os = os + self.os_version = os_version + self.os_features = os_features + self.variant = variant + self.features = features + + +class RefreshToken(msrest.serialization.Model): + """RefreshToken. + + :param refresh_token: The refresh token to be used for generating access tokens. + :type refresh_token: str + """ + + _attribute_map = { + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + } + + def __init__( + self, + *, + refresh_token: Optional[str] = None, + **kwargs + ): + super(RefreshToken, self).__init__(**kwargs) + self.refresh_token = refresh_token + + +class Repositories(msrest.serialization.Model): + """List of repositories. + + :param names: Repository names. + :type names: list[str] + """ + + _attribute_map = { + 'names': {'key': 'repositories', 'type': '[str]'}, + } + + def __init__( + self, + *, + names: Optional[List[str]] = None, + **kwargs + ): + super(Repositories, self).__init__(**kwargs) + self.names = names + + +class RepositoryAttributes(msrest.serialization.Model): + """Repository attributes. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param created_time: Image created time. + :type created_time: str + :param last_update_time: Image last update time. + :type last_update_time: str + :param manifest_count: Number of the manifests. + :type manifest_count: int + :param tag_count: Number of the tags. + :type tag_count: int + :param changeable_attributes: Changeable attributes. + :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'created_time': {'key': 'createdTime', 'type': 'str'}, + 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, + 'manifest_count': {'key': 'manifestCount', 'type': 'int'}, + 'tag_count': {'key': 'tagCount', 'type': 'int'}, + 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + } + + def __init__( + self, + *, + registry: Optional[str] = None, + image_name: Optional[str] = None, + created_time: Optional[str] = None, + last_update_time: Optional[str] = None, + manifest_count: Optional[int] = None, + tag_count: Optional[int] = None, + changeable_attributes: Optional["ChangeableAttributes"] = None, + **kwargs + ): + super(RepositoryAttributes, self).__init__(**kwargs) + self.registry = registry + self.image_name = image_name + self.created_time = created_time + self.last_update_time = last_update_time + self.manifest_count = manifest_count + self.tag_count = tag_count + self.changeable_attributes = changeable_attributes + + +class RepositoryTags(msrest.serialization.Model): + """Result of the request to list tags of the image. + + :param name: Name of the image. + :type name: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + """ + + _attribute_map = { + 'name': {'key': 'name', 'type': 'str'}, + 'tags': {'key': 'tags', 'type': '[str]'}, + } + + def __init__( + self, + *, + name: Optional[str] = None, + tags: Optional[List[str]] = None, + **kwargs + ): + super(RepositoryTags, self).__init__(**kwargs) + self.name = name + self.tags = tags + + +class TagAttributes(msrest.serialization.Model): + """Tag attributes. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param attributes: List of tag attribute details. + :type attributes: ~azure.containerregistry.models.TagAttributesBase + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'attributes': {'key': 'tag', 'type': 'TagAttributesBase'}, + } + + def __init__( + self, + *, + registry: Optional[str] = None, + image_name: Optional[str] = None, + attributes: Optional["TagAttributesBase"] = None, + **kwargs + ): + super(TagAttributes, self).__init__(**kwargs) + self.registry = registry + self.image_name = image_name + self.attributes = attributes + + +class TagAttributesBase(msrest.serialization.Model): + """Tag attribute details. + + :param name: Tag name. + :type name: str + :param digest: Tag digest. + :type digest: str + :param created_time: Tag created time. + :type created_time: str + :param last_update_time: Tag last update time. + :type last_update_time: str + :param signed: Is signed. + :type signed: bool + :param changeable_attributes: Changeable attributes. + :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + """ + + _attribute_map = { + 'name': {'key': 'name', 'type': 'str'}, + 'digest': {'key': 'digest', 'type': 'str'}, + 'created_time': {'key': 'createdTime', 'type': 'str'}, + 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, + 'signed': {'key': 'signed', 'type': 'bool'}, + 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + } + + def __init__( + self, + *, + name: Optional[str] = None, + digest: Optional[str] = None, + created_time: Optional[str] = None, + last_update_time: Optional[str] = None, + signed: Optional[bool] = None, + changeable_attributes: Optional["ChangeableAttributes"] = None, + **kwargs + ): + super(TagAttributesBase, self).__init__(**kwargs) + self.name = name + self.digest = digest + self.created_time = created_time + self.last_update_time = last_update_time + self.signed = signed + self.changeable_attributes = changeable_attributes + + +class TagAttributesTag(msrest.serialization.Model): + """Tag. + + :param signature_record: SignatureRecord value. + :type signature_record: str + """ + + _attribute_map = { + 'signature_record': {'key': 'signatureRecord', 'type': 'str'}, + } + + def __init__( + self, + *, + signature_record: Optional[str] = None, + **kwargs + ): + super(TagAttributesTag, self).__init__(**kwargs) + self.signature_record = signature_record + + +class TagList(msrest.serialization.Model): + """List of tag details. + + :param registry: Registry name. + :type registry: str + :param image_name: Image name. + :type image_name: str + :param tags: A set of tags. List of tag attribute details. + :type tags: list[~azure.containerregistry.models.TagAttributesBase] + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'image_name': {'key': 'imageName', 'type': 'str'}, + 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, + } + + def __init__( + self, + *, + registry: Optional[str] = None, + image_name: Optional[str] = None, + tags: Optional[List["TagAttributesBase"]] = None, + **kwargs + ): + super(TagList, self).__init__(**kwargs) + self.registry = registry + self.image_name = image_name + self.tags = tags + + +class V1Manifest(Manifest): + """Returns the requested V1 manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param architecture: CPU architecture. + :type architecture: str + :param name: Image name. + :type name: str + :param tag: Image tag. + :type tag: str + :param fs_layers: List of layer information. + :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :param history: Image history. + :type history: list[~azure.containerregistry.models.History] + :param signatures: Image signature. + :type signatures: list[~azure.containerregistry.models.ImageSignature] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'architecture': {'key': 'architecture', 'type': 'str'}, + 'name': {'key': 'name', 'type': 'str'}, + 'tag': {'key': 'tag', 'type': 'str'}, + 'fs_layers': {'key': 'fsLayers', 'type': '[FsLayer]'}, + 'history': {'key': 'history', 'type': '[History]'}, + 'signatures': {'key': 'signatures', 'type': '[ImageSignature]'}, + } + + def __init__( + self, + *, + schema_version: Optional[int] = None, + architecture: Optional[str] = None, + name: Optional[str] = None, + tag: Optional[str] = None, + fs_layers: Optional[List["FsLayer"]] = None, + history: Optional[List["History"]] = None, + signatures: Optional[List["ImageSignature"]] = None, + **kwargs + ): + super(V1Manifest, self).__init__(schema_version=schema_version, **kwargs) + self.architecture = architecture + self.name = name + self.tag = tag + self.fs_layers = fs_layers + self.history = history + self.signatures = signatures + + +class V2Manifest(Manifest): + """Returns the requested Docker V2 Manifest file. + + :param schema_version: Schema version. + :type schema_version: int + :param media_type: Media type for this Manifest. + :type media_type: str + :param config: V2 image config descriptor. + :type config: ~azure.containerregistry.models.Descriptor + :param layers: List of V2 image layer information. + :type layers: list[~azure.containerregistry.models.Descriptor] + """ + + _attribute_map = { + 'schema_version': {'key': 'schemaVersion', 'type': 'int'}, + 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'config': {'key': 'config', 'type': 'Descriptor'}, + 'layers': {'key': 'layers', 'type': '[Descriptor]'}, + } + + def __init__( + self, + *, + schema_version: Optional[int] = None, + media_type: Optional[str] = None, + config: Optional["Descriptor"] = None, + layers: Optional[List["Descriptor"]] = None, + **kwargs + ): + super(V2Manifest, self).__init__(schema_version=schema_version, **kwargs) + self.media_type = media_type + self.config = config + self.layers = layers diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py new file mode 100644 index 000000000000..d6560dfe7906 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py @@ -0,0 +1,25 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._v2_support_operations import V2SupportOperations +from ._manifests_operations import ManifestsOperations +from ._blob_operations import BlobOperations +from ._repository_operations import RepositoryOperations +from ._tag_operations import TagOperations +from ._refresh_tokens_operations import RefreshTokensOperations +from ._access_tokens_operations import AccessTokensOperations + +__all__ = [ + 'V2SupportOperations', + 'ManifestsOperations', + 'BlobOperations', + 'RepositoryOperations', + 'TagOperations', + 'RefreshTokensOperations', + 'AccessTokensOperations', +] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py new file mode 100644 index 000000000000..556176224bc0 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py @@ -0,0 +1,171 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, Optional, TypeVar + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class AccessTokensOperations(object): + """AccessTokensOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def get( + self, + service, # type: str + scope, # type: str + refresh_token, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.AccessToken" + """Exchange ACR Refresh token for an ACR Access Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Which is expected to be a valid scope, and can be specified more than once for + multiple scope requests. You obtained this from the Www-Authenticate response header from the + challenge. + :type scope: str + :param refresh_token: Must be a valid ACR refresh token. + :type refresh_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AccessToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AccessToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "refresh_token" + accept = "application/json" + + # Construct URL + url = self.get.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AccessToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get.metadata = {'url': '/oauth2/token'} # type: ignore + + def get_from_login( + self, + service, # type: str + scope, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.AccessToken" + """Exchange Username, Password, and Scope for an ACR Access Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Expected to be a valid scope, and can be specified more than once for multiple + scope requests. You can obtain this from the Www-Authenticate response header from the + challenge. + :type scope: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AccessToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AccessToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_from_login.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + query_parameters['service'] = self._serialize.query("service", service, 'str') + query_parameters['scope'] = self._serialize.query("scope", scope, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AccessToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_from_login.metadata = {'url': '/oauth2/token'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_blob_operations.py new file mode 100644 index 000000000000..6299667471ec --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_blob_operations.py @@ -0,0 +1,726 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, IO, Optional, TypeVar + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class BlobOperations(object): + """BlobOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def get( + self, + name, # type: str + digest, # type: str + **kwargs # type: Any + ): + # type: (...) -> Optional[IO] + """Retrieve the blob from the registry identified by digest. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: IO, or the result of cls(response) + :rtype: IO or None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[Optional[IO]] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/octet-stream" + + # Construct URL + url = self.get.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 307]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + deserialized = None + if response.status_code == 200: + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + deserialized = response.stream_download(self._client._pipeline) + + if response.status_code == 307: + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + get.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + def check( + self, + name, # type: str + digest, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Same as GET, except only the headers are returned. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.head(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200, 307]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + if response.status_code == 200: + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + + if response.status_code == 307: + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + + if cls: + return cls(pipeline_response, None, response_headers) + + check.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + def delete( + self, + name, # type: str + digest, # type: str + **kwargs # type: Any + ): + # type: (...) -> IO + """Removes an already uploaded blob. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: IO, or the result of cls(response) + :rtype: IO + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[IO] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/octet-stream" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + deserialized = response.stream_download(self._client._pipeline) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + delete.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + def mount( + self, + name, # type: str + from_parameter, # type: str + mount, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Mount a blob identified by the ``mount`` parameter from another repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param from_parameter: Name of the source repository. + :type from_parameter: str + :param mount: Digest of blob to mount from the source repository. + :type mount: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.mount.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + query_parameters['from'] = self._serialize.query("from_parameter", from_parameter, 'str') + query_parameters['mount'] = self._serialize.query("mount", mount, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.post(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [201]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + + if cls: + return cls(pipeline_response, None, response_headers) + + mount.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore + + def get_status( + self, + location, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Retrieve status of upload identified by uuid. The primary purpose of this endpoint is to + resolve the current status of a resumable upload. + + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_status.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + + if cls: + return cls(pipeline_response, None, response_headers) + + get_status.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + def upload( + self, + location, # type: str + value, # type: IO + **kwargs # type: Any + ): + # type: (...) -> None + """Upload a stream of data without completing the upload. + + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :param value: Raw data of blob. + :type value: IO + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/octet-stream") + accept = "application/json" + + # Construct URL + url = self.upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content_kwargs['stream_content'] = value + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + + if cls: + return cls(pipeline_response, None, response_headers) + + upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + def end_upload( + self, + digest, # type: str + location, # type: str + value=None, # type: Optional[IO] + **kwargs # type: Any + ): + # type: (...) -> None + """Complete the upload, providing all the data in the body, if necessary. A request without a body + will just complete the upload with previously uploaded content. + + :param digest: Digest of a BLOB. + :type digest: str + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :param value: Optional raw data of blob. + :type value: IO + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/octet-stream") + accept = "application/json" + + # Construct URL + url = self.end_upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content_kwargs['stream_content'] = value + request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [201]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + + if cls: + return cls(pipeline_response, None, response_headers) + + end_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + def cancel_upload( + self, + location, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Cancel outstanding upload processes, releasing associated resources. If this is not called, the + unfinished uploads will eventually timeout. + + :param location: Link acquired from upload start or previous chunk. Note, do not include + initial / (must do substring(1) ). + :type location: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.cancel_upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + cancel_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + + def start_upload( + self, + name, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Initiate a resumable blob upload with an empty request body. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.start_upload.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.post(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Range']=self._deserialize('str', response.headers.get('Range')) + response_headers['Docker-Upload-UUID']=self._deserialize('str', response.headers.get('Docker-Upload-UUID')) + + if cls: + return cls(pipeline_response, None, response_headers) + + start_upload.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore + + def get_chunk( + self, + name, # type: str + digest, # type: str + range, # type: str + **kwargs # type: Any + ): + # type: (...) -> IO + """Retrieve the blob from the registry identified by ``digest``. This endpoint may also support + RFC7233 compliant range requests. Support can be detected by issuing a HEAD request. If the + header ``Accept-Range: bytes`` is returned, range requests can be used to fetch partial + content. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :param range: Format : bytes=:code:``-:code:``, HTTP Range header specifying blob + chunk. + :type range: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: IO, or the result of cls(response) + :rtype: IO + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[IO] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/octet-stream" + + # Construct URL + url = self.get_chunk.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Range'] = self._serialize.header("range", range, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=True, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [206]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Content-Range']=self._deserialize('str', response.headers.get('Content-Range')) + deserialized = response.stream_download(self._client._pipeline) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + get_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + + def check_chunk( + self, + name, # type: str + digest, # type: str + range, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Same as GET, except only the headers are returned. + + :param name: Name of the image (including the namespace). + :type name: str + :param digest: Digest of a BLOB. + :type digest: str + :param range: Format : bytes=:code:``-:code:``, HTTP Range header specifying blob + chunk. + :type range: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check_chunk.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Range'] = self._serialize.header("range", range, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.head(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + response_headers['Content-Range']=self._deserialize('str', response.headers.get('Content-Range')) + + if cls: + return cls(pipeline_response, None, response_headers) + + check_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_manifests_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_manifests_operations.py new file mode 100644 index 000000000000..af564014302a --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_manifests_operations.py @@ -0,0 +1,432 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, Optional, TypeVar + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class ManifestsOperations(object): + """ManifestsOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def get( + self, + name, # type: str + reference, # type: str + accept=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> "_models.ManifestWrapper" + """Get the manifest identified by ``name`` and ``reference`` where ``reference`` can be a tag or + digest. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :param accept: Accept header string delimited by comma. For example, + application/vnd.docker.distribution.manifest.v2+json. + :type accept: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: ManifestWrapper, or the result of cls(response) + :rtype: ~azure.containerregistry.models.ManifestWrapper + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestWrapper"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + if accept is not None: + header_parameters['accept'] = self._serialize.header("accept", accept, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('ManifestWrapper', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + + def create( + self, + name, # type: str + reference, # type: str + schema_version=None, # type: Optional[int] + **kwargs # type: Any + ): + # type: (...) -> object + """Put the manifest identified by ``name`` and ``reference`` where ``reference`` can be a tag or + digest. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :param schema_version: Schema version. + :type schema_version: int + :keyword callable cls: A custom type or function that will be passed the direct response + :return: object, or the result of cls(response) + :rtype: object + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[object] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + + _payload = _models.Manifest(schema_version=schema_version) + content_type = kwargs.pop("content_type", "application/vnd.docker.distribution.manifest.v2+json") + accept = "application/json" + + # Construct URL + url = self.create.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(_payload, 'Manifest') + body_content_kwargs['content'] = body_content + request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [201]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Docker-Content-Digest']=self._deserialize('str', response.headers.get('Docker-Content-Digest')) + response_headers['Location']=self._deserialize('str', response.headers.get('Location')) + response_headers['Content-Length']=self._deserialize('long', response.headers.get('Content-Length')) + deserialized = self._deserialize('object', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + create.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + + def delete( + self, + name, # type: str + reference, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Delete the manifest identified by ``name`` and ``reference``. Note that a manifest can *only* + be deleted by ``digest``. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + delete.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + + def get_list( + self, + name, # type: str + last=None, # type: Optional[str] + n=None, # type: Optional[int] + orderby=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> "_models.AcrManifests" + """List manifests of a repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :param orderby: orderby query parameter. + :type orderby: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AcrManifests, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AcrManifests + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrManifests"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_list.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AcrManifests', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_list.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore + + def get_attributes( + self, + name, # type: str + reference, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.ManifestAttributes" + """Get manifest attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: ManifestAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.ManifestAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('ManifestAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + + def update_attributes( + self, + name, # type: str + reference, # type: str + value=None, # type: Optional["_models.ChangeableAttributes"] + **kwargs # type: Any + ): + # type: (...) -> None + """Update attributes of a manifest. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: A tag or a digest, pointing to a specific image. + :type reference: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py new file mode 100644 index 000000000000..77f400b22aad --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py @@ -0,0 +1,117 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, Optional, TypeVar, Union + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class RefreshTokensOperations(object): + """RefreshTokensOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def get_from_exchange( + self, + grant_type, # type: Union[str, "_models.PostContentSchemaGrantType"] + service, # type: str + tenant=None, # type: Optional[str] + refresh_token=None, # type: Optional[str] + access_token=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> "_models.RefreshToken" + """Exchange AAD tokens for an ACR refresh Token. + + :param grant_type: Can take a value of access_token_refresh_token, or access_token, or + refresh_token. + :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType + :param service: Indicates the name of your Azure container registry. + :type service: str + :param tenant: AAD tenant associated to the AAD credentials. + :type tenant: str + :param refresh_token: AAD refresh token, mandatory when grant_type is + access_token_refresh_token or refresh_token. + :type refresh_token: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: RefreshToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RefreshToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.RefreshToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + accept = "application/json" + + # Construct URL + url = self.get_from_exchange.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('RefreshToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_from_exchange.metadata = {'url': '/oauth2/exchange'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_repository_operations.py new file mode 100644 index 000000000000..e052b61810ce --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_repository_operations.py @@ -0,0 +1,277 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, Optional, TypeVar + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class RepositoryOperations(object): + """RepositoryOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def get_list( + self, + last=None, # type: Optional[str] + n=None, # type: Optional[int] + **kwargs # type: Any + ): + # type: (...) -> "_models.Repositories" + """List repositories. + + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :keyword callable cls: A custom type or function that will be passed the direct response + :return: Repositories, or the result of cls(response) + :rtype: ~azure.containerregistry.models.Repositories + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.Repositories"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_list.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + response_headers = {} + response_headers['Link']=self._deserialize('str', response.headers.get('Link')) + deserialized = self._deserialize('Repositories', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, response_headers) + + return deserialized + get_list.metadata = {'url': '/acr/v1/_catalog'} # type: ignore + + def get_attributes( + self, + name, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.RepositoryAttributes" + """Get repository attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: RepositoryAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RepositoryAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('RepositoryAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore + + def delete( + self, + name, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.DeletedRepository" + """Delete the repository identified by ``name``. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: DeletedRepository, or the result of cls(response) + :rtype: ~azure.containerregistry.models.DeletedRepository + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepository"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('DeletedRepository', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + delete.metadata = {'url': '/acr/v1/{name}'} # type: ignore + + def update_attributes( + self, + name, # type: str + value=None, # type: Optional["_models.ChangeableAttributes"] + **kwargs # type: Any + ): + # type: (...) -> None + """Update the attribute identified by ``name`` where ``reference`` is the name of the repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py new file mode 100644 index 000000000000..91687e56f057 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py @@ -0,0 +1,298 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, Optional, TypeVar + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class TagOperations(object): + """TagOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def get_list( + self, + name, # type: str + last=None, # type: Optional[str] + n=None, # type: Optional[int] + orderby=None, # type: Optional[str] + digest=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> "_models.TagList" + """List tags of a repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :param orderby: orderby query parameter. + :type orderby: str + :param digest: filter by digest. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagList, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagList + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_list.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + if digest is not None: + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagList', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_list.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore + + def get_attributes( + self, + name, # type: str + reference, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.TagAttributes" + """Get tag attributes by tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + def update_attributes( + self, + name, # type: str + reference, # type: str + value=None, # type: Optional["_models.ChangeableAttributes"] + **kwargs # type: Any + ): + # type: (...) -> None + """Update tag attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + def delete( + self, + name, # type: str + reference, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Delete tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + delete.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py new file mode 100644 index 000000000000..30ee5166ea93 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py @@ -0,0 +1,91 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, Optional, TypeVar + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class V2SupportOperations(object): + """V2SupportOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def check( + self, + **kwargs # type: Any + ): + # type: (...) -> None + """Tells whether this Docker Registry instance supports Docker Registry HTTP API v2. + + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + check.metadata = {'url': '/v2/'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/py.typed b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/py.typed new file mode 100644 index 000000000000..e5aff4f83af8 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. \ No newline at end of file From eb5eb54dd23c1e2149e460cc2e6e8954f62a093f Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Feb 2021 15:12:54 -0500 Subject: [PATCH 02/86] adding files from template --- .../azure-containerregistry/CHANGELOG.md | 31 ++++++++ .../azure-containerregistry/MANIFEST.in | 3 + .../azure-containerregistry/README.md | 35 +++++++++ .../azure-containerregistry/azure/__init__.py | 1 + .../azure/containerregistry/__init__.py | 1 + .../azure/containerregistry/_version.py | 6 ++ .../dev_requirements.txt | 2 + .../sdk_packaging.toml | 2 + .../azure-containerregistry/setup.cfg | 2 + .../azure-containerregistry/setup.py | 74 +++++++++++++++++++ 10 files changed, 157 insertions(+) create mode 100644 sdk/containerregistry/azure-containerregistry/CHANGELOG.md create mode 100644 sdk/containerregistry/azure-containerregistry/MANIFEST.in create mode 100644 sdk/containerregistry/azure-containerregistry/README.md create mode 100644 sdk/containerregistry/azure-containerregistry/azure/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py create mode 100644 sdk/containerregistry/azure-containerregistry/dev_requirements.txt create mode 100644 sdk/containerregistry/azure-containerregistry/sdk_packaging.toml create mode 100644 sdk/containerregistry/azure-containerregistry/setup.cfg create mode 100644 sdk/containerregistry/azure-containerregistry/setup.py diff --git a/sdk/containerregistry/azure-containerregistry/CHANGELOG.md b/sdk/containerregistry/azure-containerregistry/CHANGELOG.md new file mode 100644 index 000000000000..999dfa7dc075 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/CHANGELOG.md @@ -0,0 +1,31 @@ +# Release History + +## 0.0.18b3 (Unreleased) + + +## 0.0.18b2 (2020-09-04) +- Testing release tag version + +## 0.0.13b1 (2020-08-27) +- Testing out some alpha and beta versioning + +## 0.0.12 (Unreleased) +- Test a successful Release + +## 0.0.7 (2020-07-02) +- Test a successful Release + +## 0.0.6 (2020-05-20) +- Test a successful Release + +## 0.0.5 (2020-05-20) +- Test a successful Release + +## 0.0.3 (Unreleased) + +## 0.0.2 (2020-03-24) +- Test Release Pipeline + + +## 0.0.1 (2019-10-06) + - Template package diff --git a/sdk/containerregistry/azure-containerregistry/MANIFEST.in b/sdk/containerregistry/azure-containerregistry/MANIFEST.in new file mode 100644 index 000000000000..dd20dd67408b --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/MANIFEST.in @@ -0,0 +1,3 @@ +include *.md +include azure/__init__.py +recursive-include tests *.py \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md new file mode 100644 index 000000000000..92c7ca73c592 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -0,0 +1,35 @@ +[![Build Status](https://dev.azure.com/azure-sdk/public/_apis/build/status/azure-sdk-for-python.client?branchName=master)](https://dev.azure.com/azure-sdk/public/_build/latest?definitionId=46?branchName=master) + +# Azure Template Package client library for Python + +This template package matches necessary patterns that the development team has established to create a unified sdk functional from Python 2.7 onwards. The packages contained herein can be installed singly or as part of the `azure` namespace. Any other introductory text should go here. + +This package has been tested with Python 2.7, 3.5, 3.6, 3.7 and 3.8 + +For a more complete set of Azure libraries, see https://aka.ms/azsdk/python/all + +# Getting started + +For a rich example of a well formatted readme, please check [here.](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-TEMPLATE.md) In addition, this is an [example readme](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-EXAMPLE.md) that should be emulated. Note that the top-level sections in this template align with that of the [template.](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-TEMPLATE.md) + +# Key concepts + +Bullet point list of your library's main concepts. + +# Examples + +Examples of some of the key concepts for your library. + +# Troubleshooting + +Running into issues? This section should contain details as to what to do there. + +# Next steps + +More sample code should go here, along with links out to the appropriate example tests. + +# Contributing + +If you encounter any bugs or have suggestions, please file an issue in the [Issues]() section of the project. + +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-python%2Fsdk%2Ftemplate%2Fazure-template%2FREADME.png) diff --git a/sdk/containerregistry/azure-containerregistry/azure/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/__init__.py new file mode 100644 index 000000000000..8db66d3d0f0f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/__init__.py @@ -0,0 +1 @@ +__path__ = __import__("pkgutil").extend_path(__path__, __name__) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py new file mode 100644 index 000000000000..8db66d3d0f0f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -0,0 +1 @@ +__path__ = __import__("pkgutil").extend_path(__path__, __name__) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py new file mode 100644 index 000000000000..a58dbf5af24a --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py @@ -0,0 +1,6 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +VERSION = "0.0.1" diff --git a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt new file mode 100644 index 000000000000..fc4514eab3ef --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt @@ -0,0 +1,2 @@ +-e ../../../tools/azure-sdk-tools +../../core/azure-core diff --git a/sdk/containerregistry/azure-containerregistry/sdk_packaging.toml b/sdk/containerregistry/azure-containerregistry/sdk_packaging.toml new file mode 100644 index 000000000000..901bc8ccbfa6 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/sdk_packaging.toml @@ -0,0 +1,2 @@ +[packaging] +auto_update = false diff --git a/sdk/containerregistry/azure-containerregistry/setup.cfg b/sdk/containerregistry/azure-containerregistry/setup.cfg new file mode 100644 index 000000000000..3c6e79cf31da --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal=1 diff --git a/sdk/containerregistry/azure-containerregistry/setup.py b/sdk/containerregistry/azure-containerregistry/setup.py new file mode 100644 index 000000000000..197245b28e40 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/setup.py @@ -0,0 +1,74 @@ +from setuptools import setup, find_packages +import os +from io import open +import re + +# example setup.py Feel free to copy the entire "azure-template" folder into a package folder named +# with "azure-". Ensure that the below arguments to setup() are updated to reflect +# your package. + +# this setup.py is set up in a specific way to keep the azure* and azure-mgmt-* namespaces WORKING all the way +# up from python 2.7. Reference here: https://github.com/Azure/azure-sdk-for-python/wiki/Azure-packaging + +PACKAGE_NAME = "azure-containerregistry" +PACKAGE_PPRINT_NAME = "Template Package" + +# a-b-c => a/b/c +package_folder_path = PACKAGE_NAME.replace('-', '/') +# a-b-c => a.b.c +namespace_name = PACKAGE_NAME.replace('-', '.') + +# Version extraction inspired from 'requests' +with open(os.path.join(package_folder_path, '_version.py'), 'r') as fd: + version = re.search(r'^VERSION\s*=\s*[\'"]([^\'"]*)[\'"]', + fd.read(), re.MULTILINE).group(1) +if not version: + raise RuntimeError('Cannot find version information') + +with open('README.md', encoding='utf-8') as f: + long_description = f.read() + +setup( + name=PACKAGE_NAME, + version=version, + description='Microsoft Azure {} Client Library for Python'.format(PACKAGE_PPRINT_NAME), + + # ensure that these are updated to reflect the package owners' information + long_description=long_description, + url='https://github.com/Azure/azure-sdk-for-python', + author='Microsoft Corporation', + author_email='azuresdkengsysadmins@microsoft.com', + + license='MIT License', + # ensure that the development status reflects the status of your package + classifiers=[ + "Development Status :: 4 - Beta", + + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'License :: OSI Approved :: MIT License', + ], + packages=find_packages(exclude=[ + 'tests', + # Exclude packages that will be covered by PEP420 or nspkg + 'azure' + ]), + install_requires=[ + #'msrest>=0.5.0', + #'msrestazure>=0.4.32,<2.0.0', + #'azure-common~=1.1', + ], + extras_require={ + ":python_version<'3.0'": ['azure-nspkg'], + }, + project_urls={ + 'Bug Reports': 'https://github.com/Azure/azure-sdk-for-python/issues', + 'Source': 'https://github.com/Azure/azure-sdk-python', + } +) From 785564d1d85143c47ee5b9e46c58dca008ed305c Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Feb 2021 15:41:14 -0500 Subject: [PATCH 03/86] adding a tests.yml file --- sdk/containerregistry/tests.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 sdk/containerregistry/tests.yml diff --git a/sdk/containerregistry/tests.yml b/sdk/containerregistry/tests.yml new file mode 100644 index 000000000000..f3215b43e4d5 --- /dev/null +++ b/sdk/containerregistry/tests.yml @@ -0,0 +1,14 @@ +trigger: none + +stages: + - template: ../../eng/pipelines/templates/stages/archetype-sdk-tests.yml + parameters: + AllocateResourceGroup: 'false' + BuildTargetingString: $(BuildTargetingString) + ServiceDirectory: template + EnvVars: + TEMPLATE_CONFIG_CONNECTION: $(python-template-connection-string) # Add variables/mappings as appropriate for your service. + AZURE_CLIENT_ID: $(aad-azure-sdk-test-client-id) + AZURE_CLIENT_SECRET: $(aad-azure-sdk-test-client-secret) + AZURE_TENANT_ID: $(aad-azure-sdk-test-tenant-id) + TEST_MODE: 'RunLiveNoRecord' \ No newline at end of file From 561128fdca81f0119708c2d18db132859198366b Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 23 Feb 2021 17:38:59 -0500 Subject: [PATCH 04/86] outlining base structures --- .../azure/containerregistry/_base_client.py | 17 ++++ .../_container_registry_client.py | 36 +++++++++ .../_container_repository_client.py | 45 +++++++++++ .../azure/containerregistry/_models.py | 80 +++++++++++++++++++ .../azure/containerregistry/_version.py | 2 +- .../azure-containerregistry/samples/README.md | 1 + .../samples/sample_repository_actions.py | 64 +++++++++++++++ 7 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py create mode 100644 sdk/containerregistry/azure-containerregistry/samples/README.md create mode 100644 sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py new file mode 100644 index 000000000000..8a97ad2fa2e1 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -0,0 +1,17 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +class ContainerRegistryApiVersion(str, Enum): + """Container Registry API version supported by this package""" + + V0_PREVIEW = "" + +class ContainerRegistryBaseClient(object): + + def __init__(self, base_url, credential, **kwargs): + + pass + diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py new file mode 100644 index 000000000000..c3b4502b0b54 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -0,0 +1,36 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + + + +class ContainerRegistryClient(object): + + def __init__(self, base_url, credential, **kwargs): + # type: (str, TokenCredential) -> None + + pass + + def delete_repository(self, name): + # type: (str) -> DeleteRepositoryResult + + pass + + def list_repositories(self, **kwargs): + # type: (...) -> Pageable[str] + + pass + + def get_repository_client(self, name): + # type: (str) -> ContainerRepositoryClient + + pass + + def get_repository_attributes(self, name): + # type: (str) -> RepositoryAttributes + + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py new file mode 100644 index 000000000000..e4d85d3e493b --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -0,0 +1,45 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + + + +class ContainerRepositoryClient(object): + + + def __init__(self, endpoint, repository_name, credential, **kwargs): + # type: (str, str, TokenCredential) -> None + pass + + def delete(self): + # type: (...) -> None + pass + + def delete_manifest(self, name, digest): + # type: (str, str) -> None + pass + + def delete_tag(self, name): + # type: (str) -> None + pass + + def get_artifact_storage_client(self): + # type: (...) -> ArtifactStorageClient + pass + + def get_attributes(self): + # type: (...) -> RepositoryAttributes + pass + + def get_manifest(self, tag_or_digest): + # type: (str) -> ManifestAttributes + pass + + def get_tag(self, tag_name): + # type: (str) -> TagAttributes + pass + diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py new file mode 100644 index 000000000000..a2311e241dc2 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -0,0 +1,80 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from enum import Enum + +from ._generated.models import ( + DeletedRepository, +) + +class AzureAdminUserCredential(object): + + def __init__(self, username, password): + # type: (str, str) -> None + self.username = username + self.password = password + + def update_password(self, password): + # type: (str) -> None + self.password = password + + +class ContentPermissions(object): + + def __init__(self, **kwargs): + self.delete = kwargs.get("delete") + self.list = kwargs.get("list") + self.read = kwargs.get("read") + self.write = kwargs.get("write") + + +class DeleteRepositoryResult(DeletedRepository): + + def __init__(self, **kwargs): + super(DeleteRepositoryResult, self).__init__(**kwargs) + pass + + +class GetManifestOptions(object): + + def __init__(self): + pass + + +class GetTagOptions(object): + + def __init__(self): + pass + + +class ManifestAttributes(object): + + def __init__(self): + pass + + +class ManifestOrderBy(int, Enum): + + LastUpdateTimeDescending = 0 + LastUpdateTimeAscending = 1 + + +class RepositoryAttributes(object): + + def __init__(self, **kwargs): + pass + + +class TagAttributes(object): + + def __init__(self, **kwargs): + pass + + +class TagOrderBy(int, Enum): + + LastUpdateTimeDescending = 0 + LastUpdateTimeAscending = 1 diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py index a58dbf5af24a..366e8a430a68 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py @@ -3,4 +3,4 @@ # Licensed under the MIT License. # ------------------------------------ -VERSION = "0.0.1" +VERSION = "0.1.0" diff --git a/sdk/containerregistry/azure-containerregistry/samples/README.md b/sdk/containerregistry/azure-containerregistry/samples/README.md new file mode 100644 index 000000000000..83e56cfd5395 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/samples/README.md @@ -0,0 +1 @@ +# Samples for Azure Container Registry diff --git a/sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py b/sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py new file mode 100644 index 000000000000..2856fc973b3c --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py @@ -0,0 +1,64 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +import os + +class SampleRepositoryActions(object): + + base_url = os.environ.get("ACR_BASE_URL") + + def view_repositories(self): + client = ContainerRegistryClient(self.base_url, DefaultAzureCredential()) + + repositories = client.list_repositories() + + for idx, repo in enumerate(repositories): + print("Repository #{}: {}".format(idx, repo)) + + def get_repository_metadata(self): + client = ContainerRegistryClient(self.base_url, DefaultAzureCredential()) + + repo_client = client.get_repository_client("hello-world") + + attributes = repo_client.get_attributes() + + print(attributes.name) + print(attributes.registry) + print(attributes.created_time) + print(attributes.last_updated_time) + print(attributes.manifest_count) + print(attributes.tag_count) + print(attributes.permission.can_list) + print(attributes.permission.can_read) + print(attributes.permission.can_write) + print(attributes.permission.can_delete) + + def set_repository_permissions(self): + client = ContainerRegistryClient(self.base_url, DefaultAzureCredential()) + + repo_client = client.get_repository_client("hello-world") + + permissions = ContentPermissions( + list=true, + read=true, + write=true, + delete=false + ) + + repo_client.set_permissions(permissions) + + def delete_repository(self): + client = ContainerRegistryClient(self.base_url, DefaultAzureCredential()) + + result = client.delete_repository("hello-world") + + for manifest in result.manifests_deleted: + print("Deleted {}".format(manifest)) + + for tag in result.tags_deleted: + print("Deleted tags {}".format(tag)) From beba7fc488f804eed50ed6df720e8120348e1e8e Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Feb 2021 16:59:36 -0500 Subject: [PATCH 05/86] adding more skeleton code --- .../_artifact_storage_client.py | 67 +++++ .../_container_registry_authentication.py | 14 + .../_container_registry_client.py | 11 +- .../_container_repository_client.py | 24 +- .../azure/containerregistry/_models.py | 2 +- .../containerregistry/_storage_models.py | 264 ++++++++++++++++++ 6 files changed, 371 insertions(+), 11 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py new file mode 100644 index 000000000000..9e027dfc3005 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py @@ -0,0 +1,67 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +class ArtifactClient(object): + + def __init__(self, endpoint, repository_name, credential): + # type: (str, str, TokenCredential) -> None + pass + + def cancel_upload(self, location): + # type: (str) -> None + pass + + def check_blob_exists(self, digest): + # type: (str) -> bool + pass + + def check_chunk_exists(self, digest, range): + # type: (str, HttpRange) -> bool + pass + + def complete_upload(self, upload_details, digest, value=None): + # type: (CreateUploadResult, str, Stream) -> None + pass + + def create_manifest(self, manifest, tag=None): + # type: (ArtifactManifest, str) -> None + pass + + def create_upload(self): + # type: (...) -> CreateUploadResult + pass + + def delete(self): + # type: (...) -> None + + def delete_blob(self, digest): + # type: (str) -> Stream + pass + + def get_blob(self, digest): + # type: (str) -> Stream + pass + + def get_chunk(self, digest, range): + # type: (str, HttpRange) -> Stream + pass + + def get_manifest(self, tag_or_digest, accept_media_types=None): + # type: (str, Optional[List[ManifestMediaType]]) -> ArtifactManifest + pass + + def get_upload_status(self, location): + # type: (str) -> Response + pass + + def mount_blob(self, blob_from, mount): + # type: (str, str) -> Response + pass + + def upload_chunk(self, upload_details, value): + # type: (CreateUploadResult, Stream) -> CreateUploadResult + # TODO: upload_details should prob be a different type than the returned one + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py new file mode 100644 index 000000000000..441e96b6e7fb --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py @@ -0,0 +1,14 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +class ContainerRegistryStsClient(object): + + def __init__(self, endpoint, credential, **kwargs): + # type: (str, TokenCredential) -> None + pass + + def get_access_token(self): + # type: (...) -> None \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index c3b4502b0b54..9b59a77eceb3 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -1,11 +1,8 @@ # coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- - +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ class ContainerRegistryClient(object): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index e4d85d3e493b..4e2a18f16766 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -7,7 +7,6 @@ # -------------------------------------------------------------------------- - class ContainerRepositoryClient(object): @@ -28,7 +27,7 @@ def delete_tag(self, name): pass def get_artifact_storage_client(self): - # type: (...) -> ArtifactStorageClient + # type: (...) -> ArtifactClient pass def get_attributes(self): @@ -36,10 +35,29 @@ def get_attributes(self): pass def get_manifest(self, tag_or_digest): - # type: (str) -> ManifestAttributes + # type: (str) -> ArtifactAttributes pass def get_tag(self, tag_name): # type: (str) -> TagAttributes pass + def list_manifests(self, **kwargs): + # type: (...) -> Pageable[ArtifactAttributes] + pass + + def list_tags(self, **kwargs): + # type: (...) -> Pageable[TagAttributes] + pass + + def set_manifest_permissions(self, tag_or_digest, value): + # type: (str, ContentPermissions) -> None + pass + + def set_permissions(self, value): + # type: (ContentPermissions) -> None + pass + + def set_tag_permissions(self, tag, permissions): + # type: (str, ContentPermissions) -> None + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index a2311e241dc2..fe12b7a30a03 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -50,7 +50,7 @@ def __init__(self): pass -class ManifestAttributes(object): +class ArtifactAttributes(object): def __init__(self): pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py new file mode 100644 index 000000000000..cf2236dfd421 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py @@ -0,0 +1,264 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +class ArtifactManifest(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.media_type = kwargs.get('media_type', None) + self.schema_version = kwargs.get('media_version', None) + + def as_docker_manifest_list(self): + # type: (...) -> DockerManifestList + pass + + def as_docker_manifest_v1(self): + # type: (...) -> DockerManifestV1 + pass + + def as_docker_manifest_v2(self): + # type: (...) -> DockerManifestV2 + pass + + def as_docker_manifest_v1(self): + # type: (...) -> DockerManifestV1 + pass + + def as_oci_index(self): + # type: (...) -> OCIIndex + pass + + def as_oci_manifest(self): + # type: (...) -> OCIManifest + pass + + + + + + +class CompleteUploadResult(object): + + def __init__(self, digest, location, http_range): + # type: (str, str, HttpRange) + self.digest = digest + self.location = location + self.http_range = http_range + + +class ConfigMediaType(object): + + def __init__(self): + self.docker_image_v1 = None + self.oci_image_config = None + pass + + def __eq__(self, right): + # type: (ConfigMediaType) -> bool + pass + + def __ne__(self, right): + # type: (ConfigMediaType) -> bool + return not self.__eq__(right) + + def get_has_code(self): + # type: (...) -> int + pass + + def __repr__(self): + # type: (...) -> str + pass + + +class ContentDescriptor(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.media_type = kwargs.get('media_type', None) + self.annotations = kwargs.get('annotations', None) + self.digest = kwargs.get('digest', None) + self.size = kwargs.get('size', None) + self.urls = kwargs.get('urls', None) + self.compute_digest = kwargs.get('compute_digest', None) + + @classmethod + def _from_generated(self, generated): + # type: (Generated) -> ContentDescriptor + pass + + +class CreateManifestResult(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.content_length = kwargs.get('content_length', None) + self.digest = kwargs.get('digest', None) + self.location = kwargs.get('location', None) + + @classmethod + def _from_generated(self, generated): + # type: (Generated) -> CreateManifestResult + pass + + +class CreateUploadResult(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.location = kwargs.get('location', None) + self.http_range = kwargs.get('http_range', None) + self.upload_id = kwargs.get('upload_id', None) + + @classmethod + def _from_generated(self, generated): + # type: (Generated) -> CreateUploadResult + pass + + +# NOTE: This might be unnecessary, Pageable[ArtifactManifest] +class DockerManifestList(ArtifactManifest): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.manifests = kwargs.get('manifests', None) + + +class DockerManifestV1(ArtifactManifest): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.architecture = kwargs.get('architecture', None) + self.fs_layers = kwargs.get('fs_layers', None) + self.history = kwargs.get('history', None) + self.name = kwargs.get('name', None) + self.signatures = kwargs.get('signatures', None) + self.tag = kwargs.get('tag', None) + + +class DockerManifestV1FsLayer(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.blob_sum = kwargs.get('blob_sum', None) + + +class DockerManifestV1History(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.v1_compatibility = kwargs.get('v1_compatibility', None) + + +class DockerManifestV1ImageHistory(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.header = kwargs.get('header', None) + self.protected = kwargs.get('protected', None) + self.signature = kwargs.get('signature', None) + + +class DockerManifestV1Jwk(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.alg = kwargs.get('alg', None) + self.jwk = kwargs.get('jwk', None) + + +class DockerManifestV1JwkHeader(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.crv = kwargs.get('crv', None) + self.kid = kwargs.get('kid', None) + self.kty = kwargs.get('kty', None) + self.x = kwargs.get('x', None) + self.y = kwargs.get('y', None) + + +class DockerManifestV2(ArtifactManifest): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.config_descriptor = kwargs.get('config_descriptor') + self.layers = kwargs.get('layers') + + @classmethod + def from_stream(self, stream): + # type: (Stream) -> DockerManifestV2 + + +class ManifestListAttributes(object): + + def __init__(self, **kwargs): + # type: (...) -> None + self.digest = kwargs.get('digest', None) + self.media_type = kwargs.get('media_type', None) + self.platform = kwargs.get('platform', None) + self.size = kwargs.get('size', None) + + +class ManifestMediaType(object): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + pass + + def __eq__(self, other): + # type: (ManifestMediaType) -> bool + pass + + def __ne__(self, other): + # type: (ManifestMediaType) -> bool + return not self.__eq__(other) + + def __repr__(self): + # type: (...) -> str + pass + + def get_hash_code(self): + # type: (...) -> int + pass + + +class OCIIndex(ArtifactManifest): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.annotations = kwargs.get('annotations', None) + self.manifests = kwargs.get('manifests', None) + + +class OCIManifest(ArtifactManifest): + + def __init__(self, **kwargs): + # type: (Optional[Dict[str, Any]]) -> None + self.annotations = kwargs.get('annotations', None) + self.config_descriptor = kwargs.get('config_descriptos', None) + self.layers = kwargs.get('layers', None) + + +# NOTE: This might not be needed, could return just a dict +class OCIManifestAnnotations(dict): + + def __init__(self): + # type: (...) -> None + pass + + +class RuntimePlatform(object): + + def __init__(self): + # type: (...) -> None + pass + + +class UploadStatus(object): + + def __init__(self): + self.http_range = kwargs.get('http_range', None) + self.upload_id = kwargs.get('upload_id', None) \ No newline at end of file From 9c7acd5080a062ef13492cbc377a8374c75b6cc2 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 25 Feb 2021 09:18:48 -0500 Subject: [PATCH 06/86] formatting code --- .../azure/containerregistry/__init__.py | 89 ++++++++++++++++++- .../_artifact_storage_client.py | 1 + .../azure/containerregistry/_base_client.py | 4 +- .../_container_registry_authentication.py | 3 +- .../_container_registry_client.py | 3 +- .../_container_repository_client.py | 2 - .../azure/containerregistry/_models.py | 13 +-- .../containerregistry/_storage_models.py | 6 +- .../samples/sample_repository_actions.py | 8 +- .../azure-containerregistry/setup.py | 68 +++++++------- 10 files changed, 135 insertions(+), 62 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 8db66d3d0f0f..cff4918cf140 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -1 +1,88 @@ -__path__ = __import__("pkgutil").extend_path(__path__, __name__) +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from ._artifact_storage_client import ArtifactClient +from ._container_registry_authentication import ContainerRegistryStsClient +from ._container_registry_client import ContainerRegistryClient +from ._container_repository_client import ContainerRepositoryClient +from ._models import ( + AzureAdminUserCredential, + ContentPermissions, + DeletedRepositoryResult, + GetManifestOptions, + GetTagOptions, + ArtifactAttributes, + ManifestOrderBy, + RepositoryAttributes, + TagAttributes, + TagOrderBy +) +from ._storage_models import ( + ArtifactManifest, + CompleteUploadResult, + ConfigMediaType, + ContentDescriptor, + CreateManifestResult, + CreateUploadResult, + DockerManifestList, + DockerManifestV1, + DockerManifestV1FsLayer, + DockerManifestV1History, + DockerManifestV1ImageHistory, + DockerManifestV1Jwk, + DockerManifestV1JwkHeader, + DockerManifestV2, + ManifestListAttributes, + ManifestMediaType, + OCIIndex, + OCIManifest, + OCIManifestAnnotations, + RuntimePlatform, + UploadStatus +) +from ._version import VERSION + +__version__ = VERSION + +__all__ = [ + "ArtifactClient", + "ContainerRegistryStsClient", + "ContainerRegistryClient", + "ContainerRepositoryClient", + "AzureAdminUserCredential", + "ContentPermissions", + "DeletedRepositoryResult", + "GetManifestOptions", + "GetTagOptions", + "ArtifactAttributes", + "ManifestOrderBy", + "RepositoryAttributes", + "TagAttributes", + "TagOrderBy", + "ArtifactManifest", + "CompleteUploadResult", + "ConfigMediaType", + "ContentDescriptor", + "CreateManifestResult", + "CreateUploadResult", + "DockerManifestList", + "DockerManifestV1", + "DockerManifestV1FsLayer", + "DockerManifestV1History", + "DockerManifestV1ImageHistory", + "DockerManifestV1Jwk", + "DockerManifestV1JwkHeader", + "DockerManifestV2", + "ManifestListAttributes", + "ManifestMediaType", + "OCIIndex", + "OCIManifest", + "OCIManifestAnnotations", + "RuntimePlatform", + "UploadStatus", +] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py index 9e027dfc3005..7e0dc0c0f96d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py @@ -36,6 +36,7 @@ def create_upload(self): def delete(self): # type: (...) -> None + pass def delete_blob(self, digest): # type: (str) -> Stream diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 8a97ad2fa2e1..9b0eb215b3b5 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -4,14 +4,14 @@ # Licensed under the MIT License. # ------------------------------------ + class ContainerRegistryApiVersion(str, Enum): """Container Registry API version supported by this package""" V0_PREVIEW = "" -class ContainerRegistryBaseClient(object): +class ContainerRegistryBaseClient(object): def __init__(self, base_url, credential, **kwargs): pass - diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py index 441e96b6e7fb..d5f395998a0f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py @@ -11,4 +11,5 @@ def __init__(self, endpoint, credential, **kwargs): pass def get_access_token(self): - # type: (...) -> None \ No newline at end of file + # type: (...) -> None + pass \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 9b59a77eceb3..46b719b3740c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -6,14 +6,13 @@ class ContainerRegistryClient(object): - def __init__(self, base_url, credential, **kwargs): # type: (str, TokenCredential) -> None pass def delete_repository(self, name): - # type: (str) -> DeleteRepositoryResult + # type: (str) -> DeletedRepositoryResult pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 4e2a18f16766..e6be8d3aaba2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -8,8 +8,6 @@ class ContainerRepositoryClient(object): - - def __init__(self, endpoint, repository_name, credential, **kwargs): # type: (str, str, TokenCredential) -> None pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index fe12b7a30a03..c4839d231ed7 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -10,8 +10,8 @@ DeletedRepository, ) -class AzureAdminUserCredential(object): +class AzureAdminUserCredential(object): def __init__(self, username, password): # type: (str, str) -> None self.username = username @@ -23,7 +23,6 @@ def update_password(self, password): class ContentPermissions(object): - def __init__(self, **kwargs): self.delete = kwargs.get("delete") self.list = kwargs.get("list") @@ -31,27 +30,23 @@ def __init__(self, **kwargs): self.write = kwargs.get("write") -class DeleteRepositoryResult(DeletedRepository): - +class DeletedRepositoryResult(DeletedRepository): def __init__(self, **kwargs): - super(DeleteRepositoryResult, self).__init__(**kwargs) + super(DeletedRepositoryResult, self).__init__(**kwargs) pass class GetManifestOptions(object): - def __init__(self): pass class GetTagOptions(object): - def __init__(self): pass class ArtifactAttributes(object): - def __init__(self): pass @@ -63,13 +58,11 @@ class ManifestOrderBy(int, Enum): class RepositoryAttributes(object): - def __init__(self, **kwargs): pass class TagAttributes(object): - def __init__(self, **kwargs): pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py index cf2236dfd421..ce11e8c63aec 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py @@ -36,10 +36,6 @@ def as_oci_manifest(self): pass - - - - class CompleteUploadResult(object): def __init__(self, digest, location, http_range): @@ -190,7 +186,7 @@ def __init__(self, **kwargs): @classmethod def from_stream(self, stream): # type: (Stream) -> DockerManifestV2 - + pass class ManifestListAttributes(object): diff --git a/sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py b/sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py index 2856fc973b3c..d58e44cff21b 100644 --- a/sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py +++ b/sdk/containerregistry/azure-containerregistry/samples/sample_repository_actions.py @@ -8,6 +8,7 @@ import os + class SampleRepositoryActions(object): base_url = os.environ.get("ACR_BASE_URL") @@ -43,12 +44,7 @@ def set_repository_permissions(self): repo_client = client.get_repository_client("hello-world") - permissions = ContentPermissions( - list=true, - read=true, - write=true, - delete=false - ) + permissions = ContentPermissions(list=true, read=true, write=true, delete=false) repo_client.set_permissions(permissions) diff --git a/sdk/containerregistry/azure-containerregistry/setup.py b/sdk/containerregistry/azure-containerregistry/setup.py index 197245b28e40..700a55ae600c 100644 --- a/sdk/containerregistry/azure-containerregistry/setup.py +++ b/sdk/containerregistry/azure-containerregistry/setup.py @@ -14,61 +14,63 @@ PACKAGE_PPRINT_NAME = "Template Package" # a-b-c => a/b/c -package_folder_path = PACKAGE_NAME.replace('-', '/') +package_folder_path = PACKAGE_NAME.replace("-", "/") # a-b-c => a.b.c -namespace_name = PACKAGE_NAME.replace('-', '.') +namespace_name = PACKAGE_NAME.replace("-", ".") # Version extraction inspired from 'requests' -with open(os.path.join(package_folder_path, '_version.py'), 'r') as fd: - version = re.search(r'^VERSION\s*=\s*[\'"]([^\'"]*)[\'"]', - fd.read(), re.MULTILINE).group(1) +with open(os.path.join(package_folder_path, "_version.py"), "r") as fd: + version = re.search( + r'^VERSION\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), re.MULTILINE + ).group(1) if not version: - raise RuntimeError('Cannot find version information') + raise RuntimeError("Cannot find version information") -with open('README.md', encoding='utf-8') as f: +with open("README.md", encoding="utf-8") as f: long_description = f.read() setup( name=PACKAGE_NAME, version=version, - description='Microsoft Azure {} Client Library for Python'.format(PACKAGE_PPRINT_NAME), - + description="Microsoft Azure {} Client Library for Python".format( + PACKAGE_PPRINT_NAME + ), # ensure that these are updated to reflect the package owners' information long_description=long_description, - url='https://github.com/Azure/azure-sdk-for-python', - author='Microsoft Corporation', - author_email='azuresdkengsysadmins@microsoft.com', - - license='MIT License', + url="https://github.com/Azure/azure-sdk-for-python", + author="Microsoft Corporation", + author_email="azuresdkengsysadmins@microsoft.com", + license="MIT License", # ensure that the development status reflects the status of your package classifiers=[ "Development Status :: 4 - Beta", - - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'License :: OSI Approved :: MIT License', + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "License :: OSI Approved :: MIT License", ], - packages=find_packages(exclude=[ - 'tests', - # Exclude packages that will be covered by PEP420 or nspkg - 'azure' - ]), + packages=find_packages( + exclude=[ + "tests", + # Exclude packages that will be covered by PEP420 or nspkg + "azure", + ] + ), install_requires=[ #'msrest>=0.5.0', #'msrestazure>=0.4.32,<2.0.0', #'azure-common~=1.1', ], extras_require={ - ":python_version<'3.0'": ['azure-nspkg'], + ":python_version<'3.0'": ["azure-nspkg"], }, project_urls={ - 'Bug Reports': 'https://github.com/Azure/azure-sdk-for-python/issues', - 'Source': 'https://github.com/Azure/azure-sdk-python', - } + "Bug Reports": "https://github.com/Azure/azure-sdk-for-python/issues", + "Source": "https://github.com/Azure/azure-sdk-python", + }, ) From 8c03d93eaa07a1aae8ac20b499d536f67cdc04f8 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 25 Feb 2021 14:57:41 -0500 Subject: [PATCH 07/86] adding some async files --- .../azure/containerregistry/__init__.py | 4 +- .../containerregistry/_artifact_client.py | 9 +++ .../_artifact_storage_client.py | 30 +++++----- .../_container_registry_authentication.py | 2 +- .../_container_registry_client.py | 6 +- .../_container_repository_client.py | 12 ++-- .../azure/containerregistry/_models.py | 10 ++-- .../containerregistry/_storage_models.py | 32 +++++----- .../azure/containerregistry/aio/__init__.py | 5 ++ .../aio/_async_artifact_storage_client.py | 60 +++++++++++++++++++ .../aio/_async_container_registry_client.py | 22 +++++++ 11 files changed, 143 insertions(+), 49 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index cff4918cf140..4701be16511b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -6,7 +6,7 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._artifact_storage_client import ArtifactClient +from ._artifact_storage_client import ArtifactStorageClient from ._container_registry_authentication import ContainerRegistryStsClient from ._container_registry_client import ContainerRegistryClient from ._container_repository_client import ContainerRepositoryClient @@ -50,7 +50,7 @@ __version__ = VERSION __all__ = [ - "ArtifactClient", + "ArtifactStorageClient", "ContainerRegistryStsClient", "ContainerRegistryClient", "ContainerRepositoryClient", diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py new file mode 100644 index 000000000000..403539bc0a77 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py @@ -0,0 +1,9 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + + +class ArtifactClient(object): + def __init__(self): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py index 7e0dc0c0f96d..63a9baaa2b01 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py @@ -4,65 +4,65 @@ # Licensed under the MIT License. # ------------------------------------ -class ArtifactClient(object): +class ArtifactStorageClient(object): def __init__(self, endpoint, repository_name, credential): # type: (str, str, TokenCredential) -> None pass - def cancel_upload(self, location): + def cancel_upload(self, location, **kwargs): # type: (str) -> None pass - def check_blob_exists(self, digest): + def check_blob_exists(self, digest, **kwargs): # type: (str) -> bool pass - def check_chunk_exists(self, digest, range): + def check_chunk_exists(self, digest, range, **kwargs): # type: (str, HttpRange) -> bool pass - def complete_upload(self, upload_details, digest, value=None): + def complete_upload(self, upload_details, digest, value=None, **kwargs): # type: (CreateUploadResult, str, Stream) -> None pass - def create_manifest(self, manifest, tag=None): + def create_manifest(self, manifest, tag=None, **kwargs): # type: (ArtifactManifest, str) -> None pass - def create_upload(self): + def create_upload(self, **kwargs): # type: (...) -> CreateUploadResult pass - def delete(self): + def delete(self, **kwargs): # type: (...) -> None pass - def delete_blob(self, digest): + def delete_blob(self, digest, **kwargs): # type: (str) -> Stream pass - def get_blob(self, digest): + def get_blob(self, digest, **kwargs): # type: (str) -> Stream pass - def get_chunk(self, digest, range): + def get_chunk(self, digest, range, **kwargs): # type: (str, HttpRange) -> Stream pass - def get_manifest(self, tag_or_digest, accept_media_types=None): + def get_manifest(self, tag_or_digest, accept_media_types=None, **kwargs): # type: (str, Optional[List[ManifestMediaType]]) -> ArtifactManifest pass - def get_upload_status(self, location): + def get_upload_status(self, location, **kwargs): # type: (str) -> Response pass - def mount_blob(self, blob_from, mount): + def mount_blob(self, blob_from, mount, **kwargs): # type: (str, str) -> Response pass - def upload_chunk(self, upload_details, value): + def upload_chunk(self, upload_details, value, **kwargs): # type: (CreateUploadResult, Stream) -> CreateUploadResult # TODO: upload_details should prob be a different type than the returned one pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py index d5f395998a0f..6e1e46536c10 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py @@ -10,6 +10,6 @@ def __init__(self, endpoint, credential, **kwargs): # type: (str, TokenCredential) -> None pass - def get_access_token(self): + def get_access_token(self, **kwargs): # type: (...) -> None pass \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 46b719b3740c..50891d688dc3 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -11,7 +11,7 @@ def __init__(self, base_url, credential, **kwargs): pass - def delete_repository(self, name): + def delete_repository(self, name, **kwargs): # type: (str) -> DeletedRepositoryResult pass @@ -21,12 +21,12 @@ def list_repositories(self, **kwargs): pass - def get_repository_client(self, name): + def get_repository_client(self, name, **kwargs): # type: (str) -> ContainerRepositoryClient pass - def get_repository_attributes(self, name): + def get_repository_attributes(self, name, **kwargs): # type: (str) -> RepositoryAttributes pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index e6be8d3aaba2..87ec2713b1bf 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -1,10 +1,8 @@ # coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ class ContainerRepositoryClient(object): @@ -25,7 +23,7 @@ def delete_tag(self, name): pass def get_artifact_storage_client(self): - # type: (...) -> ArtifactClient + # type: (...) -> ArtifactStorageClient pass def get_attributes(self): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index c4839d231ed7..8ff83cdf3790 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -12,12 +12,12 @@ class AzureAdminUserCredential(object): - def __init__(self, username, password): + def __init__(self, username, password, **kwargs): # type: (str, str) -> None self.username = username self.password = password - def update_password(self, password): + def update_password(self, password, **kwargs): # type: (str) -> None self.password = password @@ -37,17 +37,17 @@ def __init__(self, **kwargs): class GetManifestOptions(object): - def __init__(self): + def __init__(self, **kwargs): pass class GetTagOptions(object): - def __init__(self): + def __init__(self, **kwargs): pass class ArtifactAttributes(object): - def __init__(self): + def __init__(self, **kwargs): pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py index ce11e8c63aec..1fc4236e093e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py @@ -11,34 +11,34 @@ def __init__(self, **kwargs): self.media_type = kwargs.get('media_type', None) self.schema_version = kwargs.get('media_version', None) - def as_docker_manifest_list(self): + def as_docker_manifest_list(self, **kwargs): # type: (...) -> DockerManifestList pass - def as_docker_manifest_v1(self): + def as_docker_manifest_v1(self, **kwargs): # type: (...) -> DockerManifestV1 pass - def as_docker_manifest_v2(self): + def as_docker_manifest_v2(self, **kwargs): # type: (...) -> DockerManifestV2 pass - def as_docker_manifest_v1(self): + def as_docker_manifest_v1(self, **kwargs): # type: (...) -> DockerManifestV1 pass - def as_oci_index(self): + def as_oci_index(self, **kwargs): # type: (...) -> OCIIndex pass - def as_oci_manifest(self): + def as_oci_manifest(self, **kwargs): # type: (...) -> OCIManifest pass class CompleteUploadResult(object): - def __init__(self, digest, location, http_range): + def __init__(self, digest, location, http_range, **kwargs): # type: (str, str, HttpRange) self.digest = digest self.location = location @@ -60,7 +60,7 @@ def __ne__(self, right): # type: (ConfigMediaType) -> bool return not self.__eq__(right) - def get_has_code(self): + def get_has_code(self, **kwargs): # type: (...) -> int pass @@ -81,7 +81,7 @@ def __init__(self, **kwargs): self.compute_digest = kwargs.get('compute_digest', None) @classmethod - def _from_generated(self, generated): + def _from_generated(self, generated, **kwargs): # type: (Generated) -> ContentDescriptor pass @@ -95,7 +95,7 @@ def __init__(self, **kwargs): self.location = kwargs.get('location', None) @classmethod - def _from_generated(self, generated): + def _from_generated(self, generated, **kwargs): # type: (Generated) -> CreateManifestResult pass @@ -109,7 +109,7 @@ def __init__(self, **kwargs): self.upload_id = kwargs.get('upload_id', None) @classmethod - def _from_generated(self, generated): + def _from_generated(self, generated, **kwargs): # type: (Generated) -> CreateUploadResult pass @@ -184,7 +184,7 @@ def __init__(self, **kwargs): self.layers = kwargs.get('layers') @classmethod - def from_stream(self, stream): + def from_stream(self, stream, **kwargs): # type: (Stream) -> DockerManifestV2 pass @@ -216,7 +216,7 @@ def __repr__(self): # type: (...) -> str pass - def get_hash_code(self): + def get_hash_code(self, **kwargs): # type: (...) -> int pass @@ -241,20 +241,20 @@ def __init__(self, **kwargs): # NOTE: This might not be needed, could return just a dict class OCIManifestAnnotations(dict): - def __init__(self): + def __init__(self, **kwargs): # type: (...) -> None pass class RuntimePlatform(object): - def __init__(self): + def __init__(self, **kwargs): # type: (...) -> None pass class UploadStatus(object): - def __init__(self): + def __init__(self, **kwargs): self.http_range = kwargs.get('http_range', None) self.upload_id = kwargs.get('upload_id', None) \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py new file mode 100644 index 000000000000..ba3fbad75c27 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py @@ -0,0 +1,5 @@ +from ._async_container_registry_client import ContainerRegistryClient + +__all__ = [ + "ContainerRegistryClient", +] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py new file mode 100644 index 000000000000..04de6b1ff44d --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py @@ -0,0 +1,60 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + + +class ArtifactStorageClient(object): + def __init__( + self, endpoint: str, repository_name: str, credential: TokenCredential, **kwargs + ) -> None: + pass + + def cancel_upload(self, location: str, **kwargs) -> None: + pass + + def check_blob_exists(self, digest: str, **kwargs) -> bool: + pass + + def check_chunk_exists(self, digest: str, range: HttpRange, **kwargs) -> bool: + pass + + def complete_upload( + self, upload_details: CreateUploadResult, digest: str, value: Stream = None, **kwargs + ) -> None: + pass + + def create_manifest(self, manifest: ArtifactManifest, tag: str = None, **kwargs) -> None: + pass + + def create_upload(self, **kwargs) -> CreateUploadResult: + pass + + def delete(self, **kwargs) -> None: + pass + + def delete_blob(self, digest: str, **kwargs) -> Stream: + pass + + def get_blob(self, digest: str, **kwargs) -> Stream: + pass + + def get_chunk(self, digest: str, range: HttpRange, **kwargs) -> Stream: + pass + + def get_manifest( + self, tag_or_digest: str, accept_media_types: list[ManifestMediaType] = None, **kwargs + ) -> ArtifactManifest: + pass + + def get_upload_status(self, location: str, **kwargs) -> Response: + pass + + def mount_blob(self, blob_from: str, mount: str, **kwargs) -> Response: + pass + + def upload_chunk( + self, upload_details: CreateUploadResult, value: Stream, **kwargs + ) -> CreateUploadResult: + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py new file mode 100644 index 000000000000..1f1936adef83 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -0,0 +1,22 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + + +class ContainerRegistryClient(object): + def __init__(self, base_url: str, credential: TokenCredential, **kwargs): + pass + + def delete_repository(self, name: str, **kwargs) -> None: + pass + + def list_repositories(self, **kwargs) -> Pageable[str]: + pass + + def get_repository_client(self, name: str, **kwargs) -> ContainerRepositoryClient: + pass + + def get_repository_attributes(self, name: str, **kwargs) -> RepositoryAttributes: + pass From 5a16d1cdea4cfd9e22c48ec79fd5b2e15a48e4f1 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Feb 2021 16:01:01 -0500 Subject: [PATCH 08/86] fixes for apiview --- .../aio/_async_artifact_storage_client.py | 16 +++++++++++++--- .../aio/_async_container_registry_client.py | 14 ++++++++++++-- .../azure-containerregistry/setup.py | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py index 04de6b1ff44d..eb73b41ed8b0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py @@ -4,10 +4,20 @@ # Licensed under the MIT License. # ------------------------------------ +from typing import TYPE_CHECKING + +from .._models import ( + CreateUploadResult, + ArtifactManifest, + ManifestMediaType +) + +if TYPE_CHECKING: + from azure.core.async_credentials import AsyncTokenCredential class ArtifactStorageClient(object): def __init__( - self, endpoint: str, repository_name: str, credential: TokenCredential, **kwargs + self, endpoint: str, repository_name: str, credential: "AsyncTokenCredential", **kwargs ) -> None: pass @@ -17,11 +27,11 @@ def cancel_upload(self, location: str, **kwargs) -> None: def check_blob_exists(self, digest: str, **kwargs) -> bool: pass - def check_chunk_exists(self, digest: str, range: HttpRange, **kwargs) -> bool: + def check_chunk_exists(self, digest: str, range: "HttpRange", **kwargs) -> bool: pass def complete_upload( - self, upload_details: CreateUploadResult, digest: str, value: Stream = None, **kwargs + self, upload_details: CreateUploadResult, digest: str, value: "Stream" = None, **kwargs ) -> None: pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index 1f1936adef83..8b57195363cb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -4,15 +4,25 @@ # Licensed under the MIT License. # ------------------------------------ +from typing import TYPE_CHECKING + +from azure.core.async_paging import AsyncItemPaged +from .._container_repository_client import ContainerRepositoryClient +from .._models import ( + RepositoryAttributes +) + +if TYPE_CHECKING: + from azure.core.async_credentials import AsyncTokenCredential class ContainerRegistryClient(object): - def __init__(self, base_url: str, credential: TokenCredential, **kwargs): + def __init__(self, base_url: str, credential: "AsyncTokenCredential", **kwargs): pass def delete_repository(self, name: str, **kwargs) -> None: pass - def list_repositories(self, **kwargs) -> Pageable[str]: + def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: pass def get_repository_client(self, name: str, **kwargs) -> ContainerRepositoryClient: diff --git a/sdk/containerregistry/azure-containerregistry/setup.py b/sdk/containerregistry/azure-containerregistry/setup.py index 700a55ae600c..ee79dfdb4983 100644 --- a/sdk/containerregistry/azure-containerregistry/setup.py +++ b/sdk/containerregistry/azure-containerregistry/setup.py @@ -65,6 +65,8 @@ #'msrest>=0.5.0', #'msrestazure>=0.4.32,<2.0.0', #'azure-common~=1.1', + "azure-core>=1.4.0,<2.0.0", + "msrest>=0.5.0" ], extras_require={ ":python_version<'3.0'": ["azure-nspkg"], From b628b6fdadd2d0d38669d562cd45b0499c3c0334 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 8 Mar 2021 14:46:02 -0500 Subject: [PATCH 09/86] added models and clients based on feedback from arch board --- .../azure/containerregistry/__init__.py | 20 +--- .../_artifact_storage_client.py | 2 +- .../azure/containerregistry/_base_client.py | 28 ++++- .../_container_registry_authentication.py | 11 +- .../_container_registry_client.py | 55 +++++++-- ...ntainer_registry_user_credential_policy.py | 13 ++ .../_container_repository_client.py | 111 ++++++++++++++---- .../azure/containerregistry/_helpers.py | 23 ++++ .../azure/containerregistry/_models.py | 53 +++++---- .../azure/containerregistry/_user_agent.py | 10 ++ .../aio/_async_artifact_storage_client.py | 2 +- .../aio/_async_container_registry_client.py | 4 +- .../tests/test_container_registry_client.py | 32 +++++ 13 files changed, 288 insertions(+), 76 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py create mode 100644 sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 4701be16511b..858a83076e42 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -11,15 +11,11 @@ from ._container_registry_client import ContainerRegistryClient from ._container_repository_client import ContainerRepositoryClient from ._models import ( - AzureAdminUserCredential, + ContainerRegistryUserCredential, ContentPermissions, DeletedRepositoryResult, - GetManifestOptions, - GetTagOptions, - ArtifactAttributes, - ManifestOrderBy, - RepositoryAttributes, - TagAttributes, + RegistryArtifactOrderBy, + RepositoryProperties, TagOrderBy ) from ._storage_models import ( @@ -54,15 +50,11 @@ "ContainerRegistryStsClient", "ContainerRegistryClient", "ContainerRepositoryClient", - "AzureAdminUserCredential", + "ContainerRegistryUserCredential", "ContentPermissions", "DeletedRepositoryResult", - "GetManifestOptions", - "GetTagOptions", - "ArtifactAttributes", - "ManifestOrderBy", - "RepositoryAttributes", - "TagAttributes", + "RegistryArtifactOrderBy", + "RepositoryProperties", "TagOrderBy", "ArtifactManifest", "CompleteUploadResult", diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py index 63a9baaa2b01..89e3748db4b7 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py @@ -6,7 +6,7 @@ class ArtifactStorageClient(object): - def __init__(self, endpoint, repository_name, credential): + def __init__(self, endpoint, repository, credential): # type: (str, str, TokenCredential) -> None pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 9b0eb215b3b5..6def5da0ef2d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -4,6 +4,11 @@ # Licensed under the MIT License. # ------------------------------------ +from enum import Enum + +from ._generated import AzureContainerRegistry +from ._helpers import get_authentication_policy +from ._user_agent import USER_AGENT class ContainerRegistryApiVersion(str, Enum): """Container Registry API version supported by this package""" @@ -12,6 +17,25 @@ class ContainerRegistryApiVersion(str, Enum): class ContainerRegistryBaseClient(object): - def __init__(self, base_url, credential, **kwargs): + def __init__(self, endpoint, credential, **kwargs): + self._client = AzureContainerRegistry( + credential=credential, + url=endpoint, + sdk_moniker=USER_AGENT, + authentication_policy=get_authentication_policy(endpoint, credential), + **kwargs + ) + + def __enter__(self): + self._client.__enter__() + return self + + def __exit__(self, *args): + self._client.__exit__(*args) - pass + def close(self): + # type: () -> None + """Close sockets opened by the client. + Calling this method is unnecessary when using the client as a context manager. + """ + self._client.close() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py index 6e1e46536c10..8c90339aa658 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py @@ -8,8 +8,17 @@ class ContainerRegistryStsClient(object): def __init__(self, endpoint, credential, **kwargs): # type: (str, TokenCredential) -> None + """Create a ContainerRepositoryStsClient from an endpoint and a credential + + :param endpoint: An ACR endpoint + :type endpoint: str + :param credential: The credential with which to authenticate + :type credential: TokenCredential + :returns: None + :raises: None + """ pass def get_access_token(self, **kwargs): # type: (...) -> None - pass \ No newline at end of file + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 50891d688dc3..945dd1d0d8ac 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -4,29 +4,62 @@ # Licensed under the MIT License. # ------------------------------------ +from ._base_client import ContainerRegistryBaseClient -class ContainerRegistryClient(object): - def __init__(self, base_url, credential, **kwargs): +class ContainerRegistryClient(ContainerRegistryBaseClient): + def __init__(self, endpoint, credential, **kwargs): # type: (str, TokenCredential) -> None + """Create a ContainerRegistryClient from an ACR endpoint and a credential + + :param endpoint: An ACR endpoint + :type endpoint: str + :param credential: The credential with which to authenticate + :type credential: TokenCredential + :returns: None + :raises: None + """ + super(ContainerRegistryClient, self).__init__( + endpoint=endpoint, + credential=credential, + **kwargs + ) pass - def delete_repository(self, name, **kwargs): + def delete_repository(self, repository, **kwargs): # type: (str) -> DeletedRepositoryResult + """Delete a repository + :param repository: The repository to delete + :type repository: str + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ pass def list_repositories(self, **kwargs): - # type: (...) -> Pageable[str] + # type: (...) -> ItemPaged[str] + """List all repositories + :keyword max: Maximum number of repositories to return + :type max: int + :keyword last: Query parameter for the last item in previous query + :type last: str + :returns: ~azure.core.paging.ItemPaged[str] + :raises: None + """ + repos = self._client.repository.get_list( + last=kwargs.get('last', None), + n=kwargs.get('max', None) + ) pass - def get_repository_client(self, name, **kwargs): + def get_repository_client(self, repository, **kwargs): # type: (str) -> ContainerRepositoryClient + """Get a repository client - pass - - def get_repository_attributes(self, name, **kwargs): - # type: (str) -> RepositoryAttributes - - pass + :param repository: The repository to create a client for + :type repository: str + :returns: :class:~azure.containerregistry.ContainerRepositoryClient + """ + pass \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py new file mode 100644 index 000000000000..177c10025141 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py @@ -0,0 +1,13 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +# JS implementation as a guide +# https://github.com/jeremymeng/azure-sdk-for-js/commit/654bbf957c04d56004cc08102008af76f12abf59#diff-2a5770d88b7304d5683f1c8e9c358f5d783396e5b6e5e2a0ff0e2f4c6c3b7045 + + +# This will be removed before the first preview, basic auth will be disabled by the service +class ContainerRegistryUserCredentialPolicy(BaseRequestPolicy): + pass \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 87ec2713b1bf..3fe5202d2f37 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -6,54 +6,123 @@ class ContainerRepositoryClient(object): - def __init__(self, endpoint, repository_name, credential, **kwargs): + def __init__(self, endpoint, repository, credential, **kwargs): # type: (str, str, TokenCredential) -> None + """Create a ContainerRepositoryClient from an endpoint, repository name, and credential + + :param endpoint: An ACR endpoint + :type endpoint: str + :param repository: The name of a repository + :type repository: str + :param credential: The credential with which to authenticate + :type credential: TokenCredential + :returns: None + :raises: None + """ pass def delete(self): # type: (...) -> None - pass + """Delete a repository - def delete_manifest(self, name, digest): - # type: (str, str) -> None + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ pass - def delete_tag(self, name): + def delete_registry_artifact(self, digest): # type: (str) -> None + """Delete a registry artifact + + :param digest: The digest of the artifact to be deleted + :type digest: str + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ pass - def get_artifact_storage_client(self): - # type: (...) -> ArtifactStorageClient + def delete_tag(self, tag): + # type: (str) -> None + """Delete a tag + + :param tag: The digest of the artifact to be deleted + :type tag: str + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ pass - def get_attributes(self): - # type: (...) -> RepositoryAttributes + def get_properties(self): + # type: (...) -> RepositoryProperties + """Get the properties of a repository + + :returns: :class:~azure.containerregistry.RepositoryProperties + :raises: None + """ pass - def get_manifest(self, tag_or_digest): - # type: (str) -> ArtifactAttributes + def get_registry_artifact_properties(self, tag_or_digest, **kwargs): + # type: (str) -> RegistryArtifactProperties + """Get the properties of a registry artifact + + :param tag_or_digest: The tag/digest of a registry artifact + :type tag_or_digest: str + :returns: :class:~azure.containerregistry.RegistryArtifactProperties + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ pass - def get_tag(self, tag_name): - # type: (str) -> TagAttributes + def list_registry_artifacts(self, **kwargs): + # type: (...) -> ItemPaged[RegistryArtifactProperties] + """List the registry artifacts for a repository + + :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] + :raises: None + """ pass - def list_manifests(self, **kwargs): - # type: (...) -> Pageable[ArtifactAttributes] + def get_tag_properties(self, tag, **kwargs): + # type: (str) -> TagProperties + """Get the properties for a tag + + :param tag: The tag to get properties for + :type tag: str + :returns: :class:~azure.containerregistry.TagProperties + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ pass def list_tags(self, **kwargs): - # type: (...) -> Pageable[TagAttributes] + # type: (...) -> ItemPaged[TagProperties] + """List the tags for a repository + + :returns: ~azure.core.paging.ItemPaged[TagProperties] + :raises: None + """ pass - def set_manifest_permissions(self, tag_or_digest, value): + def set_manifest_properties(self, digest, value): # type: (str, ContentPermissions) -> None - pass + """Set the properties for a manifest - def set_permissions(self, value): - # type: (ContentPermissions) -> None + :param digest: Digest of a manifest + :type digest: str + :param value: The property's values to be set + :type value: ContentPermissions + :returns: ~azure.core.paging.ItemPaged[TagProperties] + :raises: None + """ pass - def set_tag_permissions(self, tag, permissions): + def set_tag_properties(self, tag, permissions): # type: (str, ContentPermissions) -> None + """Set the properties for a tag + + :param tag: Tag to set properties for + :type tag: str + :param value: The property's values to be set + :type value: ContentPermissions + :returns: ~azure.core.paging.ItemPaged[TagProperties] + :raises: None + """ pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py new file mode 100644 index 000000000000..ad180b75cafe --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py @@ -0,0 +1,23 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from azure.core.pipeline.policies import ( + BearerTokenCredentialPolicy, +) + +def get_authentication_policy(base_url, credential): + # type: (TokenCredential) -> SansIOHttpPolicy + authentication_policy = None + scope = base_url.strip("/") + "/.default" + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + if hasattr(credential, "get_token"): + authentication_policy = BearerTokenCredentialPolicy(credential, scope) + else: + raise TypeError("Please provide an instance from azure-identity " + "or a class that implement the 'get_token protocol") + + return authentication_policy \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 8ff83cdf3790..71dbc56e2804 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -11,7 +11,7 @@ ) -class AzureAdminUserCredential(object): +class ContainerRegistryUserCredential(object): def __init__(self, username, password, **kwargs): # type: (str, str) -> None self.username = username @@ -21,6 +21,10 @@ def update_password(self, password, **kwargs): # type: (str) -> None self.password = password + def update_username(self, username, **kwargs): + # type: (str) -> None + self.username = username + class ContentPermissions(object): def __init__(self, **kwargs): @@ -33,40 +37,43 @@ def __init__(self, **kwargs): class DeletedRepositoryResult(DeletedRepository): def __init__(self, **kwargs): super(DeletedRepositoryResult, self).__init__(**kwargs) + self.deleted_registry_artifact_digests = kwargs.get("deleted_registry_artifact_digests", None) + self.deleted_tags = kwargs.get("deleted_tags", None) pass -class GetManifestOptions(object): +class RegistryArtifactProperties(object): def __init__(self, **kwargs): - pass - - -class GetTagOptions(object): + self.cpu_arch = kwargs.get("arch", None) + self.created_on = kwargs.get("created_on", None) + self.digest = kwargs.get('digest', None) + self.last_updated = kwargs.get('last_updated', None) + self.manifest_properties = kwargs.get('manifest_properties', None) + self.operating_system = kwargs.get('operating_system', None) + self.registry = kwargs.get('registry', None) + self.registry_artifacts = kwargs.get('registry_artifacts', None) + self.repository = kwargs.get('repository', None) + self.size = kwargs.get('size', None) + self.tags = kwargs.get('tags', None) + + +class RepositoryProperties(object): def __init__(self, **kwargs): - pass - + self.created_on = kwargs.get('created_on', None) + self.digest = kwargs.get('digest', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.modifiable_properties = kwargs.get('modifiable_properties', None) + self.name = kwargs.get('name', None) + self.registry = kwargs.get('registry', None) + self.repository = kwargs.get('repository', None) -class ArtifactAttributes(object): - def __init__(self, **kwargs): - pass - -class ManifestOrderBy(int, Enum): +class RegistryArtifactOrderBy(int, Enum): LastUpdateTimeDescending = 0 LastUpdateTimeAscending = 1 -class RepositoryAttributes(object): - def __init__(self, **kwargs): - pass - - -class TagAttributes(object): - def __init__(self, **kwargs): - pass - - class TagOrderBy(int, Enum): LastUpdateTimeDescending = 0 diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py new file mode 100644 index 000000000000..9b1c086970d2 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py @@ -0,0 +1,10 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import sys + +from ._version import VERSION + +USER_AGENT = "azure-containerregistry/{}/{}".format(VERSION, sys.version) \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py index eb73b41ed8b0..85411f9fd0fd 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py @@ -17,7 +17,7 @@ class ArtifactStorageClient(object): def __init__( - self, endpoint: str, repository_name: str, credential: "AsyncTokenCredential", **kwargs + self, endpoint: str, repository: str, credential: "AsyncTokenCredential", **kwargs ) -> None: pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index 8b57195363cb..dcb891e156f2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING from azure.core.async_paging import AsyncItemPaged -from .._container_repository_client import ContainerRepositoryClient +from .._container_repository_client import ContainerRegistryClient from .._models import ( RepositoryAttributes ) @@ -25,7 +25,7 @@ def delete_repository(self, name: str, **kwargs) -> None: def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: pass - def get_repository_client(self, name: str, **kwargs) -> ContainerRepositoryClient: + def get_repository_client(self, name: str, **kwargs) -> ContainerRegistryClient: pass def get_repository_attributes(self, name: str, **kwargs) -> RepositoryAttributes: diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py new file mode 100644 index 000000000000..463e9d9f9c0d --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -0,0 +1,32 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import os + +from devtools_testutils import AzureTestCase + +from azure.containerregistry import ( + ContainerRegistryClient +) +from azure.identity import DefaultAzureCredential + + +class TestContainerRegistryClient(AzureTestCase): + + def _set_up(self): + return self.create_client_from_credential( + ContainerRegistryClient, + self.get_credential(ContainerRegistryClient), + endpoint=os.environ['CONTAINERREGISTRY_BASEURL'], + ) + + def test_list_repositories(self): + client = self._set_up() + + repos = 0 + for repo in client.list_repositories(): + repos += 1 + + assert repos > 0 \ No newline at end of file From b70ce9650e8c239a7a209c7c2a3c4f6133b1cac8 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 8 Mar 2021 14:49:05 -0500 Subject: [PATCH 10/86] running black to keep code clean --- .../azure/containerregistry/__init__.py | 4 +- .../containerregistry/_artifact_client.py | 1 + .../_artifact_storage_client.py | 2 +- .../azure/containerregistry/_base_client.py | 1 + .../_container_registry_authentication.py | 2 +- .../_container_registry_client.py | 10 +- ...ntainer_registry_user_credential_policy.py | 2 +- .../azure/containerregistry/_helpers.py | 9 +- .../azure/containerregistry/_models.py | 36 +++--- .../containerregistry/_storage_models.py | 115 ++++++++---------- .../azure/containerregistry/_user_agent.py | 2 +- .../aio/_async_artifact_storage_client.py | 28 +++-- .../aio/_async_container_registry_client.py | 5 +- .../azure-containerregistry/setup.py | 11 +- .../tests/test_container_registry_client.py | 9 +- 15 files changed, 113 insertions(+), 124 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 858a83076e42..c0f23f858176 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -16,7 +16,7 @@ DeletedRepositoryResult, RegistryArtifactOrderBy, RepositoryProperties, - TagOrderBy + TagOrderBy, ) from ._storage_models import ( ArtifactManifest, @@ -39,7 +39,7 @@ OCIManifest, OCIManifestAnnotations, RuntimePlatform, - UploadStatus + UploadStatus, ) from ._version import VERSION diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py index 403539bc0a77..364bcc93b2e2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py @@ -7,3 +7,4 @@ class ArtifactClient(object): def __init__(self): + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py index 89e3748db4b7..4e2571189af9 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py @@ -4,8 +4,8 @@ # Licensed under the MIT License. # ------------------------------------ -class ArtifactStorageClient(object): +class ArtifactStorageClient(object): def __init__(self, endpoint, repository, credential): # type: (str, str, TokenCredential) -> None pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 6def5da0ef2d..52c7d511e9ca 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -10,6 +10,7 @@ from ._helpers import get_authentication_policy from ._user_agent import USER_AGENT + class ContainerRegistryApiVersion(str, Enum): """Container Registry API version supported by this package""" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py index 8c90339aa658..d49f8bac04cf 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py @@ -4,8 +4,8 @@ # Licensed under the MIT License. # ------------------------------------ -class ContainerRegistryStsClient(object): +class ContainerRegistryStsClient(object): def __init__(self, endpoint, credential, **kwargs): # type: (str, TokenCredential) -> None """Create a ContainerRepositoryStsClient from an endpoint and a credential diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 945dd1d0d8ac..3fcd6013a57e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -6,6 +6,7 @@ from ._base_client import ContainerRegistryBaseClient + class ContainerRegistryClient(ContainerRegistryBaseClient): def __init__(self, endpoint, credential, **kwargs): # type: (str, TokenCredential) -> None @@ -19,9 +20,7 @@ def __init__(self, endpoint, credential, **kwargs): :raises: None """ super(ContainerRegistryClient, self).__init__( - endpoint=endpoint, - credential=credential, - **kwargs + endpoint=endpoint, credential=credential, **kwargs ) pass @@ -49,8 +48,7 @@ def list_repositories(self, **kwargs): :raises: None """ repos = self._client.repository.get_list( - last=kwargs.get('last', None), - n=kwargs.get('max', None) + last=kwargs.get("last", None), n=kwargs.get("max", None) ) pass @@ -62,4 +60,4 @@ def get_repository_client(self, repository, **kwargs): :type repository: str :returns: :class:~azure.containerregistry.ContainerRepositoryClient """ - pass \ No newline at end of file + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py index 177c10025141..2d8bbea6ab56 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py @@ -10,4 +10,4 @@ # This will be removed before the first preview, basic auth will be disabled by the service class ContainerRegistryUserCredentialPolicy(BaseRequestPolicy): - pass \ No newline at end of file + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py index ad180b75cafe..5a8f173ef8fb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py @@ -8,6 +8,7 @@ BearerTokenCredentialPolicy, ) + def get_authentication_policy(base_url, credential): # type: (TokenCredential) -> SansIOHttpPolicy authentication_policy = None @@ -17,7 +18,9 @@ def get_authentication_policy(base_url, credential): if hasattr(credential, "get_token"): authentication_policy = BearerTokenCredentialPolicy(credential, scope) else: - raise TypeError("Please provide an instance from azure-identity " - "or a class that implement the 'get_token protocol") + raise TypeError( + "Please provide an instance from azure-identity " + "or a class that implement the 'get_token protocol" + ) - return authentication_policy \ No newline at end of file + return authentication_policy diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 71dbc56e2804..10f31eb20d3e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -37,7 +37,9 @@ def __init__(self, **kwargs): class DeletedRepositoryResult(DeletedRepository): def __init__(self, **kwargs): super(DeletedRepositoryResult, self).__init__(**kwargs) - self.deleted_registry_artifact_digests = kwargs.get("deleted_registry_artifact_digests", None) + self.deleted_registry_artifact_digests = kwargs.get( + "deleted_registry_artifact_digests", None + ) self.deleted_tags = kwargs.get("deleted_tags", None) pass @@ -46,26 +48,26 @@ class RegistryArtifactProperties(object): def __init__(self, **kwargs): self.cpu_arch = kwargs.get("arch", None) self.created_on = kwargs.get("created_on", None) - self.digest = kwargs.get('digest', None) - self.last_updated = kwargs.get('last_updated', None) - self.manifest_properties = kwargs.get('manifest_properties', None) - self.operating_system = kwargs.get('operating_system', None) - self.registry = kwargs.get('registry', None) - self.registry_artifacts = kwargs.get('registry_artifacts', None) - self.repository = kwargs.get('repository', None) - self.size = kwargs.get('size', None) - self.tags = kwargs.get('tags', None) + self.digest = kwargs.get("digest", None) + self.last_updated = kwargs.get("last_updated", None) + self.manifest_properties = kwargs.get("manifest_properties", None) + self.operating_system = kwargs.get("operating_system", None) + self.registry = kwargs.get("registry", None) + self.registry_artifacts = kwargs.get("registry_artifacts", None) + self.repository = kwargs.get("repository", None) + self.size = kwargs.get("size", None) + self.tags = kwargs.get("tags", None) class RepositoryProperties(object): def __init__(self, **kwargs): - self.created_on = kwargs.get('created_on', None) - self.digest = kwargs.get('digest', None) - self.last_updated_on = kwargs.get('last_updated_on', None) - self.modifiable_properties = kwargs.get('modifiable_properties', None) - self.name = kwargs.get('name', None) - self.registry = kwargs.get('registry', None) - self.repository = kwargs.get('repository', None) + self.created_on = kwargs.get("created_on", None) + self.digest = kwargs.get("digest", None) + self.last_updated_on = kwargs.get("last_updated_on", None) + self.modifiable_properties = kwargs.get("modifiable_properties", None) + self.name = kwargs.get("name", None) + self.registry = kwargs.get("registry", None) + self.repository = kwargs.get("repository", None) class RegistryArtifactOrderBy(int, Enum): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py index 1fc4236e093e..d076bf5284f8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py @@ -4,12 +4,12 @@ # Licensed under the MIT License. # ------------------------------------ -class ArtifactManifest(object): +class ArtifactManifest(object): def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.media_type = kwargs.get('media_type', None) - self.schema_version = kwargs.get('media_version', None) + self.media_type = kwargs.get("media_type", None) + self.schema_version = kwargs.get("media_version", None) def as_docker_manifest_list(self, **kwargs): # type: (...) -> DockerManifestList @@ -37,7 +37,6 @@ def as_oci_manifest(self, **kwargs): class CompleteUploadResult(object): - def __init__(self, digest, location, http_range, **kwargs): # type: (str, str, HttpRange) self.digest = digest @@ -46,7 +45,6 @@ def __init__(self, digest, location, http_range, **kwargs): class ConfigMediaType(object): - def __init__(self): self.docker_image_v1 = None self.oci_image_config = None @@ -70,15 +68,14 @@ def __repr__(self): class ContentDescriptor(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.media_type = kwargs.get('media_type', None) - self.annotations = kwargs.get('annotations', None) - self.digest = kwargs.get('digest', None) - self.size = kwargs.get('size', None) - self.urls = kwargs.get('urls', None) - self.compute_digest = kwargs.get('compute_digest', None) + self.media_type = kwargs.get("media_type", None) + self.annotations = kwargs.get("annotations", None) + self.digest = kwargs.get("digest", None) + self.size = kwargs.get("size", None) + self.urls = kwargs.get("urls", None) + self.compute_digest = kwargs.get("compute_digest", None) @classmethod def _from_generated(self, generated, **kwargs): @@ -87,12 +84,11 @@ def _from_generated(self, generated, **kwargs): class CreateManifestResult(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.content_length = kwargs.get('content_length', None) - self.digest = kwargs.get('digest', None) - self.location = kwargs.get('location', None) + self.content_length = kwargs.get("content_length", None) + self.digest = kwargs.get("digest", None) + self.location = kwargs.get("location", None) @classmethod def _from_generated(self, generated, **kwargs): @@ -101,12 +97,11 @@ def _from_generated(self, generated, **kwargs): class CreateUploadResult(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.location = kwargs.get('location', None) - self.http_range = kwargs.get('http_range', None) - self.upload_id = kwargs.get('upload_id', None) + self.location = kwargs.get("location", None) + self.http_range = kwargs.get("http_range", None) + self.upload_id = kwargs.get("upload_id", None) @classmethod def _from_generated(self, generated, **kwargs): @@ -116,90 +111,81 @@ def _from_generated(self, generated, **kwargs): # NOTE: This might be unnecessary, Pageable[ArtifactManifest] class DockerManifestList(ArtifactManifest): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.manifests = kwargs.get('manifests', None) + self.manifests = kwargs.get("manifests", None) class DockerManifestV1(ArtifactManifest): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.architecture = kwargs.get('architecture', None) - self.fs_layers = kwargs.get('fs_layers', None) - self.history = kwargs.get('history', None) - self.name = kwargs.get('name', None) - self.signatures = kwargs.get('signatures', None) - self.tag = kwargs.get('tag', None) + self.architecture = kwargs.get("architecture", None) + self.fs_layers = kwargs.get("fs_layers", None) + self.history = kwargs.get("history", None) + self.name = kwargs.get("name", None) + self.signatures = kwargs.get("signatures", None) + self.tag = kwargs.get("tag", None) class DockerManifestV1FsLayer(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.blob_sum = kwargs.get('blob_sum', None) + self.blob_sum = kwargs.get("blob_sum", None) class DockerManifestV1History(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.v1_compatibility = kwargs.get('v1_compatibility', None) + self.v1_compatibility = kwargs.get("v1_compatibility", None) class DockerManifestV1ImageHistory(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.header = kwargs.get('header', None) - self.protected = kwargs.get('protected', None) - self.signature = kwargs.get('signature', None) + self.header = kwargs.get("header", None) + self.protected = kwargs.get("protected", None) + self.signature = kwargs.get("signature", None) class DockerManifestV1Jwk(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.alg = kwargs.get('alg', None) - self.jwk = kwargs.get('jwk', None) + self.alg = kwargs.get("alg", None) + self.jwk = kwargs.get("jwk", None) class DockerManifestV1JwkHeader(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.crv = kwargs.get('crv', None) - self.kid = kwargs.get('kid', None) - self.kty = kwargs.get('kty', None) - self.x = kwargs.get('x', None) - self.y = kwargs.get('y', None) + self.crv = kwargs.get("crv", None) + self.kid = kwargs.get("kid", None) + self.kty = kwargs.get("kty", None) + self.x = kwargs.get("x", None) + self.y = kwargs.get("y", None) class DockerManifestV2(ArtifactManifest): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.config_descriptor = kwargs.get('config_descriptor') - self.layers = kwargs.get('layers') + self.config_descriptor = kwargs.get("config_descriptor") + self.layers = kwargs.get("layers") @classmethod def from_stream(self, stream, **kwargs): # type: (Stream) -> DockerManifestV2 pass -class ManifestListAttributes(object): +class ManifestListAttributes(object): def __init__(self, **kwargs): # type: (...) -> None - self.digest = kwargs.get('digest', None) - self.media_type = kwargs.get('media_type', None) - self.platform = kwargs.get('platform', None) - self.size = kwargs.get('size', None) + self.digest = kwargs.get("digest", None) + self.media_type = kwargs.get("media_type", None) + self.platform = kwargs.get("platform", None) + self.size = kwargs.get("size", None) class ManifestMediaType(object): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None pass @@ -222,39 +208,34 @@ def get_hash_code(self, **kwargs): class OCIIndex(ArtifactManifest): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.annotations = kwargs.get('annotations', None) - self.manifests = kwargs.get('manifests', None) + self.annotations = kwargs.get("annotations", None) + self.manifests = kwargs.get("manifests", None) class OCIManifest(ArtifactManifest): - def __init__(self, **kwargs): # type: (Optional[Dict[str, Any]]) -> None - self.annotations = kwargs.get('annotations', None) - self.config_descriptor = kwargs.get('config_descriptos', None) - self.layers = kwargs.get('layers', None) + self.annotations = kwargs.get("annotations", None) + self.config_descriptor = kwargs.get("config_descriptos", None) + self.layers = kwargs.get("layers", None) # NOTE: This might not be needed, could return just a dict class OCIManifestAnnotations(dict): - def __init__(self, **kwargs): # type: (...) -> None pass class RuntimePlatform(object): - def __init__(self, **kwargs): # type: (...) -> None pass class UploadStatus(object): - def __init__(self, **kwargs): - self.http_range = kwargs.get('http_range', None) - self.upload_id = kwargs.get('upload_id', None) \ No newline at end of file + self.http_range = kwargs.get("http_range", None) + self.upload_id = kwargs.get("upload_id", None) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py index 9b1c086970d2..2eb77068ff86 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py @@ -7,4 +7,4 @@ from ._version import VERSION -USER_AGENT = "azure-containerregistry/{}/{}".format(VERSION, sys.version) \ No newline at end of file +USER_AGENT = "azure-containerregistry/{}/{}".format(VERSION, sys.version) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py index 85411f9fd0fd..101f3b53c60d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py @@ -6,18 +6,19 @@ from typing import TYPE_CHECKING -from .._models import ( - CreateUploadResult, - ArtifactManifest, - ManifestMediaType -) +from .._models import CreateUploadResult, ArtifactManifest, ManifestMediaType if TYPE_CHECKING: from azure.core.async_credentials import AsyncTokenCredential + class ArtifactStorageClient(object): def __init__( - self, endpoint: str, repository: str, credential: "AsyncTokenCredential", **kwargs + self, + endpoint: str, + repository: str, + credential: "AsyncTokenCredential", + **kwargs ) -> None: pass @@ -31,11 +32,17 @@ def check_chunk_exists(self, digest: str, range: "HttpRange", **kwargs) -> bool: pass def complete_upload( - self, upload_details: CreateUploadResult, digest: str, value: "Stream" = None, **kwargs + self, + upload_details: CreateUploadResult, + digest: str, + value: "Stream" = None, + **kwargs ) -> None: pass - def create_manifest(self, manifest: ArtifactManifest, tag: str = None, **kwargs) -> None: + def create_manifest( + self, manifest: ArtifactManifest, tag: str = None, **kwargs + ) -> None: pass def create_upload(self, **kwargs) -> CreateUploadResult: @@ -54,7 +61,10 @@ def get_chunk(self, digest: str, range: HttpRange, **kwargs) -> Stream: pass def get_manifest( - self, tag_or_digest: str, accept_media_types: list[ManifestMediaType] = None, **kwargs + self, + tag_or_digest: str, + accept_media_types: list[ManifestMediaType] = None, + **kwargs ) -> ArtifactManifest: pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index dcb891e156f2..13cf772df228 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -8,13 +8,12 @@ from azure.core.async_paging import AsyncItemPaged from .._container_repository_client import ContainerRegistryClient -from .._models import ( - RepositoryAttributes -) +from .._models import RepositoryAttributes if TYPE_CHECKING: from azure.core.async_credentials import AsyncTokenCredential + class ContainerRegistryClient(object): def __init__(self, base_url: str, credential: "AsyncTokenCredential", **kwargs): pass diff --git a/sdk/containerregistry/azure-containerregistry/setup.py b/sdk/containerregistry/azure-containerregistry/setup.py index ee79dfdb4983..368c146999d9 100644 --- a/sdk/containerregistry/azure-containerregistry/setup.py +++ b/sdk/containerregistry/azure-containerregistry/setup.py @@ -48,10 +48,10 @@ "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "License :: OSI Approved :: MIT License", ], packages=find_packages( @@ -62,14 +62,11 @@ ] ), install_requires=[ - #'msrest>=0.5.0', - #'msrestazure>=0.4.32,<2.0.0', - #'azure-common~=1.1', "azure-core>=1.4.0,<2.0.0", - "msrest>=0.5.0" + "msrest>=0.5.0", ], extras_require={ - ":python_version<'3.0'": ["azure-nspkg"], + # ":python_version<'3.0'": ["azure-nspkg"], }, project_urls={ "Bug Reports": "https://github.com/Azure/azure-sdk-for-python/issues", diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 463e9d9f9c0d..4666a20b0165 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -7,19 +7,16 @@ from devtools_testutils import AzureTestCase -from azure.containerregistry import ( - ContainerRegistryClient -) +from azure.containerregistry import ContainerRegistryClient from azure.identity import DefaultAzureCredential class TestContainerRegistryClient(AzureTestCase): - def _set_up(self): return self.create_client_from_credential( ContainerRegistryClient, self.get_credential(ContainerRegistryClient), - endpoint=os.environ['CONTAINERREGISTRY_BASEURL'], + endpoint=os.environ["CONTAINERREGISTRY_BASEURL"], ) def test_list_repositories(self): @@ -29,4 +26,4 @@ def test_list_repositories(self): for repo in client.list_repositories(): repos += 1 - assert repos > 0 \ No newline at end of file + assert repos > 0 From 2bedabe1dc1131754ca7035bd0691d5451cb3da1 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 9 Mar 2021 14:33:31 -0500 Subject: [PATCH 11/86] more changes to auth --- .../azure/containerregistry/_base_client.py | 6 +++++- .../tests/test_container_registry_client.py | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 52c7d511e9ca..f1339eb9fd9a 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -6,6 +6,10 @@ from enum import Enum +from azure.core.pipeline.policies import ( + BearerTokenCredentialPolicy, +) + from ._generated import AzureContainerRegistry from ._helpers import get_authentication_policy from ._user_agent import USER_AGENT @@ -23,7 +27,7 @@ def __init__(self, endpoint, credential, **kwargs): credential=credential, url=endpoint, sdk_moniker=USER_AGENT, - authentication_policy=get_authentication_policy(endpoint, credential), + authentication_policy=BearerTokenCredentialPolicy, **kwargs ) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 4666a20b0165..a8fdaed76be9 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -13,10 +13,13 @@ class TestContainerRegistryClient(AzureTestCase): def _set_up(self): + self.endpoint = os.environ["CONTAINERREGISTRY_BASEURL"] + if not self.endpoint.startswith("https://"): + self.endpoint = "https://" + self.endpoint return self.create_client_from_credential( ContainerRegistryClient, self.get_credential(ContainerRegistryClient), - endpoint=os.environ["CONTAINERREGISTRY_BASEURL"], + endpoint=self.endpoint, ) def test_list_repositories(self): From fa6f78ec03bf3d3872e3cd3e68d22998e1af2809 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 9 Mar 2021 16:04:54 -0500 Subject: [PATCH 12/86] have a basic pipeline --- .../azure/containerregistry/_base_client.py | 3 +- ...egistry_client.test_list_repositories.yaml | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index f1339eb9fd9a..71dc53e441a4 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -27,7 +27,8 @@ def __init__(self, endpoint, credential, **kwargs): credential=credential, url=endpoint, sdk_moniker=USER_AGENT, - authentication_policy=BearerTokenCredentialPolicy, + # authentication_policy=BearerTokenCredentialPolicy, + credential_scopes=kwargs.pop("credential_scopes", "https://dev.azurecr.io/.default"), **kwargs ) diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml new file mode 100644 index 000000000000..bc32aa0a73fa --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -0,0 +1,50 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://seankane.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '196' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 09 Mar 2021 21:03:07 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="malformed_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +version: 1 From 514d03b0bdf9af3f1bf30cdcf2685dbfb24711e9 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 10 Mar 2021 08:00:07 -0500 Subject: [PATCH 13/86] added an auth policy for username & password --- .../azure/containerregistry/__init__.py | 6 +++ .../_authentication_policy.py | 48 +++++++++++++++++++ .../azure/containerregistry/_base_client.py | 8 +++- .../_container_registry_client.py | 8 ++++ ...egistry_client.test_list_repositories.yaml | 6 +-- .../tests/test_container_registry_client.py | 39 ++++++++++----- 6 files changed, 98 insertions(+), 17 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index c0f23f858176..5610e6e7d501 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -41,6 +41,10 @@ RuntimePlatform, UploadStatus, ) +from ._authentication_policy import ( + ContainerRegistryUserCredential, + ContainerRegistryUserCredentialPolicy, +) from ._version import VERSION __version__ = VERSION @@ -77,4 +81,6 @@ "OCIManifestAnnotations", "RuntimePlatform", "UploadStatus", + "ContainerRegistryUserCredential", + "ContainerRegistryUserCredentialPolicy", ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py new file mode 100644 index 000000000000..e312dae01a51 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -0,0 +1,48 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from base64 import b64encode + +from azure.core.pipeline.policies import SansIOHTTPPolicy + +class ContainerRegistryUserCredential(object): + """Credential used to authenticate with Container Registry service""" + def __init__(self, username, password): + self._user = username + self._password = password + + def get_token(self): + token = "{}:{}".format(self._user, self._password) + token = bytes(token, "utf-8") + return str(b64encode(token)) + + +class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): + """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" + def __init__(self, credential): + self.credential = credential + + def _enforce_https(self, request): + # Copied from BearerTokenCredentialPolicy + option = request.context.options.pop("enforce_https", None) + + if option is False: + request.context["enforce_https"] = option + + enforce_https = request.context.get("enforce_https", True) + if enforce_https and not request.http_request.url.lower().startswith("https"): + raise Exception( + "Auth is not permitted for non-TLS protected (non-https) URLs." + ) + + @staticmethod + def _update_headers(headers, token): + headers["Authorization"] = "Basic {}".format(token) + + def on_request(self, request): + # type: (PipelineRequest) -> None + # self._enforce_https(request) + self._update_headers(request.http_request.headers, self.credential.get_token()) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 71dc53e441a4..0c52b1fda497 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -10,6 +10,7 @@ BearerTokenCredentialPolicy, ) +from ._authentication_policy import ContainerRegistryUserCredentialPolicy from ._generated import AzureContainerRegistry from ._helpers import get_authentication_policy from ._user_agent import USER_AGENT @@ -23,12 +24,15 @@ class ContainerRegistryApiVersion(str, Enum): class ContainerRegistryBaseClient(object): def __init__(self, endpoint, credential, **kwargs): + auth_policy = ContainerRegistryUserCredentialPolicy( + credential=credential + ) self._client = AzureContainerRegistry( credential=credential, url=endpoint, sdk_moniker=USER_AGENT, - # authentication_policy=BearerTokenCredentialPolicy, - credential_scopes=kwargs.pop("credential_scopes", "https://dev.azurecr.io/.default"), + authentication_policy=auth_policy, + credential_scopes=kwargs.pop("credential_scopes", ["https://dev.azurecr.io/.default"]), **kwargs ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 3fcd6013a57e..f5ffea6faec9 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -3,6 +3,9 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import functools + +from azure.core.paging import ItemPaged from ._base_client import ContainerRegistryBaseClient @@ -47,9 +50,14 @@ def list_repositories(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[str] :raises: None """ + command = functools.partial(self._client.repository.get_list, **kwargs) repos = self._client.repository.get_list( last=kwargs.get("last", None), n=kwargs.get("max", None) ) + return ItemPaged( + command + # page_iterator_class=s + ) pass def get_repository_client(self, repository, **kwargs): diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index bc32aa0a73fa..dc67d47781b0 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -12,7 +12,7 @@ interactions: - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://seankane.azurecr.io/acr/v1/_catalog + uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, @@ -32,7 +32,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Tue, 09 Mar 2021 21:03:07 GMT + - Wed, 10 Mar 2021 12:59:24 GMT docker-distribution-api-version: - registry/2.0 server: @@ -41,7 +41,7 @@ interactions: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="malformed_token" + - Basic realm="Azure Container Registry" x-content-type-options: - nosniff status: diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index a8fdaed76be9..9d6b93bf5f58 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -3,27 +3,42 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import functools import os -from devtools_testutils import AzureTestCase +from devtools_testutils import AzureTestCase, PowerShellPreparer -from azure.containerregistry import ContainerRegistryClient +from azure.containerregistry import ContainerRegistryClient, ContainerRegistryUserCredential from azure.identity import DefaultAzureCredential +acr_preparer = functools.partial( + PowerShellPreparer, + "containerregistry", + containerregistry_baseurl="fake_url.azurecr.io", +) + + class TestContainerRegistryClient(AzureTestCase): - def _set_up(self): - self.endpoint = os.environ["CONTAINERREGISTRY_BASEURL"] - if not self.endpoint.startswith("https://"): - self.endpoint = "https://" + self.endpoint - return self.create_client_from_credential( - ContainerRegistryClient, - self.get_credential(ContainerRegistryClient), - endpoint=self.endpoint, + def set_up(self, endpoint): + if not endpoint.startswith("https://"): + endpoint = "https://" + endpoint + # return self.create_client_from_credential( + # ContainerRegistryClient, + # self.get_credential(ContainerRegistryClient), + # endpoint=endpoint, + # ) + return ContainerRegistryClient( + endpoint = endpoint, + credential=ContainerRegistryUserCredential( + username=os.environ["CONTAINERREGISTRY_USERNAME"], + password=os.environ["CONTAINERREGISTRY_PASSWORD"] + ) ) - def test_list_repositories(self): - client = self._set_up() + @acr_preparer() + def test_list_repositories(self, containerregistry_baseurl): + client = self.set_up(containerregistry_baseurl) repos = 0 for repo in client.list_repositories(): From 4063d4d5a456486e3d1d1cff60078baa1bf610b2 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 10 Mar 2021 08:14:58 -0500 Subject: [PATCH 14/86] have a working auth policy --- .../containerregistry/_authentication_policy.py | 7 ++++--- ...iner_registry_client.test_list_repositories.yaml | 13 +++++-------- .../tests/test_container_registry_client.py | 1 + 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index e312dae01a51..b2aef8d7d75d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -15,9 +15,10 @@ def __init__(self, username, password): self._password = password def get_token(self): - token = "{}:{}".format(self._user, self._password) - token = bytes(token, "utf-8") - return str(b64encode(token)) + token_str = "{}:{}".format(self._user, self._password) + token_bytes = token_str.encode("ascii") + b64_bytes = b64encode(token_bytes) + return b64_bytes.decode("ascii") class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index dc67d47781b0..e0696062a8cc 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -15,8 +15,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + string: '{"repositories":["debian","hello-world"]} ' headers: @@ -28,11 +27,11 @@ interactions: connection: - keep-alive content-length: - - '196' + - '42' content-type: - application/json; charset=utf-8 date: - - Wed, 10 Mar 2021 12:59:24 GMT + - Wed, 10 Mar 2021 13:14:29 GMT docker-distribution-api-version: - registry/2.0 server: @@ -40,11 +39,9 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Basic realm="Azure Container Registry" x-content-type-options: - nosniff status: - code: 401 - message: Unauthorized + code: 200 + message: OK version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 9d6b93bf5f58..e300fa721b4b 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -28,6 +28,7 @@ def set_up(self, endpoint): # self.get_credential(ContainerRegistryClient), # endpoint=endpoint, # ) + print(os.environ["CONTAINERREGISTRY_PASSWORD"]) return ContainerRegistryClient( endpoint = endpoint, credential=ContainerRegistryUserCredential( From c2805208074dea9326d93f9ac00893043c7740ec Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 10 Mar 2021 10:45:19 -0500 Subject: [PATCH 15/86] need to add a page iterator class for returned repositories --- .../azure/containerregistry/_container_registry_client.py | 2 ++ ..._container_registry_client.test_list_repositories.yaml | 2 +- .../tests/test_container_registry_client.py | 8 -------- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index f5ffea6faec9..dad03543869c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -22,6 +22,8 @@ def __init__(self, endpoint, credential, **kwargs): :returns: None :raises: None """ + if not endpoint.startswith("https://"): + endpoint = "https://" + endpoint super(ContainerRegistryClient, self).__init__( endpoint=endpoint, credential=credential, **kwargs ) diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index e0696062a8cc..1d7729e58614 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 10 Mar 2021 13:14:29 GMT + - Wed, 10 Mar 2021 15:44:37 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index e300fa721b4b..7536545b74bf 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -21,14 +21,6 @@ class TestContainerRegistryClient(AzureTestCase): def set_up(self, endpoint): - if not endpoint.startswith("https://"): - endpoint = "https://" + endpoint - # return self.create_client_from_credential( - # ContainerRegistryClient, - # self.get_credential(ContainerRegistryClient), - # endpoint=endpoint, - # ) - print(os.environ["CONTAINERREGISTRY_PASSWORD"]) return ContainerRegistryClient( endpoint = endpoint, credential=ContainerRegistryUserCredential( From 4a9cc33fc9dada011e13e5697b59b698140f249b Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 10 Mar 2021 12:08:53 -0500 Subject: [PATCH 16/86] working list tags and list repositories methods --- .../azure/containerregistry/__init__.py | 2 - .../_container_registry_client.py | 19 +++++--- .../_container_repository_client.py | 17 +++++-- .../azure/containerregistry/_models.py | 25 ++++------ ...egistry_client.test_list_repositories.yaml | 2 +- ...iner_repository_client.test_list_tags.yaml | 47 +++++++++++++++++++ .../tests/test_container_registry_client.py | 9 ++-- .../tests/test_container_repository_client.py | 43 +++++++++++++++++ 8 files changed, 131 insertions(+), 33 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 5610e6e7d501..e10e196e32df 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -11,7 +11,6 @@ from ._container_registry_client import ContainerRegistryClient from ._container_repository_client import ContainerRepositoryClient from ._models import ( - ContainerRegistryUserCredential, ContentPermissions, DeletedRepositoryResult, RegistryArtifactOrderBy, @@ -54,7 +53,6 @@ "ContainerRegistryStsClient", "ContainerRegistryClient", "ContainerRepositoryClient", - "ContainerRegistryUserCredential", "ContentPermissions", "DeletedRepositoryResult", "RegistryArtifactOrderBy", diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index dad03543869c..1f242ec81463 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -8,6 +8,7 @@ from azure.core.paging import ItemPaged from ._base_client import ContainerRegistryBaseClient +from ._models import RepositoryProperties class ContainerRegistryClient(ContainerRegistryBaseClient): @@ -24,6 +25,7 @@ def __init__(self, endpoint, credential, **kwargs): """ if not endpoint.startswith("https://"): endpoint = "https://" + endpoint + self.credential = credential super(ContainerRegistryClient, self).__init__( endpoint=endpoint, credential=credential, **kwargs ) @@ -52,15 +54,16 @@ def list_repositories(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[str] :raises: None """ - command = functools.partial(self._client.repository.get_list, **kwargs) + # command = functools.partial(self._client.repository.get_list, **kwargs) repos = self._client.repository.get_list( last=kwargs.get("last", None), n=kwargs.get("max", None) ) - return ItemPaged( - command - # page_iterator_class=s - ) - pass + return RepositoryProperties.from_generated(repos) + # return ItemPaged( + # command, + # page_iterator_class=RepositoryPropertiesPaged + # ) + # pass def get_repository_client(self, repository, **kwargs): # type: (str) -> ContainerRepositoryClient @@ -70,4 +73,8 @@ def get_repository_client(self, repository, **kwargs): :type repository: str :returns: :class:~azure.containerregistry.ContainerRepositoryClient """ + return ContainerRepositoryClient( + repository, + credential = self.credential, + ) pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 3fe5202d2f37..3b772f18592f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -4,8 +4,9 @@ # Licensed under the MIT License. # ------------------------------------ +from ._base_client import ContainerRegistryBaseClient -class ContainerRepositoryClient(object): +class ContainerRepositoryClient(ContainerRegistryBaseClient): def __init__(self, endpoint, repository, credential, **kwargs): # type: (str, str, TokenCredential) -> None """Create a ContainerRepositoryClient from an endpoint, repository name, and credential @@ -19,7 +20,14 @@ def __init__(self, endpoint, repository, credential, **kwargs): :returns: None :raises: None """ - pass + if not endpoint.startswith("https://"): + endpoint = "https://" + endpoint + self.endpoint = endpoint + self.repository = repository + super(ContainerRepositoryClient, self).__init__( + endpoint=self.endpoint, credential=credential, **kwargs + ) + def delete(self): # type: (...) -> None @@ -99,7 +107,10 @@ def list_tags(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[TagProperties] :raises: None """ - pass + tags = self._client.repository.get_attributes( + self.repository, **kwargs + ) + return tags def set_manifest_properties(self, digest, value): # type: (str, ContentPermissions) -> None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 10f31eb20d3e..c701e7de763f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -6,26 +6,12 @@ from enum import Enum +from azure.core.paging import PageIterator + from ._generated.models import ( DeletedRepository, ) - -class ContainerRegistryUserCredential(object): - def __init__(self, username, password, **kwargs): - # type: (str, str) -> None - self.username = username - self.password = password - - def update_password(self, password, **kwargs): - # type: (str) -> None - self.password = password - - def update_username(self, username, **kwargs): - # type: (str) -> None - self.username = username - - class ContentPermissions(object): def __init__(self, **kwargs): self.delete = kwargs.get("delete") @@ -60,7 +46,8 @@ def __init__(self, **kwargs): class RepositoryProperties(object): - def __init__(self, **kwargs): + def __init__(self, repositories, **kwargs): + self._repositories = repositories self.created_on = kwargs.get("created_on", None) self.digest = kwargs.get("digest", None) self.last_updated_on = kwargs.get("last_updated_on", None) @@ -69,6 +56,10 @@ def __init__(self, **kwargs): self.registry = kwargs.get("registry", None) self.repository = kwargs.get("repository", None) + @classmethod + def from_generated(cls, generated): + return cls(generated.names) + class RegistryArtifactOrderBy(int, Enum): diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index 1d7729e58614..69ceee59a26d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 10 Mar 2021 15:44:37 GMT + - Wed, 10 Mar 2021 16:53:45 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml new file mode 100644 index 000000000000..b6f4d0d16ae2 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-03T13:06:08.1190646Z","lastUpdateTime":"2021-03-03T13:06:08.2369442Z","manifestCount":1,"tagCount":1,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '289' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 10 Mar 2021 17:08:02 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 7536545b74bf..2ab0beae7c69 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -33,8 +33,9 @@ def set_up(self, endpoint): def test_list_repositories(self, containerregistry_baseurl): client = self.set_up(containerregistry_baseurl) - repos = 0 - for repo in client.list_repositories(): - repos += 1 + repos = client.list_repositories() + count = 0 + for repo in repos._repositories: + count += 1 - assert repos > 0 + assert count > 0 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py new file mode 100644 index 000000000000..9c1b36c80044 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -0,0 +1,43 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools +import os + +from devtools_testutils import AzureTestCase, PowerShellPreparer + +from azure.containerregistry import ContainerRepositoryClient, ContainerRegistryUserCredential +from azure.identity import DefaultAzureCredential + + +acr_preparer = functools.partial( + PowerShellPreparer, + "containerregistry", + containerregistry_baseurl="fake_url.azurecr.io", +) + + +class TestContainerRepositoryClient(AzureTestCase): + def set_up(self, endpoint): + return ContainerRepositoryClient( + endpoint=endpoint, + repository="hello-world", + credential=ContainerRegistryUserCredential( + username=os.environ["CONTAINERREGISTRY_USERNAME"], + password=os.environ["CONTAINERREGISTRY_PASSWORD"] + ) + ) + + @acr_preparer() + def test_list_tags(self, containerregistry_baseurl): + client = self.set_up(containerregistry_baseurl) + + repos = client.list_tags() + count = 0 + # for repo in repos._repositories: + # count += 1 + print(repos) + + # assert count > 0 From 5e2270cc190e5560391ff9a2bf156793b89d1b91 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 10 Mar 2021 16:34:22 -0500 Subject: [PATCH 17/86] adding a change to the tests.yml file to run in live mode once I get there --- sdk/containerregistry/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/containerregistry/tests.yml b/sdk/containerregistry/tests.yml index f3215b43e4d5..b95787fd918f 100644 --- a/sdk/containerregistry/tests.yml +++ b/sdk/containerregistry/tests.yml @@ -11,4 +11,6 @@ stages: AZURE_CLIENT_ID: $(aad-azure-sdk-test-client-id) AZURE_CLIENT_SECRET: $(aad-azure-sdk-test-client-secret) AZURE_TENANT_ID: $(aad-azure-sdk-test-tenant-id) - TEST_MODE: 'RunLiveNoRecord' \ No newline at end of file + TEST_MODE: 'RunLiveNoRecord' + AZURE_TEST_RUN_LIVE: 'true' + AZURE_SKIP_LIVE_RECORDING: 'True' \ No newline at end of file From b2ba50f2b84becd71512d96ecbc23224294eae11 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 15 Mar 2021 20:01:27 -0400 Subject: [PATCH 18/86] added more methods --- .../azure/containerregistry/_base_client.py | 2 +- .../_container_registry_client.py | 2 +- .../_container_repository_client.py | 34 ++++++++---- .../azure/containerregistry/_models.py | 53 ++++++++++++++++--- ...y_client.test_list_registry_artifacts.yaml | 47 ++++++++++++++++ .../tests/test_container_repository_client.py | 19 +++++++ 6 files changed, 139 insertions(+), 18 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 0c52b1fda497..6e7b5da3dbe0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -32,7 +32,7 @@ def __init__(self, endpoint, credential, **kwargs): url=endpoint, sdk_moniker=USER_AGENT, authentication_policy=auth_policy, - credential_scopes=kwargs.pop("credential_scopes", ["https://dev.azurecr.io/.default"]), + credential_scopes=kwargs.pop("credential_scopes", ["https://management.core.windows.net/.default"]), **kwargs ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 1f242ec81463..2715ab379053 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -75,6 +75,6 @@ def get_repository_client(self, repository, **kwargs): """ return ContainerRepositoryClient( repository, - credential = self.credential, + credential=self.credential, ) pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 3b772f18592f..707299098fd1 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -5,6 +5,8 @@ # ------------------------------------ from ._base_client import ContainerRegistryBaseClient +from ._models import RepositoryProperties + class ContainerRepositoryClient(ContainerRegistryBaseClient): def __init__(self, endpoint, repository, credential, **kwargs): @@ -67,7 +69,8 @@ def get_properties(self): :returns: :class:~azure.containerregistry.RepositoryProperties :raises: None """ - pass + resp = self._client.repository.get_attributes(self.repository) + return RepositoryProperties.from_generated(resp) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): # type: (str) -> RegistryArtifactProperties @@ -80,15 +83,6 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): """ pass - def list_registry_artifacts(self, **kwargs): - # type: (...) -> ItemPaged[RegistryArtifactProperties] - """List the registry artifacts for a repository - - :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] - :raises: None - """ - pass - def get_tag_properties(self, tag, **kwargs): # type: (str) -> TagProperties """Get the properties for a tag @@ -100,6 +94,26 @@ def get_tag_properties(self, tag, **kwargs): """ pass + def list_registry_artifacts(self, **kwargs): + # type: (...) -> ItemPaged[RegistryArtifactProperties] + """List the registry artifacts for a repository + + :keyword last: Query parameter for the last item in the previous query + :type last: str + :keyword n: Max number of items to be returned + :type n: int + :keyword orderby: Order by query parameter + :type orderby: :class:~azure.containerregistry.RegistryArtifactOrderBy + :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] + :raises: None + """ + + return self._client.manifests.get_list( + self.repository, + last=kwargs.get("last", None), + n=kwargs.get("n", None), + orderby=kwargs.get("orderby")) + def list_tags(self, **kwargs): # type: (...) -> ItemPaged[TagProperties] """List the tags for a repository diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index c701e7de763f..c3c040787d49 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -19,6 +19,16 @@ def __init__(self, **kwargs): self.read = kwargs.get("read") self.write = kwargs.get("write") + @classmethod + def from_generated(cls, generated): + # type: (azure.containerregistry._generated.models.ChangeableAttributes) -> ContentPermissions + return cls( + delete=generated.delete_enabled, + list=generated.list_enabled, + read=generated.read_enabled, + write=generated.write_enabled + ) + class DeletedRepositoryResult(DeletedRepository): def __init__(self, **kwargs): @@ -46,19 +56,50 @@ def __init__(self, **kwargs): class RepositoryProperties(object): - def __init__(self, repositories, **kwargs): - self._repositories = repositories - self.created_on = kwargs.get("created_on", None) - self.digest = kwargs.get("digest", None) - self.last_updated_on = kwargs.get("last_updated_on", None) + """Model for storing properties of a single repository + + :ivar created_time: Time the repository was created + :vartype created_time: str + :ivar last_updated_time: Time the repository was last updated + :vartype last_updated_time: str + :ivar modifiable_properties: Read/Write/Update/Delete permissions for the repository + :vartype modifiable_properties: ContentPermissions + :ivar name: Name of the repository + :vartype name: str + :ivar registry: Registry the repository belongs to + :vartype registry: str + :ivar digest: The digest of the repository + :vartype digest: str + :ivar tag_count: Number of tags associated with the repository + :vartype tag_count: int + :ivar manifest_count: Number of manifest in the repository + :vartype manifest_count: int + """ + + def __init__(self, **kwargs): + self.created_time = kwargs.get("created_time", None) + self.last_updated_time = kwargs.get("last_updated_time", None) self.modifiable_properties = kwargs.get("modifiable_properties", None) self.name = kwargs.get("name", None) self.registry = kwargs.get("registry", None) self.repository = kwargs.get("repository", None) + self.digest = kwargs.get("digest", None) + self.tag_count = kwargs.get("tag_count", None) + self.manifest_count = kwargs.get("manifest_count", None) @classmethod def from_generated(cls, generated): - return cls(generated.names) + # type: (azure.containerregistry._generated.models.RepositoryAttributes) -> RepositoryProperties + return cls( + created_time=generated.created_time, + name=generated.image_name, + last_updated_time=generated.last_updated_time, + registry=generated.registry, + manifest_count=generated.manifest_count, + tag_count=generated.tag_count, + content_permissions=generated.changeable_attributes + ) + return cls(generated) class RegistryArtifactOrderBy(int, Enum): diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml new file mode 100644 index 000000000000..4a14f81675f3 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-03T13:06:08.1768035Z","lastUpdateTime":"2021-03-03T13:06:08.1768035Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '589' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 16 Mar 2021 00:01:12 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 9c1b36c80044..f58183cda105 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -41,3 +41,22 @@ def test_list_tags(self, containerregistry_baseurl): print(repos) # assert count > 0 + + @acr_preparer() + def test_get_attributes(self, containerregistry_baseurl): + client = self.set_up(containerregistry_baseurl) + + repo_attribs = client.get_properties() + + assert repo_attribs is not None + assert repo_attribs.content_permissions is not None + + @acr_preparer() + def test_list_registry_artifacts(self, containerregistry_baseurl): + client = self.set_up(containerregistry_baseurl) + + repo_attribs = client.list_registry_artifacts() + + print(repo_attribs) + + From fb4189f4bfc051116e414050496c747f956b82b7 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 16 Mar 2021 12:18:28 -0400 Subject: [PATCH 19/86] adding test infra --- .../_container_repository_client.py | 26 ++++++---- .../azure/containerregistry/_models.py | 38 +++++++++----- .../tests/_shared/testcase.py | 32 ++++++++++++ ...ository_client.test_delete_repository.yaml | 50 +++++++++++++++++++ ...epository_client.test_get_attributes.yaml} | 8 +-- ...iner_repository_client.test_list_tags.yaml | 2 +- .../tests/test_container_registry_client.py | 19 +++---- .../tests/test_container_repository_client.py | 44 ++++++++++------ sdk/containerregistry/test-resources-post.ps1 | 5 ++ 9 files changed, 171 insertions(+), 53 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml rename sdk/containerregistry/azure-containerregistry/tests/recordings/{test_container_repository_client.test_list_registry_artifacts.yaml => test_container_repository_client.test_get_attributes.yaml} (62%) create mode 100644 sdk/containerregistry/test-resources-post.ps1 diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 707299098fd1..0df5d5f0e0dc 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -31,14 +31,15 @@ def __init__(self, endpoint, repository, credential, **kwargs): ) - def delete(self): + def delete(self, **kwargs): # type: (...) -> None """Delete a repository :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - pass + self._client.repository.delete(self.repository, **kwargs) + # raise NotImplementedError("Has not been implemented") def delete_registry_artifact(self, digest): # type: (str) -> None @@ -49,7 +50,7 @@ def delete_registry_artifact(self, digest): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - pass + raise NotImplementedError("Has not been implemented") def delete_tag(self, tag): # type: (str) -> None @@ -60,7 +61,7 @@ def delete_tag(self, tag): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - pass + raise NotImplementedError("Has not been implemented") def get_properties(self): # type: (...) -> RepositoryProperties @@ -81,7 +82,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :returns: :class:~azure.containerregistry.RegistryArtifactProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - pass + raise NotImplementedError("Has not been implemented") def get_tag_properties(self, tag, **kwargs): # type: (str) -> TagProperties @@ -92,7 +93,7 @@ def get_tag_properties(self, tag, **kwargs): :returns: :class:~azure.containerregistry.TagProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - pass + return self._client.tag.get_attributes() def list_registry_artifacts(self, **kwargs): # type: (...) -> ItemPaged[RegistryArtifactProperties] @@ -107,12 +108,15 @@ def list_registry_artifacts(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] :raises: None """ - - return self._client.manifests.get_list( + # TODO: turn this into an ItemPaged + artifacts = self._client.manifests.get_list( self.repository, last=kwargs.get("last", None), n=kwargs.get("n", None), - orderby=kwargs.get("orderby")) + orderby=kwargs.get("orderby"))#, + # cls=lambda objs: [RegistryArtifacts.from_generated(x) for x in objs]) + + return RegistryArtifactProperties.from_generated(artifacts) def list_tags(self, **kwargs): # type: (...) -> ItemPaged[TagProperties] @@ -137,7 +141,7 @@ def set_manifest_properties(self, digest, value): :returns: ~azure.core.paging.ItemPaged[TagProperties] :raises: None """ - pass + raise NotImplementedError("Has not been implemented") def set_tag_properties(self, tag, permissions): # type: (str, ContentPermissions) -> None @@ -150,4 +154,4 @@ def set_tag_properties(self, tag, permissions): :returns: ~azure.core.paging.ItemPaged[TagProperties] :raises: None """ - pass + raise NotImplementedError("Has not been implemented") diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index c3c040787d49..361e1f2df2b7 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -42,17 +42,31 @@ def __init__(self, **kwargs): class RegistryArtifactProperties(object): def __init__(self, **kwargs): - self.cpu_arch = kwargs.get("arch", None) - self.created_on = kwargs.get("created_on", None) - self.digest = kwargs.get("digest", None) - self.last_updated = kwargs.get("last_updated", None) - self.manifest_properties = kwargs.get("manifest_properties", None) - self.operating_system = kwargs.get("operating_system", None) + self.created_time = kwargs.get("created_time", None) + self.image_name = kwargs.get("image_name", None) self.registry = kwargs.get("registry", None) - self.registry_artifacts = kwargs.get("registry_artifacts", None) - self.repository = kwargs.get("repository", None) - self.size = kwargs.get("size", None) - self.tags = kwargs.get("tags", None) + self.manifest_properties = ManifestProperties.from_generated(kwargs.get("manifest_attributes")) + + # self.cpu_arch = kwargs.get("arch", None) + # self.digest = kwargs.get("digest", None) + # self.last_updated = kwargs.get("last_updated", None) + # self.manifest_properties = kwargs.get("manifest_properties", None) + # self.operating_system = kwargs.get("operating_system", None) + # self.registry = kwargs.get("registry", None) + # self.registry_artifacts = kwargs.get("registry_artifacts", None) + # self.repository = kwargs.get("repository", None) + # self.size = kwargs.get("size", None) + # self.tags = kwargs.get("tags", None) + + @classmethod + def from_generated(cls, generated): + # type: (azure.containerregistry._generated.models.ManfiestAttributestBase) -> RegistryArtifactProperties + cls( + created_time=generated.created_time, + image_name=generated.image_name, + registry=generated.registry, + manifest_attributes=generated.manifest_attributes, + ) class RepositoryProperties(object): @@ -82,10 +96,10 @@ def __init__(self, **kwargs): self.modifiable_properties = kwargs.get("modifiable_properties", None) self.name = kwargs.get("name", None) self.registry = kwargs.get("registry", None) - self.repository = kwargs.get("repository", None) - self.digest = kwargs.get("digest", None) self.tag_count = kwargs.get("tag_count", None) self.manifest_count = kwargs.get("manifest_count", None) + # self.repository = kwargs.get("repository", None) + # self.digest = kwargs.get("digest", None) @classmethod def from_generated(cls, generated): diff --git a/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py new file mode 100644 index 000000000000..537cb0184f77 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py @@ -0,0 +1,32 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import os + +from azure.containerregistry import ( + ContainerRepositoryClient, + ContainerRegistryClient, + ContainerRegistryUserCredential, +) + +class ContainerRegistryTestClass(object): + def create_registry_client(self, endpoint): + return ContainerRegistryClient( + endpoint=containerregistry_baseurl, + credential=ContainerRegistryUserCredential( + username=os.environ["CONTAINERREGISTRY_USERNAME"], + password=os.environ["CONTAINERREGISTRY_PASSWORD"], + ), + ) + + def create_repository_client(self, endpoint, name): + return ContainerRepositoryClient( + endpoint=endpoint, + repository=name, + credential=ContainerRegistryUserCredential( + username=os.environ["CONTAINERREGISTRY_USERNAME"], + password=os.environ["CONTAINERREGISTRY_PASSWORD"], + ), + ) diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml new file mode 100644 index 000000000000..eccb8c9ed4a1 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml @@ -0,0 +1,50 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"hello-world"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '119' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 16 Mar 2021 14:58:42 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 404 + message: Not Found +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml similarity index 62% rename from sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml rename to sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml index 4a14f81675f3..652bdb6dacaf 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -12,10 +12,10 @@ interactions: - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + uri: https://fake_url.azurecr.io/acr/v1/hello-world response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-03T13:06:08.1768035Z","lastUpdateTime":"2021-03-03T13:06:08.1768035Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-03T13:06:08.1190646Z","lastUpdateTime":"2021-03-03T13:06:08.2369442Z","manifestCount":1,"tagCount":1,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} ' headers: @@ -27,11 +27,11 @@ interactions: connection: - keep-alive content-length: - - '589' + - '289' content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 00:01:12 GMT + - Tue, 16 Mar 2021 12:30:22 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index b6f4d0d16ae2..c1f456d93a33 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 10 Mar 2021 17:08:02 GMT + - Tue, 16 Mar 2021 14:51:19 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 2ab0beae7c69..0ab094fd25cf 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -8,9 +8,14 @@ from devtools_testutils import AzureTestCase, PowerShellPreparer -from azure.containerregistry import ContainerRegistryClient, ContainerRegistryUserCredential +from azure.containerregistry import ( + ContainerRegistryClient, + ContainerRegistryUserCredential, +) from azure.identity import DefaultAzureCredential +from _shared.testcase import ContainerRegistryTestClass + acr_preparer = functools.partial( PowerShellPreparer, @@ -19,19 +24,11 @@ ) -class TestContainerRegistryClient(AzureTestCase): - def set_up(self, endpoint): - return ContainerRegistryClient( - endpoint = endpoint, - credential=ContainerRegistryUserCredential( - username=os.environ["CONTAINERREGISTRY_USERNAME"], - password=os.environ["CONTAINERREGISTRY_PASSWORD"] - ) - ) +class TestContainerRegistryClient(AzureTestCase, ContainerRegistryTestClass): @acr_preparer() def test_list_repositories(self, containerregistry_baseurl): - client = self.set_up(containerregistry_baseurl) + client = self.create_registry_client(containerregistry_baseurl) repos = client.list_repositories() count = 0 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index f58183cda105..d1ea4e374745 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -8,9 +8,13 @@ from devtools_testutils import AzureTestCase, PowerShellPreparer -from azure.containerregistry import ContainerRepositoryClient, ContainerRegistryUserCredential +from azure.containerregistry import ( + ContainerRepositoryClient, + ContainerRegistryClient, +) from azure.identity import DefaultAzureCredential +from _shared.testcase import ContainerRegistryTestClass acr_preparer = functools.partial( PowerShellPreparer, @@ -19,20 +23,26 @@ ) -class TestContainerRepositoryClient(AzureTestCase): - def set_up(self, endpoint): - return ContainerRepositoryClient( - endpoint=endpoint, - repository="hello-world", - credential=ContainerRegistryUserCredential( - username=os.environ["CONTAINERREGISTRY_USERNAME"], - password=os.environ["CONTAINERREGISTRY_PASSWORD"] - ) - ) +class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): + + repository = "hello-world" + + @acr_preparer() + def test_delete_repository(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + client.delete() + + reg_client = self.create_registry_client(containerregistry_baseurl) + + repo_count = 0 + for repo in reg_client.list_repositories(): + repo_count += 1 + + assert repo_count == 0 @acr_preparer() def test_list_tags(self, containerregistry_baseurl): - client = self.set_up(containerregistry_baseurl) + client = self.create_repository_client(containerregistry_baseurl, self.repository) repos = client.list_tags() count = 0 @@ -44,7 +54,7 @@ def test_list_tags(self, containerregistry_baseurl): @acr_preparer() def test_get_attributes(self, containerregistry_baseurl): - client = self.set_up(containerregistry_baseurl) + client = self.create_repository_client(containerregistry_baseurl, self.repository) repo_attribs = client.get_properties() @@ -53,10 +63,16 @@ def test_get_attributes(self, containerregistry_baseurl): @acr_preparer() def test_list_registry_artifacts(self, containerregistry_baseurl): - client = self.set_up(containerregistry_baseurl) + client = self.create_repository_client(containerregistry_baseurl, self.repository) repo_attribs = client.list_registry_artifacts() print(repo_attribs) + @acr_preparer() + def test_get_tag(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + + repos = client.list_tags() + tag = client.get_tag_properties() diff --git a/sdk/containerregistry/test-resources-post.ps1 b/sdk/containerregistry/test-resources-post.ps1 new file mode 100644 index 000000000000..67366d89507a --- /dev/null +++ b/sdk/containerregistry/test-resources-post.ps1 @@ -0,0 +1,5 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# Install docker + From 7108594fe7e8633eb21726a3ec58eeb8856d33ec Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 16 Mar 2021 12:46:32 -0400 Subject: [PATCH 20/86] adding swagger file --- .../_container_registry_client.py | 9 +++------ .../azure-containerregistry/swagger/README.md | 16 ++++++++++++++++ .../tests/_shared/testcase.py | 2 +- ...ory_client.test_list_registry_artifacts.yaml} | 8 ++++---- ...ntainer_repository_client.test_list_tags.yaml | 4 ++-- 5 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/swagger/README.md rename sdk/containerregistry/azure-containerregistry/tests/recordings/{test_container_registry_client.test_list_repositories.yaml => test_container_repository_client.test_list_registry_artifacts.yaml} (58%) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 2715ab379053..1e7c9c46cbb7 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -58,12 +58,9 @@ def list_repositories(self, **kwargs): repos = self._client.repository.get_list( last=kwargs.get("last", None), n=kwargs.get("max", None) ) - return RepositoryProperties.from_generated(repos) - # return ItemPaged( - # command, - # page_iterator_class=RepositoryPropertiesPaged - # ) - # pass + return ItemPaged( + + ) def get_repository_client(self, repository, **kwargs): # type: (str) -> ContainerRepositoryClient diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md new file mode 100644 index 000000000000..651bee61bf13 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -0,0 +1,16 @@ +## Azure Appconfiguration for Python + +### Settings +``` yaml +input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/8642ffaf0354502860d31b4b07a506299cbed3f4/sdk/containerregistry/container-registry/swagger/containerregistry.json +output-folder: "../azure/containerregistry/_generated" +namespace: azure.containerregistry +no-namespace-folders: true +python: true +python-mode: create +license-header: MICROSOFT_MIT_NO_VERSION +package-name: azure-containerregistry +clear-output-folder: true +enable-xml: true +vanilla: true +``` \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py index 537cb0184f77..b713a23cefd9 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py @@ -14,7 +14,7 @@ class ContainerRegistryTestClass(object): def create_registry_client(self, endpoint): return ContainerRegistryClient( - endpoint=containerregistry_baseurl, + endpoint=endpoint, credential=ContainerRegistryUserCredential( username=os.environ["CONTAINERREGISTRY_USERNAME"], password=os.environ["CONTAINERREGISTRY_PASSWORD"], diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml similarity index 58% rename from sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml rename to sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml index 69ceee59a26d..21f6714348b8 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml @@ -12,10 +12,10 @@ interactions: - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests response: body: - string: '{"repositories":["debian","hello-world"]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: @@ -27,11 +27,11 @@ interactions: connection: - keep-alive content-length: - - '42' + - '597' content-type: - application/json; charset=utf-8 date: - - Wed, 10 Mar 2021 16:53:45 GMT + - Tue, 16 Mar 2021 16:28:33 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index c1f456d93a33..cfd32042523b 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -15,7 +15,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-03T13:06:08.1190646Z","lastUpdateTime":"2021-03-03T13:06:08.2369442Z","manifestCount":1,"tagCount":1,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} ' headers: @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 14:51:19 GMT + - Tue, 16 Mar 2021 16:28:33 GMT docker-distribution-api-version: - registry/2.0 server: From 4dd3c8cb8f6b98f3df8f2448c4c4806e384696a6 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 16 Mar 2021 13:10:38 -0400 Subject: [PATCH 21/86] regen with Jeremys swagger, fixing up implementations --- .../azure/containerregistry/_base_client.py | 4 +- .../_container_registry_client.py | 5 +- .../_container_repository_client.py | 9 +- .../containerregistry/_generated/__init__.py | 7 +- .../_generated/_configuration.py | 22 +- ...ner_registry.py => _container_registry.py} | 67 ++-- .../containerregistry/_generated/_version.py | 9 - .../_generated/aio/__init__.py | 4 +- .../_generated/aio/_configuration.py | 26 +- ...ner_registry.py => _container_registry.py} | 69 ++-- .../_generated/aio/operations/__init__.py | 16 +- .../operations/_access_tokens_operations.py | 2 +- ...=> _container_registry_blob_operations.py} | 52 +-- ...s.py => _container_registry_operations.py} | 74 +++- ...ntainer_registry_repository_operations.py} | 326 ++++++++++++++--- .../aio/operations/_tag_operations.py | 290 --------------- .../aio/operations/_v2_support_operations.py | 86 ----- .../_generated/models/__init__.py | 2 +- ..._enums.py => _container_registry_enums.py} | 0 .../_generated/models/_models.py | 256 ++++++++------ .../_generated/models/_models_py3.py | 322 ++++++++++------- .../_generated/operations/__init__.py | 16 +- .../operations/_access_tokens_operations.py | 2 +- ...=> _container_registry_blob_operations.py} | 52 +-- ...s.py => _container_registry_operations.py} | 75 +++- ...ntainer_registry_repository_operations.py} | 330 +++++++++++++++--- .../_generated/operations/_tag_operations.py | 298 ---------------- .../operations/_v2_support_operations.py | 91 ----- .../azure/containerregistry/_models.py | 47 +-- ...repository_client.test_get_attributes.yaml | 4 +- ...epository_client.test_get_properties.yaml} | 15 +- .../tests/test_container_repository_client.py | 14 +- 32 files changed, 1247 insertions(+), 1345 deletions(-) rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/{_azure_container_registry.py => _container_registry.py} (52%) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/{_azure_container_registry.py => _container_registry.py} (50%) rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/{_blob_operations.py => _container_registry_blob_operations.py} (95%) rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/{_repository_operations.py => _container_registry_operations.py} (79%) rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/{_manifests_operations.py => _container_registry_repository_operations.py} (57%) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/{_azure_container_registry_enums.py => _container_registry_enums.py} (100%) rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/{_blob_operations.py => _container_registry_blob_operations.py} (95%) rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/{_repository_operations.py => _container_registry_operations.py} (80%) rename sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/{_manifests_operations.py => _container_registry_repository_operations.py} (57%) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py rename sdk/containerregistry/azure-containerregistry/tests/recordings/{test_container_repository_client.test_delete_repository.yaml => test_container_repository_client.test_get_properties.yaml} (71%) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 6e7b5da3dbe0..7187e2a23563 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -11,7 +11,7 @@ ) from ._authentication_policy import ContainerRegistryUserCredentialPolicy -from ._generated import AzureContainerRegistry +from ._generated import ContainerRegistry from ._helpers import get_authentication_policy from ._user_agent import USER_AGENT @@ -27,7 +27,7 @@ def __init__(self, endpoint, credential, **kwargs): auth_policy = ContainerRegistryUserCredentialPolicy( credential=credential ) - self._client = AzureContainerRegistry( + self._client = ContainerRegistry( credential=credential, url=endpoint, sdk_moniker=USER_AGENT, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 1e7c9c46cbb7..22be45dcf345 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -41,7 +41,7 @@ def delete_repository(self, repository, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - pass + raise NotImplementedError("Not implemented") def list_repositories(self, **kwargs): # type: (...) -> ItemPaged[str] @@ -54,7 +54,7 @@ def list_repositories(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[str] :raises: None """ - # command = functools.partial(self._client.repository.get_list, **kwargs) + raise NotImplementedError("Not implemented") repos = self._client.repository.get_list( last=kwargs.get("last", None), n=kwargs.get("max", None) ) @@ -74,4 +74,3 @@ def get_repository_client(self, repository, **kwargs): repository, credential=self.credential, ) - pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 0df5d5f0e0dc..2bdde23d262b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -38,8 +38,7 @@ def delete(self, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - self._client.repository.delete(self.repository, **kwargs) - # raise NotImplementedError("Has not been implemented") + self._client.container_registry.delete(self.repository, **kwargs) def delete_registry_artifact(self, digest): # type: (str) -> None @@ -70,7 +69,7 @@ def get_properties(self): :returns: :class:~azure.containerregistry.RepositoryProperties :raises: None """ - resp = self._client.repository.get_attributes(self.repository) + resp = self._client.container_registry.get_repository_attributes(self.repository) return RepositoryProperties.from_generated(resp) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): @@ -108,6 +107,7 @@ def list_registry_artifacts(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] :raises: None """ + raise NotImplementedError("Not implemented") # TODO: turn this into an ItemPaged artifacts = self._client.manifests.get_list( self.repository, @@ -125,7 +125,8 @@ def list_tags(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[TagProperties] :raises: None """ - tags = self._client.repository.get_attributes( + raise NotImplementedError("Not implemented") + tags = self._client.container_registry.get_attributes( self.repository, **kwargs ) return tags diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py index 89894c5e7034..930c62f8adda 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py @@ -6,11 +6,8 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._azure_container_registry import AzureContainerRegistry -from ._version import VERSION - -__version__ = VERSION -__all__ = ['AzureContainerRegistry'] +from ._container_registry import ContainerRegistry +__all__ = ['ContainerRegistry'] try: from ._patch import patch_sdk # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py index 760fb1df0b03..0a03c9b6323b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py @@ -11,43 +11,33 @@ from azure.core.configuration import Configuration from azure.core.pipeline import policies -from ._version import VERSION - if TYPE_CHECKING: # pylint: disable=unused-import,ungrouped-imports from typing import Any - from azure.core.credentials import TokenCredential - +VERSION = "unknown" -class AzureContainerRegistryConfiguration(Configuration): - """Configuration for AzureContainerRegistry. +class ContainerRegistryConfiguration(Configuration): + """Configuration for ContainerRegistry. Note that all parameters used to create this instance are saved as instance attributes. - :param credential: Credential needed for the client to connect to Azure. - :type credential: ~azure.core.credentials.TokenCredential :param url: Registry login URL. :type url: str """ def __init__( self, - credential, # type: "TokenCredential" url, # type: str **kwargs # type: Any ): # type: (...) -> None - if credential is None: - raise ValueError("Parameter 'credential' must not be None.") if url is None: raise ValueError("Parameter 'url' must not be None.") - super(AzureContainerRegistryConfiguration, self).__init__(**kwargs) + super(ContainerRegistryConfiguration, self).__init__(**kwargs) - self.credential = credential self.url = url - self.credential_scopes = kwargs.pop('credential_scopes', []) kwargs.setdefault('sdk_moniker', 'containerregistry/{}'.format(VERSION)) self._configure(**kwargs) @@ -65,7 +55,3 @@ def _configure( self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs) self.redirect_policy = kwargs.get('redirect_policy') or policies.RedirectPolicy(**kwargs) self.authentication_policy = kwargs.get('authentication_policy') - if not self.credential_scopes and not self.authentication_policy: - raise ValueError("You must provide either credential_scopes or authentication_policy as kwargs") - if self.credential and not self.authentication_policy: - self.authentication_policy = policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_azure_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py similarity index 52% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_azure_container_registry.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py index 65c20111ba47..127f168e8ac3 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_azure_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py @@ -15,51 +15,42 @@ # pylint: disable=unused-import,ungrouped-imports from typing import Any - from azure.core.credentials import TokenCredential - -from ._configuration import AzureContainerRegistryConfiguration -from .operations import V2SupportOperations -from .operations import ManifestsOperations -from .operations import BlobOperations -from .operations import RepositoryOperations -from .operations import TagOperations + from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from ._configuration import ContainerRegistryConfiguration +from .operations import ContainerRegistryOperations +from .operations import ContainerRegistryRepositoryOperations +from .operations import ContainerRegistryBlobOperations from .operations import RefreshTokensOperations from .operations import AccessTokensOperations from . import models -class AzureContainerRegistry(object): +class ContainerRegistry(object): """Metadata API definition for the Azure Container Registry runtime. - :ivar v2_support: V2SupportOperations operations - :vartype v2_support: azure.containerregistry.operations.V2SupportOperations - :ivar manifests: ManifestsOperations operations - :vartype manifests: azure.containerregistry.operations.ManifestsOperations - :ivar blob: BlobOperations operations - :vartype blob: azure.containerregistry.operations.BlobOperations - :ivar repository: RepositoryOperations operations - :vartype repository: azure.containerregistry.operations.RepositoryOperations - :ivar tag: TagOperations operations - :vartype tag: azure.containerregistry.operations.TagOperations + :ivar container_registry: ContainerRegistryOperations operations + :vartype container_registry: azure.containerregistry.operations.ContainerRegistryOperations + :ivar container_registry_repository: ContainerRegistryRepositoryOperations operations + :vartype container_registry_repository: azure.containerregistry.operations.ContainerRegistryRepositoryOperations + :ivar container_registry_blob: ContainerRegistryBlobOperations operations + :vartype container_registry_blob: azure.containerregistry.operations.ContainerRegistryBlobOperations :ivar refresh_tokens: RefreshTokensOperations operations :vartype refresh_tokens: azure.containerregistry.operations.RefreshTokensOperations :ivar access_tokens: AccessTokensOperations operations :vartype access_tokens: azure.containerregistry.operations.AccessTokensOperations - :param credential: Credential needed for the client to connect to Azure. - :type credential: ~azure.core.credentials.TokenCredential :param url: Registry login URL. :type url: str """ def __init__( self, - credential, # type: "TokenCredential" url, # type: str **kwargs # type: Any ): # type: (...) -> None base_url = '{url}' - self._config = AzureContainerRegistryConfiguration(credential, url, **kwargs) + self._config = ContainerRegistryConfiguration(url, **kwargs) self._client = PipelineClient(base_url=base_url, config=self._config, **kwargs) client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)} @@ -67,27 +58,41 @@ def __init__( self._serialize.client_side_validation = False self._deserialize = Deserializer(client_models) - self.v2_support = V2SupportOperations( - self._client, self._config, self._serialize, self._deserialize) - self.manifests = ManifestsOperations( - self._client, self._config, self._serialize, self._deserialize) - self.blob = BlobOperations( + self.container_registry = ContainerRegistryOperations( self._client, self._config, self._serialize, self._deserialize) - self.repository = RepositoryOperations( + self.container_registry_repository = ContainerRegistryRepositoryOperations( self._client, self._config, self._serialize, self._deserialize) - self.tag = TagOperations( + self.container_registry_blob = ContainerRegistryBlobOperations( self._client, self._config, self._serialize, self._deserialize) self.refresh_tokens = RefreshTokensOperations( self._client, self._config, self._serialize, self._deserialize) self.access_tokens = AccessTokensOperations( self._client, self._config, self._serialize, self._deserialize) + def _send_request(self, http_request, **kwargs): + # type: (HttpRequest, Any) -> HttpResponse + """Runs the network request through the client's chained policies. + + :param http_request: The network request you want to make. Required. + :type http_request: ~azure.core.pipeline.transport.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to True. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.pipeline.transport.HttpResponse + """ + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + http_request.url = self._client.format_url(http_request.url, **path_format_arguments) + stream = kwargs.pop("stream", True) + pipeline_response = self._client._pipeline.run(http_request, stream=stream, **kwargs) + return pipeline_response.http_response + def close(self): # type: () -> None self._client.close() def __enter__(self): - # type: () -> AzureContainerRegistry + # type: () -> ContainerRegistry self._client.__enter__() return self diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py deleted file mode 100644 index eae7c95b6fbd..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_version.py +++ /dev/null @@ -1,9 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- - -VERSION = "0.1.0" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py index eebca06c77c9..00c3ae0ed2bb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py @@ -6,5 +6,5 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._azure_container_registry import AzureContainerRegistry -__all__ = ['AzureContainerRegistry'] +from ._container_registry import ContainerRegistry +__all__ = ['ContainerRegistry'] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py index 73b8600479b8..d54574b49de1 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py @@ -6,45 +6,33 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from typing import Any, TYPE_CHECKING +from typing import Any from azure.core.configuration import Configuration from azure.core.pipeline import policies -from .._version import VERSION +VERSION = "unknown" -if TYPE_CHECKING: - # pylint: disable=unused-import,ungrouped-imports - from azure.core.credentials_async import AsyncTokenCredential - - -class AzureContainerRegistryConfiguration(Configuration): - """Configuration for AzureContainerRegistry. +class ContainerRegistryConfiguration(Configuration): + """Configuration for ContainerRegistry. Note that all parameters used to create this instance are saved as instance attributes. - :param credential: Credential needed for the client to connect to Azure. - :type credential: ~azure.core.credentials_async.AsyncTokenCredential :param url: Registry login URL. :type url: str """ def __init__( self, - credential: "AsyncTokenCredential", url: str, **kwargs: Any ) -> None: - if credential is None: - raise ValueError("Parameter 'credential' must not be None.") if url is None: raise ValueError("Parameter 'url' must not be None.") - super(AzureContainerRegistryConfiguration, self).__init__(**kwargs) + super(ContainerRegistryConfiguration, self).__init__(**kwargs) - self.credential = credential self.url = url - self.credential_scopes = kwargs.pop('credential_scopes', []) kwargs.setdefault('sdk_moniker', 'containerregistry/{}'.format(VERSION)) self._configure(**kwargs) @@ -61,7 +49,3 @@ def _configure( self.custom_hook_policy = kwargs.get('custom_hook_policy') or policies.CustomHookPolicy(**kwargs) self.redirect_policy = kwargs.get('redirect_policy') or policies.AsyncRedirectPolicy(**kwargs) self.authentication_policy = kwargs.get('authentication_policy') - if not self.credential_scopes and not self.authentication_policy: - raise ValueError("You must provide either credential_scopes or authentication_policy as kwargs") - if self.credential and not self.authentication_policy: - self.authentication_policy = policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_azure_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py similarity index 50% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_azure_container_registry.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py index bdf6c1d1e6c3..a344b66b5a8e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_azure_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py @@ -6,57 +6,45 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from typing import Any, TYPE_CHECKING +from typing import Any from azure.core import AsyncPipelineClient +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest from msrest import Deserializer, Serializer -if TYPE_CHECKING: - # pylint: disable=unused-import,ungrouped-imports - from azure.core.credentials_async import AsyncTokenCredential - -from ._configuration import AzureContainerRegistryConfiguration -from .operations import V2SupportOperations -from .operations import ManifestsOperations -from .operations import BlobOperations -from .operations import RepositoryOperations -from .operations import TagOperations +from ._configuration import ContainerRegistryConfiguration +from .operations import ContainerRegistryOperations +from .operations import ContainerRegistryRepositoryOperations +from .operations import ContainerRegistryBlobOperations from .operations import RefreshTokensOperations from .operations import AccessTokensOperations from .. import models -class AzureContainerRegistry(object): +class ContainerRegistry(object): """Metadata API definition for the Azure Container Registry runtime. - :ivar v2_support: V2SupportOperations operations - :vartype v2_support: azure.containerregistry.aio.operations.V2SupportOperations - :ivar manifests: ManifestsOperations operations - :vartype manifests: azure.containerregistry.aio.operations.ManifestsOperations - :ivar blob: BlobOperations operations - :vartype blob: azure.containerregistry.aio.operations.BlobOperations - :ivar repository: RepositoryOperations operations - :vartype repository: azure.containerregistry.aio.operations.RepositoryOperations - :ivar tag: TagOperations operations - :vartype tag: azure.containerregistry.aio.operations.TagOperations + :ivar container_registry: ContainerRegistryOperations operations + :vartype container_registry: azure.containerregistry.aio.operations.ContainerRegistryOperations + :ivar container_registry_repository: ContainerRegistryRepositoryOperations operations + :vartype container_registry_repository: azure.containerregistry.aio.operations.ContainerRegistryRepositoryOperations + :ivar container_registry_blob: ContainerRegistryBlobOperations operations + :vartype container_registry_blob: azure.containerregistry.aio.operations.ContainerRegistryBlobOperations :ivar refresh_tokens: RefreshTokensOperations operations :vartype refresh_tokens: azure.containerregistry.aio.operations.RefreshTokensOperations :ivar access_tokens: AccessTokensOperations operations :vartype access_tokens: azure.containerregistry.aio.operations.AccessTokensOperations - :param credential: Credential needed for the client to connect to Azure. - :type credential: ~azure.core.credentials_async.AsyncTokenCredential :param url: Registry login URL. :type url: str """ def __init__( self, - credential: "AsyncTokenCredential", url: str, **kwargs: Any ) -> None: base_url = '{url}' - self._config = AzureContainerRegistryConfiguration(credential, url, **kwargs) + self._config = ContainerRegistryConfiguration(url, **kwargs) self._client = AsyncPipelineClient(base_url=base_url, config=self._config, **kwargs) client_models = {k: v for k, v in models.__dict__.items() if isinstance(v, type)} @@ -64,25 +52,38 @@ def __init__( self._serialize.client_side_validation = False self._deserialize = Deserializer(client_models) - self.v2_support = V2SupportOperations( - self._client, self._config, self._serialize, self._deserialize) - self.manifests = ManifestsOperations( - self._client, self._config, self._serialize, self._deserialize) - self.blob = BlobOperations( + self.container_registry = ContainerRegistryOperations( self._client, self._config, self._serialize, self._deserialize) - self.repository = RepositoryOperations( + self.container_registry_repository = ContainerRegistryRepositoryOperations( self._client, self._config, self._serialize, self._deserialize) - self.tag = TagOperations( + self.container_registry_blob = ContainerRegistryBlobOperations( self._client, self._config, self._serialize, self._deserialize) self.refresh_tokens = RefreshTokensOperations( self._client, self._config, self._serialize, self._deserialize) self.access_tokens = AccessTokensOperations( self._client, self._config, self._serialize, self._deserialize) + async def _send_request(self, http_request: HttpRequest, **kwargs: Any) -> AsyncHttpResponse: + """Runs the network request through the client's chained policies. + + :param http_request: The network request you want to make. Required. + :type http_request: ~azure.core.pipeline.transport.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to True. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.pipeline.transport.AsyncHttpResponse + """ + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + http_request.url = self._client.format_url(http_request.url, **path_format_arguments) + stream = kwargs.pop("stream", True) + pipeline_response = await self._client._pipeline.run(http_request, stream=stream, **kwargs) + return pipeline_response.http_response + async def close(self) -> None: await self._client.close() - async def __aenter__(self) -> "AzureContainerRegistry": + async def __aenter__(self) -> "ContainerRegistry": await self._client.__aenter__() return self diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py index d6560dfe7906..95b29f5d1bda 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py @@ -6,20 +6,16 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._v2_support_operations import V2SupportOperations -from ._manifests_operations import ManifestsOperations -from ._blob_operations import BlobOperations -from ._repository_operations import RepositoryOperations -from ._tag_operations import TagOperations +from ._container_registry_operations import ContainerRegistryOperations +from ._container_registry_repository_operations import ContainerRegistryRepositoryOperations +from ._container_registry_blob_operations import ContainerRegistryBlobOperations from ._refresh_tokens_operations import RefreshTokensOperations from ._access_tokens_operations import AccessTokensOperations __all__ = [ - 'V2SupportOperations', - 'ManifestsOperations', - 'BlobOperations', - 'RepositoryOperations', - 'TagOperations', + 'ContainerRegistryOperations', + 'ContainerRegistryRepositoryOperations', + 'ContainerRegistryBlobOperations', 'RefreshTokensOperations', 'AccessTokensOperations', ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py index edf931e348cb..81a047426fb2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py @@ -111,7 +111,7 @@ async def get_from_login( scope: str, **kwargs ) -> "_models.AccessToken": - """Exchange Username, Password, and Scope for an ACR Access Token. + """Exchange Username, Password and Scope an ACR Access Token. :param service: Indicates the name of your Azure container registry. :type service: str diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py similarity index 95% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_blob_operations.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py index d7079ed69af2..3afa8d85d4b0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py @@ -17,8 +17,8 @@ T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] -class BlobOperations: - """BlobOperations async operations. +class ContainerRegistryBlobOperations: + """ContainerRegistryBlobOperations async operations. You should not instantiate this class directly. Instead, you should create a Client instance that instantiates it for you and attaches it as an attribute. @@ -39,7 +39,7 @@ def __init__(self, client, config, serializer, deserializer) -> None: self._deserialize = deserializer self._config = config - async def get( + async def get_blob( self, name: str, digest: str, @@ -64,7 +64,7 @@ async def get( accept = "application/octet-stream" # Construct URL - url = self.get.metadata['url'] # type: ignore + url = self.get_blob.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -101,9 +101,9 @@ async def get( return cls(pipeline_response, deserialized, response_headers) return deserialized - get.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + get_blob.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - async def check( + async def check_blob_exists( self, name: str, digest: str, @@ -128,7 +128,7 @@ async def check( accept = "application/json" # Construct URL - url = self.check.metadata['url'] # type: ignore + url = self.check_blob_exists.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -163,9 +163,9 @@ async def check( if cls: return cls(pipeline_response, None, response_headers) - check.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + check_blob_exists.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - async def delete( + async def delete_blob( self, name: str, digest: str, @@ -190,7 +190,7 @@ async def delete( accept = "application/octet-stream" # Construct URL - url = self.delete.metadata['url'] # type: ignore + url = self.delete_blob.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -221,9 +221,9 @@ async def delete( return cls(pipeline_response, deserialized, response_headers) return deserialized - delete.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + delete_blob.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - async def mount( + async def mount_blob( self, name: str, from_parameter: str, @@ -251,7 +251,7 @@ async def mount( accept = "application/json" # Construct URL - url = self.mount.metadata['url'] # type: ignore + url = self.mount_blob.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -284,9 +284,9 @@ async def mount( if cls: return cls(pipeline_response, None, response_headers) - mount.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore + mount_blob.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore - async def get_status( + async def get_upload_status( self, location: str, **kwargs @@ -310,7 +310,7 @@ async def get_status( accept = "application/json" # Construct URL - url = self.get_status.metadata['url'] # type: ignore + url = self.get_upload_status.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), @@ -340,9 +340,9 @@ async def get_status( if cls: return cls(pipeline_response, None, response_headers) - get_status.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + get_upload_status.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore - async def upload( + async def upload_chunk( self, location: str, value: IO, @@ -369,7 +369,7 @@ async def upload( accept = "application/json" # Construct URL - url = self.upload.metadata['url'] # type: ignore + url = self.upload_chunk.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), @@ -403,9 +403,9 @@ async def upload( if cls: return cls(pipeline_response, None, response_headers) - upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + upload_chunk.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore - async def end_upload( + async def complete_upload( self, digest: str, location: str, @@ -436,7 +436,7 @@ async def end_upload( accept = "application/json" # Construct URL - url = self.end_upload.metadata['url'] # type: ignore + url = self.complete_upload.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), @@ -471,7 +471,7 @@ async def end_upload( if cls: return cls(pipeline_response, None, response_headers) - end_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + complete_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore async def cancel_upload( self, @@ -647,7 +647,7 @@ async def get_chunk( return deserialized get_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - async def check_chunk( + async def check_chunk_exists( self, name: str, digest: str, @@ -676,7 +676,7 @@ async def check_chunk( accept = "application/json" # Construct URL - url = self.check_chunk.metadata['url'] # type: ignore + url = self.check_chunk_exists.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -708,4 +708,4 @@ async def check_chunk( if cls: return cls(pipeline_response, None, response_headers) - check_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + check_chunk_exists.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py similarity index 79% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_repository_operations.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py index b0200ad8469b..1d4b9139e330 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py @@ -17,8 +17,8 @@ T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] -class RepositoryOperations: - """RepositoryOperations async operations. +class ContainerRegistryOperations: + """ContainerRegistryOperations async operations. You should not instantiate this class directly. Instead, you should create a Client instance that instantiates it for you and attaches it as an attribute. @@ -39,7 +39,53 @@ def __init__(self, client, config, serializer, deserializer) -> None: self._deserialize = deserializer self._config = config - async def get_list( + async def check_docker_v2_support( + self, + **kwargs + ) -> None: + """Tells whether this Docker Registry instance supports Docker Registry HTTP API v2. + + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check_docker_v2_support.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + check_docker_v2_support.metadata = {'url': '/v2/'} # type: ignore + + async def get_repositories( self, last: Optional[str] = None, n: Optional[int] = None, @@ -65,7 +111,7 @@ async def get_list( accept = "application/json" # Construct URL - url = self.get_list.metadata['url'] # type: ignore + url = self.get_repositories.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), } @@ -99,9 +145,9 @@ async def get_list( return cls(pipeline_response, deserialized, response_headers) return deserialized - get_list.metadata = {'url': '/acr/v1/_catalog'} # type: ignore + get_repositories.metadata = {'url': '/acr/v1/_catalog'} # type: ignore - async def get_attributes( + async def get_repository_attributes( self, name: str, **kwargs @@ -123,7 +169,7 @@ async def get_attributes( accept = "application/json" # Construct URL - url = self.get_attributes.metadata['url'] # type: ignore + url = self.get_repository_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -152,9 +198,9 @@ async def get_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore + get_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore - async def delete( + async def delete_repository( self, name: str, **kwargs @@ -176,7 +222,7 @@ async def delete( accept = "application/json" # Construct URL - url = self.delete.metadata['url'] # type: ignore + url = self.delete_repository.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -205,9 +251,9 @@ async def delete( return cls(pipeline_response, deserialized, {}) return deserialized - delete.metadata = {'url': '/acr/v1/{name}'} # type: ignore + delete_repository.metadata = {'url': '/acr/v1/{name}'} # type: ignore - async def update_attributes( + async def update_repository_attributes( self, name: str, value: Optional["_models.ChangeableAttributes"] = None, @@ -233,7 +279,7 @@ async def update_attributes( accept = "application/json" # Construct URL - url = self.update_attributes.metadata['url'] # type: ignore + url = self.update_repository_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -266,4 +312,4 @@ async def update_attributes( if cls: return cls(pipeline_response, None, {}) - update_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore + update_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_manifests_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py similarity index 57% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_manifests_operations.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index ab4dd318ba23..f3bc8e9356f4 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_manifests_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -17,8 +17,8 @@ T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] -class ManifestsOperations: - """ManifestsOperations async operations. +class ContainerRegistryRepositoryOperations: + """ContainerRegistryRepositoryOperations async operations. You should not instantiate this class directly. Instead, you should create a Client instance that instantiates it for you and attaches it as an attribute. @@ -39,13 +39,13 @@ def __init__(self, client, config, serializer, deserializer) -> None: self._deserialize = deserializer self._config = config - async def get( + async def get_manifest( self, name: str, reference: str, accept: Optional[str] = None, **kwargs - ) -> "_models.ManifestWrapper": + ) -> "_models.Manifest": """Get the manifest identified by ``name`` and ``reference`` where ``reference`` can be a tag or digest. @@ -57,11 +57,11 @@ async def get( application/vnd.docker.distribution.manifest.v2+json. :type accept: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: ManifestWrapper, or the result of cls(response) - :rtype: ~azure.containerregistry.models.ManifestWrapper + :return: Manifest, or the result of cls(response) + :rtype: ~azure.containerregistry.models.Manifest :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestWrapper"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.Manifest"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -69,7 +69,7 @@ async def get( accept = "application/json" # Construct URL - url = self.get.metadata['url'] # type: ignore + url = self.get_manifest.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -95,19 +95,19 @@ async def get( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('ManifestWrapper', pipeline_response) + deserialized = self._deserialize('Manifest', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) return deserialized - get.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + get_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore - async def create( + async def create_manifest( self, name: str, reference: str, - schema_version: Optional[int] = None, + payload: "_models.Manifest", **kwargs ) -> object: """Put the manifest identified by ``name`` and ``reference`` where ``reference`` can be a tag or @@ -117,8 +117,8 @@ async def create( :type name: str :param reference: A tag or a digest, pointing to a specific image. :type reference: str - :param schema_version: Schema version. - :type schema_version: int + :param payload: Manifest body, can take v1 or v2 values depending on accept header. + :type payload: ~azure.containerregistry.models.Manifest :keyword callable cls: A custom type or function that will be passed the direct response :return: object, or the result of cls(response) :rtype: object @@ -129,13 +129,11 @@ async def create( 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } error_map.update(kwargs.pop('error_map', {})) - - _payload = _models.Manifest(schema_version=schema_version) content_type = kwargs.pop("content_type", "application/vnd.docker.distribution.manifest.v2+json") accept = "application/json" # Construct URL - url = self.create.metadata['url'] # type: ignore + url = self.create_manifest.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -152,7 +150,7 @@ async def create( header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(_payload, 'Manifest') + body_content = self._serialize.body(payload, 'Manifest') body_content_kwargs['content'] = body_content request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) @@ -173,9 +171,9 @@ async def create( return cls(pipeline_response, deserialized, response_headers) return deserialized - create.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + create_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore - async def delete( + async def delete_manifest( self, name: str, reference: str, @@ -201,7 +199,7 @@ async def delete( accept = "application/json" # Construct URL - url = self.delete.metadata['url'] # type: ignore + url = self.delete_manifest.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -228,9 +226,259 @@ async def delete( if cls: return cls(pipeline_response, None, {}) - delete.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + delete_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore - async def get_list( + async def get_tags( + self, + name: str, + last: Optional[str] = None, + n: Optional[int] = None, + orderby: Optional[str] = None, + digest: Optional[str] = None, + **kwargs + ) -> "_models.TagList": + """List tags of a repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :param orderby: orderby query parameter. + :type orderby: str + :param digest: filter by digest. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagList, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagList + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_tags.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + if digest is not None: + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagList', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_tags.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore + + async def get_tag_attributes( + self, + name: str, + reference: str, + **kwargs + ) -> "_models.TagAttributes": + """Get tag attributes by tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_tag_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_tag_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + async def update_tag_attributes( + self, + name: str, + reference: str, + value: Optional["_models.ChangeableAttributes"] = None, + **kwargs + ) -> None: + """Update tag attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_tag_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_tag_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + async def delete_tag( + self, + name: str, + reference: str, + **kwargs + ) -> None: + """Delete tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete_tag.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + delete_tag.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + async def get_manifests( self, name: str, last: Optional[str] = None, @@ -262,7 +510,7 @@ async def get_list( accept = "application/json" # Construct URL - url = self.get_list.metadata['url'] # type: ignore + url = self.get_manifests.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -297,20 +545,20 @@ async def get_list( return cls(pipeline_response, deserialized, {}) return deserialized - get_list.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore + get_manifests.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore - async def get_attributes( + async def get_manifest_attributes( self, name: str, - reference: str, + digest: str, **kwargs ) -> "_models.ManifestAttributes": """Get manifest attributes. :param name: Name of the image (including the namespace). :type name: str - :param reference: A tag or a digest, pointing to a specific image. - :type reference: str + :param digest: Digest of a BLOB. + :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response :return: ManifestAttributes, or the result of cls(response) :rtype: ~azure.containerregistry.models.ManifestAttributes @@ -324,11 +572,11 @@ async def get_attributes( accept = "application/json" # Construct URL - url = self.get_attributes.metadata['url'] # type: ignore + url = self.get_manifest_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), } url = self._client.format_url(url, **path_format_arguments) @@ -354,12 +602,12 @@ async def get_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore - async def update_attributes( + async def update_manifest_attributes( self, name: str, - reference: str, + digest: str, value: Optional["_models.ChangeableAttributes"] = None, **kwargs ) -> None: @@ -367,8 +615,8 @@ async def update_attributes( :param name: Name of the image (including the namespace). :type name: str - :param reference: A tag or a digest, pointing to a specific image. - :type reference: str + :param digest: Digest of a BLOB. + :type digest: str :param value: Repository attribute value. :type value: ~azure.containerregistry.models.ChangeableAttributes :keyword callable cls: A custom type or function that will be passed the direct response @@ -385,11 +633,11 @@ async def update_attributes( accept = "application/json" # Construct URL - url = self.update_attributes.metadata['url'] # type: ignore + url = self.update_manifest_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), } url = self._client.format_url(url, **path_format_arguments) @@ -419,4 +667,4 @@ async def update_attributes( if cls: return cls(pipeline_response, None, {}) - update_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + update_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py deleted file mode 100644 index 2fb3ee4d65cf..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_tag_operations.py +++ /dev/null @@ -1,290 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import Any, Callable, Dict, Generic, Optional, TypeVar -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest - -from ... import models as _models - -T = TypeVar('T') -ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] - -class TagOperations: - """TagOperations async operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer) -> None: - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - async def get_list( - self, - name: str, - last: Optional[str] = None, - n: Optional[int] = None, - orderby: Optional[str] = None, - digest: Optional[str] = None, - **kwargs - ) -> "_models.TagList": - """List tags of a repository. - - :param name: Name of the image (including the namespace). - :type name: str - :param last: Query parameter for the last item in previous query. Result set will include - values lexically after last. - :type last: str - :param n: query parameter for max number of items. - :type n: int - :param orderby: orderby query parameter. - :type orderby: str - :param digest: filter by digest. - :type digest: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagList, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagList - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_list.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - if orderby is not None: - query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') - if digest is not None: - query_parameters['digest'] = self._serialize.query("digest", digest, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('TagList', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_list.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore - - async def get_attributes( - self, - name: str, - reference: str, - **kwargs - ) -> "_models.TagAttributes": - """Get tag attributes by tag. - - :param name: Name of the image (including the namespace). - :type name: str - :param reference: Tag name. - :type reference: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagAttributes - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('TagAttributes', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore - - async def update_attributes( - self, - name: str, - reference: str, - value: Optional["_models.ChangeableAttributes"] = None, - **kwargs - ) -> None: - """Update tag attributes. - - :param name: Name of the image (including the namespace). - :type name: str - :param reference: Tag name. - :type reference: str - :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/json") - accept = "application/json" - - # Construct URL - url = self.update_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - update_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore - - async def delete( - self, - name: str, - reference: str, - **kwargs - ) -> None: - """Delete tag. - - :param name: Name of the image (including the namespace). - :type name: str - :param reference: Tag name. - :type reference: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.delete.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.delete(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [202]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - delete.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py deleted file mode 100644 index cbe93d0a48a2..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_v2_support_operations.py +++ /dev/null @@ -1,86 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import Any, Callable, Dict, Generic, Optional, TypeVar -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest - -from ... import models as _models - -T = TypeVar('T') -ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] - -class V2SupportOperations: - """V2SupportOperations async operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer) -> None: - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - async def check( - self, - **kwargs - ) -> None: - """Tells whether this Docker Registry instance supports Docker Registry HTTP API v2. - - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.check.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - check.metadata = {'url': '/v2/'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py index 13c72aec8b41..0012768e010b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py @@ -83,7 +83,7 @@ from ._models import V1Manifest # type: ignore from ._models import V2Manifest # type: ignore -from ._azure_container_registry_enums import ( +from ._container_registry_enums import ( PostContentSchemaGrantType, ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_azure_container_registry_enums.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py similarity index 100% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_azure_container_registry_enums.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 1d5a605ea4a1..99f68ce16846 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -176,21 +176,21 @@ def __init__( class ChangeableAttributes(msrest.serialization.Model): """ChangeableAttributes. - :param delete_enabled: Delete enabled. - :type delete_enabled: bool - :param write_enabled: Write enabled. - :type write_enabled: bool - :param list_enabled: List enabled. - :type list_enabled: bool - :param read_enabled: Read enabled. - :type read_enabled: bool + :param can_delete: Delete enabled. + :type can_delete: bool + :param can_write: Write enabled. + :type can_write: bool + :param can_list: List enabled. + :type can_list: bool + :param can_read: Read enabled. + :type can_read: bool """ _attribute_map = { - 'delete_enabled': {'key': 'deleteEnabled', 'type': 'bool'}, - 'write_enabled': {'key': 'writeEnabled', 'type': 'bool'}, - 'list_enabled': {'key': 'listEnabled', 'type': 'bool'}, - 'read_enabled': {'key': 'readEnabled', 'type': 'bool'}, + 'can_delete': {'key': 'deleteEnabled', 'type': 'bool'}, + 'can_write': {'key': 'writeEnabled', 'type': 'bool'}, + 'can_list': {'key': 'listEnabled', 'type': 'bool'}, + 'can_read': {'key': 'readEnabled', 'type': 'bool'}, } def __init__( @@ -198,24 +198,24 @@ def __init__( **kwargs ): super(ChangeableAttributes, self).__init__(**kwargs) - self.delete_enabled = kwargs.get('delete_enabled', None) - self.write_enabled = kwargs.get('write_enabled', None) - self.list_enabled = kwargs.get('list_enabled', None) - self.read_enabled = kwargs.get('read_enabled', None) + self.can_delete = kwargs.get('can_delete', None) + self.can_write = kwargs.get('can_write', None) + self.can_list = kwargs.get('can_list', None) + self.can_read = kwargs.get('can_read', None) class DeletedRepository(msrest.serialization.Model): """Deleted repository. - :param manifests_deleted: SHA of the deleted image. - :type manifests_deleted: list[str] - :param tags_deleted: Tag of the deleted image. - :type tags_deleted: list[str] + :param deleted_registry_artifact_digests: SHA of the deleted image. + :type deleted_registry_artifact_digests: list[str] + :param deleted_tags: Tag of the deleted image. + :type deleted_tags: list[str] """ _attribute_map = { - 'manifests_deleted': {'key': 'manifestsDeleted', 'type': '[str]'}, - 'tags_deleted': {'key': 'tagsDeleted', 'type': '[str]'}, + 'deleted_registry_artifact_digests': {'key': 'manifestsDeleted', 'type': '[str]'}, + 'deleted_tags': {'key': 'tagsDeleted', 'type': '[str]'}, } def __init__( @@ -223,8 +223,8 @@ def __init__( **kwargs ): super(DeletedRepository, self).__init__(**kwargs) - self.manifests_deleted = kwargs.get('manifests_deleted', None) - self.tags_deleted = kwargs.get('tags_deleted', None) + self.deleted_registry_artifact_digests = kwargs.get('deleted_registry_artifact_digests', None) + self.deleted_tags = kwargs.get('deleted_tags', None) class Descriptor(msrest.serialization.Model): @@ -409,16 +409,43 @@ class ManifestAttributes(msrest.serialization.Model): :param registry: Registry name. :type registry: str - :param image_name: Image name. - :type image_name: str - :param attributes: Manifest attributes. - :type attributes: ~azure.containerregistry.models.ManifestAttributesBase + :param repository: Image name. + :type repository: str + :param digest: Manifest. + :type digest: str + :param size: Image size. + :type size: long + :param created_on: Created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Last update time. + :type last_updated_on: ~datetime.datetime + :param cpu_architecture: CPU architecture. + :type cpu_architecture: str + :param operating_system: Operating system. + :type operating_system: str + :param manifest_media_type: Media type. + :type manifest_media_type: str + :param config_media_type: Config blob media type. + :type config_media_type: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + :param manifest_properties: Changeable attributes. + :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, - 'attributes': {'key': 'manifest', 'type': 'ManifestAttributesBase'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'digest': {'key': 'manifest.digest', 'type': 'str'}, + 'size': {'key': 'manifest.imageSize', 'type': 'long'}, + 'created_on': {'key': 'manifest.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, + 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, + 'operating_system': {'key': 'manifest.os', 'type': 'str'}, + 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, + 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, + 'tags': {'key': 'manifest.tags', 'type': '[str]'}, + 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( @@ -427,8 +454,17 @@ def __init__( ): super(ManifestAttributes, self).__init__(**kwargs) self.registry = kwargs.get('registry', None) - self.image_name = kwargs.get('image_name', None) - self.attributes = kwargs.get('attributes', None) + self.repository = kwargs.get('repository', None) + self.digest = kwargs.get('digest', None) + self.size = kwargs.get('size', None) + self.created_on = kwargs.get('created_on', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.cpu_architecture = kwargs.get('cpu_architecture', None) + self.operating_system = kwargs.get('operating_system', None) + self.manifest_media_type = kwargs.get('manifest_media_type', None) + self.config_media_type = kwargs.get('config_media_type', None) + self.tags = kwargs.get('tags', None) + self.manifest_properties = kwargs.get('manifest_properties', None) class ManifestAttributesBase(msrest.serialization.Model): @@ -436,37 +472,37 @@ class ManifestAttributesBase(msrest.serialization.Model): :param digest: Manifest. :type digest: str - :param image_size: Image size. - :type image_size: long - :param created_time: Created time. - :type created_time: str - :param last_update_time: Last update time. - :type last_update_time: str - :param architecture: CPU architecture. - :type architecture: str - :param os: Operating system. - :type os: str - :param media_type: Media type. - :type media_type: str + :param size: Image size. + :type size: long + :param created_on: Created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Last update time. + :type last_updated_on: ~datetime.datetime + :param cpu_architecture: CPU architecture. + :type cpu_architecture: str + :param operating_system: Operating system. + :type operating_system: str + :param manifest_media_type: Media type. + :type manifest_media_type: str :param config_media_type: Config blob media type. :type config_media_type: str :param tags: A set of tags. List of tags. :type tags: list[str] - :param changeable_attributes: Changeable attributes. - :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + :param manifest_properties: Changeable attributes. + :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'digest': {'key': 'digest', 'type': 'str'}, - 'image_size': {'key': 'imageSize', 'type': 'long'}, - 'created_time': {'key': 'createdTime', 'type': 'str'}, - 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, - 'architecture': {'key': 'architecture', 'type': 'str'}, - 'os': {'key': 'os', 'type': 'str'}, - 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'size': {'key': 'imageSize', 'type': 'long'}, + 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, + 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, + 'operating_system': {'key': 'os', 'type': 'str'}, + 'manifest_media_type': {'key': 'mediaType', 'type': 'str'}, 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( @@ -475,15 +511,15 @@ def __init__( ): super(ManifestAttributesBase, self).__init__(**kwargs) self.digest = kwargs.get('digest', None) - self.image_size = kwargs.get('image_size', None) - self.created_time = kwargs.get('created_time', None) - self.last_update_time = kwargs.get('last_update_time', None) - self.architecture = kwargs.get('architecture', None) - self.os = kwargs.get('os', None) - self.media_type = kwargs.get('media_type', None) + self.size = kwargs.get('size', None) + self.created_on = kwargs.get('created_on', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.cpu_architecture = kwargs.get('cpu_architecture', None) + self.operating_system = kwargs.get('operating_system', None) + self.manifest_media_type = kwargs.get('manifest_media_type', None) self.config_media_type = kwargs.get('config_media_type', None) self.tags = kwargs.get('tags', None) - self.changeable_attributes = kwargs.get('changeable_attributes', None) + self.manifest_properties = kwargs.get('manifest_properties', None) class ManifestAttributesManifest(msrest.serialization.Model): @@ -932,28 +968,28 @@ class RepositoryAttributes(msrest.serialization.Model): :param registry: Registry name. :type registry: str - :param image_name: Image name. - :type image_name: str - :param created_time: Image created time. - :type created_time: str - :param last_update_time: Image last update time. - :type last_update_time: str - :param manifest_count: Number of the manifests. - :type manifest_count: int + :param name: Image name. + :type name: str + :param created_on: Image created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Image last update time. + :type last_updated_on: ~datetime.datetime + :param registry_artifact_count: Number of the manifests. + :type registry_artifact_count: int :param tag_count: Number of the tags. :type tag_count: int - :param changeable_attributes: Changeable attributes. - :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + :param writeable_properties: Changeable attributes. + :type writeable_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, - 'created_time': {'key': 'createdTime', 'type': 'str'}, - 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, - 'manifest_count': {'key': 'manifestCount', 'type': 'int'}, + 'name': {'key': 'imageName', 'type': 'str'}, + 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, + 'registry_artifact_count': {'key': 'manifestCount', 'type': 'int'}, 'tag_count': {'key': 'tagCount', 'type': 'int'}, - 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( @@ -962,12 +998,12 @@ def __init__( ): super(RepositoryAttributes, self).__init__(**kwargs) self.registry = kwargs.get('registry', None) - self.image_name = kwargs.get('image_name', None) - self.created_time = kwargs.get('created_time', None) - self.last_update_time = kwargs.get('last_update_time', None) - self.manifest_count = kwargs.get('manifest_count', None) + self.name = kwargs.get('name', None) + self.created_on = kwargs.get('created_on', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.registry_artifact_count = kwargs.get('registry_artifact_count', None) self.tag_count = kwargs.get('tag_count', None) - self.changeable_attributes = kwargs.get('changeable_attributes', None) + self.writeable_properties = kwargs.get('writeable_properties', None) class RepositoryTags(msrest.serialization.Model): @@ -998,16 +1034,28 @@ class TagAttributes(msrest.serialization.Model): :param registry: Registry name. :type registry: str - :param image_name: Image name. - :type image_name: str - :param attributes: List of tag attribute details. - :type attributes: ~azure.containerregistry.models.TagAttributesBase + :param repository: Image name. + :type repository: str + :param name: Tag name. + :type name: str + :param digest: Tag digest. + :type digest: str + :param created_on: Tag created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Tag last update time. + :type last_updated_on: ~datetime.datetime + :param modifiable_properties: Changeable attributes. + :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, - 'attributes': {'key': 'tag', 'type': 'TagAttributesBase'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'name': {'key': 'tag.name', 'type': 'str'}, + 'digest': {'key': 'tag.digest', 'type': 'str'}, + 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, + 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( @@ -1016,8 +1064,12 @@ def __init__( ): super(TagAttributes, self).__init__(**kwargs) self.registry = kwargs.get('registry', None) - self.image_name = kwargs.get('image_name', None) - self.attributes = kwargs.get('attributes', None) + self.repository = kwargs.get('repository', None) + self.name = kwargs.get('name', None) + self.digest = kwargs.get('digest', None) + self.created_on = kwargs.get('created_on', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.modifiable_properties = kwargs.get('modifiable_properties', None) class TagAttributesBase(msrest.serialization.Model): @@ -1027,23 +1079,20 @@ class TagAttributesBase(msrest.serialization.Model): :type name: str :param digest: Tag digest. :type digest: str - :param created_time: Tag created time. - :type created_time: str - :param last_update_time: Tag last update time. - :type last_update_time: str - :param signed: Is signed. - :type signed: bool - :param changeable_attributes: Changeable attributes. - :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + :param created_on: Tag created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Tag last update time. + :type last_updated_on: ~datetime.datetime + :param modifiable_properties: Changeable attributes. + :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'name': {'key': 'name', 'type': 'str'}, 'digest': {'key': 'digest', 'type': 'str'}, - 'created_time': {'key': 'createdTime', 'type': 'str'}, - 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, - 'signed': {'key': 'signed', 'type': 'bool'}, - 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, + 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( @@ -1053,10 +1102,9 @@ def __init__( super(TagAttributesBase, self).__init__(**kwargs) self.name = kwargs.get('name', None) self.digest = kwargs.get('digest', None) - self.created_time = kwargs.get('created_time', None) - self.last_update_time = kwargs.get('last_update_time', None) - self.signed = kwargs.get('signed', None) - self.changeable_attributes = kwargs.get('changeable_attributes', None) + self.created_on = kwargs.get('created_on', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.modifiable_properties = kwargs.get('modifiable_properties', None) class TagAttributesTag(msrest.serialization.Model): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index 5da6ec963853..02c41fcec0c2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -12,7 +12,7 @@ from azure.core.exceptions import HttpResponseError import msrest.serialization -from ._azure_container_registry_enums import * +from ._container_registry_enums import * class AccessToken(msrest.serialization.Model): @@ -207,63 +207,63 @@ def __init__( class ChangeableAttributes(msrest.serialization.Model): """ChangeableAttributes. - :param delete_enabled: Delete enabled. - :type delete_enabled: bool - :param write_enabled: Write enabled. - :type write_enabled: bool - :param list_enabled: List enabled. - :type list_enabled: bool - :param read_enabled: Read enabled. - :type read_enabled: bool + :param can_delete: Delete enabled. + :type can_delete: bool + :param can_write: Write enabled. + :type can_write: bool + :param can_list: List enabled. + :type can_list: bool + :param can_read: Read enabled. + :type can_read: bool """ _attribute_map = { - 'delete_enabled': {'key': 'deleteEnabled', 'type': 'bool'}, - 'write_enabled': {'key': 'writeEnabled', 'type': 'bool'}, - 'list_enabled': {'key': 'listEnabled', 'type': 'bool'}, - 'read_enabled': {'key': 'readEnabled', 'type': 'bool'}, + 'can_delete': {'key': 'deleteEnabled', 'type': 'bool'}, + 'can_write': {'key': 'writeEnabled', 'type': 'bool'}, + 'can_list': {'key': 'listEnabled', 'type': 'bool'}, + 'can_read': {'key': 'readEnabled', 'type': 'bool'}, } def __init__( self, *, - delete_enabled: Optional[bool] = None, - write_enabled: Optional[bool] = None, - list_enabled: Optional[bool] = None, - read_enabled: Optional[bool] = None, + can_delete: Optional[bool] = None, + can_write: Optional[bool] = None, + can_list: Optional[bool] = None, + can_read: Optional[bool] = None, **kwargs ): super(ChangeableAttributes, self).__init__(**kwargs) - self.delete_enabled = delete_enabled - self.write_enabled = write_enabled - self.list_enabled = list_enabled - self.read_enabled = read_enabled + self.can_delete = can_delete + self.can_write = can_write + self.can_list = can_list + self.can_read = can_read class DeletedRepository(msrest.serialization.Model): """Deleted repository. - :param manifests_deleted: SHA of the deleted image. - :type manifests_deleted: list[str] - :param tags_deleted: Tag of the deleted image. - :type tags_deleted: list[str] + :param deleted_registry_artifact_digests: SHA of the deleted image. + :type deleted_registry_artifact_digests: list[str] + :param deleted_tags: Tag of the deleted image. + :type deleted_tags: list[str] """ _attribute_map = { - 'manifests_deleted': {'key': 'manifestsDeleted', 'type': '[str]'}, - 'tags_deleted': {'key': 'tagsDeleted', 'type': '[str]'}, + 'deleted_registry_artifact_digests': {'key': 'manifestsDeleted', 'type': '[str]'}, + 'deleted_tags': {'key': 'tagsDeleted', 'type': '[str]'}, } def __init__( self, *, - manifests_deleted: Optional[List[str]] = None, - tags_deleted: Optional[List[str]] = None, + deleted_registry_artifact_digests: Optional[List[str]] = None, + deleted_tags: Optional[List[str]] = None, **kwargs ): super(DeletedRepository, self).__init__(**kwargs) - self.manifests_deleted = manifests_deleted - self.tags_deleted = tags_deleted + self.deleted_registry_artifact_digests = deleted_registry_artifact_digests + self.deleted_tags = deleted_tags class Descriptor(msrest.serialization.Model): @@ -473,30 +473,75 @@ class ManifestAttributes(msrest.serialization.Model): :param registry: Registry name. :type registry: str - :param image_name: Image name. - :type image_name: str - :param attributes: Manifest attributes. - :type attributes: ~azure.containerregistry.models.ManifestAttributesBase + :param repository: Image name. + :type repository: str + :param digest: Manifest. + :type digest: str + :param size: Image size. + :type size: long + :param created_on: Created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Last update time. + :type last_updated_on: ~datetime.datetime + :param cpu_architecture: CPU architecture. + :type cpu_architecture: str + :param operating_system: Operating system. + :type operating_system: str + :param manifest_media_type: Media type. + :type manifest_media_type: str + :param config_media_type: Config blob media type. + :type config_media_type: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + :param manifest_properties: Changeable attributes. + :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, - 'attributes': {'key': 'manifest', 'type': 'ManifestAttributesBase'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'digest': {'key': 'manifest.digest', 'type': 'str'}, + 'size': {'key': 'manifest.imageSize', 'type': 'long'}, + 'created_on': {'key': 'manifest.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, + 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, + 'operating_system': {'key': 'manifest.os', 'type': 'str'}, + 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, + 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, + 'tags': {'key': 'manifest.tags', 'type': '[str]'}, + 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( self, *, registry: Optional[str] = None, - image_name: Optional[str] = None, - attributes: Optional["ManifestAttributesBase"] = None, + repository: Optional[str] = None, + digest: Optional[str] = None, + size: Optional[int] = None, + created_on: Optional[datetime.datetime] = None, + last_updated_on: Optional[datetime.datetime] = None, + cpu_architecture: Optional[str] = None, + operating_system: Optional[str] = None, + manifest_media_type: Optional[str] = None, + config_media_type: Optional[str] = None, + tags: Optional[List[str]] = None, + manifest_properties: Optional["ChangeableAttributes"] = None, **kwargs ): super(ManifestAttributes, self).__init__(**kwargs) self.registry = registry - self.image_name = image_name - self.attributes = attributes + self.repository = repository + self.digest = digest + self.size = size + self.created_on = created_on + self.last_updated_on = last_updated_on + self.cpu_architecture = cpu_architecture + self.operating_system = operating_system + self.manifest_media_type = manifest_media_type + self.config_media_type = config_media_type + self.tags = tags + self.manifest_properties = manifest_properties class ManifestAttributesBase(msrest.serialization.Model): @@ -504,65 +549,65 @@ class ManifestAttributesBase(msrest.serialization.Model): :param digest: Manifest. :type digest: str - :param image_size: Image size. - :type image_size: long - :param created_time: Created time. - :type created_time: str - :param last_update_time: Last update time. - :type last_update_time: str - :param architecture: CPU architecture. - :type architecture: str - :param os: Operating system. - :type os: str - :param media_type: Media type. - :type media_type: str + :param size: Image size. + :type size: long + :param created_on: Created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Last update time. + :type last_updated_on: ~datetime.datetime + :param cpu_architecture: CPU architecture. + :type cpu_architecture: str + :param operating_system: Operating system. + :type operating_system: str + :param manifest_media_type: Media type. + :type manifest_media_type: str :param config_media_type: Config blob media type. :type config_media_type: str :param tags: A set of tags. List of tags. :type tags: list[str] - :param changeable_attributes: Changeable attributes. - :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + :param manifest_properties: Changeable attributes. + :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'digest': {'key': 'digest', 'type': 'str'}, - 'image_size': {'key': 'imageSize', 'type': 'long'}, - 'created_time': {'key': 'createdTime', 'type': 'str'}, - 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, - 'architecture': {'key': 'architecture', 'type': 'str'}, - 'os': {'key': 'os', 'type': 'str'}, - 'media_type': {'key': 'mediaType', 'type': 'str'}, + 'size': {'key': 'imageSize', 'type': 'long'}, + 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, + 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, + 'operating_system': {'key': 'os', 'type': 'str'}, + 'manifest_media_type': {'key': 'mediaType', 'type': 'str'}, 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( self, *, digest: Optional[str] = None, - image_size: Optional[int] = None, - created_time: Optional[str] = None, - last_update_time: Optional[str] = None, - architecture: Optional[str] = None, - os: Optional[str] = None, - media_type: Optional[str] = None, + size: Optional[int] = None, + created_on: Optional[datetime.datetime] = None, + last_updated_on: Optional[datetime.datetime] = None, + cpu_architecture: Optional[str] = None, + operating_system: Optional[str] = None, + manifest_media_type: Optional[str] = None, config_media_type: Optional[str] = None, tags: Optional[List[str]] = None, - changeable_attributes: Optional["ChangeableAttributes"] = None, + manifest_properties: Optional["ChangeableAttributes"] = None, **kwargs ): super(ManifestAttributesBase, self).__init__(**kwargs) self.digest = digest - self.image_size = image_size - self.created_time = created_time - self.last_update_time = last_update_time - self.architecture = architecture - self.os = os - self.media_type = media_type + self.size = size + self.created_on = created_on + self.last_updated_on = last_updated_on + self.cpu_architecture = cpu_architecture + self.operating_system = operating_system + self.manifest_media_type = manifest_media_type self.config_media_type = config_media_type self.tags = tags - self.changeable_attributes = changeable_attributes + self.manifest_properties = manifest_properties class ManifestAttributesManifest(msrest.serialization.Model): @@ -1077,50 +1122,50 @@ class RepositoryAttributes(msrest.serialization.Model): :param registry: Registry name. :type registry: str - :param image_name: Image name. - :type image_name: str - :param created_time: Image created time. - :type created_time: str - :param last_update_time: Image last update time. - :type last_update_time: str - :param manifest_count: Number of the manifests. - :type manifest_count: int + :param name: Image name. + :type name: str + :param created_on: Image created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Image last update time. + :type last_updated_on: ~datetime.datetime + :param registry_artifact_count: Number of the manifests. + :type registry_artifact_count: int :param tag_count: Number of the tags. :type tag_count: int - :param changeable_attributes: Changeable attributes. - :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + :param writeable_properties: Changeable attributes. + :type writeable_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, - 'created_time': {'key': 'createdTime', 'type': 'str'}, - 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, - 'manifest_count': {'key': 'manifestCount', 'type': 'int'}, + 'name': {'key': 'imageName', 'type': 'str'}, + 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, + 'registry_artifact_count': {'key': 'manifestCount', 'type': 'int'}, 'tag_count': {'key': 'tagCount', 'type': 'int'}, - 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( self, *, registry: Optional[str] = None, - image_name: Optional[str] = None, - created_time: Optional[str] = None, - last_update_time: Optional[str] = None, - manifest_count: Optional[int] = None, + name: Optional[str] = None, + created_on: Optional[datetime.datetime] = None, + last_updated_on: Optional[datetime.datetime] = None, + registry_artifact_count: Optional[int] = None, tag_count: Optional[int] = None, - changeable_attributes: Optional["ChangeableAttributes"] = None, + writeable_properties: Optional["ChangeableAttributes"] = None, **kwargs ): super(RepositoryAttributes, self).__init__(**kwargs) self.registry = registry - self.image_name = image_name - self.created_time = created_time - self.last_update_time = last_update_time - self.manifest_count = manifest_count + self.name = name + self.created_on = created_on + self.last_updated_on = last_updated_on + self.registry_artifact_count = registry_artifact_count self.tag_count = tag_count - self.changeable_attributes = changeable_attributes + self.writeable_properties = writeable_properties class RepositoryTags(msrest.serialization.Model): @@ -1154,30 +1199,50 @@ class TagAttributes(msrest.serialization.Model): :param registry: Registry name. :type registry: str - :param image_name: Image name. - :type image_name: str - :param attributes: List of tag attribute details. - :type attributes: ~azure.containerregistry.models.TagAttributesBase + :param repository: Image name. + :type repository: str + :param name: Tag name. + :type name: str + :param digest: Tag digest. + :type digest: str + :param created_on: Tag created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Tag last update time. + :type last_updated_on: ~datetime.datetime + :param modifiable_properties: Changeable attributes. + :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, - 'attributes': {'key': 'tag', 'type': 'TagAttributesBase'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'name': {'key': 'tag.name', 'type': 'str'}, + 'digest': {'key': 'tag.digest', 'type': 'str'}, + 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, + 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( self, *, registry: Optional[str] = None, - image_name: Optional[str] = None, - attributes: Optional["TagAttributesBase"] = None, + repository: Optional[str] = None, + name: Optional[str] = None, + digest: Optional[str] = None, + created_on: Optional[datetime.datetime] = None, + last_updated_on: Optional[datetime.datetime] = None, + modifiable_properties: Optional["ChangeableAttributes"] = None, **kwargs ): super(TagAttributes, self).__init__(**kwargs) self.registry = registry - self.image_name = image_name - self.attributes = attributes + self.repository = repository + self.name = name + self.digest = digest + self.created_on = created_on + self.last_updated_on = last_updated_on + self.modifiable_properties = modifiable_properties class TagAttributesBase(msrest.serialization.Model): @@ -1187,23 +1252,20 @@ class TagAttributesBase(msrest.serialization.Model): :type name: str :param digest: Tag digest. :type digest: str - :param created_time: Tag created time. - :type created_time: str - :param last_update_time: Tag last update time. - :type last_update_time: str - :param signed: Is signed. - :type signed: bool - :param changeable_attributes: Changeable attributes. - :type changeable_attributes: ~azure.containerregistry.models.ChangeableAttributes + :param created_on: Tag created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Tag last update time. + :type last_updated_on: ~datetime.datetime + :param modifiable_properties: Changeable attributes. + :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes """ _attribute_map = { 'name': {'key': 'name', 'type': 'str'}, 'digest': {'key': 'digest', 'type': 'str'}, - 'created_time': {'key': 'createdTime', 'type': 'str'}, - 'last_update_time': {'key': 'lastUpdateTime', 'type': 'str'}, - 'signed': {'key': 'signed', 'type': 'bool'}, - 'changeable_attributes': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, + 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, } def __init__( @@ -1211,19 +1273,17 @@ def __init__( *, name: Optional[str] = None, digest: Optional[str] = None, - created_time: Optional[str] = None, - last_update_time: Optional[str] = None, - signed: Optional[bool] = None, - changeable_attributes: Optional["ChangeableAttributes"] = None, + created_on: Optional[datetime.datetime] = None, + last_updated_on: Optional[datetime.datetime] = None, + modifiable_properties: Optional["ChangeableAttributes"] = None, **kwargs ): super(TagAttributesBase, self).__init__(**kwargs) self.name = name self.digest = digest - self.created_time = created_time - self.last_update_time = last_update_time - self.signed = signed - self.changeable_attributes = changeable_attributes + self.created_on = created_on + self.last_updated_on = last_updated_on + self.modifiable_properties = modifiable_properties class TagAttributesTag(msrest.serialization.Model): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py index d6560dfe7906..95b29f5d1bda 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py @@ -6,20 +6,16 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._v2_support_operations import V2SupportOperations -from ._manifests_operations import ManifestsOperations -from ._blob_operations import BlobOperations -from ._repository_operations import RepositoryOperations -from ._tag_operations import TagOperations +from ._container_registry_operations import ContainerRegistryOperations +from ._container_registry_repository_operations import ContainerRegistryRepositoryOperations +from ._container_registry_blob_operations import ContainerRegistryBlobOperations from ._refresh_tokens_operations import RefreshTokensOperations from ._access_tokens_operations import AccessTokensOperations __all__ = [ - 'V2SupportOperations', - 'ManifestsOperations', - 'BlobOperations', - 'RepositoryOperations', - 'TagOperations', + 'ContainerRegistryOperations', + 'ContainerRegistryRepositoryOperations', + 'ContainerRegistryBlobOperations', 'RefreshTokensOperations', 'AccessTokensOperations', ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py index 556176224bc0..5b11a2fb1de9 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py @@ -117,7 +117,7 @@ def get_from_login( **kwargs # type: Any ): # type: (...) -> "_models.AccessToken" - """Exchange Username, Password, and Scope for an ACR Access Token. + """Exchange Username, Password and Scope an ACR Access Token. :param service: Indicates the name of your Azure container registry. :type service: str diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py similarity index 95% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_blob_operations.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py index 6299667471ec..c20df3d43b5a 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py @@ -21,8 +21,8 @@ T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] -class BlobOperations(object): - """BlobOperations operations. +class ContainerRegistryBlobOperations(object): + """ContainerRegistryBlobOperations operations. You should not instantiate this class directly. Instead, you should create a Client instance that instantiates it for you and attaches it as an attribute. @@ -43,7 +43,7 @@ def __init__(self, client, config, serializer, deserializer): self._deserialize = deserializer self._config = config - def get( + def get_blob( self, name, # type: str digest, # type: str @@ -69,7 +69,7 @@ def get( accept = "application/octet-stream" # Construct URL - url = self.get.metadata['url'] # type: ignore + url = self.get_blob.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -106,9 +106,9 @@ def get( return cls(pipeline_response, deserialized, response_headers) return deserialized - get.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + get_blob.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - def check( + def check_blob_exists( self, name, # type: str digest, # type: str @@ -134,7 +134,7 @@ def check( accept = "application/json" # Construct URL - url = self.check.metadata['url'] # type: ignore + url = self.check_blob_exists.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -169,9 +169,9 @@ def check( if cls: return cls(pipeline_response, None, response_headers) - check.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + check_blob_exists.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - def delete( + def delete_blob( self, name, # type: str digest, # type: str @@ -197,7 +197,7 @@ def delete( accept = "application/octet-stream" # Construct URL - url = self.delete.metadata['url'] # type: ignore + url = self.delete_blob.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -228,9 +228,9 @@ def delete( return cls(pipeline_response, deserialized, response_headers) return deserialized - delete.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + delete_blob.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - def mount( + def mount_blob( self, name, # type: str from_parameter, # type: str @@ -259,7 +259,7 @@ def mount( accept = "application/json" # Construct URL - url = self.mount.metadata['url'] # type: ignore + url = self.mount_blob.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -292,9 +292,9 @@ def mount( if cls: return cls(pipeline_response, None, response_headers) - mount.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore + mount_blob.metadata = {'url': '/v2/{name}/blobs/uploads/'} # type: ignore - def get_status( + def get_upload_status( self, location, # type: str **kwargs # type: Any @@ -319,7 +319,7 @@ def get_status( accept = "application/json" # Construct URL - url = self.get_status.metadata['url'] # type: ignore + url = self.get_upload_status.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), @@ -349,9 +349,9 @@ def get_status( if cls: return cls(pipeline_response, None, response_headers) - get_status.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + get_upload_status.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore - def upload( + def upload_chunk( self, location, # type: str value, # type: IO @@ -379,7 +379,7 @@ def upload( accept = "application/json" # Construct URL - url = self.upload.metadata['url'] # type: ignore + url = self.upload_chunk.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), @@ -413,9 +413,9 @@ def upload( if cls: return cls(pipeline_response, None, response_headers) - upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + upload_chunk.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore - def end_upload( + def complete_upload( self, digest, # type: str location, # type: str @@ -447,7 +447,7 @@ def end_upload( accept = "application/json" # Construct URL - url = self.end_upload.metadata['url'] # type: ignore + url = self.complete_upload.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'nextBlobUuidLink': self._serialize.url("location", location, 'str', skip_quote=True), @@ -482,7 +482,7 @@ def end_upload( if cls: return cls(pipeline_response, None, response_headers) - end_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore + complete_upload.metadata = {'url': '/{nextBlobUuidLink}'} # type: ignore def cancel_upload( self, @@ -661,7 +661,7 @@ def get_chunk( return deserialized get_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore - def check_chunk( + def check_chunk_exists( self, name, # type: str digest, # type: str @@ -691,7 +691,7 @@ def check_chunk( accept = "application/json" # Construct URL - url = self.check_chunk.metadata['url'] # type: ignore + url = self.check_chunk_exists.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -723,4 +723,4 @@ def check_chunk( if cls: return cls(pipeline_response, None, response_headers) - check_chunk.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore + check_chunk_exists.metadata = {'url': '/v2/{name}/blobs/{digest}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py similarity index 80% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_repository_operations.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py index e052b61810ce..f738bcf7913b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py @@ -21,8 +21,8 @@ T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] -class RepositoryOperations(object): - """RepositoryOperations operations. +class ContainerRegistryOperations(object): + """ContainerRegistryOperations operations. You should not instantiate this class directly. Instead, you should create a Client instance that instantiates it for you and attaches it as an attribute. @@ -43,7 +43,54 @@ def __init__(self, client, config, serializer, deserializer): self._deserialize = deserializer self._config = config - def get_list( + def check_docker_v2_support( + self, + **kwargs # type: Any + ): + # type: (...) -> None + """Tells whether this Docker Registry instance supports Docker Registry HTTP API v2. + + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.check_docker_v2_support.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + check_docker_v2_support.metadata = {'url': '/v2/'} # type: ignore + + def get_repositories( self, last=None, # type: Optional[str] n=None, # type: Optional[int] @@ -70,7 +117,7 @@ def get_list( accept = "application/json" # Construct URL - url = self.get_list.metadata['url'] # type: ignore + url = self.get_repositories.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), } @@ -104,9 +151,9 @@ def get_list( return cls(pipeline_response, deserialized, response_headers) return deserialized - get_list.metadata = {'url': '/acr/v1/_catalog'} # type: ignore + get_repositories.metadata = {'url': '/acr/v1/_catalog'} # type: ignore - def get_attributes( + def get_repository_attributes( self, name, # type: str **kwargs # type: Any @@ -129,7 +176,7 @@ def get_attributes( accept = "application/json" # Construct URL - url = self.get_attributes.metadata['url'] # type: ignore + url = self.get_repository_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -158,9 +205,9 @@ def get_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore + get_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore - def delete( + def delete_repository( self, name, # type: str **kwargs # type: Any @@ -183,7 +230,7 @@ def delete( accept = "application/json" # Construct URL - url = self.delete.metadata['url'] # type: ignore + url = self.delete_repository.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -212,9 +259,9 @@ def delete( return cls(pipeline_response, deserialized, {}) return deserialized - delete.metadata = {'url': '/acr/v1/{name}'} # type: ignore + delete_repository.metadata = {'url': '/acr/v1/{name}'} # type: ignore - def update_attributes( + def update_repository_attributes( self, name, # type: str value=None, # type: Optional["_models.ChangeableAttributes"] @@ -241,7 +288,7 @@ def update_attributes( accept = "application/json" # Construct URL - url = self.update_attributes.metadata['url'] # type: ignore + url = self.update_repository_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -274,4 +321,4 @@ def update_attributes( if cls: return cls(pipeline_response, None, {}) - update_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore + update_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_manifests_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py similarity index 57% rename from sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_manifests_operations.py rename to sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index af564014302a..e286c08e6106 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_manifests_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -21,8 +21,8 @@ T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] -class ManifestsOperations(object): - """ManifestsOperations operations. +class ContainerRegistryRepositoryOperations(object): + """ContainerRegistryRepositoryOperations operations. You should not instantiate this class directly. Instead, you should create a Client instance that instantiates it for you and attaches it as an attribute. @@ -43,14 +43,14 @@ def __init__(self, client, config, serializer, deserializer): self._deserialize = deserializer self._config = config - def get( + def get_manifest( self, name, # type: str reference, # type: str accept=None, # type: Optional[str] **kwargs # type: Any ): - # type: (...) -> "_models.ManifestWrapper" + # type: (...) -> "_models.Manifest" """Get the manifest identified by ``name`` and ``reference`` where ``reference`` can be a tag or digest. @@ -62,11 +62,11 @@ def get( application/vnd.docker.distribution.manifest.v2+json. :type accept: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: ManifestWrapper, or the result of cls(response) - :rtype: ~azure.containerregistry.models.ManifestWrapper + :return: Manifest, or the result of cls(response) + :rtype: ~azure.containerregistry.models.Manifest :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestWrapper"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.Manifest"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -74,7 +74,7 @@ def get( accept = "application/json" # Construct URL - url = self.get.metadata['url'] # type: ignore + url = self.get_manifest.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -100,19 +100,19 @@ def get( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('ManifestWrapper', pipeline_response) + deserialized = self._deserialize('Manifest', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) return deserialized - get.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + get_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore - def create( + def create_manifest( self, name, # type: str reference, # type: str - schema_version=None, # type: Optional[int] + payload, # type: "_models.Manifest" **kwargs # type: Any ): # type: (...) -> object @@ -123,8 +123,8 @@ def create( :type name: str :param reference: A tag or a digest, pointing to a specific image. :type reference: str - :param schema_version: Schema version. - :type schema_version: int + :param payload: Manifest body, can take v1 or v2 values depending on accept header. + :type payload: ~azure.containerregistry.models.Manifest :keyword callable cls: A custom type or function that will be passed the direct response :return: object, or the result of cls(response) :rtype: object @@ -135,13 +135,11 @@ def create( 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } error_map.update(kwargs.pop('error_map', {})) - - _payload = _models.Manifest(schema_version=schema_version) content_type = kwargs.pop("content_type", "application/vnd.docker.distribution.manifest.v2+json") accept = "application/json" # Construct URL - url = self.create.metadata['url'] # type: ignore + url = self.create_manifest.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -158,7 +156,7 @@ def create( header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(_payload, 'Manifest') + body_content = self._serialize.body(payload, 'Manifest') body_content_kwargs['content'] = body_content request = self._client.put(url, query_parameters, header_parameters, **body_content_kwargs) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) @@ -179,9 +177,9 @@ def create( return cls(pipeline_response, deserialized, response_headers) return deserialized - create.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + create_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore - def delete( + def delete_manifest( self, name, # type: str reference, # type: str @@ -208,7 +206,7 @@ def delete( accept = "application/json" # Construct URL - url = self.delete.metadata['url'] # type: ignore + url = self.delete_manifest.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -235,9 +233,263 @@ def delete( if cls: return cls(pipeline_response, None, {}) - delete.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + delete_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore - def get_list( + def get_tags( + self, + name, # type: str + last=None, # type: Optional[str] + n=None, # type: Optional[int] + orderby=None, # type: Optional[str] + digest=None, # type: Optional[str] + **kwargs # type: Any + ): + # type: (...) -> "_models.TagList" + """List tags of a repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param last: Query parameter for the last item in previous query. Result set will include + values lexically after last. + :type last: str + :param n: query parameter for max number of items. + :type n: int + :param orderby: orderby query parameter. + :type orderby: str + :param digest: filter by digest. + :type digest: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagList, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagList + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_tags.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + if digest is not None: + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagList', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_tags.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore + + def get_tag_attributes( + self, + name, # type: str + reference, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.TagAttributes" + """Get tag attributes by tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: TagAttributes, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagAttributes + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_tag_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('TagAttributes', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_tag_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + def update_tag_attributes( + self, + name, # type: str + reference, # type: str + value=None, # type: Optional["_models.ChangeableAttributes"] + **kwargs # type: Any + ): + # type: (...) -> None + """Update tag attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ChangeableAttributes + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.update_tag_attributes.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ChangeableAttributes') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + update_tag_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + def delete_tag( + self, + name, # type: str + reference, # type: str + **kwargs # type: Any + ): + # type: (...) -> None + """Delete tag. + + :param name: Name of the image (including the namespace). + :type name: str + :param reference: Tag name. + :type reference: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.delete_tag.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + 'reference': self._serialize.url("reference", reference, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.delete(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [202]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + delete_tag.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + + def get_manifests( self, name, # type: str last=None, # type: Optional[str] @@ -270,7 +522,7 @@ def get_list( accept = "application/json" # Construct URL - url = self.get_list.metadata['url'] # type: ignore + url = self.get_manifests.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -305,12 +557,12 @@ def get_list( return cls(pipeline_response, deserialized, {}) return deserialized - get_list.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore + get_manifests.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore - def get_attributes( + def get_manifest_attributes( self, name, # type: str - reference, # type: str + digest, # type: str **kwargs # type: Any ): # type: (...) -> "_models.ManifestAttributes" @@ -318,8 +570,8 @@ def get_attributes( :param name: Name of the image (including the namespace). :type name: str - :param reference: A tag or a digest, pointing to a specific image. - :type reference: str + :param digest: Digest of a BLOB. + :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response :return: ManifestAttributes, or the result of cls(response) :rtype: ~azure.containerregistry.models.ManifestAttributes @@ -333,11 +585,11 @@ def get_attributes( accept = "application/json" # Construct URL - url = self.get_attributes.metadata['url'] # type: ignore + url = self.get_manifest_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), } url = self._client.format_url(url, **path_format_arguments) @@ -363,12 +615,12 @@ def get_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore - def update_attributes( + def update_manifest_attributes( self, name, # type: str - reference, # type: str + digest, # type: str value=None, # type: Optional["_models.ChangeableAttributes"] **kwargs # type: Any ): @@ -377,8 +629,8 @@ def update_attributes( :param name: Name of the image (including the namespace). :type name: str - :param reference: A tag or a digest, pointing to a specific image. - :type reference: str + :param digest: Digest of a BLOB. + :type digest: str :param value: Repository attribute value. :type value: ~azure.containerregistry.models.ChangeableAttributes :keyword callable cls: A custom type or function that will be passed the direct response @@ -395,11 +647,11 @@ def update_attributes( accept = "application/json" # Construct URL - url = self.update_attributes.metadata['url'] # type: ignore + url = self.update_manifest_attributes.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), + 'digest': self._serialize.url("digest", digest, 'str'), } url = self._client.format_url(url, **path_format_arguments) @@ -429,4 +681,4 @@ def update_attributes( if cls: return cls(pipeline_response, None, {}) - update_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + update_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py deleted file mode 100644 index 91687e56f057..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_tag_operations.py +++ /dev/null @@ -1,298 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import TYPE_CHECKING -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import HttpRequest, HttpResponse - -from .. import models as _models - -if TYPE_CHECKING: - # pylint: disable=unused-import,ungrouped-imports - from typing import Any, Callable, Dict, Generic, Optional, TypeVar - - T = TypeVar('T') - ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] - -class TagOperations(object): - """TagOperations operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer): - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - def get_list( - self, - name, # type: str - last=None, # type: Optional[str] - n=None, # type: Optional[int] - orderby=None, # type: Optional[str] - digest=None, # type: Optional[str] - **kwargs # type: Any - ): - # type: (...) -> "_models.TagList" - """List tags of a repository. - - :param name: Name of the image (including the namespace). - :type name: str - :param last: Query parameter for the last item in previous query. Result set will include - values lexically after last. - :type last: str - :param n: query parameter for max number of items. - :type n: int - :param orderby: orderby query parameter. - :type orderby: str - :param digest: filter by digest. - :type digest: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagList, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagList - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_list.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - if orderby is not None: - query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') - if digest is not None: - query_parameters['digest'] = self._serialize.query("digest", digest, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('TagList', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_list.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore - - def get_attributes( - self, - name, # type: str - reference, # type: str - **kwargs # type: Any - ): - # type: (...) -> "_models.TagAttributes" - """Get tag attributes by tag. - - :param name: Name of the image (including the namespace). - :type name: str - :param reference: Tag name. - :type reference: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagAttributes - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('TagAttributes', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore - - def update_attributes( - self, - name, # type: str - reference, # type: str - value=None, # type: Optional["_models.ChangeableAttributes"] - **kwargs # type: Any - ): - # type: (...) -> None - """Update tag attributes. - - :param name: Name of the image (including the namespace). - :type name: str - :param reference: Tag name. - :type reference: str - :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/json") - accept = "application/json" - - # Construct URL - url = self.update_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - update_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore - - def delete( - self, - name, # type: str - reference, # type: str - **kwargs # type: Any - ): - # type: (...) -> None - """Delete tag. - - :param name: Name of the image (including the namespace). - :type name: str - :param reference: Tag name. - :type reference: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.delete.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - 'reference': self._serialize.url("reference", reference, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.delete(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [202]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - delete.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py deleted file mode 100644 index 30ee5166ea93..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_v2_support_operations.py +++ /dev/null @@ -1,91 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import TYPE_CHECKING -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import HttpRequest, HttpResponse - -from .. import models as _models - -if TYPE_CHECKING: - # pylint: disable=unused-import,ungrouped-imports - from typing import Any, Callable, Dict, Generic, Optional, TypeVar - - T = TypeVar('T') - ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] - -class V2SupportOperations(object): - """V2SupportOperations operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer): - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - def check( - self, - **kwargs # type: Any - ): - # type: (...) -> None - """Tells whether this Docker Registry instance supports Docker Registry HTTP API v2. - - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.check.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - check.metadata = {'url': '/v2/'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 361e1f2df2b7..356e0aaafd0c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -14,19 +14,19 @@ class ContentPermissions(object): def __init__(self, **kwargs): - self.delete = kwargs.get("delete") - self.list = kwargs.get("list") - self.read = kwargs.get("read") - self.write = kwargs.get("write") + self.can_delete = kwargs.get("can_delete") + self.can_list = kwargs.get("can_list") + self.can_read = kwargs.get("can_read") + self.can_write = kwargs.get("can_write") @classmethod def from_generated(cls, generated): # type: (azure.containerregistry._generated.models.ChangeableAttributes) -> ContentPermissions return cls( - delete=generated.delete_enabled, - list=generated.list_enabled, - read=generated.read_enabled, - write=generated.write_enabled + delete=generated.can_delete, + list=generated.can_list, + read=generated.can_read, + write=generated.can_write ) @@ -42,7 +42,7 @@ def __init__(self, **kwargs): class RegistryArtifactProperties(object): def __init__(self, **kwargs): - self.created_time = kwargs.get("created_time", None) + self.created_on = kwargs.get("created_on", None) self.image_name = kwargs.get("image_name", None) self.registry = kwargs.get("registry", None) self.manifest_properties = ManifestProperties.from_generated(kwargs.get("manifest_attributes")) @@ -62,7 +62,7 @@ def __init__(self, **kwargs): def from_generated(cls, generated): # type: (azure.containerregistry._generated.models.ManfiestAttributestBase) -> RegistryArtifactProperties cls( - created_time=generated.created_time, + created_on=generated.created_on, image_name=generated.image_name, registry=generated.registry, manifest_attributes=generated.manifest_attributes, @@ -72,10 +72,10 @@ def from_generated(cls, generated): class RepositoryProperties(object): """Model for storing properties of a single repository - :ivar created_time: Time the repository was created - :vartype created_time: str - :ivar last_updated_time: Time the repository was last updated - :vartype last_updated_time: str + :ivar created_on: Time the repository was created + :vartype created_on: str + :ivar last_updated_on: Time the repository was last updated + :vartype last_updated_on: str :ivar modifiable_properties: Read/Write/Update/Delete permissions for the repository :vartype modifiable_properties: ContentPermissions :ivar name: Name of the repository @@ -91,27 +91,28 @@ class RepositoryProperties(object): """ def __init__(self, **kwargs): - self.created_time = kwargs.get("created_time", None) - self.last_updated_time = kwargs.get("last_updated_time", None) + self.created_on = kwargs.get("created_on", None) + self.last_updated_on = kwargs.get("last_updated_on", None) self.modifiable_properties = kwargs.get("modifiable_properties", None) self.name = kwargs.get("name", None) self.registry = kwargs.get("registry", None) self.tag_count = kwargs.get("tag_count", None) self.manifest_count = kwargs.get("manifest_count", None) - # self.repository = kwargs.get("repository", None) - # self.digest = kwargs.get("digest", None) + self.content_permissions = kwargs.get('content_permissions', None) + if self.content_permissions: + self.content_permissions = ContentPermissions.from_generated(self.content_permissions) @classmethod def from_generated(cls, generated): # type: (azure.containerregistry._generated.models.RepositoryAttributes) -> RepositoryProperties return cls( - created_time=generated.created_time, - name=generated.image_name, - last_updated_time=generated.last_updated_time, + created_on=generated.created_on, + last_updated_on=generated.last_updated_on, + name=generated.name, registry=generated.registry, - manifest_count=generated.manifest_count, + manifest_count=generated.registry_artifact_count, tag_count=generated.tag_count, - content_permissions=generated.changeable_attributes + content_permissions=generated.writeable_properties ) return cls(generated) diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml index 652bdb6dacaf..85577d77558d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -15,7 +15,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-03T13:06:08.1190646Z","lastUpdateTime":"2021-03-03T13:06:08.2369442Z","manifestCount":1,"tagCount":1,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} ' headers: @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 12:30:22 GMT + - Tue, 16 Mar 2021 17:05:14 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml similarity index 71% rename from sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml rename to sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml index eccb8c9ed4a1..00cfb50242e5 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -8,17 +8,14 @@ interactions: - gzip, deflate Connection: - keep-alive - Content-Length: - - '0' User-Agent: - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE + method: GET uri: https://fake_url.azurecr.io/acr/v1/hello-world response: body: - string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known - to registry","detail":{"name":"hello-world"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} ' headers: @@ -30,11 +27,11 @@ interactions: connection: - keep-alive content-length: - - '119' + - '289' content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 14:58:42 GMT + - Tue, 16 Mar 2021 17:10:14 GMT docker-distribution-api-version: - registry/2.0 server: @@ -45,6 +42,6 @@ interactions: x-content-type-options: - nosniff status: - code: 404 - message: Not Found + code: 200 + message: OK version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index d1ea4e374745..1860012a9c1c 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -11,8 +11,9 @@ from azure.containerregistry import ( ContainerRepositoryClient, ContainerRegistryClient, + RepositoryProperties, + ContentPermissions ) -from azure.identity import DefaultAzureCredential from _shared.testcase import ContainerRegistryTestClass @@ -40,6 +41,17 @@ def test_delete_repository(self, containerregistry_baseurl): assert repo_count == 0 + @acr_preparer() + def test_get_properties(self, containerregistry_baseurl): + reg_client = self.create_repository_client(containerregistry_baseurl, "hello-world") + + properties = reg_client.get_properties() + + assert isinstance(properties, RepositoryProperties) + assert properties.name == "hello-world" + assert properties.registry == containerregistry_baseurl + assert isinstance(properties.content_permissions, ContentPermissions) + @acr_preparer() def test_list_tags(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) From 4533ccefd8db928a637d6d5d21d2b00ddaba8189 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 16 Mar 2021 15:24:58 -0400 Subject: [PATCH 22/86] added delete method, more models are filled out --- .../azure/containerregistry/__init__.py | 4 + .../_container_registry_client.py | 7 +- .../_container_repository_client.py | 12 ++- .../azure/containerregistry/_models.py | 76 ++++++++++++++++--- .../tests/_shared/testcase.py | 45 +++++++++++ ...repository_client.test_get_attributes.yaml | 2 +- ...repository_client.test_get_properties.yaml | 2 +- ...tainer_repository_client.test_get_tag.yaml | 47 ++++++++++++ .../tests/test_container_registry_client.py | 11 +++ .../tests/test_container_repository_client.py | 54 ++++++++----- 10 files changed, 223 insertions(+), 37 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index e10e196e32df..e70fcdf27c83 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -14,8 +14,10 @@ ContentPermissions, DeletedRepositoryResult, RegistryArtifactOrderBy, + RegistryArtifactProperties, RepositoryProperties, TagOrderBy, + TagProperties ) from ._storage_models import ( ArtifactManifest, @@ -56,8 +58,10 @@ "ContentPermissions", "DeletedRepositoryResult", "RegistryArtifactOrderBy", + "RegistryArtifactProperties", "RepositoryProperties", "TagOrderBy", + "TagProperties", "ArtifactManifest", "CompleteUploadResult", "ConfigMediaType", diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 22be45dcf345..588057a40480 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -8,7 +8,7 @@ from azure.core.paging import ItemPaged from ._base_client import ContainerRegistryBaseClient -from ._models import RepositoryProperties +from ._models import RepositoryProperties, DeletedRepositoryResult class ContainerRegistryClient(ContainerRegistryBaseClient): @@ -41,7 +41,9 @@ def delete_repository(self, repository, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - raise NotImplementedError("Not implemented") + # NOTE: DELETE `/acr/v1/{name}` + deleted_repository = self._client.container_registry.delete_repository(repository) + return DeletedRepositoryResult.from_generated(deleted_repository) def list_repositories(self, **kwargs): # type: (...) -> ItemPaged[str] @@ -54,6 +56,7 @@ def list_repositories(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[str] :raises: None """ + # NOTE: `/acr/v1/_catalog` raise NotImplementedError("Not implemented") repos = self._client.repository.get_list( last=kwargs.get("last", None), n=kwargs.get("max", None) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 2bdde23d262b..1cdcda45c730 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -5,7 +5,7 @@ # ------------------------------------ from ._base_client import ContainerRegistryBaseClient -from ._models import RepositoryProperties +from ._models import RepositoryProperties, TagProperties, RegistryArtifactProperties class ContainerRepositoryClient(ContainerRegistryBaseClient): @@ -81,7 +81,11 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :returns: :class:~azure.containerregistry.RegistryArtifactProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - raise NotImplementedError("Has not been implemented") + # TODO: If `tag_or_digest` is a tag, need to do a get_tags to find the appropriate digest, generated code only takes a digest + # TODO: The returned object from the generated code is not being deserialized properly + return RegistryArtifactProperties.from_generated( + self._client.container_registry_repository.get_manifest_attributes(self.repository, tag_or_digest) + ) def get_tag_properties(self, tag, **kwargs): # type: (str) -> TagProperties @@ -92,7 +96,9 @@ def get_tag_properties(self, tag, **kwargs): :returns: :class:~azure.containerregistry.TagProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - return self._client.tag.get_attributes() + return TagProperties.from_generated( + self._client.container_registry_repository.get_tag_attributes(self.repository, tag) + ) def list_registry_artifacts(self, **kwargs): # type: (...) -> ItemPaged[RegistryArtifactProperties] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 356e0aaafd0c..ad45a7eb09ca 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -8,9 +8,6 @@ from azure.core.paging import PageIterator -from ._generated.models import ( - DeletedRepository, -) class ContentPermissions(object): def __init__(self, **kwargs): @@ -30,23 +27,25 @@ def from_generated(cls, generated): ) -class DeletedRepositoryResult(DeletedRepository): +class DeletedRepositoryResult(object): def __init__(self, **kwargs): - super(DeletedRepositoryResult, self).__init__(**kwargs) self.deleted_registry_artifact_digests = kwargs.get( "deleted_registry_artifact_digests", None ) self.deleted_tags = kwargs.get("deleted_tags", None) - pass + + @classmethod + def from_generated(cls, gen): + return cls( + deleted_tags=gen.deleted_tags, + deleted_registry_artifact_digests=gen.deleted_registry_artifact_digests + ) class RegistryArtifactProperties(object): def __init__(self, **kwargs): self.created_on = kwargs.get("created_on", None) - self.image_name = kwargs.get("image_name", None) self.registry = kwargs.get("registry", None) - self.manifest_properties = ManifestProperties.from_generated(kwargs.get("manifest_attributes")) - # self.cpu_arch = kwargs.get("arch", None) # self.digest = kwargs.get("digest", None) # self.last_updated = kwargs.get("last_updated", None) @@ -61,11 +60,19 @@ def __init__(self, **kwargs): @classmethod def from_generated(cls, generated): # type: (azure.containerregistry._generated.models.ManfiestAttributestBase) -> RegistryArtifactProperties - cls( + return cls( + config_media_type=generated.config_media_type, + cpu_architecture=generated.cpu_architecture, created_on=generated.created_on, - image_name=generated.image_name, + digest=generated.digest, + last_updated_on=generated.last_updated_on, + manifest_media_type=generated.manifest_media_type, + manifest_properties=generated.manifest_properties, + operating_system=generated.operating_system, registry=generated.registry, - manifest_attributes=generated.manifest_attributes, + repository=generated.repository, + size=generated.size, + tags=generated.tags, ) @@ -127,3 +134,48 @@ class TagOrderBy(int, Enum): LastUpdateTimeDescending = 0 LastUpdateTimeAscending = 1 + + +class TagProperties(object): + """Model for storing properties of a single tag + + :ivar created_on: Time the tag was created + :vartype created_on: datetime + :ivar digest: Digest for the tag + :vartype digest: str + :ivar last_updated_on: Time the tag was last updated + :vartype last_updated_on: datetime + :ivar modifiable_properties: Read/Write/Update/Delete permissions for the tag + :vartype modifiable_properties: ContentPermissions + :ivar name: Name of the image the tag corresponds to + :vartype name: str + :ivar registry: Registry the tag belongs to + :vartype registry: str + :ivar repository: Repository the tag belongs to + :vartype repository: str + """ + + def __init__(self, **kwargs): + self.created_on = kwargs.get("created_on", None) + self.digest = kwargs.get("digest", None) + self.last_updated_on = kwargs.get("last_updated_on", None) + self.content_permissions = kwargs.get("content_permissions", None) + if self.content_permissions: + self.content_permissions = ContentPermissions.from_generated(self.content_permissions) + self.name = kwargs.get("name", None) + self.registry = kwargs.get("registry", None) + self.repository = kwargs.get("repository", None) + + @classmethod + def from_generated(cls, generated): + return cls( + created_on=generated.created_on, + digest=generated.digest, + last_updated_on=generated.last_updated_on, + content_permissions=generated.modifiable_properties, + name=generated.name, + registry=generated.registry, + repository=generated.repository, + ) + + diff --git a/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py index b713a23cefd9..4e469668719c 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py @@ -3,14 +3,19 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from datetime import datetime import os from azure.containerregistry import ( ContainerRepositoryClient, ContainerRegistryClient, ContainerRegistryUserCredential, + TagProperties, + ContentPermissions, + RegistryArtifactProperties, ) + class ContainerRegistryTestClass(object): def create_registry_client(self, endpoint): return ContainerRegistryClient( @@ -30,3 +35,43 @@ def create_repository_client(self, endpoint, name): password=os.environ["CONTAINERREGISTRY_PASSWORD"], ), ) + + def assert_content_permission(self, content_perm, content_perm2): + assert isinstance(content_perm, ContentPermissions) + assert isinstance(content_perm2, ContentPermissions) + assert content_perm.can_delete == content_perm.can_delete + assert content_perm.can_list == content_perm.can_list + assert content_perm.can_read == content_perm.can_read + assert content_perm.can_write == content_perm.can_write + + def assert_tag( + self, + tag, + created_on=None, + digest=None, + last_updated_on=None, + content_permission=None, + name=None, + registry=None, + repository=None, + ): + assert isinstance(tag, TagProperties) + assert isinstance(tag.content_permissions, ContentPermissions) + assert isinstance(tag.created_on, datetime) + assert isinstance(tag.last_updated_on, datetime) + if content_permission: + self.assert_content_permission(tag.content_permission, content_permission) + if created_on: + assert tag.created_on == created_on + if last_updated_on: + assert tag.last_updated_on == last_updated_on + if name: + assert tag.name == name + if registry: + assert tag.registry == registry + if repository: + assert tag.repository == repository + + def assert_registry_artifact(self, tag_or_digest, expected_tag_or_digest): + assert isinstance(tag_or_digest, RegistryArtifactProperties) + assert tag_or_digest == expected_tag_or_digest \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml index 85577d77558d..e684d3d1f5b8 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 17:05:14 GMT + - Tue, 16 Mar 2021 18:02:17 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml index 00cfb50242e5..7f335e2c90c3 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 17:10:14 GMT + - Tue, 16 Mar 2021 18:02:18 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml new file mode 100644 index 000000000000..b66fb4c2793c --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '380' + content-type: + - application/json; charset=utf-8 + date: + - Tue, 16 Mar 2021 18:12:20 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 0ab094fd25cf..d2b518458a77 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -11,6 +11,7 @@ from azure.containerregistry import ( ContainerRegistryClient, ContainerRegistryUserCredential, + DeletedRepositoryResult, ) from azure.identity import DefaultAzureCredential @@ -36,3 +37,13 @@ def test_list_repositories(self, containerregistry_baseurl): count += 1 assert count > 0 + + @acr_preparer() + def test_delete_repository(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + deleted_result = client.delete_repository("debian") + + assert isinstance(deleted_result, DeletedRepositoryResult) + assert len(deleted_result.deleted_registry_artifact_digests) == 1 + assert len(deleted_result.deleted_tags) == 1 \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 1860012a9c1c..0ff00701ab15 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -5,6 +5,7 @@ # ------------------------------------ import functools import os +import pytest from devtools_testutils import AzureTestCase, PowerShellPreparer @@ -12,7 +13,8 @@ ContainerRepositoryClient, ContainerRegistryClient, RepositoryProperties, - ContentPermissions + ContentPermissions, + TagProperties, ) from _shared.testcase import ContainerRegistryTestClass @@ -41,6 +43,15 @@ def test_delete_repository(self, containerregistry_baseurl): assert repo_count == 0 + @acr_preparer() + def test_get_attributes(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + + repo_attribs = client.get_properties() + + assert repo_attribs is not None + assert repo_attribs.content_permissions is not None + @acr_preparer() def test_get_properties(self, containerregistry_baseurl): reg_client = self.create_repository_client(containerregistry_baseurl, "hello-world") @@ -50,8 +61,31 @@ def test_get_properties(self, containerregistry_baseurl): assert isinstance(properties, RepositoryProperties) assert properties.name == "hello-world" assert properties.registry == containerregistry_baseurl + assert properties.content_permissions is not None assert isinstance(properties.content_permissions, ContentPermissions) + @acr_preparer() + def test_get_registry_artifact_properties(self, containerregistry_baseurl): + reg_client = self.create_repository_client(containerregistry_baseurl, "hello-world") + + digest = "sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042" + tag = "first" + + properties = reg_client.get_registry_artifact_properties(digest) + first_properties = reg_client.get_registry_artifact_properties(tag) + + self.assert_registry_artifact(properties, digest) + self.assert_registry_artifact(first_properties, tag) + + @acr_preparer() + def test_get_tag(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + + tag = client.get_tag_properties("latest") + + self.assert_tag(tag) + + @pytest.mark.skip("List pending") @acr_preparer() def test_list_tags(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -64,15 +98,7 @@ def test_list_tags(self, containerregistry_baseurl): # assert count > 0 - @acr_preparer() - def test_get_attributes(self, containerregistry_baseurl): - client = self.create_repository_client(containerregistry_baseurl, self.repository) - - repo_attribs = client.get_properties() - - assert repo_attribs is not None - assert repo_attribs.content_permissions is not None - + @pytest.mark.skip("List pending") @acr_preparer() def test_list_registry_artifacts(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -80,11 +106,3 @@ def test_list_registry_artifacts(self, containerregistry_baseurl): repo_attribs = client.list_registry_artifacts() print(repo_attribs) - - @acr_preparer() - def test_get_tag(self, containerregistry_baseurl): - client = self.create_repository_client(containerregistry_baseurl, self.repository) - - repos = client.list_tags() - - tag = client.get_tag_properties() From 2b3bb91b5ad996497f50903325ed9ae2b11207ea Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 16 Mar 2021 15:50:56 -0400 Subject: [PATCH 23/86] code formatting and adding helper method to repository client --- .../azure/containerregistry/__init__.py | 2 +- .../_authentication_policy.py | 3 ++ .../azure/containerregistry/_base_client.py | 12 +++++--- .../_container_registry_client.py | 8 ++--- .../_container_repository_client.py | 30 +++++++++++++------ .../azure/containerregistry/_models.py | 18 ++++++----- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index e70fcdf27c83..b1761c81e194 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -17,7 +17,7 @@ RegistryArtifactProperties, RepositoryProperties, TagOrderBy, - TagProperties + TagProperties, ) from ._storage_models import ( ArtifactManifest, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index b2aef8d7d75d..81ebb8075d86 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -8,8 +8,10 @@ from azure.core.pipeline.policies import SansIOHTTPPolicy + class ContainerRegistryUserCredential(object): """Credential used to authenticate with Container Registry service""" + def __init__(self, username, password): self._user = username self._password = password @@ -23,6 +25,7 @@ def get_token(self): class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" + def __init__(self, credential): self.credential = credential diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 7187e2a23563..f261c64b7479 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -24,15 +24,15 @@ class ContainerRegistryApiVersion(str, Enum): class ContainerRegistryBaseClient(object): def __init__(self, endpoint, credential, **kwargs): - auth_policy = ContainerRegistryUserCredentialPolicy( - credential=credential - ) + auth_policy = ContainerRegistryUserCredentialPolicy(credential=credential) self._client = ContainerRegistry( credential=credential, url=endpoint, sdk_moniker=USER_AGENT, authentication_policy=auth_policy, - credential_scopes=kwargs.pop("credential_scopes", ["https://management.core.windows.net/.default"]), + credential_scopes=kwargs.pop( + "credential_scopes", ["https://management.core.windows.net/.default"] + ), **kwargs ) @@ -49,3 +49,7 @@ def close(self): Calling this method is unnecessary when using the client as a context manager. """ self._client.close() + + def _is_tag(self, tag_or_digest): + tag = tag_or_digest.split(":") + return len(tag) == 2 and tag[0] == u"sha" \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 588057a40480..f91c6b758ae6 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -42,7 +42,9 @@ def delete_repository(self, repository, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # NOTE: DELETE `/acr/v1/{name}` - deleted_repository = self._client.container_registry.delete_repository(repository) + deleted_repository = self._client.container_registry.delete_repository( + repository + ) return DeletedRepositoryResult.from_generated(deleted_repository) def list_repositories(self, **kwargs): @@ -61,9 +63,7 @@ def list_repositories(self, **kwargs): repos = self._client.repository.get_list( last=kwargs.get("last", None), n=kwargs.get("max", None) ) - return ItemPaged( - - ) + return ItemPaged() def get_repository_client(self, repository, **kwargs): # type: (str) -> ContainerRepositoryClient diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 1cdcda45c730..ee11503dc077 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -30,7 +30,6 @@ def __init__(self, endpoint, repository, credential, **kwargs): endpoint=self.endpoint, credential=credential, **kwargs ) - def delete(self, **kwargs): # type: (...) -> None """Delete a repository @@ -62,6 +61,12 @@ def delete_tag(self, tag): """ raise NotImplementedError("Has not been implemented") + def get_digest_from_tag(self, tag): + # type: (str) -> str + for t in self.list_tags(): + if t.tag == tag: + return t.digest + def get_properties(self): # type: (...) -> RepositoryProperties """Get the properties of a repository @@ -69,7 +74,9 @@ def get_properties(self): :returns: :class:~azure.containerregistry.RepositoryProperties :raises: None """ - resp = self._client.container_registry.get_repository_attributes(self.repository) + resp = self._client.container_registry.get_repository_attributes( + self.repository + ) return RepositoryProperties.from_generated(resp) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): @@ -82,9 +89,13 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # TODO: If `tag_or_digest` is a tag, need to do a get_tags to find the appropriate digest, generated code only takes a digest + if self._is_tag(tag_or_digest): + tag_or_digest = self.get_digest_from_tag(tag_or_digest) # TODO: The returned object from the generated code is not being deserialized properly return RegistryArtifactProperties.from_generated( - self._client.container_registry_repository.get_manifest_attributes(self.repository, tag_or_digest) + self._client.container_registry_repository.get_manifest_attributes( + self.repository, tag_or_digest + ) ) def get_tag_properties(self, tag, **kwargs): @@ -97,7 +108,9 @@ def get_tag_properties(self, tag, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ return TagProperties.from_generated( - self._client.container_registry_repository.get_tag_attributes(self.repository, tag) + self._client.container_registry_repository.get_tag_attributes( + self.repository, tag + ) ) def list_registry_artifacts(self, **kwargs): @@ -119,8 +132,9 @@ def list_registry_artifacts(self, **kwargs): self.repository, last=kwargs.get("last", None), n=kwargs.get("n", None), - orderby=kwargs.get("orderby"))#, - # cls=lambda objs: [RegistryArtifacts.from_generated(x) for x in objs]) + orderby=kwargs.get("orderby"), + ) # , + # cls=lambda objs: [RegistryArtifacts.from_generated(x) for x in objs]) return RegistryArtifactProperties.from_generated(artifacts) @@ -132,9 +146,7 @@ def list_tags(self, **kwargs): :raises: None """ raise NotImplementedError("Not implemented") - tags = self._client.container_registry.get_attributes( - self.repository, **kwargs - ) + tags = self._client.container_registry.get_attributes(self.repository, **kwargs) return tags def set_manifest_properties(self, digest, value): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index ad45a7eb09ca..401f13f5115b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -23,7 +23,7 @@ def from_generated(cls, generated): delete=generated.can_delete, list=generated.can_list, read=generated.can_read, - write=generated.can_write + write=generated.can_write, ) @@ -38,7 +38,7 @@ def __init__(self, **kwargs): def from_generated(cls, gen): return cls( deleted_tags=gen.deleted_tags, - deleted_registry_artifact_digests=gen.deleted_registry_artifact_digests + deleted_registry_artifact_digests=gen.deleted_registry_artifact_digests, ) @@ -105,9 +105,11 @@ def __init__(self, **kwargs): self.registry = kwargs.get("registry", None) self.tag_count = kwargs.get("tag_count", None) self.manifest_count = kwargs.get("manifest_count", None) - self.content_permissions = kwargs.get('content_permissions', None) + self.content_permissions = kwargs.get("content_permissions", None) if self.content_permissions: - self.content_permissions = ContentPermissions.from_generated(self.content_permissions) + self.content_permissions = ContentPermissions.from_generated( + self.content_permissions + ) @classmethod def from_generated(cls, generated): @@ -119,7 +121,7 @@ def from_generated(cls, generated): registry=generated.registry, manifest_count=generated.registry_artifact_count, tag_count=generated.tag_count, - content_permissions=generated.writeable_properties + content_permissions=generated.writeable_properties, ) return cls(generated) @@ -161,7 +163,9 @@ def __init__(self, **kwargs): self.last_updated_on = kwargs.get("last_updated_on", None) self.content_permissions = kwargs.get("content_permissions", None) if self.content_permissions: - self.content_permissions = ContentPermissions.from_generated(self.content_permissions) + self.content_permissions = ContentPermissions.from_generated( + self.content_permissions + ) self.name = kwargs.get("name", None) self.registry = kwargs.get("registry", None) self.repository = kwargs.get("repository", None) @@ -177,5 +181,3 @@ def from_generated(cls, generated): registry=generated.registry, repository=generated.repository, ) - - From 34b094ef1a4246bd0b1aed46b07fa3d7a302dcdc Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 17 Mar 2021 12:01:08 -0400 Subject: [PATCH 24/86] adding changes from newest swagger --- .../azure-containerregistry/swagger/README.md | 8 +++- ...repository_client.test_get_attributes.yaml | 2 +- ...repository_client.test_get_properties.yaml | 2 +- ...tainer_repository_client.test_get_tag.yaml | 47 ------------------- 4 files changed, 8 insertions(+), 51 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index 651bee61bf13..3669e8109f0c 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -2,7 +2,7 @@ ### Settings ``` yaml -input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/8642ffaf0354502860d31b4b07a506299cbed3f4/sdk/containerregistry/container-registry/swagger/containerregistry.json +input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/bb7ef909d6e465085cee3aa29f27453551722769/sdk/containerregistry/container-registry/swagger/containerregistry.json output-folder: "../azure/containerregistry/_generated" namespace: azure.containerregistry no-namespace-folders: true @@ -13,4 +13,8 @@ package-name: azure-containerregistry clear-output-folder: true enable-xml: true vanilla: true -``` \ No newline at end of file +``` + + \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml index e684d3d1f5b8..92b820121aa9 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 18:02:17 GMT + - Wed, 17 Mar 2021 15:00:58 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml index 7f335e2c90c3..0dfa210dfcc0 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 18:02:18 GMT + - Wed, 17 Mar 2021 15:00:59 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml deleted file mode 100644 index b66fb4c2793c..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '380' - content-type: - - application/json; charset=utf-8 - date: - - Tue, 16 Mar 2021 18:12:20 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 From a4d02587f716b6fee2435bc282d01d6962a66e24 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 17 Mar 2021 18:55:54 -0400 Subject: [PATCH 25/86] updated generated code --- .../_container_registry_operations.py | 125 ++++--- ...ontainer_registry_repository_operations.py | 245 +++++++------ .../_generated/models/__init__.py | 30 +- .../_generated/models/_models.py | 266 ++++++++------- .../_generated/models/_models_py3.py | 321 +++++++++--------- .../_container_registry_operations.py | 123 ++++--- ...ontainer_registry_repository_operations.py | 241 +++++++------ .../azure-containerregistry/swagger/README.md | 3 +- 8 files changed, 753 insertions(+), 601 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py index 1d4b9139e330..db138684e546 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py @@ -5,9 +5,10 @@ # Code generated by Microsoft (R) AutoRest Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from typing import Any, Callable, Dict, Generic, Optional, TypeVar +from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar import warnings +from azure.core.async_paging import AsyncItemPaged, AsyncList from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error from azure.core.pipeline import PipelineResponse from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest @@ -85,12 +86,12 @@ async def check_docker_v2_support( check_docker_v2_support.metadata = {'url': '/v2/'} # type: ignore - async def get_repositories( + def get_repositories( self, last: Optional[str] = None, n: Optional[int] = None, **kwargs - ) -> "_models.Repositories": + ) -> AsyncIterable["_models.Repositories"]: """List repositories. :param last: Query parameter for the last item in previous query. Result set will include @@ -99,8 +100,8 @@ async def get_repositories( :param n: query parameter for max number of items. :type n: int :keyword callable cls: A custom type or function that will be passed the direct response - :return: Repositories, or the result of cls(response) - :rtype: ~azure.containerregistry.models.Repositories + :return: An iterator like instance of either Repositories or the result of cls(response) + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.containerregistry.models.Repositories] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.Repositories"] @@ -110,58 +111,76 @@ async def get_repositories( error_map.update(kwargs.pop('error_map', {})) accept = "application/json" - # Construct URL - url = self.get_repositories.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers['Link']=self._deserialize('str', response.headers.get('Link')) - deserialized = self._deserialize('Repositories', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, response_headers) - - return deserialized + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.get_repositories.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + request = self._client.get(url, query_parameters, header_parameters) + return request + + async def extract_data(pipeline_response): + deserialized = self._deserialize('Repositories', pipeline_response) + list_of_elem = deserialized.repositories + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.link or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return AsyncItemPaged( + get_next, extract_data + ) get_repositories.metadata = {'url': '/acr/v1/_catalog'} # type: ignore async def get_repository_attributes( self, name: str, **kwargs - ) -> "_models.RepositoryAttributes": + ) -> "_models.RepositoryProperties": """Get repository attributes. :param name: Name of the image (including the namespace). :type name: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: RepositoryAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RepositoryAttributes + :return: RepositoryProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RepositoryProperties :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryAttributes"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -192,7 +211,7 @@ async def get_repository_attributes( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('RepositoryAttributes', pipeline_response) + deserialized = self._deserialize('RepositoryProperties', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) @@ -204,17 +223,17 @@ async def delete_repository( self, name: str, **kwargs - ) -> "_models.DeletedRepository": + ) -> "_models.DeletedRepositoryResult": """Delete the repository identified by ``name``. :param name: Name of the image (including the namespace). :type name: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: DeletedRepository, or the result of cls(response) - :rtype: ~azure.containerregistry.models.DeletedRepository + :return: DeletedRepositoryResult, or the result of cls(response) + :rtype: ~azure.containerregistry.models.DeletedRepositoryResult :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepository"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepositoryResult"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -245,7 +264,7 @@ async def delete_repository( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('DeletedRepository', pipeline_response) + deserialized = self._deserialize('DeletedRepositoryResult', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) @@ -256,7 +275,7 @@ async def delete_repository( async def update_repository_attributes( self, name: str, - value: Optional["_models.ChangeableAttributes"] = None, + value: Optional["_models.ContentProperties"] = None, **kwargs ) -> None: """Update the attribute identified by ``name`` where ``reference`` is the name of the repository. @@ -264,7 +283,7 @@ async def update_repository_attributes( :param name: Name of the image (including the namespace). :type name: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes + :type value: ~azure.containerregistry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -296,7 +315,7 @@ async def update_repository_attributes( body_content_kwargs = {} # type: Dict[str, Any] if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') + body_content = self._serialize.body(value, 'ContentProperties') else: body_content = None body_content_kwargs['content'] = body_content diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index f3bc8e9356f4..f35dba7c05d9 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -5,9 +5,10 @@ # Code generated by Microsoft (R) AutoRest Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from typing import Any, Callable, Dict, Generic, Optional, TypeVar +from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar import warnings +from azure.core.async_paging import AsyncItemPaged, AsyncList from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error from azure.core.pipeline import PipelineResponse from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest @@ -228,7 +229,7 @@ async def delete_manifest( delete_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore - async def get_tags( + def get_tags( self, name: str, last: Optional[str] = None, @@ -236,7 +237,7 @@ async def get_tags( orderby: Optional[str] = None, digest: Optional[str] = None, **kwargs - ) -> "_models.TagList": + ) -> AsyncIterable["_models.TagList"]: """List tags of a repository. :param name: Name of the image (including the namespace). @@ -251,8 +252,8 @@ async def get_tags( :param digest: filter by digest. :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagList, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagList + :return: An iterator like instance of either TagList or the result of cls(response) + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.containerregistry.models.TagList] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] @@ -262,44 +263,65 @@ async def get_tags( error_map.update(kwargs.pop('error_map', {})) accept = "application/json" - # Construct URL - url = self.get_tags.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - if orderby is not None: - query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') - if digest is not None: - query_parameters['digest'] = self._serialize.query("digest", digest, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('TagList', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.get_tags.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + if digest is not None: + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + request = self._client.get(url, query_parameters, header_parameters) + return request + + async def extract_data(pipeline_response): + deserialized = self._deserialize('TagList', pipeline_response) + list_of_elem = deserialized.tags + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.link or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return AsyncItemPaged( + get_next, extract_data + ) get_tags.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore async def get_tag_attributes( @@ -307,7 +329,7 @@ async def get_tag_attributes( name: str, reference: str, **kwargs - ) -> "_models.TagAttributes": + ) -> "_models.TagProperties": """Get tag attributes by tag. :param name: Name of the image (including the namespace). @@ -315,11 +337,11 @@ async def get_tag_attributes( :param reference: Tag name. :type reference: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagAttributes + :return: TagProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagProperties :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagProperties"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -351,7 +373,7 @@ async def get_tag_attributes( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('TagAttributes', pipeline_response) + deserialized = self._deserialize('TagProperties', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) @@ -363,7 +385,7 @@ async def update_tag_attributes( self, name: str, reference: str, - value: Optional["_models.ChangeableAttributes"] = None, + value: Optional["_models.ContentProperties"] = None, **kwargs ) -> None: """Update tag attributes. @@ -373,7 +395,7 @@ async def update_tag_attributes( :param reference: Tag name. :type reference: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes + :type value: ~azure.containerregistry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -406,7 +428,7 @@ async def update_tag_attributes( body_content_kwargs = {} # type: Dict[str, Any] if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') + body_content = self._serialize.body(value, 'ContentProperties') else: body_content = None body_content_kwargs['content'] = body_content @@ -478,14 +500,14 @@ async def delete_tag( delete_tag.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore - async def get_manifests( + def get_manifests( self, name: str, last: Optional[str] = None, n: Optional[int] = None, orderby: Optional[str] = None, **kwargs - ) -> "_models.AcrManifests": + ) -> AsyncIterable["_models.AcrManifests"]: """List manifests of a repository. :param name: Name of the image (including the namespace). @@ -498,8 +520,8 @@ async def get_manifests( :param orderby: orderby query parameter. :type orderby: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: AcrManifests, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AcrManifests + :return: An iterator like instance of either AcrManifests or the result of cls(response) + :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.containerregistry.models.AcrManifests] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrManifests"] @@ -509,42 +531,63 @@ async def get_manifests( error_map.update(kwargs.pop('error_map', {})) accept = "application/json" - # Construct URL - url = self.get_manifests.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - if orderby is not None: - query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('AcrManifests', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.get_manifests.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + request = self._client.get(url, query_parameters, header_parameters) + return request + + async def extract_data(pipeline_response): + deserialized = self._deserialize('AcrManifests', pipeline_response) + list_of_elem = deserialized.manifests + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.link or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return AsyncItemPaged( + get_next, extract_data + ) get_manifests.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore async def get_manifest_attributes( @@ -552,7 +595,7 @@ async def get_manifest_attributes( name: str, digest: str, **kwargs - ) -> "_models.ManifestAttributes": + ) -> "_models.RegistryArtifactProperties": """Get manifest attributes. :param name: Name of the image (including the namespace). @@ -560,11 +603,11 @@ async def get_manifest_attributes( :param digest: Digest of a BLOB. :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: ManifestAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.ManifestAttributes + :return: RegistryArtifactProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RegistryArtifactProperties :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestAttributes"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.RegistryArtifactProperties"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -596,19 +639,19 @@ async def get_manifest_attributes( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('ManifestAttributes', pipeline_response) + deserialized = self._deserialize('RegistryArtifactProperties', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) return deserialized - get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore async def update_manifest_attributes( self, name: str, digest: str, - value: Optional["_models.ChangeableAttributes"] = None, + value: Optional["_models.ContentProperties"] = None, **kwargs ) -> None: """Update attributes of a manifest. @@ -618,7 +661,7 @@ async def update_manifest_attributes( :param digest: Digest of a BLOB. :type digest: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes + :type value: ~azure.containerregistry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -651,7 +694,7 @@ async def update_manifest_attributes( body_content_kwargs = {} # type: Dict[str, Any] if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') + body_content = self._serialize.body(value, 'ContentProperties') else: body_content = None body_content_kwargs['content'] = body_content @@ -667,4 +710,4 @@ async def update_manifest_attributes( if cls: return cls(pipeline_response, None, {}) - update_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + update_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py index 0012768e010b..9a15e8ba2208 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py @@ -12,8 +12,8 @@ from ._models_py3 import AcrErrors from ._models_py3 import AcrManifests from ._models_py3 import Annotations - from ._models_py3 import ChangeableAttributes - from ._models_py3 import DeletedRepository + from ._models_py3 import ContentProperties + from ._models_py3 import DeletedRepositoryResult from ._models_py3 import Descriptor from ._models_py3 import FsLayer from ._models_py3 import History @@ -21,7 +21,6 @@ from ._models_py3 import JWK from ._models_py3 import JWKHeader from ._models_py3 import Manifest - from ._models_py3 import ManifestAttributes from ._models_py3 import ManifestAttributesBase from ._models_py3 import ManifestAttributesManifest from ._models_py3 import ManifestAttributesManifestReferences @@ -35,13 +34,14 @@ from ._models_py3 import PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema from ._models_py3 import Platform from ._models_py3 import RefreshToken + from ._models_py3 import RegistryArtifactProperties from ._models_py3 import Repositories - from ._models_py3 import RepositoryAttributes + from ._models_py3 import RepositoryProperties from ._models_py3 import RepositoryTags - from ._models_py3 import TagAttributes from ._models_py3 import TagAttributesBase from ._models_py3 import TagAttributesTag from ._models_py3 import TagList + from ._models_py3 import TagProperties from ._models_py3 import V1Manifest from ._models_py3 import V2Manifest except (SyntaxError, ImportError): @@ -50,8 +50,8 @@ from ._models import AcrErrors # type: ignore from ._models import AcrManifests # type: ignore from ._models import Annotations # type: ignore - from ._models import ChangeableAttributes # type: ignore - from ._models import DeletedRepository # type: ignore + from ._models import ContentProperties # type: ignore + from ._models import DeletedRepositoryResult # type: ignore from ._models import Descriptor # type: ignore from ._models import FsLayer # type: ignore from ._models import History # type: ignore @@ -59,7 +59,6 @@ from ._models import JWK # type: ignore from ._models import JWKHeader # type: ignore from ._models import Manifest # type: ignore - from ._models import ManifestAttributes # type: ignore from ._models import ManifestAttributesBase # type: ignore from ._models import ManifestAttributesManifest # type: ignore from ._models import ManifestAttributesManifestReferences # type: ignore @@ -73,13 +72,14 @@ from ._models import PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema # type: ignore from ._models import Platform # type: ignore from ._models import RefreshToken # type: ignore + from ._models import RegistryArtifactProperties # type: ignore from ._models import Repositories # type: ignore - from ._models import RepositoryAttributes # type: ignore + from ._models import RepositoryProperties # type: ignore from ._models import RepositoryTags # type: ignore - from ._models import TagAttributes # type: ignore from ._models import TagAttributesBase # type: ignore from ._models import TagAttributesTag # type: ignore from ._models import TagList # type: ignore + from ._models import TagProperties # type: ignore from ._models import V1Manifest # type: ignore from ._models import V2Manifest # type: ignore @@ -93,8 +93,8 @@ 'AcrErrors', 'AcrManifests', 'Annotations', - 'ChangeableAttributes', - 'DeletedRepository', + 'ContentProperties', + 'DeletedRepositoryResult', 'Descriptor', 'FsLayer', 'History', @@ -102,7 +102,6 @@ 'JWK', 'JWKHeader', 'Manifest', - 'ManifestAttributes', 'ManifestAttributesBase', 'ManifestAttributesManifest', 'ManifestAttributesManifestReferences', @@ -116,13 +115,14 @@ 'PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema', 'Platform', 'RefreshToken', + 'RegistryArtifactProperties', 'Repositories', - 'RepositoryAttributes', + 'RepositoryProperties', 'RepositoryTags', - 'TagAttributes', 'TagAttributesBase', 'TagAttributesTag', 'TagList', + 'TagProperties', 'V1Manifest', 'V2Manifest', 'PostContentSchemaGrantType', diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 99f68ce16846..5c2bc505f589 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -82,14 +82,17 @@ class AcrManifests(msrest.serialization.Model): :type registry: str :param image_name: Image name. :type image_name: str - :param manifests_attributes: List of manifests. - :type manifests_attributes: list[~azure.containerregistry.models.ManifestAttributesBase] + :param manifests: List of manifests. + :type manifests: list[~azure.containerregistry.models.ManifestAttributesBase] + :param link: + :type link: str """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, 'image_name': {'key': 'imageName', 'type': 'str'}, - 'manifests_attributes': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, + 'link': {'key': 'link', 'type': 'str'}, } def __init__( @@ -99,7 +102,8 @@ def __init__( super(AcrManifests, self).__init__(**kwargs) self.registry = kwargs.get('registry', None) self.image_name = kwargs.get('image_name', None) - self.manifests_attributes = kwargs.get('manifests_attributes', None) + self.manifests = kwargs.get('manifests', None) + self.link = kwargs.get('link', None) class Annotations(msrest.serialization.Model): @@ -173,8 +177,8 @@ def __init__( self.description = kwargs.get('description', None) -class ChangeableAttributes(msrest.serialization.Model): - """ChangeableAttributes. +class ContentProperties(msrest.serialization.Model): + """ContentProperties. :param can_delete: Delete enabled. :type can_delete: bool @@ -197,14 +201,14 @@ def __init__( self, **kwargs ): - super(ChangeableAttributes, self).__init__(**kwargs) + super(ContentProperties, self).__init__(**kwargs) self.can_delete = kwargs.get('can_delete', None) self.can_write = kwargs.get('can_write', None) self.can_list = kwargs.get('can_list', None) self.can_read = kwargs.get('can_read', None) -class DeletedRepository(msrest.serialization.Model): +class DeletedRepositoryResult(msrest.serialization.Model): """Deleted repository. :param deleted_registry_artifact_digests: SHA of the deleted image. @@ -222,7 +226,7 @@ def __init__( self, **kwargs ): - super(DeletedRepository, self).__init__(**kwargs) + super(DeletedRepositoryResult, self).__init__(**kwargs) self.deleted_registry_artifact_digests = kwargs.get('deleted_registry_artifact_digests', None) self.deleted_tags = kwargs.get('deleted_tags', None) @@ -404,69 +408,6 @@ def __init__( self.schema_version = kwargs.get('schema_version', None) -class ManifestAttributes(msrest.serialization.Model): - """Manifest attributes details. - - :param registry: Registry name. - :type registry: str - :param repository: Image name. - :type repository: str - :param digest: Manifest. - :type digest: str - :param size: Image size. - :type size: long - :param created_on: Created time. - :type created_on: ~datetime.datetime - :param last_updated_on: Last update time. - :type last_updated_on: ~datetime.datetime - :param cpu_architecture: CPU architecture. - :type cpu_architecture: str - :param operating_system: Operating system. - :type operating_system: str - :param manifest_media_type: Media type. - :type manifest_media_type: str - :param config_media_type: Config blob media type. - :type config_media_type: str - :param tags: A set of tags. List of tags. - :type tags: list[str] - :param manifest_properties: Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes - """ - - _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'repository': {'key': 'imageName', 'type': 'str'}, - 'digest': {'key': 'manifest.digest', 'type': 'str'}, - 'size': {'key': 'manifest.imageSize', 'type': 'long'}, - 'created_on': {'key': 'manifest.createdTime', 'type': 'iso-8601'}, - 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, - 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, - 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, - 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, - 'tags': {'key': 'manifest.tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ChangeableAttributes'}, - } - - def __init__( - self, - **kwargs - ): - super(ManifestAttributes, self).__init__(**kwargs) - self.registry = kwargs.get('registry', None) - self.repository = kwargs.get('repository', None) - self.digest = kwargs.get('digest', None) - self.size = kwargs.get('size', None) - self.created_on = kwargs.get('created_on', None) - self.last_updated_on = kwargs.get('last_updated_on', None) - self.cpu_architecture = kwargs.get('cpu_architecture', None) - self.operating_system = kwargs.get('operating_system', None) - self.manifest_media_type = kwargs.get('manifest_media_type', None) - self.config_media_type = kwargs.get('config_media_type', None) - self.tags = kwargs.get('tags', None) - self.manifest_properties = kwargs.get('manifest_properties', None) - - class ManifestAttributesBase(msrest.serialization.Model): """Manifest details. @@ -489,7 +430,7 @@ class ManifestAttributesBase(msrest.serialization.Model): :param tags: A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes + :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { @@ -502,7 +443,7 @@ class ManifestAttributesBase(msrest.serialization.Model): 'manifest_media_type': {'key': 'mediaType', 'type': 'str'}, 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -944,15 +885,81 @@ def __init__( self.refresh_token = kwargs.get('refresh_token', None) +class RegistryArtifactProperties(msrest.serialization.Model): + """Manifest attributes details. + + :param registry: Registry name. + :type registry: str + :param repository: Image name. + :type repository: str + :param digest: Manifest. + :type digest: str + :param size: Image size. + :type size: long + :param created_on: Created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Last update time. + :type last_updated_on: ~datetime.datetime + :param cpu_architecture: CPU architecture. + :type cpu_architecture: str + :param operating_system: Operating system. + :type operating_system: str + :param manifest_media_type: Media type. + :type manifest_media_type: str + :param config_media_type: Config blob media type. + :type config_media_type: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + :param manifest_properties: Changeable attributes. + :type manifest_properties: ~azure.containerregistry.models.ContentProperties + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'digest': {'key': 'manifest.digest', 'type': 'str'}, + 'size': {'key': 'manifest.imageSize', 'type': 'long'}, + 'created_on': {'key': 'manifest.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, + 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, + 'operating_system': {'key': 'manifest.os', 'type': 'str'}, + 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, + 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, + 'tags': {'key': 'manifest.tags', 'type': '[str]'}, + 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, + } + + def __init__( + self, + **kwargs + ): + super(RegistryArtifactProperties, self).__init__(**kwargs) + self.registry = kwargs.get('registry', None) + self.repository = kwargs.get('repository', None) + self.digest = kwargs.get('digest', None) + self.size = kwargs.get('size', None) + self.created_on = kwargs.get('created_on', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.cpu_architecture = kwargs.get('cpu_architecture', None) + self.operating_system = kwargs.get('operating_system', None) + self.manifest_media_type = kwargs.get('manifest_media_type', None) + self.config_media_type = kwargs.get('config_media_type', None) + self.tags = kwargs.get('tags', None) + self.manifest_properties = kwargs.get('manifest_properties', None) + + class Repositories(msrest.serialization.Model): """List of repositories. - :param names: Repository names. - :type names: list[str] + :param repositories: Repository names. + :type repositories: list[str] + :param link: + :type link: str """ _attribute_map = { - 'names': {'key': 'repositories', 'type': '[str]'}, + 'repositories': {'key': 'repositories', 'type': '[str]'}, + 'link': {'key': 'link', 'type': 'str'}, } def __init__( @@ -960,10 +967,11 @@ def __init__( **kwargs ): super(Repositories, self).__init__(**kwargs) - self.names = kwargs.get('names', None) + self.repositories = kwargs.get('repositories', None) + self.link = kwargs.get('link', None) -class RepositoryAttributes(msrest.serialization.Model): +class RepositoryProperties(msrest.serialization.Model): """Repository attributes. :param registry: Registry name. @@ -979,7 +987,7 @@ class RepositoryAttributes(msrest.serialization.Model): :param tag_count: Number of the tags. :type tag_count: int :param writeable_properties: Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ChangeableAttributes + :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { @@ -989,14 +997,14 @@ class RepositoryAttributes(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'registry_artifact_count': {'key': 'manifestCount', 'type': 'int'}, 'tag_count': {'key': 'tagCount', 'type': 'int'}, - 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( self, **kwargs ): - super(RepositoryAttributes, self).__init__(**kwargs) + super(RepositoryProperties, self).__init__(**kwargs) self.registry = kwargs.get('registry', None) self.name = kwargs.get('name', None) self.created_on = kwargs.get('created_on', None) @@ -1029,49 +1037,6 @@ def __init__( self.tags = kwargs.get('tags', None) -class TagAttributes(msrest.serialization.Model): - """Tag attributes. - - :param registry: Registry name. - :type registry: str - :param repository: Image name. - :type repository: str - :param name: Tag name. - :type name: str - :param digest: Tag digest. - :type digest: str - :param created_on: Tag created time. - :type created_on: ~datetime.datetime - :param last_updated_on: Tag last update time. - :type last_updated_on: ~datetime.datetime - :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes - """ - - _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'repository': {'key': 'imageName', 'type': 'str'}, - 'name': {'key': 'tag.name', 'type': 'str'}, - 'digest': {'key': 'tag.digest', 'type': 'str'}, - 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, - 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ChangeableAttributes'}, - } - - def __init__( - self, - **kwargs - ): - super(TagAttributes, self).__init__(**kwargs) - self.registry = kwargs.get('registry', None) - self.repository = kwargs.get('repository', None) - self.name = kwargs.get('name', None) - self.digest = kwargs.get('digest', None) - self.created_on = kwargs.get('created_on', None) - self.last_updated_on = kwargs.get('last_updated_on', None) - self.modifiable_properties = kwargs.get('modifiable_properties', None) - - class TagAttributesBase(msrest.serialization.Model): """Tag attribute details. @@ -1084,7 +1049,7 @@ class TagAttributesBase(msrest.serialization.Model): :param last_updated_on: Tag last update time. :type last_updated_on: ~datetime.datetime :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes + :type modifiable_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { @@ -1092,7 +1057,7 @@ class TagAttributesBase(msrest.serialization.Model): 'digest': {'key': 'digest', 'type': 'str'}, 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -1135,12 +1100,15 @@ class TagList(msrest.serialization.Model): :type image_name: str :param tags: A set of tags. List of tag attribute details. :type tags: list[~azure.containerregistry.models.TagAttributesBase] + :param link: + :type link: str """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, 'image_name': {'key': 'imageName', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, + 'link': {'key': 'link', 'type': 'str'}, } def __init__( @@ -1151,6 +1119,50 @@ def __init__( self.registry = kwargs.get('registry', None) self.image_name = kwargs.get('image_name', None) self.tags = kwargs.get('tags', None) + self.link = kwargs.get('link', None) + + +class TagProperties(msrest.serialization.Model): + """Tag attributes. + + :param registry: Registry name. + :type registry: str + :param repository: Image name. + :type repository: str + :param name: Tag name. + :type name: str + :param digest: Tag digest. + :type digest: str + :param created_on: Tag created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Tag last update time. + :type last_updated_on: ~datetime.datetime + :param modifiable_properties: Changeable attributes. + :type modifiable_properties: ~azure.containerregistry.models.ContentProperties + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'name': {'key': 'tag.name', 'type': 'str'}, + 'digest': {'key': 'tag.digest', 'type': 'str'}, + 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, + 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ContentProperties'}, + } + + def __init__( + self, + **kwargs + ): + super(TagProperties, self).__init__(**kwargs) + self.registry = kwargs.get('registry', None) + self.repository = kwargs.get('repository', None) + self.name = kwargs.get('name', None) + self.digest = kwargs.get('digest', None) + self.created_on = kwargs.get('created_on', None) + self.last_updated_on = kwargs.get('last_updated_on', None) + self.modifiable_properties = kwargs.get('modifiable_properties', None) class V1Manifest(Manifest): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index 02c41fcec0c2..0ab6ceae9ce2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -95,14 +95,17 @@ class AcrManifests(msrest.serialization.Model): :type registry: str :param image_name: Image name. :type image_name: str - :param manifests_attributes: List of manifests. - :type manifests_attributes: list[~azure.containerregistry.models.ManifestAttributesBase] + :param manifests: List of manifests. + :type manifests: list[~azure.containerregistry.models.ManifestAttributesBase] + :param link: + :type link: str """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, 'image_name': {'key': 'imageName', 'type': 'str'}, - 'manifests_attributes': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, + 'manifests': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, + 'link': {'key': 'link', 'type': 'str'}, } def __init__( @@ -110,13 +113,15 @@ def __init__( *, registry: Optional[str] = None, image_name: Optional[str] = None, - manifests_attributes: Optional[List["ManifestAttributesBase"]] = None, + manifests: Optional[List["ManifestAttributesBase"]] = None, + link: Optional[str] = None, **kwargs ): super(AcrManifests, self).__init__(**kwargs) self.registry = registry self.image_name = image_name - self.manifests_attributes = manifests_attributes + self.manifests = manifests + self.link = link class Annotations(msrest.serialization.Model): @@ -204,8 +209,8 @@ def __init__( self.description = description -class ChangeableAttributes(msrest.serialization.Model): - """ChangeableAttributes. +class ContentProperties(msrest.serialization.Model): + """ContentProperties. :param can_delete: Delete enabled. :type can_delete: bool @@ -233,14 +238,14 @@ def __init__( can_read: Optional[bool] = None, **kwargs ): - super(ChangeableAttributes, self).__init__(**kwargs) + super(ContentProperties, self).__init__(**kwargs) self.can_delete = can_delete self.can_write = can_write self.can_list = can_list self.can_read = can_read -class DeletedRepository(msrest.serialization.Model): +class DeletedRepositoryResult(msrest.serialization.Model): """Deleted repository. :param deleted_registry_artifact_digests: SHA of the deleted image. @@ -261,7 +266,7 @@ def __init__( deleted_tags: Optional[List[str]] = None, **kwargs ): - super(DeletedRepository, self).__init__(**kwargs) + super(DeletedRepositoryResult, self).__init__(**kwargs) self.deleted_registry_artifact_digests = deleted_registry_artifact_digests self.deleted_tags = deleted_tags @@ -468,82 +473,6 @@ def __init__( self.schema_version = schema_version -class ManifestAttributes(msrest.serialization.Model): - """Manifest attributes details. - - :param registry: Registry name. - :type registry: str - :param repository: Image name. - :type repository: str - :param digest: Manifest. - :type digest: str - :param size: Image size. - :type size: long - :param created_on: Created time. - :type created_on: ~datetime.datetime - :param last_updated_on: Last update time. - :type last_updated_on: ~datetime.datetime - :param cpu_architecture: CPU architecture. - :type cpu_architecture: str - :param operating_system: Operating system. - :type operating_system: str - :param manifest_media_type: Media type. - :type manifest_media_type: str - :param config_media_type: Config blob media type. - :type config_media_type: str - :param tags: A set of tags. List of tags. - :type tags: list[str] - :param manifest_properties: Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes - """ - - _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'repository': {'key': 'imageName', 'type': 'str'}, - 'digest': {'key': 'manifest.digest', 'type': 'str'}, - 'size': {'key': 'manifest.imageSize', 'type': 'long'}, - 'created_on': {'key': 'manifest.createdTime', 'type': 'iso-8601'}, - 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, - 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, - 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, - 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, - 'tags': {'key': 'manifest.tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ChangeableAttributes'}, - } - - def __init__( - self, - *, - registry: Optional[str] = None, - repository: Optional[str] = None, - digest: Optional[str] = None, - size: Optional[int] = None, - created_on: Optional[datetime.datetime] = None, - last_updated_on: Optional[datetime.datetime] = None, - cpu_architecture: Optional[str] = None, - operating_system: Optional[str] = None, - manifest_media_type: Optional[str] = None, - config_media_type: Optional[str] = None, - tags: Optional[List[str]] = None, - manifest_properties: Optional["ChangeableAttributes"] = None, - **kwargs - ): - super(ManifestAttributes, self).__init__(**kwargs) - self.registry = registry - self.repository = repository - self.digest = digest - self.size = size - self.created_on = created_on - self.last_updated_on = last_updated_on - self.cpu_architecture = cpu_architecture - self.operating_system = operating_system - self.manifest_media_type = manifest_media_type - self.config_media_type = config_media_type - self.tags = tags - self.manifest_properties = manifest_properties - - class ManifestAttributesBase(msrest.serialization.Model): """Manifest details. @@ -566,7 +495,7 @@ class ManifestAttributesBase(msrest.serialization.Model): :param tags: A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ChangeableAttributes + :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { @@ -579,7 +508,7 @@ class ManifestAttributesBase(msrest.serialization.Model): 'manifest_media_type': {'key': 'mediaType', 'type': 'str'}, 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -594,7 +523,7 @@ def __init__( manifest_media_type: Optional[str] = None, config_media_type: Optional[str] = None, tags: Optional[List[str]] = None, - manifest_properties: Optional["ChangeableAttributes"] = None, + manifest_properties: Optional["ContentProperties"] = None, **kwargs ): super(ManifestAttributesBase, self).__init__(**kwargs) @@ -1096,28 +1025,109 @@ def __init__( self.refresh_token = refresh_token +class RegistryArtifactProperties(msrest.serialization.Model): + """Manifest attributes details. + + :param registry: Registry name. + :type registry: str + :param repository: Image name. + :type repository: str + :param digest: Manifest. + :type digest: str + :param size: Image size. + :type size: long + :param created_on: Created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Last update time. + :type last_updated_on: ~datetime.datetime + :param cpu_architecture: CPU architecture. + :type cpu_architecture: str + :param operating_system: Operating system. + :type operating_system: str + :param manifest_media_type: Media type. + :type manifest_media_type: str + :param config_media_type: Config blob media type. + :type config_media_type: str + :param tags: A set of tags. List of tags. + :type tags: list[str] + :param manifest_properties: Changeable attributes. + :type manifest_properties: ~azure.containerregistry.models.ContentProperties + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'digest': {'key': 'manifest.digest', 'type': 'str'}, + 'size': {'key': 'manifest.imageSize', 'type': 'long'}, + 'created_on': {'key': 'manifest.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, + 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, + 'operating_system': {'key': 'manifest.os', 'type': 'str'}, + 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, + 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, + 'tags': {'key': 'manifest.tags', 'type': '[str]'}, + 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, + } + + def __init__( + self, + *, + registry: Optional[str] = None, + repository: Optional[str] = None, + digest: Optional[str] = None, + size: Optional[int] = None, + created_on: Optional[datetime.datetime] = None, + last_updated_on: Optional[datetime.datetime] = None, + cpu_architecture: Optional[str] = None, + operating_system: Optional[str] = None, + manifest_media_type: Optional[str] = None, + config_media_type: Optional[str] = None, + tags: Optional[List[str]] = None, + manifest_properties: Optional["ContentProperties"] = None, + **kwargs + ): + super(RegistryArtifactProperties, self).__init__(**kwargs) + self.registry = registry + self.repository = repository + self.digest = digest + self.size = size + self.created_on = created_on + self.last_updated_on = last_updated_on + self.cpu_architecture = cpu_architecture + self.operating_system = operating_system + self.manifest_media_type = manifest_media_type + self.config_media_type = config_media_type + self.tags = tags + self.manifest_properties = manifest_properties + + class Repositories(msrest.serialization.Model): """List of repositories. - :param names: Repository names. - :type names: list[str] + :param repositories: Repository names. + :type repositories: list[str] + :param link: + :type link: str """ _attribute_map = { - 'names': {'key': 'repositories', 'type': '[str]'}, + 'repositories': {'key': 'repositories', 'type': '[str]'}, + 'link': {'key': 'link', 'type': 'str'}, } def __init__( self, *, - names: Optional[List[str]] = None, + repositories: Optional[List[str]] = None, + link: Optional[str] = None, **kwargs ): super(Repositories, self).__init__(**kwargs) - self.names = names + self.repositories = repositories + self.link = link -class RepositoryAttributes(msrest.serialization.Model): +class RepositoryProperties(msrest.serialization.Model): """Repository attributes. :param registry: Registry name. @@ -1133,7 +1143,7 @@ class RepositoryAttributes(msrest.serialization.Model): :param tag_count: Number of the tags. :type tag_count: int :param writeable_properties: Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ChangeableAttributes + :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { @@ -1143,7 +1153,7 @@ class RepositoryAttributes(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'registry_artifact_count': {'key': 'manifestCount', 'type': 'int'}, 'tag_count': {'key': 'tagCount', 'type': 'int'}, - 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -1155,10 +1165,10 @@ def __init__( last_updated_on: Optional[datetime.datetime] = None, registry_artifact_count: Optional[int] = None, tag_count: Optional[int] = None, - writeable_properties: Optional["ChangeableAttributes"] = None, + writeable_properties: Optional["ContentProperties"] = None, **kwargs ): - super(RepositoryAttributes, self).__init__(**kwargs) + super(RepositoryProperties, self).__init__(**kwargs) self.registry = registry self.name = name self.created_on = created_on @@ -1194,57 +1204,6 @@ def __init__( self.tags = tags -class TagAttributes(msrest.serialization.Model): - """Tag attributes. - - :param registry: Registry name. - :type registry: str - :param repository: Image name. - :type repository: str - :param name: Tag name. - :type name: str - :param digest: Tag digest. - :type digest: str - :param created_on: Tag created time. - :type created_on: ~datetime.datetime - :param last_updated_on: Tag last update time. - :type last_updated_on: ~datetime.datetime - :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes - """ - - _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'repository': {'key': 'imageName', 'type': 'str'}, - 'name': {'key': 'tag.name', 'type': 'str'}, - 'digest': {'key': 'tag.digest', 'type': 'str'}, - 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, - 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ChangeableAttributes'}, - } - - def __init__( - self, - *, - registry: Optional[str] = None, - repository: Optional[str] = None, - name: Optional[str] = None, - digest: Optional[str] = None, - created_on: Optional[datetime.datetime] = None, - last_updated_on: Optional[datetime.datetime] = None, - modifiable_properties: Optional["ChangeableAttributes"] = None, - **kwargs - ): - super(TagAttributes, self).__init__(**kwargs) - self.registry = registry - self.repository = repository - self.name = name - self.digest = digest - self.created_on = created_on - self.last_updated_on = last_updated_on - self.modifiable_properties = modifiable_properties - - class TagAttributesBase(msrest.serialization.Model): """Tag attribute details. @@ -1257,7 +1216,7 @@ class TagAttributesBase(msrest.serialization.Model): :param last_updated_on: Tag last update time. :type last_updated_on: ~datetime.datetime :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ChangeableAttributes + :type modifiable_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { @@ -1265,7 +1224,7 @@ class TagAttributesBase(msrest.serialization.Model): 'digest': {'key': 'digest', 'type': 'str'}, 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ChangeableAttributes'}, + 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -1275,7 +1234,7 @@ def __init__( digest: Optional[str] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, - modifiable_properties: Optional["ChangeableAttributes"] = None, + modifiable_properties: Optional["ContentProperties"] = None, **kwargs ): super(TagAttributesBase, self).__init__(**kwargs) @@ -1316,12 +1275,15 @@ class TagList(msrest.serialization.Model): :type image_name: str :param tags: A set of tags. List of tag attribute details. :type tags: list[~azure.containerregistry.models.TagAttributesBase] + :param link: + :type link: str """ _attribute_map = { 'registry': {'key': 'registry', 'type': 'str'}, 'image_name': {'key': 'imageName', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, + 'link': {'key': 'link', 'type': 'str'}, } def __init__( @@ -1330,12 +1292,65 @@ def __init__( registry: Optional[str] = None, image_name: Optional[str] = None, tags: Optional[List["TagAttributesBase"]] = None, + link: Optional[str] = None, **kwargs ): super(TagList, self).__init__(**kwargs) self.registry = registry self.image_name = image_name self.tags = tags + self.link = link + + +class TagProperties(msrest.serialization.Model): + """Tag attributes. + + :param registry: Registry name. + :type registry: str + :param repository: Image name. + :type repository: str + :param name: Tag name. + :type name: str + :param digest: Tag digest. + :type digest: str + :param created_on: Tag created time. + :type created_on: ~datetime.datetime + :param last_updated_on: Tag last update time. + :type last_updated_on: ~datetime.datetime + :param modifiable_properties: Changeable attributes. + :type modifiable_properties: ~azure.containerregistry.models.ContentProperties + """ + + _attribute_map = { + 'registry': {'key': 'registry', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, + 'name': {'key': 'tag.name', 'type': 'str'}, + 'digest': {'key': 'tag.digest', 'type': 'str'}, + 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, + 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, + 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ContentProperties'}, + } + + def __init__( + self, + *, + registry: Optional[str] = None, + repository: Optional[str] = None, + name: Optional[str] = None, + digest: Optional[str] = None, + created_on: Optional[datetime.datetime] = None, + last_updated_on: Optional[datetime.datetime] = None, + modifiable_properties: Optional["ContentProperties"] = None, + **kwargs + ): + super(TagProperties, self).__init__(**kwargs) + self.registry = registry + self.repository = repository + self.name = name + self.digest = digest + self.created_on = created_on + self.last_updated_on = last_updated_on + self.modifiable_properties = modifiable_properties class V1Manifest(Manifest): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py index f738bcf7913b..6e677bfca461 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py @@ -9,6 +9,7 @@ import warnings from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.paging import ItemPaged from azure.core.pipeline import PipelineResponse from azure.core.pipeline.transport import HttpRequest, HttpResponse @@ -16,7 +17,7 @@ if TYPE_CHECKING: # pylint: disable=unused-import,ungrouped-imports - from typing import Any, Callable, Dict, Generic, Optional, TypeVar + from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] @@ -96,7 +97,7 @@ def get_repositories( n=None, # type: Optional[int] **kwargs # type: Any ): - # type: (...) -> "_models.Repositories" + # type: (...) -> Iterable["_models.Repositories"] """List repositories. :param last: Query parameter for the last item in previous query. Result set will include @@ -105,8 +106,8 @@ def get_repositories( :param n: query parameter for max number of items. :type n: int :keyword callable cls: A custom type or function that will be passed the direct response - :return: Repositories, or the result of cls(response) - :rtype: ~azure.containerregistry.models.Repositories + :return: An iterator like instance of either Repositories or the result of cls(response) + :rtype: ~azure.core.paging.ItemPaged[~azure.containerregistry.models.Repositories] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.Repositories"] @@ -116,41 +117,59 @@ def get_repositories( error_map.update(kwargs.pop('error_map', {})) accept = "application/json" - # Construct URL - url = self.get_repositories.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - response_headers = {} - response_headers['Link']=self._deserialize('str', response.headers.get('Link')) - deserialized = self._deserialize('Repositories', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, response_headers) - - return deserialized + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.get_repositories.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + request = self._client.get(url, query_parameters, header_parameters) + return request + + def extract_data(pipeline_response): + deserialized = self._deserialize('Repositories', pipeline_response) + list_of_elem = deserialized.repositories + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.link or None, iter(list_of_elem) + + def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return ItemPaged( + get_next, extract_data + ) get_repositories.metadata = {'url': '/acr/v1/_catalog'} # type: ignore def get_repository_attributes( @@ -158,17 +177,17 @@ def get_repository_attributes( name, # type: str **kwargs # type: Any ): - # type: (...) -> "_models.RepositoryAttributes" + # type: (...) -> "_models.RepositoryProperties" """Get repository attributes. :param name: Name of the image (including the namespace). :type name: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: RepositoryAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RepositoryAttributes + :return: RepositoryProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RepositoryProperties :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryAttributes"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -199,7 +218,7 @@ def get_repository_attributes( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('RepositoryAttributes', pipeline_response) + deserialized = self._deserialize('RepositoryProperties', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) @@ -212,17 +231,17 @@ def delete_repository( name, # type: str **kwargs # type: Any ): - # type: (...) -> "_models.DeletedRepository" + # type: (...) -> "_models.DeletedRepositoryResult" """Delete the repository identified by ``name``. :param name: Name of the image (including the namespace). :type name: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: DeletedRepository, or the result of cls(response) - :rtype: ~azure.containerregistry.models.DeletedRepository + :return: DeletedRepositoryResult, or the result of cls(response) + :rtype: ~azure.containerregistry.models.DeletedRepositoryResult :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepository"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepositoryResult"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -253,7 +272,7 @@ def delete_repository( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('DeletedRepository', pipeline_response) + deserialized = self._deserialize('DeletedRepositoryResult', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) @@ -264,7 +283,7 @@ def delete_repository( def update_repository_attributes( self, name, # type: str - value=None, # type: Optional["_models.ChangeableAttributes"] + value=None, # type: Optional["_models.ContentProperties"] **kwargs # type: Any ): # type: (...) -> None @@ -273,7 +292,7 @@ def update_repository_attributes( :param name: Name of the image (including the namespace). :type name: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes + :type value: ~azure.containerregistry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -305,7 +324,7 @@ def update_repository_attributes( body_content_kwargs = {} # type: Dict[str, Any] if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') + body_content = self._serialize.body(value, 'ContentProperties') else: body_content = None body_content_kwargs['content'] = body_content diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index e286c08e6106..fafcf82b965b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -9,6 +9,7 @@ import warnings from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.paging import ItemPaged from azure.core.pipeline import PipelineResponse from azure.core.pipeline.transport import HttpRequest, HttpResponse @@ -16,7 +17,7 @@ if TYPE_CHECKING: # pylint: disable=unused-import,ungrouped-imports - from typing import Any, Callable, Dict, Generic, Optional, TypeVar + from typing import Any, Callable, Dict, Generic, Iterable, Optional, TypeVar T = TypeVar('T') ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] @@ -244,7 +245,7 @@ def get_tags( digest=None, # type: Optional[str] **kwargs # type: Any ): - # type: (...) -> "_models.TagList" + # type: (...) -> Iterable["_models.TagList"] """List tags of a repository. :param name: Name of the image (including the namespace). @@ -259,8 +260,8 @@ def get_tags( :param digest: filter by digest. :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagList, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagList + :return: An iterator like instance of either TagList or the result of cls(response) + :rtype: ~azure.core.paging.ItemPaged[~azure.containerregistry.models.TagList] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] @@ -270,44 +271,65 @@ def get_tags( error_map.update(kwargs.pop('error_map', {})) accept = "application/json" - # Construct URL - url = self.get_tags.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - if orderby is not None: - query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') - if digest is not None: - query_parameters['digest'] = self._serialize.query("digest", digest, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('TagList', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.get_tags.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + if digest is not None: + query_parameters['digest'] = self._serialize.query("digest", digest, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + request = self._client.get(url, query_parameters, header_parameters) + return request + + def extract_data(pipeline_response): + deserialized = self._deserialize('TagList', pipeline_response) + list_of_elem = deserialized.tags + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.link or None, iter(list_of_elem) + + def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return ItemPaged( + get_next, extract_data + ) get_tags.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore def get_tag_attributes( @@ -316,7 +338,7 @@ def get_tag_attributes( reference, # type: str **kwargs # type: Any ): - # type: (...) -> "_models.TagAttributes" + # type: (...) -> "_models.TagProperties" """Get tag attributes by tag. :param name: Name of the image (including the namespace). @@ -324,11 +346,11 @@ def get_tag_attributes( :param reference: Tag name. :type reference: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: TagAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagAttributes + :return: TagProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.TagProperties :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.TagAttributes"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.TagProperties"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -360,7 +382,7 @@ def get_tag_attributes( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('TagAttributes', pipeline_response) + deserialized = self._deserialize('TagProperties', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) @@ -372,7 +394,7 @@ def update_tag_attributes( self, name, # type: str reference, # type: str - value=None, # type: Optional["_models.ChangeableAttributes"] + value=None, # type: Optional["_models.ContentProperties"] **kwargs # type: Any ): # type: (...) -> None @@ -383,7 +405,7 @@ def update_tag_attributes( :param reference: Tag name. :type reference: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes + :type value: ~azure.containerregistry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -416,7 +438,7 @@ def update_tag_attributes( body_content_kwargs = {} # type: Dict[str, Any] if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') + body_content = self._serialize.body(value, 'ContentProperties') else: body_content = None body_content_kwargs['content'] = body_content @@ -497,7 +519,7 @@ def get_manifests( orderby=None, # type: Optional[str] **kwargs # type: Any ): - # type: (...) -> "_models.AcrManifests" + # type: (...) -> Iterable["_models.AcrManifests"] """List manifests of a repository. :param name: Name of the image (including the namespace). @@ -510,8 +532,8 @@ def get_manifests( :param orderby: orderby query parameter. :type orderby: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: AcrManifests, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AcrManifests + :return: An iterator like instance of either AcrManifests or the result of cls(response) + :rtype: ~azure.core.paging.ItemPaged[~azure.containerregistry.models.AcrManifests] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrManifests"] @@ -521,42 +543,63 @@ def get_manifests( error_map.update(kwargs.pop('error_map', {})) accept = "application/json" - # Construct URL - url = self.get_manifests.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - if last is not None: - query_parameters['last'] = self._serialize.query("last", last, 'str') - if n is not None: - query_parameters['n'] = self._serialize.query("n", n, 'int') - if orderby is not None: - query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('AcrManifests', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized + def prepare_request(next_link=None): + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + if not next_link: + # Construct URL + url = self.get_manifests.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + if last is not None: + query_parameters['last'] = self._serialize.query("last", last, 'str') + if n is not None: + query_parameters['n'] = self._serialize.query("n", n, 'int') + if orderby is not None: + query_parameters['orderby'] = self._serialize.query("orderby", orderby, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + else: + url = next_link + query_parameters = {} # type: Dict[str, Any] + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + request = self._client.get(url, query_parameters, header_parameters) + return request + + def extract_data(pipeline_response): + deserialized = self._deserialize('AcrManifests', pipeline_response) + list_of_elem = deserialized.manifests + if cls: + list_of_elem = cls(list_of_elem) + return deserialized.link or None, iter(list_of_elem) + + def get_next(next_link=None): + request = prepare_request(next_link) + + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response, model=error) + + return pipeline_response + + return ItemPaged( + get_next, extract_data + ) get_manifests.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore def get_manifest_attributes( @@ -565,7 +608,7 @@ def get_manifest_attributes( digest, # type: str **kwargs # type: Any ): - # type: (...) -> "_models.ManifestAttributes" + # type: (...) -> "_models.RegistryArtifactProperties" """Get manifest attributes. :param name: Name of the image (including the namespace). @@ -573,11 +616,11 @@ def get_manifest_attributes( :param digest: Digest of a BLOB. :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: ManifestAttributes, or the result of cls(response) - :rtype: ~azure.containerregistry.models.ManifestAttributes + :return: RegistryArtifactProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RegistryArtifactProperties :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.ManifestAttributes"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.RegistryArtifactProperties"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -609,19 +652,19 @@ def get_manifest_attributes( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('ManifestAttributes', pipeline_response) + deserialized = self._deserialize('RegistryArtifactProperties', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) return deserialized - get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore def update_manifest_attributes( self, name, # type: str digest, # type: str - value=None, # type: Optional["_models.ChangeableAttributes"] + value=None, # type: Optional["_models.ContentProperties"] **kwargs # type: Any ): # type: (...) -> None @@ -632,7 +675,7 @@ def update_manifest_attributes( :param digest: Digest of a BLOB. :type digest: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ChangeableAttributes + :type value: ~azure.containerregistry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -665,7 +708,7 @@ def update_manifest_attributes( body_content_kwargs = {} # type: Dict[str, Any] if value is not None: - body_content = self._serialize.body(value, 'ChangeableAttributes') + body_content = self._serialize.body(value, 'ContentProperties') else: body_content = None body_content_kwargs['content'] = body_content @@ -681,4 +724,4 @@ def update_manifest_attributes( if cls: return cls(pipeline_response, None, {}) - update_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{reference}'} # type: ignore + update_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index 3669e8109f0c..19fc65c20728 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -2,7 +2,8 @@ ### Settings ``` yaml -input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/bb7ef909d6e465085cee3aa29f27453551722769/sdk/containerregistry/container-registry/swagger/containerregistry.json +input-file: https://github.com/Azure/azure-sdk-for-js/blob/3760670d864e3334a800687f5b6deffce9ef78d3/sdk/containerregistry/container-registry/swagger/containerregistry.json +# input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/bb7ef909d6e465085cee3aa29f27453551722769/sdk/containerregistry/container-registry/swagger/containerregistry.json output-folder: "../azure/containerregistry/_generated" namespace: azure.containerregistry no-namespace-folders: true From 2058b4a58bbd2c30ff9e4ace0d2454ed02421914 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 11:59:08 -0400 Subject: [PATCH 26/86] adding tests for list and delete not exists, small changes to tests.yml --- .../_container_registry_client.py | 8 +-- ...test_delete_repository_does_not_exist.yaml | 50 +++++++++++++++++++ ...egistry_client.test_list_repositories.yaml | 47 +++++++++++++++++ ...gistry_client.test_list_repositories2.yaml | 47 +++++++++++++++++ .../tests/test_container_registry_client.py | 21 ++++++-- sdk/containerregistry/tests.yml | 7 +-- 6 files changed, 168 insertions(+), 12 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index f91c6b758ae6..20036a1fe378 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -30,8 +30,6 @@ def __init__(self, endpoint, credential, **kwargs): endpoint=endpoint, credential=credential, **kwargs ) - pass - def delete_repository(self, repository, **kwargs): # type: (str) -> DeletedRepositoryResult """Delete a repository @@ -58,12 +56,10 @@ def list_repositories(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[str] :raises: None """ - # NOTE: `/acr/v1/_catalog` - raise NotImplementedError("Not implemented") - repos = self._client.repository.get_list( + return self._client.container_registry.get_repositories( last=kwargs.get("last", None), n=kwargs.get("max", None) ) - return ItemPaged() + def get_repository_client(self, repository, **kwargs): # type: (str) -> ContainerRepositoryClient diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml new file mode 100644 index 000000000000..31cb09c2945f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml @@ -0,0 +1,50 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"not_real_repo"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '121' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 18 Mar 2021 15:58:46 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 404 + message: Not Found +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml new file mode 100644 index 000000000000..1e7c69e0eb66 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["hello-world"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '33' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 18 Mar 2021 15:58:47 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml new file mode 100644 index 000000000000..5000163caa3c --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["hello-world"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '33' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 18 Mar 2021 15:54:32 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index d2b518458a77..dc4c78f9891d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -5,6 +5,8 @@ # ------------------------------------ import functools import os +import pytest +import six from devtools_testutils import AzureTestCase, PowerShellPreparer @@ -13,6 +15,8 @@ ContainerRegistryUserCredential, DeletedRepositoryResult, ) +from azure.core.exceptions import ResourceNotFoundError +from azure.core.paging import ItemPaged from azure.identity import DefaultAzureCredential from _shared.testcase import ContainerRegistryTestClass @@ -31,13 +35,17 @@ class TestContainerRegistryClient(AzureTestCase, ContainerRegistryTestClass): def test_list_repositories(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) - repos = client.list_repositories() + repositories = client.list_repositories() + assert isinstance(repositories, ItemPaged) + count = 0 - for repo in repos._repositories: + for repo in repositories: count += 1 + assert isinstance(repo, six.string_types) assert count > 0 + @pytest.mark.skip("Don't want to delete for now") @acr_preparer() def test_delete_repository(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) @@ -46,4 +54,11 @@ def test_delete_repository(self, containerregistry_baseurl): assert isinstance(deleted_result, DeletedRepositoryResult) assert len(deleted_result.deleted_registry_artifact_digests) == 1 - assert len(deleted_result.deleted_tags) == 1 \ No newline at end of file + assert len(deleted_result.deleted_tags) == 1 + + @acr_preparer() + def test_delete_repository_does_not_exist(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + with pytest.raises(ResourceNotFoundError): + deleted_result = client.delete_repository("not_real_repo") \ No newline at end of file diff --git a/sdk/containerregistry/tests.yml b/sdk/containerregistry/tests.yml index b95787fd918f..47d8d959fae2 100644 --- a/sdk/containerregistry/tests.yml +++ b/sdk/containerregistry/tests.yml @@ -4,10 +4,11 @@ stages: - template: ../../eng/pipelines/templates/stages/archetype-sdk-tests.yml parameters: AllocateResourceGroup: 'false' - BuildTargetingString: $(BuildTargetingString) - ServiceDirectory: template + BuildTargetingString: azure-containerregistry + ServiceDirectory: containerregistry + TestSamples: false + DeployArmTemplate: true EnvVars: - TEMPLATE_CONFIG_CONNECTION: $(python-template-connection-string) # Add variables/mappings as appropriate for your service. AZURE_CLIENT_ID: $(aad-azure-sdk-test-client-id) AZURE_CLIENT_SECRET: $(aad-azure-sdk-test-client-secret) AZURE_TENANT_ID: $(aad-azure-sdk-test-tenant-id) From 70d8524ca7815a45e1513c0066e91ba21782cbc0 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 12:52:57 -0400 Subject: [PATCH 27/86] adding more list tests --- .../_container_repository_client.py | 17 +++++-- .../azure/containerregistry/_models.py | 8 ++-- .../azure-containerregistry/swagger/README.md | 5 -- ...iner_repository_client.test_list_tags.yaml | 8 ++-- ...tory_client.test_list_tags_descending.yaml | 47 +++++++++++++++++++ .../tests/test_container_repository_client.py | 34 +++++++++++--- 6 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index ee11503dc077..bd789c3ea916 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -142,12 +142,23 @@ def list_tags(self, **kwargs): # type: (...) -> ItemPaged[TagProperties] """List the tags for a repository + :param last: Query parameter for the last item in the previous call. Ensuing + call will return values after last lexically + :type last: str + :param order_by: Query paramter for ordering by time ascending or descending :returns: ~azure.core.paging.ItemPaged[TagProperties] :raises: None """ - raise NotImplementedError("Not implemented") - tags = self._client.container_registry.get_attributes(self.repository, **kwargs) - return tags + return self._client.container_registry_repository.get_tags( + self.repository, + last=kwargs.pop("last", None), + n=kwargs.pop("top", None), + orderby=kwargs.pop("order_by", None), + digest=kwargs.pop("digest", None), + cls=lambda objs: [TagProperties.from_generated(o) for o in objs], + **kwargs + ) + def set_manifest_properties(self, digest, value): # type: (str, ContentPermissions) -> None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 401f13f5115b..fd990d33e627 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -167,8 +167,8 @@ def __init__(self, **kwargs): self.content_permissions ) self.name = kwargs.get("name", None) - self.registry = kwargs.get("registry", None) - self.repository = kwargs.get("repository", None) + self.signed = kwargs.get('signed', None) + self.quarantine_state = kwargs.get('quarantine_state', None) @classmethod def from_generated(cls, generated): @@ -178,6 +178,6 @@ def from_generated(cls, generated): last_updated_on=generated.last_updated_on, content_permissions=generated.modifiable_properties, name=generated.name, - registry=generated.registry, - repository=generated.repository, + signed=generated.additional_properties.get("signed", None), + quarantine_state=generated.additional_properties.get("quarantineState", None), ) diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index 19fc65c20728..d3b751a58b7c 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -3,7 +3,6 @@ ### Settings ``` yaml input-file: https://github.com/Azure/azure-sdk-for-js/blob/3760670d864e3334a800687f5b6deffce9ef78d3/sdk/containerregistry/container-registry/swagger/containerregistry.json -# input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/bb7ef909d6e465085cee3aa29f27453551722769/sdk/containerregistry/container-registry/swagger/containerregistry.json output-folder: "../azure/containerregistry/_generated" namespace: azure.containerregistry no-namespace-folders: true @@ -15,7 +14,3 @@ clear-output-folder: true enable-xml: true vanilla: true ``` - - \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index cfd32042523b..4c050552638a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -12,10 +12,10 @@ interactions: - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} ' headers: @@ -27,11 +27,11 @@ interactions: connection: - keep-alive content-length: - - '289' + - '722' content-type: - application/json; charset=utf-8 date: - - Tue, 16 Mar 2021 16:28:33 GMT + - Thu, 18 Mar 2021 16:09:21 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml new file mode 100644 index 000000000000..48bda3bbce8a --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '722' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 18 Mar 2021 16:52:07 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 0ff00701ab15..7dd4c92a580f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -15,7 +15,9 @@ RepositoryProperties, ContentPermissions, TagProperties, + TagOrderBy, ) +from azure.core.paging import ItemPaged from _shared.testcase import ContainerRegistryTestClass @@ -30,6 +32,7 @@ class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): repository = "hello-world" + @pytest.mark.skip("Don't want to delete right now") @acr_preparer() def test_delete_repository(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -85,18 +88,37 @@ def test_get_tag(self, containerregistry_baseurl): self.assert_tag(tag) - @pytest.mark.skip("List pending") @acr_preparer() def test_list_tags(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) - repos = client.list_tags() + tags = client.list_tags() + assert isinstance(tags, ItemPaged) count = 0 - # for repo in repos._repositories: - # count += 1 - print(repos) + for tag in tags: + count += 1 + print(tag) + + assert count > 0 + + @acr_preparer() + def test_list_tags_descending(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) - # assert count > 0 + # TODO: This is giving time in ascending order + tags = client.list_tags(order_by=TagOrderBy.LastUpdateTimeDescending) + assert isinstance(tags, ItemPaged) + last_updated_on = None + count = 0 + for tag in tags: + print(tag.last_updated_on) + # if last_updated_on: + # assert tag.last_updated_on < last_updated_on + last_updated_on = tag.last_updated_on + count += 1 + # print(tag) + + assert count > 0 @pytest.mark.skip("List pending") @acr_preparer() From 9da7eee6c4d70e92a3f7fb3cc4f125f3ca5ee70e Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 14:47:55 -0400 Subject: [PATCH 28/86] updating readme and setup --- .../azure-containerregistry/README.md | 2 +- sdk/containerregistry/azure-containerregistry/setup.py | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md index 92c7ca73c592..3de88cd06df8 100644 --- a/sdk/containerregistry/azure-containerregistry/README.md +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -1,6 +1,6 @@ [![Build Status](https://dev.azure.com/azure-sdk/public/_apis/build/status/azure-sdk-for-python.client?branchName=master)](https://dev.azure.com/azure-sdk/public/_build/latest?definitionId=46?branchName=master) -# Azure Template Package client library for Python +# Azure Container Registry client library for Python This template package matches necessary patterns that the development team has established to create a unified sdk functional from Python 2.7 onwards. The packages contained herein can be installed singly or as part of the `azure` namespace. Any other introductory text should go here. diff --git a/sdk/containerregistry/azure-containerregistry/setup.py b/sdk/containerregistry/azure-containerregistry/setup.py index 368c146999d9..e6db75b24d19 100644 --- a/sdk/containerregistry/azure-containerregistry/setup.py +++ b/sdk/containerregistry/azure-containerregistry/setup.py @@ -11,7 +11,7 @@ # up from python 2.7. Reference here: https://github.com/Azure/azure-sdk-for-python/wiki/Azure-packaging PACKAGE_NAME = "azure-containerregistry" -PACKAGE_PPRINT_NAME = "Template Package" +PACKAGE_PPRINT_NAME = "Azure Container Registry" # a-b-c => a/b/c package_folder_path = PACKAGE_NAME.replace("-", "/") @@ -20,9 +20,7 @@ # Version extraction inspired from 'requests' with open(os.path.join(package_folder_path, "_version.py"), "r") as fd: - version = re.search( - r'^VERSION\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), re.MULTILINE - ).group(1) + version = re.search(r'^VERSION\s*=\s*[\'"]([^\'"]*)[\'"]', fd.read(), re.MULTILINE).group(1) if not version: raise RuntimeError("Cannot find version information") @@ -32,9 +30,7 @@ setup( name=PACKAGE_NAME, version=version, - description="Microsoft Azure {} Client Library for Python".format( - PACKAGE_PPRINT_NAME - ), + description="Microsoft Azure {} Client Library for Python".format(PACKAGE_PPRINT_NAME), # ensure that these are updated to reflect the package owners' information long_description=long_description, url="https://github.com/Azure/azure-sdk-for-python", From eea67498120e64fd66d1f8c30714136ece21d306 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 15:01:02 -0400 Subject: [PATCH 29/86] adding more things the pipelines need --- .../dev_requirements.txt | 3 + ...test_get_registry_artifact_properties.yaml | 89 +++++++++++++++++++ ...tainer_repository_client.test_get_tag.yaml | 47 ++++++++++ .../tests/test_container_repository_client.py | 30 ++++--- 4 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml diff --git a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt index fc4514eab3ef..2546d22806ae 100644 --- a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt +++ b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt @@ -1,2 +1,5 @@ +-e ../../../tools/azure-devtools -e ../../../tools/azure-sdk-tools ../../core/azure-core +aiohttp>=3.0; python_version >= '3.5' +azure-identity \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml new file mode 100644 index 000000000000..a1fee822f8a6 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml @@ -0,0 +1,89 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security + Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/18/2021 8:35:38 AM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '911' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 18 Mar 2021 18:59:43 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/first + response: + body: + string: '404 page not found + + ' + headers: + connection: + - keep-alive + content-length: + - '19' + content-type: + - text/plain; charset=utf-8 + date: + - Thu, 18 Mar 2021 18:59:43 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 404 + message: Not Found +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml new file mode 100644 index 000000000000..f9f3c9d66fba --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '380' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 18 Mar 2021 18:59:31 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 7dd4c92a580f..d9a016256f70 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -32,20 +32,6 @@ class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): repository = "hello-world" - @pytest.mark.skip("Don't want to delete right now") - @acr_preparer() - def test_delete_repository(self, containerregistry_baseurl): - client = self.create_repository_client(containerregistry_baseurl, self.repository) - client.delete() - - reg_client = self.create_registry_client(containerregistry_baseurl) - - repo_count = 0 - for repo in reg_client.list_repositories(): - repo_count += 1 - - assert repo_count == 0 - @acr_preparer() def test_get_attributes(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -67,6 +53,7 @@ def test_get_properties(self, containerregistry_baseurl): assert properties.content_permissions is not None assert isinstance(properties.content_permissions, ContentPermissions) + @pytest.mark.skip("Pending") @acr_preparer() def test_get_registry_artifact_properties(self, containerregistry_baseurl): reg_client = self.create_repository_client(containerregistry_baseurl, "hello-world") @@ -128,3 +115,18 @@ def test_list_registry_artifacts(self, containerregistry_baseurl): repo_attribs = client.list_registry_artifacts() print(repo_attribs) + + + @pytest.mark.skip("Don't want to delete right now") + @acr_preparer() + def test_delete_repository(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + client.delete() + + reg_client = self.create_registry_client(containerregistry_baseurl) + + repo_count = 0 + for repo in reg_client.list_repositories(): + repo_count += 1 + + assert repo_count == 0 From 875b422282c6114d78ae120ae0f3320450df70a5 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 15:54:52 -0400 Subject: [PATCH 30/86] fixing pylint issues to get pipeline green --- .../azure/containerregistry/__init__.py | 48 ---- .../containerregistry/_artifact_client.py | 10 - .../_artifact_storage_client.py | 68 ----- .../_authentication_policy.py | 14 - .../azure/containerregistry/_base_client.py | 19 +- .../_container_registry_authentication.py | 30 +-- .../_container_registry_client.py | 10 +- ...ntainer_registry_user_credential_policy.py | 13 - .../_container_repository_client.py | 28 +- .../azure/containerregistry/_models.py | 4 - .../containerregistry/_storage_models.py | 241 ------------------ .../aio/_async_artifact_storage_client.py | 80 ------ .../aio/_async_container_registry_client.py | 15 +- .../dev_requirements.txt | 1 - 14 files changed, 52 insertions(+), 529 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index b1761c81e194..e4f5065f9462 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -6,8 +6,6 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -from ._artifact_storage_client import ArtifactStorageClient -from ._container_registry_authentication import ContainerRegistryStsClient from ._container_registry_client import ContainerRegistryClient from ._container_repository_client import ContainerRepositoryClient from ._models import ( @@ -19,29 +17,6 @@ TagOrderBy, TagProperties, ) -from ._storage_models import ( - ArtifactManifest, - CompleteUploadResult, - ConfigMediaType, - ContentDescriptor, - CreateManifestResult, - CreateUploadResult, - DockerManifestList, - DockerManifestV1, - DockerManifestV1FsLayer, - DockerManifestV1History, - DockerManifestV1ImageHistory, - DockerManifestV1Jwk, - DockerManifestV1JwkHeader, - DockerManifestV2, - ManifestListAttributes, - ManifestMediaType, - OCIIndex, - OCIManifest, - OCIManifestAnnotations, - RuntimePlatform, - UploadStatus, -) from ._authentication_policy import ( ContainerRegistryUserCredential, ContainerRegistryUserCredentialPolicy, @@ -51,8 +26,6 @@ __version__ = VERSION __all__ = [ - "ArtifactStorageClient", - "ContainerRegistryStsClient", "ContainerRegistryClient", "ContainerRepositoryClient", "ContentPermissions", @@ -62,27 +35,6 @@ "RepositoryProperties", "TagOrderBy", "TagProperties", - "ArtifactManifest", - "CompleteUploadResult", - "ConfigMediaType", - "ContentDescriptor", - "CreateManifestResult", - "CreateUploadResult", - "DockerManifestList", - "DockerManifestV1", - "DockerManifestV1FsLayer", - "DockerManifestV1History", - "DockerManifestV1ImageHistory", - "DockerManifestV1Jwk", - "DockerManifestV1JwkHeader", - "DockerManifestV2", - "ManifestListAttributes", - "ManifestMediaType", - "OCIIndex", - "OCIManifest", - "OCIManifestAnnotations", - "RuntimePlatform", - "UploadStatus", "ContainerRegistryUserCredential", "ContainerRegistryUserCredentialPolicy", ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py deleted file mode 100644 index 364bcc93b2e2..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_client.py +++ /dev/null @@ -1,10 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - - -class ArtifactClient(object): - def __init__(self): - pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py deleted file mode 100644 index 4e2571189af9..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_artifact_storage_client.py +++ /dev/null @@ -1,68 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - - -class ArtifactStorageClient(object): - def __init__(self, endpoint, repository, credential): - # type: (str, str, TokenCredential) -> None - pass - - def cancel_upload(self, location, **kwargs): - # type: (str) -> None - pass - - def check_blob_exists(self, digest, **kwargs): - # type: (str) -> bool - pass - - def check_chunk_exists(self, digest, range, **kwargs): - # type: (str, HttpRange) -> bool - pass - - def complete_upload(self, upload_details, digest, value=None, **kwargs): - # type: (CreateUploadResult, str, Stream) -> None - pass - - def create_manifest(self, manifest, tag=None, **kwargs): - # type: (ArtifactManifest, str) -> None - pass - - def create_upload(self, **kwargs): - # type: (...) -> CreateUploadResult - pass - - def delete(self, **kwargs): - # type: (...) -> None - pass - - def delete_blob(self, digest, **kwargs): - # type: (str) -> Stream - pass - - def get_blob(self, digest, **kwargs): - # type: (str) -> Stream - pass - - def get_chunk(self, digest, range, **kwargs): - # type: (str, HttpRange) -> Stream - pass - - def get_manifest(self, tag_or_digest, accept_media_types=None, **kwargs): - # type: (str, Optional[List[ManifestMediaType]]) -> ArtifactManifest - pass - - def get_upload_status(self, location, **kwargs): - # type: (str) -> Response - pass - - def mount_blob(self, blob_from, mount, **kwargs): - # type: (str, str) -> Response - pass - - def upload_chunk(self, upload_details, value, **kwargs): - # type: (CreateUploadResult, Stream) -> CreateUploadResult - # TODO: upload_details should prob be a different type than the returned one - pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index 81ebb8075d86..e86698fae765 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -29,24 +29,10 @@ class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): def __init__(self, credential): self.credential = credential - def _enforce_https(self, request): - # Copied from BearerTokenCredentialPolicy - option = request.context.options.pop("enforce_https", None) - - if option is False: - request.context["enforce_https"] = option - - enforce_https = request.context.get("enforce_https", True) - if enforce_https and not request.http_request.url.lower().startswith("https"): - raise Exception( - "Auth is not permitted for non-TLS protected (non-https) URLs." - ) - @staticmethod def _update_headers(headers, token): headers["Authorization"] = "Basic {}".format(token) def on_request(self, request): # type: (PipelineRequest) -> None - # self._enforce_https(request) self._update_headers(request.http_request.headers, self.credential.get_token()) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index f261c64b7479..3b90280f97ab 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -6,13 +6,8 @@ from enum import Enum -from azure.core.pipeline.policies import ( - BearerTokenCredentialPolicy, -) - from ._authentication_policy import ContainerRegistryUserCredentialPolicy from ._generated import ContainerRegistry -from ._helpers import get_authentication_policy from ._user_agent import USER_AGENT @@ -23,7 +18,15 @@ class ContainerRegistryApiVersion(str, Enum): class ContainerRegistryBaseClient(object): - def __init__(self, endpoint, credential, **kwargs): + """ Base class for ContainerRegistryClient and ContainerRepositoryClient + + :param endpoint: Azure Container Registry endpoint + :type endpoint: str + :param credential: AAD Token for authenticating requests with Azure + :type credential: :class:`azure.identity.DefaultTokenCredential` + + """ + def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-method-missing-type-annotations auth_policy = ContainerRegistryUserCredentialPolicy(credential=credential) self._client = ContainerRegistry( credential=credential, @@ -50,6 +53,6 @@ def close(self): """ self._client.close() - def _is_tag(self, tag_or_digest): + def _is_tag(self, tag_or_digest): # pylint: disable=no-self-use tag = tag_or_digest.split(":") - return len(tag) == 2 and tag[0] == u"sha" \ No newline at end of file + return len(tag) == 2 and tag[0] == u"sha" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py index d49f8bac04cf..a95714a56549 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py @@ -5,20 +5,20 @@ # ------------------------------------ -class ContainerRegistryStsClient(object): - def __init__(self, endpoint, credential, **kwargs): - # type: (str, TokenCredential) -> None - """Create a ContainerRepositoryStsClient from an endpoint and a credential +# class ContainerRegistryStsClient(object): +# def __init__(self, endpoint, credential, **kwargs): +# # type: (str, TokenCredential) -> None +# """Create a ContainerRepositoryStsClient from an endpoint and a credential - :param endpoint: An ACR endpoint - :type endpoint: str - :param credential: The credential with which to authenticate - :type credential: TokenCredential - :returns: None - :raises: None - """ - pass +# :param endpoint: An ACR endpoint +# :type endpoint: str +# :param credential: The credential with which to authenticate +# :type credential: TokenCredential +# :returns: None +# :raises: None +# """ +# pass - def get_access_token(self, **kwargs): - # type: (...) -> None - pass +# def get_access_token(self, **kwargs): +# # type: (...) -> None +# pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 20036a1fe378..a2134cf1bb87 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -3,12 +3,11 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -import functools - from azure.core.paging import ItemPaged from ._base_client import ContainerRegistryBaseClient -from ._models import RepositoryProperties, DeletedRepositoryResult +from ._container_repository_client import ContainerRepositoryClient +from ._models import DeletedRepositoryResult class ContainerRegistryClient(ContainerRegistryBaseClient): @@ -41,7 +40,7 @@ def delete_repository(self, repository, **kwargs): """ # NOTE: DELETE `/acr/v1/{name}` deleted_repository = self._client.container_registry.delete_repository( - repository + repository, **kwargs ) return DeletedRepositoryResult.from_generated(deleted_repository) @@ -57,7 +56,7 @@ def list_repositories(self, **kwargs): :raises: None """ return self._client.container_registry.get_repositories( - last=kwargs.get("last", None), n=kwargs.get("max", None) + last=kwargs.pop("last", None), n=kwargs.pop("max", None), **kwargs ) @@ -72,4 +71,5 @@ def get_repository_client(self, repository, **kwargs): return ContainerRepositoryClient( repository, credential=self.credential, + **kwargs ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py deleted file mode 100644 index 2d8bbea6ab56..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_user_credential_policy.py +++ /dev/null @@ -1,13 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - -# JS implementation as a guide -# https://github.com/jeremymeng/azure-sdk-for-js/commit/654bbf957c04d56004cc08102008af76f12abf59#diff-2a5770d88b7304d5683f1c8e9c358f5d783396e5b6e5e2a0ff0e2f4c6c3b7045 - - -# This will be removed before the first preview, basic auth will be disabled by the service -class ContainerRegistryUserCredentialPolicy(BaseRequestPolicy): - pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index bd789c3ea916..3edec77689a9 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -37,7 +37,7 @@ def delete(self, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - self._client.container_registry.delete(self.repository, **kwargs) + self._client.container_registry.delete_repository(self.repository, **kwargs) def delete_registry_artifact(self, digest): # type: (str) -> None @@ -66,6 +66,7 @@ def get_digest_from_tag(self, tag): for t in self.list_tags(): if t.tag == tag: return t.digest + return "" def get_properties(self): # type: (...) -> RepositoryProperties @@ -88,13 +89,14 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :returns: :class:~azure.containerregistry.RegistryArtifactProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - # TODO: If `tag_or_digest` is a tag, need to do a get_tags to find the appropriate digest, generated code only takes a digest + # TODO: If `tag_or_digest` is a tag, need to do a get_tags to find the appropriate digest, + # generated code only takes a digest if self._is_tag(tag_or_digest): tag_or_digest = self.get_digest_from_tag(tag_or_digest) # TODO: The returned object from the generated code is not being deserialized properly return RegistryArtifactProperties.from_generated( self._client.container_registry_repository.get_manifest_attributes( - self.repository, tag_or_digest + self.repository, tag_or_digest, **kwargs ) ) @@ -109,7 +111,7 @@ def get_tag_properties(self, tag, **kwargs): """ return TagProperties.from_generated( self._client.container_registry_repository.get_tag_attributes( - self.repository, tag + self.repository, tag, **kwargs ) ) @@ -128,15 +130,15 @@ def list_registry_artifacts(self, **kwargs): """ raise NotImplementedError("Not implemented") # TODO: turn this into an ItemPaged - artifacts = self._client.manifests.get_list( - self.repository, - last=kwargs.get("last", None), - n=kwargs.get("n", None), - orderby=kwargs.get("orderby"), - ) # , - # cls=lambda objs: [RegistryArtifacts.from_generated(x) for x in objs]) - - return RegistryArtifactProperties.from_generated(artifacts) + # artifacts = self._client.manifests.get_list( + # self.repository, + # last=kwargs.get("last", None), + # n=kwargs.get("n", None), + # orderby=kwargs.get("orderby"), + # ) # , + # # cls=lambda objs: [RegistryArtifacts.from_generated(x) for x in objs]) + + # return RegistryArtifactProperties.from_generated(artifacts) def list_tags(self, **kwargs): # type: (...) -> ItemPaged[TagProperties] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index fd990d33e627..7a293b5aade3 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -6,8 +6,6 @@ from enum import Enum -from azure.core.paging import PageIterator - class ContentPermissions(object): def __init__(self, **kwargs): @@ -123,8 +121,6 @@ def from_generated(cls, generated): tag_count=generated.tag_count, content_permissions=generated.writeable_properties, ) - return cls(generated) - class RegistryArtifactOrderBy(int, Enum): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py deleted file mode 100644 index d076bf5284f8..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_storage_models.py +++ /dev/null @@ -1,241 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - - -class ArtifactManifest(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.media_type = kwargs.get("media_type", None) - self.schema_version = kwargs.get("media_version", None) - - def as_docker_manifest_list(self, **kwargs): - # type: (...) -> DockerManifestList - pass - - def as_docker_manifest_v1(self, **kwargs): - # type: (...) -> DockerManifestV1 - pass - - def as_docker_manifest_v2(self, **kwargs): - # type: (...) -> DockerManifestV2 - pass - - def as_docker_manifest_v1(self, **kwargs): - # type: (...) -> DockerManifestV1 - pass - - def as_oci_index(self, **kwargs): - # type: (...) -> OCIIndex - pass - - def as_oci_manifest(self, **kwargs): - # type: (...) -> OCIManifest - pass - - -class CompleteUploadResult(object): - def __init__(self, digest, location, http_range, **kwargs): - # type: (str, str, HttpRange) - self.digest = digest - self.location = location - self.http_range = http_range - - -class ConfigMediaType(object): - def __init__(self): - self.docker_image_v1 = None - self.oci_image_config = None - pass - - def __eq__(self, right): - # type: (ConfigMediaType) -> bool - pass - - def __ne__(self, right): - # type: (ConfigMediaType) -> bool - return not self.__eq__(right) - - def get_has_code(self, **kwargs): - # type: (...) -> int - pass - - def __repr__(self): - # type: (...) -> str - pass - - -class ContentDescriptor(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.media_type = kwargs.get("media_type", None) - self.annotations = kwargs.get("annotations", None) - self.digest = kwargs.get("digest", None) - self.size = kwargs.get("size", None) - self.urls = kwargs.get("urls", None) - self.compute_digest = kwargs.get("compute_digest", None) - - @classmethod - def _from_generated(self, generated, **kwargs): - # type: (Generated) -> ContentDescriptor - pass - - -class CreateManifestResult(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.content_length = kwargs.get("content_length", None) - self.digest = kwargs.get("digest", None) - self.location = kwargs.get("location", None) - - @classmethod - def _from_generated(self, generated, **kwargs): - # type: (Generated) -> CreateManifestResult - pass - - -class CreateUploadResult(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.location = kwargs.get("location", None) - self.http_range = kwargs.get("http_range", None) - self.upload_id = kwargs.get("upload_id", None) - - @classmethod - def _from_generated(self, generated, **kwargs): - # type: (Generated) -> CreateUploadResult - pass - - -# NOTE: This might be unnecessary, Pageable[ArtifactManifest] -class DockerManifestList(ArtifactManifest): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.manifests = kwargs.get("manifests", None) - - -class DockerManifestV1(ArtifactManifest): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.architecture = kwargs.get("architecture", None) - self.fs_layers = kwargs.get("fs_layers", None) - self.history = kwargs.get("history", None) - self.name = kwargs.get("name", None) - self.signatures = kwargs.get("signatures", None) - self.tag = kwargs.get("tag", None) - - -class DockerManifestV1FsLayer(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.blob_sum = kwargs.get("blob_sum", None) - - -class DockerManifestV1History(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.v1_compatibility = kwargs.get("v1_compatibility", None) - - -class DockerManifestV1ImageHistory(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.header = kwargs.get("header", None) - self.protected = kwargs.get("protected", None) - self.signature = kwargs.get("signature", None) - - -class DockerManifestV1Jwk(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.alg = kwargs.get("alg", None) - self.jwk = kwargs.get("jwk", None) - - -class DockerManifestV1JwkHeader(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.crv = kwargs.get("crv", None) - self.kid = kwargs.get("kid", None) - self.kty = kwargs.get("kty", None) - self.x = kwargs.get("x", None) - self.y = kwargs.get("y", None) - - -class DockerManifestV2(ArtifactManifest): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.config_descriptor = kwargs.get("config_descriptor") - self.layers = kwargs.get("layers") - - @classmethod - def from_stream(self, stream, **kwargs): - # type: (Stream) -> DockerManifestV2 - pass - - -class ManifestListAttributes(object): - def __init__(self, **kwargs): - # type: (...) -> None - self.digest = kwargs.get("digest", None) - self.media_type = kwargs.get("media_type", None) - self.platform = kwargs.get("platform", None) - self.size = kwargs.get("size", None) - - -class ManifestMediaType(object): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - pass - - def __eq__(self, other): - # type: (ManifestMediaType) -> bool - pass - - def __ne__(self, other): - # type: (ManifestMediaType) -> bool - return not self.__eq__(other) - - def __repr__(self): - # type: (...) -> str - pass - - def get_hash_code(self, **kwargs): - # type: (...) -> int - pass - - -class OCIIndex(ArtifactManifest): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.annotations = kwargs.get("annotations", None) - self.manifests = kwargs.get("manifests", None) - - -class OCIManifest(ArtifactManifest): - def __init__(self, **kwargs): - # type: (Optional[Dict[str, Any]]) -> None - self.annotations = kwargs.get("annotations", None) - self.config_descriptor = kwargs.get("config_descriptos", None) - self.layers = kwargs.get("layers", None) - - -# NOTE: This might not be needed, could return just a dict -class OCIManifestAnnotations(dict): - def __init__(self, **kwargs): - # type: (...) -> None - pass - - -class RuntimePlatform(object): - def __init__(self, **kwargs): - # type: (...) -> None - pass - - -class UploadStatus(object): - def __init__(self, **kwargs): - self.http_range = kwargs.get("http_range", None) - self.upload_id = kwargs.get("upload_id", None) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py deleted file mode 100644 index 101f3b53c60d..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_artifact_storage_client.py +++ /dev/null @@ -1,80 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - -from typing import TYPE_CHECKING - -from .._models import CreateUploadResult, ArtifactManifest, ManifestMediaType - -if TYPE_CHECKING: - from azure.core.async_credentials import AsyncTokenCredential - - -class ArtifactStorageClient(object): - def __init__( - self, - endpoint: str, - repository: str, - credential: "AsyncTokenCredential", - **kwargs - ) -> None: - pass - - def cancel_upload(self, location: str, **kwargs) -> None: - pass - - def check_blob_exists(self, digest: str, **kwargs) -> bool: - pass - - def check_chunk_exists(self, digest: str, range: "HttpRange", **kwargs) -> bool: - pass - - def complete_upload( - self, - upload_details: CreateUploadResult, - digest: str, - value: "Stream" = None, - **kwargs - ) -> None: - pass - - def create_manifest( - self, manifest: ArtifactManifest, tag: str = None, **kwargs - ) -> None: - pass - - def create_upload(self, **kwargs) -> CreateUploadResult: - pass - - def delete(self, **kwargs) -> None: - pass - - def delete_blob(self, digest: str, **kwargs) -> Stream: - pass - - def get_blob(self, digest: str, **kwargs) -> Stream: - pass - - def get_chunk(self, digest: str, range: HttpRange, **kwargs) -> Stream: - pass - - def get_manifest( - self, - tag_or_digest: str, - accept_media_types: list[ManifestMediaType] = None, - **kwargs - ) -> ArtifactManifest: - pass - - def get_upload_status(self, location: str, **kwargs) -> Response: - pass - - def mount_blob(self, blob_from: str, mount: str, **kwargs) -> Response: - pass - - def upload_chunk( - self, upload_details: CreateUploadResult, value: Stream, **kwargs - ) -> CreateUploadResult: - pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index 13cf772df228..cb8762d43628 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -4,18 +4,15 @@ # Licensed under the MIT License. # ------------------------------------ -from typing import TYPE_CHECKING - +from azure.core.credentials_async import AsyncTokenCredential from azure.core.async_paging import AsyncItemPaged -from .._container_repository_client import ContainerRegistryClient -from .._models import RepositoryAttributes -if TYPE_CHECKING: - from azure.core.async_credentials import AsyncTokenCredential +from .._container_registry_client import ContainerRegistryClient as SyncContainerRegistryClient +from .._models import RepositoryProperties class ContainerRegistryClient(object): - def __init__(self, base_url: str, credential: "AsyncTokenCredential", **kwargs): + def __init__(self, base_url: str, credential: AsyncTokenCredential, **kwargs): # pylint: disable=client-method-missing-type-annotations pass def delete_repository(self, name: str, **kwargs) -> None: @@ -24,8 +21,8 @@ def delete_repository(self, name: str, **kwargs) -> None: def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: pass - def get_repository_client(self, name: str, **kwargs) -> ContainerRegistryClient: + def get_repository_client(self, name: str, **kwargs) -> SyncContainerRegistryClient: pass - def get_repository_attributes(self, name: str, **kwargs) -> RepositoryAttributes: + def get_repository_attributes(self, name: str, **kwargs) -> RepositoryProperties: pass diff --git a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt index 2546d22806ae..5f40d6f3e081 100644 --- a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt +++ b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt @@ -1,4 +1,3 @@ --e ../../../tools/azure-devtools -e ../../../tools/azure-sdk-tools ../../core/azure-core aiohttp>=3.0; python_version >= '3.5' From 648102b6663c0f691fe8230ddba0544cbadd85b8 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 15:57:19 -0400 Subject: [PATCH 31/86] making all tests live tests --- .../tests/test_container_registry_client.py | 2 ++ .../tests/test_container_repository_client.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index dc4c78f9891d..b1bc6b946e1a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -31,6 +31,7 @@ class TestContainerRegistryClient(AzureTestCase, ContainerRegistryTestClass): + @pytest.mark.live_test_only @acr_preparer() def test_list_repositories(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) @@ -56,6 +57,7 @@ def test_delete_repository(self, containerregistry_baseurl): assert len(deleted_result.deleted_registry_artifact_digests) == 1 assert len(deleted_result.deleted_tags) == 1 + @pytest.mark.live_test_only @acr_preparer() def test_delete_repository_does_not_exist(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index d9a016256f70..075b253c262f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -32,6 +32,7 @@ class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): repository = "hello-world" + @pytest.mark.live_test_only @acr_preparer() def test_get_attributes(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -41,6 +42,7 @@ def test_get_attributes(self, containerregistry_baseurl): assert repo_attribs is not None assert repo_attribs.content_permissions is not None + @pytest.mark.live_test_only @acr_preparer() def test_get_properties(self, containerregistry_baseurl): reg_client = self.create_repository_client(containerregistry_baseurl, "hello-world") @@ -67,6 +69,7 @@ def test_get_registry_artifact_properties(self, containerregistry_baseurl): self.assert_registry_artifact(properties, digest) self.assert_registry_artifact(first_properties, tag) + @pytest.mark.live_test_only @acr_preparer() def test_get_tag(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -75,6 +78,7 @@ def test_get_tag(self, containerregistry_baseurl): self.assert_tag(tag) + @pytest.mark.live_test_only @acr_preparer() def test_list_tags(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -88,6 +92,7 @@ def test_list_tags(self, containerregistry_baseurl): assert count > 0 + @pytest.mark.live_test_only @acr_preparer() def test_list_tags_descending(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -116,7 +121,6 @@ def test_list_registry_artifacts(self, containerregistry_baseurl): print(repo_attribs) - @pytest.mark.skip("Don't want to delete right now") @acr_preparer() def test_delete_repository(self, containerregistry_baseurl): From 7a6bd87506a405bbb3655df2ff571e4d90188ac0 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 16:50:52 -0400 Subject: [PATCH 32/86] updating ci and readme with tables copies --- .../azure-containerregistry/README.md | 152 +++++++++++++++--- sdk/containerregistry/ci.yml | 2 + 2 files changed, 136 insertions(+), 18 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md index 3de88cd06df8..61f4c0277bed 100644 --- a/sdk/containerregistry/azure-containerregistry/README.md +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -1,35 +1,151 @@ -[![Build Status](https://dev.azure.com/azure-sdk/public/_apis/build/status/azure-sdk-for-python.client?branchName=master)](https://dev.azure.com/azure-sdk/public/_build/latest?definitionId=46?branchName=master) - # Azure Container Registry client library for Python -This template package matches necessary patterns that the development team has established to create a unified sdk functional from Python 2.7 onwards. The packages contained herein can be installed singly or as part of the `azure` namespace. Any other introductory text should go here. +Azure Container Registry is a NoSQL data storage service that can be accessed from anywhere in the world via authenticated calls using HTTP or HTTPS. +Tables scales as needed to support the amount of data inserted, and allow for the storing of data with non-complex accessing. +The Azure Container Registry client can be used to access Azure Storage or Cosmos accounts. + +[Source code][source_code] | [Package (PyPI)][Tables_pypi] | [API reference documentation][Tables_ref_docs] | [Samples][Tables_samples] + +## Getting started +The Azure Container Registry SDK can access an Azure Container Registry account. + +### Prerequisites +* Python 2.7, or 3.6 or later is required to use this package. +* You must have an [Azure subscription][azure_subscription] and an ACR account. + +#### Create account + +### Install the package +Install the Azure Container Registry client library for Python with [pip][pip_link]: +```bash +pip install --pre azure-containerregistry +``` + +#### Create the client + + +## Key concepts +Common uses of the ACR include: + +### Clients +Two different clients are provided to interact with the various components of the Table Service: + + +## Examples + +The following sections provide several code snippets covering some of the most common Table tasks, including: + + + +## Optional Configuration +Optional keyword arguments can be passed in at the client and per-operation level. The azure-core [reference documentation][azure_core_ref_docs] describes available configurations for retries, logging, transport protocols, and more. + + +### Retry Policy configuration + +Use the following keyword arguments when instantiating a client to configure the retry policy: + +* __retry_total__ (int): Total number of retries to allow. Takes precedence over other counts. +Pass in `retry_total=0` if you do not want to retry on requests. Defaults to 10. +* __retry_connect__ (int): How many connection-related errors to retry on. Defaults to 3. +* __retry_read__ (int): How many times to retry on read errors. Defaults to 3. +* __retry_status__ (int): How many times to retry on bad status codes. Defaults to 3. +* __retry_to_secondary__ (bool): Whether the request should be retried to secondary, if able. +This should only be enabled of RA-GRS accounts are used and potentially stale data can be handled. +Defaults to `False`. + +### Other client / per-operation configuration + +Other optional configuration keyword arguments that can be specified on the client or per-operation. + +**Client keyword arguments:** + +* __connection_timeout__ (int): Optionally sets the connect and read timeout value, in seconds. +* __transport__ (Any): User-provided transport to send the HTTP request. + +**Per-operation keyword arguments:** + +* __raw_response_hook__ (callable): The given callback uses the response returned from the service. +* __raw_request_hook__ (callable): The given callback uses the request before being sent to service. +* __client_request_id__ (str): Optional user specified identification of the request. +* __user_agent__ (str): Appends the custom value to the user-agent header to be sent with the request. +* __logging_enable__ (bool): Enables logging at the DEBUG level. Defaults to False. Can also be passed in at +the client level to enable it for all requests. +* __headers__ (dict): Pass in custom headers as key, value pairs. E.g. `headers={'CustomValue': value}` + + +## Troubleshooting + +### General +Azure Container Registry clients raise exceptions defined in [Azure Core][azure_core_readme]. When you interact with the Azure table library using the Python SDK, errors returned by the service respond ot the same HTTP status codes for [REST API][tables_rest] requests. The Table service operations will throw a `HttpResponseError` on failure with helpful [error codes][tables_error_codes]. + +For examples, if you try to create a table that already exists, a `409` error is returned indicating "Conflict". +```python +from azure.data.tables import TableServiceClient +from azure.core.exceptions import HttpResponseError +table_name = 'YourTableName' + +service_client = TableServiceClient.from_connection_string(connection_string) + +# Create the table if it does not already exist +tc = service_client.create_table_if_not_exists(table_name) -This package has been tested with Python 2.7, 3.5, 3.6, 3.7 and 3.8 +try: + service_client.create_table(table_name) +except HttpResponseError: + print("Table with name {} already exists".format(table_name)) +``` -For a more complete set of Azure libraries, see https://aka.ms/azsdk/python/all +### Logging +This library uses the standard +[logging][python_logging] library for logging. +Basic information about HTTP sessions (URLs, headers, etc.) is logged at INFO +level. -# Getting started +Detailed DEBUG level logging, including request/response bodies and unredacted +headers, can be enabled on a client with the `logging_enable` argument: +```python +import sys +import logging +from azure.data.tables import TableServiceClient +# Create a logger for the 'azure' SDK +logger = logging.getLogger('azure') +logger.setLevel(logging.DEBUG) -For a rich example of a well formatted readme, please check [here.](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-TEMPLATE.md) In addition, this is an [example readme](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-EXAMPLE.md) that should be emulated. Note that the top-level sections in this template align with that of the [template.](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-TEMPLATE.md) +# Configure a console output +handler = logging.StreamHandler(stream=sys.stdout) +logger.addHandler(handler) -# Key concepts +# This client will log detailed information about its HTTP sessions, at DEBUG level +service_client = TableServiceClient.from_connection_string("your_connection_string", logging_enable=True) +``` -Bullet point list of your library's main concepts. +Similarly, `logging_enable` can enable detailed logging for a single operation, +even when it is not enabled for the client: +```python +service_client.create_entity(entity=my_entity, logging_enable=True) +``` -# Examples +## Next steps -Examples of some of the key concepts for your library. +Several Azure Container Registry Python SDK samples are available to you in the SDK's GitHub repository. These samples provide example code for additional scenarios commonly encountered while working with Tables. -# Troubleshooting -Running into issues? This section should contain details as to what to do there. +## Contributing +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. -# Next steps +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. -More sample code should go here, along with links out to the appropriate example tests. +This project has adopted the [Microsoft Open Source Code of Conduct][msft_oss_coc]. For more information see the [Code of Conduct FAQ][msft_oss_coc_faq] or contact [opencode@microsoft.com][contact_msft_oss] with any additional questions or comments. -# Contributing + +[pip_link]:https://pypi.org/project/pip/ +[azure_core_ref_docs]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-core/latest/azure.core.html +[azure_core_readme]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/core/azure-core/README.md +[python_logging]: https://docs.python.org/3/library/logging.html +[msft_oss_coc]:https://opensource.microsoft.com/codeofconduct/ +[msft_oss_coc_faq]:https://opensource.microsoft.com/codeofconduct/faq/ +[contact_msft_oss]:mailto:opencode@microsoft.com -If you encounter any bugs or have suggestions, please file an issue in the [Issues]() section of the project. -![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-python%2Fsdk%2Ftemplate%2Fazure-template%2FREADME.png) +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-python/sdk/tables/azure-data-tables/README.png) \ No newline at end of file diff --git a/sdk/containerregistry/ci.yml b/sdk/containerregistry/ci.yml index 34a0699c0b11..0baeb617b236 100644 --- a/sdk/containerregistry/ci.yml +++ b/sdk/containerregistry/ci.yml @@ -30,3 +30,5 @@ extends: Artifacts: - name: azure_mgmt_containerregistry safeName: azuremgmtcontainerregistry + - name: azure-containerregistry + safeName: azurecontainerregistry \ No newline at end of file From f82ed358b86079a5d6a9b7b9cdde13aec0a821d1 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 18 Mar 2021 17:08:27 -0400 Subject: [PATCH 33/86] updates to readme --- sdk/containerregistry/azure-containerregistry/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md index 61f4c0277bed..d9971745222f 100644 --- a/sdk/containerregistry/azure-containerregistry/README.md +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -45,14 +45,11 @@ Optional keyword arguments can be passed in at the client and per-operation leve Use the following keyword arguments when instantiating a client to configure the retry policy: -* __retry_total__ (int): Total number of retries to allow. Takes precedence over other counts. -Pass in `retry_total=0` if you do not want to retry on requests. Defaults to 10. +* __retry_total__ (int): Total number of retries to allow. Takes precedence over other counts. Pass in `retry_total=0` if you do not want to retry on requests. Defaults to 10. * __retry_connect__ (int): How many connection-related errors to retry on. Defaults to 3. * __retry_read__ (int): How many times to retry on read errors. Defaults to 3. * __retry_status__ (int): How many times to retry on bad status codes. Defaults to 3. -* __retry_to_secondary__ (bool): Whether the request should be retried to secondary, if able. -This should only be enabled of RA-GRS accounts are used and potentially stale data can be handled. -Defaults to `False`. +* __retry_to_secondary__ (bool): Whether the request should be retried to secondary, if able. This should only be enabled of RA-GRS accounts are used and potentially stale data can be handled. Defaults to `False`. ### Other client / per-operation configuration From 6ba90bed7e6288a77036af1deed68d25ea064f32 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 12:01:27 -0400 Subject: [PATCH 34/86] adding more changes --- .../azure/containerregistry/__init__.py | 2 +- .../_authentication_policy.py | 38 ------------------- .../azure/containerregistry/_base_client.py | 2 +- ...egistry_client.test_list_repositories.yaml | 2 +- ...iner_repository_client.test_list_tags.yaml | 2 +- ...tory_client.test_list_tags_descending.yaml | 2 +- sdk/containerregistry/ci.yml | 13 ++++++- sdk/containerregistry/tests.yml | 2 +- 8 files changed, 17 insertions(+), 46 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index e4f5065f9462..0d6259518122 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -17,7 +17,7 @@ TagOrderBy, TagProperties, ) -from ._authentication_policy import ( +from .authentication._authentication_policy import ( ContainerRegistryUserCredential, ContainerRegistryUserCredentialPolicy, ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py deleted file mode 100644 index e86698fae765..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ /dev/null @@ -1,38 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - -from base64 import b64encode - -from azure.core.pipeline.policies import SansIOHTTPPolicy - - -class ContainerRegistryUserCredential(object): - """Credential used to authenticate with Container Registry service""" - - def __init__(self, username, password): - self._user = username - self._password = password - - def get_token(self): - token_str = "{}:{}".format(self._user, self._password) - token_bytes = token_str.encode("ascii") - b64_bytes = b64encode(token_bytes) - return b64_bytes.decode("ascii") - - -class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): - """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" - - def __init__(self, credential): - self.credential = credential - - @staticmethod - def _update_headers(headers, token): - headers["Authorization"] = "Basic {}".format(token) - - def on_request(self, request): - # type: (PipelineRequest) -> None - self._update_headers(request.http_request.headers, self.credential.get_token()) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 3b90280f97ab..56a83bd4a32c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -6,7 +6,7 @@ from enum import Enum -from ._authentication_policy import ContainerRegistryUserCredentialPolicy +from .authentication._authentication_policy import ContainerRegistryUserCredentialPolicy from ._generated import ContainerRegistry from ._user_agent import USER_AGENT diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index 1e7c69e0eb66..7f82320be48d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 15:58:47 GMT + - Thu, 18 Mar 2021 22:12:59 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index 4c050552638a..df994523904e 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 16:09:21 GMT + - Thu, 18 Mar 2021 22:13:00 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml index 48bda3bbce8a..277f34bad509 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 16:52:07 GMT + - Thu, 18 Mar 2021 22:13:01 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/ci.yml b/sdk/containerregistry/ci.yml index 0baeb617b236..cd062bd930d1 100644 --- a/sdk/containerregistry/ci.yml +++ b/sdk/containerregistry/ci.yml @@ -4,24 +4,33 @@ trigger: branches: include: - master + - main - hotfix/* - release/* - restapi* paths: include: - - sdk/containerregistry/ + - sdk/tables/ + - sdk/core/ + - tools/ + - eng/ pr: branches: include: - master + - main - feature/* - hotfix/* - release/* - restapi* paths: include: - - sdk/containerregistry/ + - sdk/tables/ + - sdk/core/ + - tools/ + - eng/ + extends: template: ../../eng/pipelines/templates/stages/archetype-sdk-client.yml diff --git a/sdk/containerregistry/tests.yml b/sdk/containerregistry/tests.yml index 47d8d959fae2..234c50fd7bdc 100644 --- a/sdk/containerregistry/tests.yml +++ b/sdk/containerregistry/tests.yml @@ -3,7 +3,7 @@ trigger: none stages: - template: ../../eng/pipelines/templates/stages/archetype-sdk-tests.yml parameters: - AllocateResourceGroup: 'false' + AllocateResourceGroup: false BuildTargetingString: azure-containerregistry ServiceDirectory: containerregistry TestSamples: false From b0922ba8285de590fcdfa3c314890d781034e54b Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 12:13:26 -0400 Subject: [PATCH 35/86] draft based on pallavis code --- .../authentication/_access_token_cache.py | 0 .../authentication/_authentication_policy.py | 60 +++++++++++++ .../_container_registry_credential_policy.py | 90 +++++++++++++++++++ .../_container_registry_token_credential.py | 33 +++++++ .../_container_registry_token_service.py | 0 5 files changed, 183 insertions(+) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py new file mode 100644 index 000000000000..5a66b8549949 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py @@ -0,0 +1,60 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from base64 import b64encode +import re + +from azure.core.pipeline.policies import SansIOHTTPPolicy + + +class ContainerRegistryUserCredential(object): + """Credential used to authenticate with Container Registry service""" + + def __init__(self, username, password): + self._user = username + self._password = password + + def get_token(self): + token_str = "{}:{}".format(self._user, self._password) + token_bytes = token_str.encode("ascii") + b64_bytes = b64encode(token_bytes) + return b64_bytes.decode("ascii") + + +class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): + """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" + + def __init__(self, credential): + self.credential = credential + + @staticmethod + def _update_headers(headers, token): + headers["Authorization"] = "Basic {}".format(token) + + def on_request(self, request): + # type: (PipelineRequest) -> None + self._update_headers(request.http_request.headers, self.credential.get_token()) + + +class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): + """Challenge based authentication policy for ACR. This policy is used for getting + the AAD Token, refresh token, and access token before performing a call to service. + + :param credential: Azure Token Credential for authenticating with Azure + :type credential: TokenCredential + """ + + BEARER = "Bearer" + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + WWW_AUTHENTICATE = "WWW-Authenticate" + SCOPE_PARAMETER = "scope" + SERVICE_PARAMETER = "service" + AUTHORIZATION = "Authorization" + + def __init__(self, credential, url, pipeline): + self.credential = credential + self.url = url + self.pipeline = pipeline \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py new file mode 100644 index 000000000000..e0d4369dbd05 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py @@ -0,0 +1,90 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import re + +from azure.core.pipeline.policies import SansIOHTTPPolicy + +# Follows challenge based authorization scheme + +# For example: + +# 1. GET /api/vr/acr/repositories (no authorization included) +# Return Header: 401: www-authenticate header - Bearer realm="{url}",service="{service_name}",scope="{scope}",error="invalid_token". + +# 2. Parse service_name, scope from the service + +# 3. POST /api/oauth2/exchange (grant-type=refresh_token) +# Request Body: {service, scope, grant-type, aadToken w/ ARM scope} +# Response Body: {acr refresh token} + +# 4. POST /api/oauth2/token (grant-type=access_token) +# Request Body: {acr refresh token, scope, grant-type} +# Response Body: {acr access token} + +# 5. GET /api/v1/acr/repositories +# Request Header: {Bearer acr acces token} + + +class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): + """Challenge based authentication policy for ACR. This policy is used for getting + the AAD Token, refresh token, and access token before performing a call to service. + + :param credential: Azure Token Credential for authenticating with Azure + :type credential: TokenCredential + """ + + BEARER = "Bearer" + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + WWW_AUTHENTICATE = "WWW-Authenticate" + SCOPE_PARAMETER = "scope" + SERVICE_PARAMETER = "service" + AUTHORIZATION = "Authorization" + + def __init__(self, credential, url, pipeline): + self.credential = credential + self.url = url + self.pipeline = pipeline + + def process(self, context, next): + # type: (HttpPipelineContext, HttpPipelinePolicy) -> HttpResponse + pass + + def authorize_request(self, context, token_request_context): + # type: (HttpPipelineCallContext, ContainerRegistryTokenRequestContext) -> None + pass + + def on_challenge(self, context, response): + # type: (HttpPipelineCallContext, HttpResponse) -> bool + return False + + def parse_bearer_challenge(self, header): + # type: (str) -> dict[str, str] + if header.startswith(self.BEARER): + challenge_params = header[len(self.BEARER)+1:] + + matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) + self._clean(matches) + ret = {} + for i in range(len(matches), 2): + ret[matches[i]] = matches[i+1] + + return ret + + return {} + + def _clean(self, matches): + # type: (List[str]) -> None + while: + try: + matches.remove('') + except ValueError: + break + + while: + try: + matches.remove(',') + except ValueError: + return \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py new file mode 100644 index 000000000000..34d16fdc784d --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py @@ -0,0 +1,33 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + + +class ContainerRegistryTokenCredential(object): + """Token credential representing the container registry refresh token. + This token is unique per registry operation, + + :param token_service: TokenServiceImplementation + :type token_service: TokenServiceImpl + :param token_credential: AAD Token Credential + :type token_credential: :class:`~azure.core.credential.TokenCredential` + """ + + AAD_DEFAULT_SCOPE = "https://management.core.windows.net/.default" + + def __init__(self, token_service, aad_token_credential): + # type: (TokenServiceImpl, TokenCredential) -> None + self.token_service = token_service + self.token_credential = aad_token_credential + + def get_token(self, context): + # type: (ContainerRegistryTokenRequestContext) -> AccessToken + service_name = context.get_service_name() + + token = self.token_credential.get_token( + TokenRequestContext().add_scopes(self.AAD_DEFAULT_SCOPE) + ) + + return self.token_service.get_acr_refresh_token(token.get_token, service_name) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py new file mode 100644 index 000000000000..e69de29bb2d1 From 82c5d3c5fe655a5b8e0f8c0900734372ada4d8db Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 14:21:33 -0400 Subject: [PATCH 36/86] updating readme --- sdk/containerregistry/azure-containerregistry/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md index d9971745222f..6bbd30b92281 100644 --- a/sdk/containerregistry/azure-containerregistry/README.md +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -66,8 +66,7 @@ Other optional configuration keyword arguments that can be specified on the clie * __raw_request_hook__ (callable): The given callback uses the request before being sent to service. * __client_request_id__ (str): Optional user specified identification of the request. * __user_agent__ (str): Appends the custom value to the user-agent header to be sent with the request. -* __logging_enable__ (bool): Enables logging at the DEBUG level. Defaults to False. Can also be passed in at -the client level to enable it for all requests. +* __logging_enable__ (bool): Enables logging at the DEBUG level. Defaults to False. Can also be passed in at the client level to enable it for all requests. * __headers__ (dict): Pass in custom headers as key, value pairs. E.g. `headers={'CustomValue': value}` From 103db71409e569789c176d8508951b6290d8cbe3 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 14:38:07 -0400 Subject: [PATCH 37/86] removing old sections from readme --- .../azure-containerregistry/README.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md index 6bbd30b92281..107b300a3356 100644 --- a/sdk/containerregistry/azure-containerregistry/README.md +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -69,28 +69,10 @@ Other optional configuration keyword arguments that can be specified on the clie * __logging_enable__ (bool): Enables logging at the DEBUG level. Defaults to False. Can also be passed in at the client level to enable it for all requests. * __headers__ (dict): Pass in custom headers as key, value pairs. E.g. `headers={'CustomValue': value}` - ## Troubleshooting ### General -Azure Container Registry clients raise exceptions defined in [Azure Core][azure_core_readme]. When you interact with the Azure table library using the Python SDK, errors returned by the service respond ot the same HTTP status codes for [REST API][tables_rest] requests. The Table service operations will throw a `HttpResponseError` on failure with helpful [error codes][tables_error_codes]. - -For examples, if you try to create a table that already exists, a `409` error is returned indicating "Conflict". -```python -from azure.data.tables import TableServiceClient -from azure.core.exceptions import HttpResponseError -table_name = 'YourTableName' -service_client = TableServiceClient.from_connection_string(connection_string) - -# Create the table if it does not already exist -tc = service_client.create_table_if_not_exists(table_name) - -try: - service_client.create_table(table_name) -except HttpResponseError: - print("Table with name {} already exists".format(table_name)) -``` ### Logging This library uses the standard From 9a26fcf56beea3c25741348dca520913c32272c5 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 14:51:33 -0400 Subject: [PATCH 38/86] more readme deletions --- .../azure-containerregistry/README.md | 28 +------------------ 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md index 107b300a3356..cf721c87d2b1 100644 --- a/sdk/containerregistry/azure-containerregistry/README.md +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -75,34 +75,8 @@ Other optional configuration keyword arguments that can be specified on the clie ### Logging -This library uses the standard -[logging][python_logging] library for logging. -Basic information about HTTP sessions (URLs, headers, etc.) is logged at INFO -level. - -Detailed DEBUG level logging, including request/response bodies and unredacted -headers, can be enabled on a client with the `logging_enable` argument: -```python -import sys -import logging -from azure.data.tables import TableServiceClient -# Create a logger for the 'azure' SDK -logger = logging.getLogger('azure') -logger.setLevel(logging.DEBUG) - -# Configure a console output -handler = logging.StreamHandler(stream=sys.stdout) -logger.addHandler(handler) - -# This client will log detailed information about its HTTP sessions, at DEBUG level -service_client = TableServiceClient.from_connection_string("your_connection_string", logging_enable=True) -``` +This library uses the standard [logging][python_logging] library for logging. Basic information about HTTP sessions (URLs, headers, etc.) is logged at INFO level. -Similarly, `logging_enable` can enable detailed logging for a single operation, -even when it is not enabled for the client: -```python -service_client.create_entity(entity=my_entity, logging_enable=True) -``` ## Next steps From 8ec00fd82589e009ff1044c1c4d664d15fdc827e Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 15:12:48 -0400 Subject: [PATCH 39/86] adding auth policy back in --- .../azure-containerregistry/README.md | 104 +++--------------- .../azure/containerregistry/__init__.py | 2 +- .../_authentication_policy.py | 60 ++++++++++ .../azure/containerregistry/_base_client.py | 2 +- 4 files changed, 80 insertions(+), 88 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py diff --git a/sdk/containerregistry/azure-containerregistry/README.md b/sdk/containerregistry/azure-containerregistry/README.md index cf721c87d2b1..6257d73b1f09 100644 --- a/sdk/containerregistry/azure-containerregistry/README.md +++ b/sdk/containerregistry/azure-containerregistry/README.md @@ -1,103 +1,35 @@ -# Azure Container Registry client library for Python + -Azure Container Registry is a NoSQL data storage service that can be accessed from anywhere in the world via authenticated calls using HTTP or HTTPS. -Tables scales as needed to support the amount of data inserted, and allow for the storing of data with non-complex accessing. -The Azure Container Registry client can be used to access Azure Storage or Cosmos accounts. +# Azure Template Package client library for Python -[Source code][source_code] | [Package (PyPI)][Tables_pypi] | [API reference documentation][Tables_ref_docs] | [Samples][Tables_samples] +This template package matches necessary patterns that the development team has established to create a unified sdk functional from Python 2.7 onwards. The packages contained herein can be installed singly or as part of the `azure` namespace. Any other introductory text should go here. -## Getting started -The Azure Container Registry SDK can access an Azure Container Registry account. +This package has been tested with Python 2.7, 3.5, 3.6, 3.7 and 3.8 -### Prerequisites -* Python 2.7, or 3.6 or later is required to use this package. -* You must have an [Azure subscription][azure_subscription] and an ACR account. +For a more complete set of Azure libraries, see https://aka.ms/azsdk/python/all -#### Create account +# Getting started -### Install the package -Install the Azure Container Registry client library for Python with [pip][pip_link]: -```bash -pip install --pre azure-containerregistry -``` +For a rich example of a well formatted readme, please check [here.](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-TEMPLATE.md) In addition, this is an [example readme](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-EXAMPLE.md) that should be emulated. Note that the top-level sections in this template align with that of the [template.](https://github.com/Azure/azure-sdk/blob/master/docs/policies/README-TEMPLATE.md) -#### Create the client +# Key concepts +Bullet point list of your library's main concepts. -## Key concepts -Common uses of the ACR include: +# Examples -### Clients -Two different clients are provided to interact with the various components of the Table Service: +Examples of some of the key concepts for your library. +# Troubleshooting -## Examples +Running into issues? This section should contain details as to what to do there. -The following sections provide several code snippets covering some of the most common Table tasks, including: +# Next steps +More sample code should go here, along with links out to the appropriate example tests. +# Contributing -## Optional Configuration -Optional keyword arguments can be passed in at the client and per-operation level. The azure-core [reference documentation][azure_core_ref_docs] describes available configurations for retries, logging, transport protocols, and more. +If you encounter any bugs or have suggestions, please file an issue in the [Issues]() section of the project. - -### Retry Policy configuration - -Use the following keyword arguments when instantiating a client to configure the retry policy: - -* __retry_total__ (int): Total number of retries to allow. Takes precedence over other counts. Pass in `retry_total=0` if you do not want to retry on requests. Defaults to 10. -* __retry_connect__ (int): How many connection-related errors to retry on. Defaults to 3. -* __retry_read__ (int): How many times to retry on read errors. Defaults to 3. -* __retry_status__ (int): How many times to retry on bad status codes. Defaults to 3. -* __retry_to_secondary__ (bool): Whether the request should be retried to secondary, if able. This should only be enabled of RA-GRS accounts are used and potentially stale data can be handled. Defaults to `False`. - -### Other client / per-operation configuration - -Other optional configuration keyword arguments that can be specified on the client or per-operation. - -**Client keyword arguments:** - -* __connection_timeout__ (int): Optionally sets the connect and read timeout value, in seconds. -* __transport__ (Any): User-provided transport to send the HTTP request. - -**Per-operation keyword arguments:** - -* __raw_response_hook__ (callable): The given callback uses the response returned from the service. -* __raw_request_hook__ (callable): The given callback uses the request before being sent to service. -* __client_request_id__ (str): Optional user specified identification of the request. -* __user_agent__ (str): Appends the custom value to the user-agent header to be sent with the request. -* __logging_enable__ (bool): Enables logging at the DEBUG level. Defaults to False. Can also be passed in at the client level to enable it for all requests. -* __headers__ (dict): Pass in custom headers as key, value pairs. E.g. `headers={'CustomValue': value}` - -## Troubleshooting - -### General - - -### Logging -This library uses the standard [logging][python_logging] library for logging. Basic information about HTTP sessions (URLs, headers, etc.) is logged at INFO level. - - -## Next steps - -Several Azure Container Registry Python SDK samples are available to you in the SDK's GitHub repository. These samples provide example code for additional scenarios commonly encountered while working with Tables. - - -## Contributing -This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. - -When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. - -This project has adopted the [Microsoft Open Source Code of Conduct][msft_oss_coc]. For more information see the [Code of Conduct FAQ][msft_oss_coc_faq] or contact [opencode@microsoft.com][contact_msft_oss] with any additional questions or comments. - - -[pip_link]:https://pypi.org/project/pip/ -[azure_core_ref_docs]: https://azuresdkdocs.blob.core.windows.net/$web/python/azure-core/latest/azure.core.html -[azure_core_readme]: https://github.com/Azure/azure-sdk-for-python/blob/master/sdk/core/azure-core/README.md -[python_logging]: https://docs.python.org/3/library/logging.html -[msft_oss_coc]:https://opensource.microsoft.com/codeofconduct/ -[msft_oss_coc_faq]:https://opensource.microsoft.com/codeofconduct/faq/ -[contact_msft_oss]:mailto:opencode@microsoft.com - - -![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-python/sdk/tables/azure-data-tables/README.png) \ No newline at end of file +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-python%2Fsdk%2Ftemplate%2Fazure-template%2FREADME.png) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 0d6259518122..e4f5065f9462 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -17,7 +17,7 @@ TagOrderBy, TagProperties, ) -from .authentication._authentication_policy import ( +from ._authentication_policy import ( ContainerRegistryUserCredential, ContainerRegistryUserCredentialPolicy, ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py new file mode 100644 index 000000000000..5a66b8549949 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -0,0 +1,60 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from base64 import b64encode +import re + +from azure.core.pipeline.policies import SansIOHTTPPolicy + + +class ContainerRegistryUserCredential(object): + """Credential used to authenticate with Container Registry service""" + + def __init__(self, username, password): + self._user = username + self._password = password + + def get_token(self): + token_str = "{}:{}".format(self._user, self._password) + token_bytes = token_str.encode("ascii") + b64_bytes = b64encode(token_bytes) + return b64_bytes.decode("ascii") + + +class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): + """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" + + def __init__(self, credential): + self.credential = credential + + @staticmethod + def _update_headers(headers, token): + headers["Authorization"] = "Basic {}".format(token) + + def on_request(self, request): + # type: (PipelineRequest) -> None + self._update_headers(request.http_request.headers, self.credential.get_token()) + + +class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): + """Challenge based authentication policy for ACR. This policy is used for getting + the AAD Token, refresh token, and access token before performing a call to service. + + :param credential: Azure Token Credential for authenticating with Azure + :type credential: TokenCredential + """ + + BEARER = "Bearer" + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + WWW_AUTHENTICATE = "WWW-Authenticate" + SCOPE_PARAMETER = "scope" + SERVICE_PARAMETER = "service" + AUTHORIZATION = "Authorization" + + def __init__(self, credential, url, pipeline): + self.credential = credential + self.url = url + self.pipeline = pipeline \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 56a83bd4a32c..3b90280f97ab 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -6,7 +6,7 @@ from enum import Enum -from .authentication._authentication_policy import ContainerRegistryUserCredentialPolicy +from ._authentication_policy import ContainerRegistryUserCredentialPolicy from ._generated import ContainerRegistry from ._user_agent import USER_AGENT From 7e4333e704db035bffd85e2841c9d7fefaea3d6e Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 15:31:23 -0400 Subject: [PATCH 40/86] ignore swagger readme --- eng/.docsettings.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/.docsettings.yml b/eng/.docsettings.yml index a732c246e727..f9b23249f888 100644 --- a/eng/.docsettings.yml +++ b/eng/.docsettings.yml @@ -106,6 +106,7 @@ known_content_issues: - ['sdk/monitor/azure-monitor-opentelemetry-exporter/README.md', '#4554'] - ['sdk/digitaltwins/azure-digitaltwins-core/swagger/README.md', '#4554'] - ['sdk/media/azure-media-nspkg/README.md', '#4554'] + - ['sdk/containerregistry/azure/containerregistry/swagger/README.md', '#4554'] # nspckg and common. - ['sdk/appconfiguration/azure-appconfiguration/README.md', 'nspkg and common'] From 5d128699c92dc8faca7e65128d3116f5bf3c741f Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 15:32:55 -0400 Subject: [PATCH 41/86] adding devtoolsback --- .../azure-containerregistry/dev_requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt index 5f40d6f3e081..e0e0792d9188 100644 --- a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt +++ b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt @@ -1,4 +1,5 @@ -e ../../../tools/azure-sdk-tools +-e ../../../tools/azure-devtools ../../core/azure-core aiohttp>=3.0; python_version >= '3.5' azure-identity \ No newline at end of file From 5bd806b23363c23e73e70c3bf1a0eedd2d0a267b Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 15:56:16 -0400 Subject: [PATCH 42/86] readme fix, linting fix --- eng/.docsettings.yml | 2 +- .../azure/containerregistry/_authentication_policy.py | 2 +- .../aio/_async_container_registry_client.py | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/eng/.docsettings.yml b/eng/.docsettings.yml index f9b23249f888..31854a22defe 100644 --- a/eng/.docsettings.yml +++ b/eng/.docsettings.yml @@ -106,7 +106,7 @@ known_content_issues: - ['sdk/monitor/azure-monitor-opentelemetry-exporter/README.md', '#4554'] - ['sdk/digitaltwins/azure-digitaltwins-core/swagger/README.md', '#4554'] - ['sdk/media/azure-media-nspkg/README.md', '#4554'] - - ['sdk/containerregistry/azure/containerregistry/swagger/README.md', '#4554'] + - ['sdk/containerregistry/azure-containerregistry/swagger/README.md', '#4554'] # nspckg and common. - ['sdk/appconfiguration/azure-appconfiguration/README.md', 'nspkg and common'] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index 5a66b8549949..e3c4b8705277 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -57,4 +57,4 @@ class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): def __init__(self, credential, url, pipeline): self.credential = credential self.url = url - self.pipeline = pipeline \ No newline at end of file + self.pipeline = pipeline diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index cb8762d43628..ab51b8cd0326 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -3,16 +3,18 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from typing import TYPE_CHECKING -from azure.core.credentials_async import AsyncTokenCredential from azure.core.async_paging import AsyncItemPaged from .._container_registry_client import ContainerRegistryClient as SyncContainerRegistryClient from .._models import RepositoryProperties +if TYPE_CHECKING: + from azure.core.credentials_async import AsyncTokenCredential class ContainerRegistryClient(object): - def __init__(self, base_url: str, credential: AsyncTokenCredential, **kwargs): # pylint: disable=client-method-missing-type-annotations + def __init__(self, base_url: str, credential: "AsyncTokenCredential", **kwargs): # pylint: disable=client-method-missing-type-annotations pass def delete_repository(self, name: str, **kwargs) -> None: From b56c29ee472dc6a2c1a49943bbe890bbc6f4bb82 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 19 Mar 2021 16:33:09 -0400 Subject: [PATCH 43/86] updating shared reqs --- shared_requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/shared_requirements.txt b/shared_requirements.txt index 03d2819c522e..6abba4b085b9 100644 --- a/shared_requirements.txt +++ b/shared_requirements.txt @@ -120,6 +120,7 @@ isodate>=0.6.0 avro<2.0.0,>=1.10.0 #override azure azure-keyvault~=1.0 #override azure-mgmt-core azure-core<2.0.0,>=1.9.0 +#override azure-containerregistry azure-core>=1.4.0,<2.0.0 #override azure-core-tracing-opencensus azure-core<2.0.0,>=1.0.0 #override azure-core-tracing-opentelemetry azure-core<2.0.0,>=1.0.0 #override azure-cosmos azure-core<2.0.0,>=1.0.0 From 5151b8d5ff385dc6afcf14158886f4e4b237563c Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 08:30:10 -0400 Subject: [PATCH 44/86] regenerated code, fixed changelog, modified test structure --- .../azure-containerregistry/CHANGELOG.md | 31 +--- .../_container_registry_operations.py | 124 +--------------- ...ontainer_registry_repository_operations.py | 128 +++++++++++++++- .../_generated/models/__init__.py | 6 +- .../_generated/models/_models.py | 126 ++++++++-------- .../_generated/models/_models_py3.py | 139 +++++++++--------- .../_container_registry_operations.py | 126 +--------------- ...ontainer_registry_repository_operations.py | 130 +++++++++++++++- .../azure/containerregistry/_version.py | 2 +- .../azure-containerregistry/swagger/README.md | 5 +- .../tests/test_container_registry_client.py | 2 +- .../tests/test_container_repository_client.py | 2 +- .../tests/{_shared => }/testcase.py | 0 13 files changed, 406 insertions(+), 415 deletions(-) rename sdk/containerregistry/azure-containerregistry/tests/{_shared => }/testcase.py (100%) diff --git a/sdk/containerregistry/azure-containerregistry/CHANGELOG.md b/sdk/containerregistry/azure-containerregistry/CHANGELOG.md index 999dfa7dc075..9b8c31b8ad75 100644 --- a/sdk/containerregistry/azure-containerregistry/CHANGELOG.md +++ b/sdk/containerregistry/azure-containerregistry/CHANGELOG.md @@ -1,31 +1,4 @@ # Release History -## 0.0.18b3 (Unreleased) - - -## 0.0.18b2 (2020-09-04) -- Testing release tag version - -## 0.0.13b1 (2020-08-27) -- Testing out some alpha and beta versioning - -## 0.0.12 (Unreleased) -- Test a successful Release - -## 0.0.7 (2020-07-02) -- Test a successful Release - -## 0.0.6 (2020-05-20) -- Test a successful Release - -## 0.0.5 (2020-05-20) -- Test a successful Release - -## 0.0.3 (Unreleased) - -## 0.0.2 (2020-03-24) -- Test Release Pipeline - - -## 0.0.1 (2019-10-06) - - Template package +## 0.0.1 (Unreleased) +* First release of the Azure Container Registry library for Python \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py index db138684e546..ac829d331718 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py @@ -166,74 +166,21 @@ async def get_next(next_link=None): ) get_repositories.metadata = {'url': '/acr/v1/_catalog'} # type: ignore - async def get_repository_attributes( - self, - name: str, - **kwargs - ) -> "_models.RepositoryProperties": - """Get repository attributes. - - :param name: Name of the image (including the namespace). - :type name: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: RepositoryProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RepositoryProperties - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_repository_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('RepositoryProperties', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore - async def delete_repository( self, name: str, **kwargs - ) -> "_models.DeletedRepositoryResult": + ) -> "_models.DeleteRepositoryResult": """Delete the repository identified by ``name``. :param name: Name of the image (including the namespace). :type name: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: DeletedRepositoryResult, or the result of cls(response) - :rtype: ~azure.containerregistry.models.DeletedRepositoryResult + :return: DeleteRepositoryResult, or the result of cls(response) + :rtype: ~azure.containerregistry.models.DeleteRepositoryResult :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepositoryResult"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.DeleteRepositoryResult"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -264,71 +211,10 @@ async def delete_repository( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('DeletedRepositoryResult', pipeline_response) + deserialized = self._deserialize('DeleteRepositoryResult', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) return deserialized delete_repository.metadata = {'url': '/acr/v1/{name}'} # type: ignore - - async def update_repository_attributes( - self, - name: str, - value: Optional["_models.ContentProperties"] = None, - **kwargs - ) -> None: - """Update the attribute identified by ``name`` where ``reference`` is the name of the repository. - - :param name: Name of the image (including the namespace). - :type name: str - :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/json") - accept = "application/json" - - # Construct URL - url = self.update_repository_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - if value is not None: - body_content = self._serialize.body(value, 'ContentProperties') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - update_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index f35dba7c05d9..514fe201861b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -185,7 +185,7 @@ async def delete_manifest( :param name: Name of the image (including the namespace). :type name: str - :param reference: A tag or a digest, pointing to a specific image. + :param reference: Digest of a BLOB. :type reference: str :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) @@ -229,6 +229,120 @@ async def delete_manifest( delete_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + async def get_properties( + self, + name: str, + **kwargs + ) -> "_models.RepositoryProperties": + """Get repository attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: RepositoryProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RepositoryProperties + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_properties.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('RepositoryProperties', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_properties.metadata = {'url': '/acr/v1/{name}'} # type: ignore + + async def set_properties( + self, + name: str, + value: Optional["_models.ContentProperties"] = None, + **kwargs + ) -> None: + """Update the attribute identified by ``name`` where ``reference`` is the name of the repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ContentProperties + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.set_properties.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ContentProperties') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + set_properties.metadata = {'url': '/acr/v1/{name}'} # type: ignore + def get_tags( self, name: str, @@ -324,7 +438,7 @@ async def get_next(next_link=None): ) get_tags.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore - async def get_tag_attributes( + async def get_tag_properties( self, name: str, reference: str, @@ -349,7 +463,7 @@ async def get_tag_attributes( accept = "application/json" # Construct URL - url = self.get_tag_attributes.metadata['url'] # type: ignore + url = self.get_tag_properties.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -379,7 +493,7 @@ async def get_tag_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_tag_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + get_tag_properties.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore async def update_tag_attributes( self, @@ -590,7 +704,7 @@ async def get_next(next_link=None): ) get_manifests.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore - async def get_manifest_attributes( + async def get_registry_artifact_properties( self, name: str, digest: str, @@ -615,7 +729,7 @@ async def get_manifest_attributes( accept = "application/json" # Construct URL - url = self.get_manifest_attributes.metadata['url'] # type: ignore + url = self.get_registry_artifact_properties.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -645,7 +759,7 @@ async def get_manifest_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore + get_registry_artifact_properties.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore async def update_manifest_attributes( self, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py index 9a15e8ba2208..9c0366b04520 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py @@ -13,7 +13,7 @@ from ._models_py3 import AcrManifests from ._models_py3 import Annotations from ._models_py3 import ContentProperties - from ._models_py3 import DeletedRepositoryResult + from ._models_py3 import DeleteRepositoryResult from ._models_py3 import Descriptor from ._models_py3 import FsLayer from ._models_py3 import History @@ -51,7 +51,7 @@ from ._models import AcrManifests # type: ignore from ._models import Annotations # type: ignore from ._models import ContentProperties # type: ignore - from ._models import DeletedRepositoryResult # type: ignore + from ._models import DeleteRepositoryResult # type: ignore from ._models import Descriptor # type: ignore from ._models import FsLayer # type: ignore from ._models import History # type: ignore @@ -94,7 +94,7 @@ 'AcrManifests', 'Annotations', 'ContentProperties', - 'DeletedRepositoryResult', + 'DeleteRepositoryResult', 'Descriptor', 'FsLayer', 'History', diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 5c2bc505f589..dea33abbcdca 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -78,10 +78,8 @@ def __init__( class AcrManifests(msrest.serialization.Model): """Manifest attributes. - :param registry: Registry name. - :type registry: str - :param image_name: Image name. - :type image_name: str + :param repository: Image name. + :type repository: str :param manifests: List of manifests. :type manifests: list[~azure.containerregistry.models.ManifestAttributesBase] :param link: @@ -89,8 +87,7 @@ class AcrManifests(msrest.serialization.Model): """ _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, 'manifests': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -100,8 +97,7 @@ def __init__( **kwargs ): super(AcrManifests, self).__init__(**kwargs) - self.registry = kwargs.get('registry', None) - self.image_name = kwargs.get('image_name', None) + self.repository = kwargs.get('repository', None) self.manifests = kwargs.get('manifests', None) self.link = kwargs.get('link', None) @@ -208,7 +204,7 @@ def __init__( self.can_read = kwargs.get('can_read', None) -class DeletedRepositoryResult(msrest.serialization.Model): +class DeleteRepositoryResult(msrest.serialization.Model): """Deleted repository. :param deleted_registry_artifact_digests: SHA of the deleted image. @@ -226,7 +222,7 @@ def __init__( self, **kwargs ): - super(DeletedRepositoryResult, self).__init__(**kwargs) + super(DeleteRepositoryResult, self).__init__(**kwargs) self.deleted_registry_artifact_digests = kwargs.get('deleted_registry_artifact_digests', None) self.deleted_tags = kwargs.get('deleted_tags', None) @@ -411,7 +407,9 @@ def __init__( class ManifestAttributesBase(msrest.serialization.Model): """Manifest details. - :param digest: Manifest. + All required parameters must be populated in order to send to Azure. + + :param digest: Required. Manifest. :type digest: str :param size: Image size. :type size: long @@ -419,20 +417,27 @@ class ManifestAttributesBase(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Last update time. :type last_updated_on: ~datetime.datetime - :param cpu_architecture: CPU architecture. + :param cpu_architecture: Required. CPU architecture. :type cpu_architecture: str - :param operating_system: Operating system. + :param operating_system: Required. Operating system. :type operating_system: str :param manifest_media_type: Media type. :type manifest_media_type: str :param config_media_type: Config blob media type. :type config_media_type: str - :param tags: A set of tags. List of tags. + :param tags: Required. A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Changeable attributes. :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'digest': {'required': True}, + 'cpu_architecture': {'required': True}, + 'operating_system': {'required': True}, + 'tags': {'required': True}, + } + _attribute_map = { 'digest': {'key': 'digest', 'type': 'str'}, 'size': {'key': 'imageSize', 'type': 'long'}, @@ -451,15 +456,15 @@ def __init__( **kwargs ): super(ManifestAttributesBase, self).__init__(**kwargs) - self.digest = kwargs.get('digest', None) + self.digest = kwargs['digest'] self.size = kwargs.get('size', None) self.created_on = kwargs.get('created_on', None) self.last_updated_on = kwargs.get('last_updated_on', None) - self.cpu_architecture = kwargs.get('cpu_architecture', None) - self.operating_system = kwargs.get('operating_system', None) + self.cpu_architecture = kwargs['cpu_architecture'] + self.operating_system = kwargs['operating_system'] self.manifest_media_type = kwargs.get('manifest_media_type', None) self.config_media_type = kwargs.get('config_media_type', None) - self.tags = kwargs.get('tags', None) + self.tags = kwargs['tags'] self.manifest_properties = kwargs.get('manifest_properties', None) @@ -888,9 +893,9 @@ def __init__( class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. - :param registry: Registry name. - :type registry: str - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str :param digest: Manifest. :type digest: str @@ -914,8 +919,11 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'repository': {'required': True}, + } + _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, 'repository': {'key': 'imageName', 'type': 'str'}, 'digest': {'key': 'manifest.digest', 'type': 'str'}, 'size': {'key': 'manifest.imageSize', 'type': 'long'}, @@ -934,8 +942,7 @@ def __init__( **kwargs ): super(RegistryArtifactProperties, self).__init__(**kwargs) - self.registry = kwargs.get('registry', None) - self.repository = kwargs.get('repository', None) + self.repository = kwargs['repository'] self.digest = kwargs.get('digest', None) self.size = kwargs.get('size', None) self.created_on = kwargs.get('created_on', None) @@ -974,24 +981,29 @@ def __init__( class RepositoryProperties(msrest.serialization.Model): """Repository attributes. - :param registry: Registry name. - :type registry: str + All required parameters must be populated in order to send to Azure. + :param name: Image name. :type name: str - :param created_on: Image created time. + :param created_on: Required. Image created time. :type created_on: ~datetime.datetime :param last_updated_on: Image last update time. :type last_updated_on: ~datetime.datetime - :param registry_artifact_count: Number of the manifests. + :param registry_artifact_count: Required. Number of the manifests. :type registry_artifact_count: int - :param tag_count: Number of the tags. + :param tag_count: Required. Number of the tags. :type tag_count: int :param writeable_properties: Changeable attributes. :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'created_on': {'required': True}, + 'registry_artifact_count': {'required': True}, + 'tag_count': {'required': True}, + } + _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, 'name': {'key': 'imageName', 'type': 'str'}, 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, @@ -1005,12 +1017,11 @@ def __init__( **kwargs ): super(RepositoryProperties, self).__init__(**kwargs) - self.registry = kwargs.get('registry', None) self.name = kwargs.get('name', None) - self.created_on = kwargs.get('created_on', None) + self.created_on = kwargs['created_on'] self.last_updated_on = kwargs.get('last_updated_on', None) - self.registry_artifact_count = kwargs.get('registry_artifact_count', None) - self.tag_count = kwargs.get('tag_count', None) + self.registry_artifact_count = kwargs['registry_artifact_count'] + self.tag_count = kwargs['tag_count'] self.writeable_properties = kwargs.get('writeable_properties', None) @@ -1040,24 +1051,31 @@ def __init__( class TagAttributesBase(msrest.serialization.Model): """Tag attribute details. + All required parameters must be populated in order to send to Azure. + :param name: Tag name. :type name: str :param digest: Tag digest. :type digest: str - :param created_on: Tag created time. + :param created_on: Required. Tag created time. :type created_on: ~datetime.datetime - :param last_updated_on: Tag last update time. + :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime - :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ContentProperties + :param writeable_properties: Changeable attributes. + :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'created_on': {'required': True}, + 'last_updated_on': {'required': True}, + } + _attribute_map = { 'name': {'key': 'name', 'type': 'str'}, 'digest': {'key': 'digest', 'type': 'str'}, 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -1067,9 +1085,9 @@ def __init__( super(TagAttributesBase, self).__init__(**kwargs) self.name = kwargs.get('name', None) self.digest = kwargs.get('digest', None) - self.created_on = kwargs.get('created_on', None) - self.last_updated_on = kwargs.get('last_updated_on', None) - self.modifiable_properties = kwargs.get('modifiable_properties', None) + self.created_on = kwargs['created_on'] + self.last_updated_on = kwargs['last_updated_on'] + self.writeable_properties = kwargs.get('writeable_properties', None) class TagAttributesTag(msrest.serialization.Model): @@ -1094,10 +1112,8 @@ def __init__( class TagList(msrest.serialization.Model): """List of tag details. - :param registry: Registry name. - :type registry: str - :param image_name: Image name. - :type image_name: str + :param repository: Image name. + :type repository: str :param tags: A set of tags. List of tag attribute details. :type tags: list[~azure.containerregistry.models.TagAttributesBase] :param link: @@ -1105,8 +1121,7 @@ class TagList(msrest.serialization.Model): """ _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -1116,8 +1131,7 @@ def __init__( **kwargs ): super(TagList, self).__init__(**kwargs) - self.registry = kwargs.get('registry', None) - self.image_name = kwargs.get('image_name', None) + self.repository = kwargs.get('repository', None) self.tags = kwargs.get('tags', None) self.link = kwargs.get('link', None) @@ -1125,8 +1139,6 @@ def __init__( class TagProperties(msrest.serialization.Model): """Tag attributes. - :param registry: Registry name. - :type registry: str :param repository: Image name. :type repository: str :param name: Tag name. @@ -1137,18 +1149,17 @@ class TagProperties(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Tag last update time. :type last_updated_on: ~datetime.datetime - :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ContentProperties + :param writeable_properties: Changeable attributes. + :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, 'repository': {'key': 'imageName', 'type': 'str'}, 'name': {'key': 'tag.name', 'type': 'str'}, 'digest': {'key': 'tag.digest', 'type': 'str'}, 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'tag.changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -1156,13 +1167,12 @@ def __init__( **kwargs ): super(TagProperties, self).__init__(**kwargs) - self.registry = kwargs.get('registry', None) self.repository = kwargs.get('repository', None) self.name = kwargs.get('name', None) self.digest = kwargs.get('digest', None) self.created_on = kwargs.get('created_on', None) self.last_updated_on = kwargs.get('last_updated_on', None) - self.modifiable_properties = kwargs.get('modifiable_properties', None) + self.writeable_properties = kwargs.get('writeable_properties', None) class V1Manifest(Manifest): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index 0ab6ceae9ce2..ede8ef07e721 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -91,10 +91,8 @@ def __init__( class AcrManifests(msrest.serialization.Model): """Manifest attributes. - :param registry: Registry name. - :type registry: str - :param image_name: Image name. - :type image_name: str + :param repository: Image name. + :type repository: str :param manifests: List of manifests. :type manifests: list[~azure.containerregistry.models.ManifestAttributesBase] :param link: @@ -102,8 +100,7 @@ class AcrManifests(msrest.serialization.Model): """ _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, 'manifests': {'key': 'manifests', 'type': '[ManifestAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -111,15 +108,13 @@ class AcrManifests(msrest.serialization.Model): def __init__( self, *, - registry: Optional[str] = None, - image_name: Optional[str] = None, + repository: Optional[str] = None, manifests: Optional[List["ManifestAttributesBase"]] = None, link: Optional[str] = None, **kwargs ): super(AcrManifests, self).__init__(**kwargs) - self.registry = registry - self.image_name = image_name + self.repository = repository self.manifests = manifests self.link = link @@ -245,7 +240,7 @@ def __init__( self.can_read = can_read -class DeletedRepositoryResult(msrest.serialization.Model): +class DeleteRepositoryResult(msrest.serialization.Model): """Deleted repository. :param deleted_registry_artifact_digests: SHA of the deleted image. @@ -266,7 +261,7 @@ def __init__( deleted_tags: Optional[List[str]] = None, **kwargs ): - super(DeletedRepositoryResult, self).__init__(**kwargs) + super(DeleteRepositoryResult, self).__init__(**kwargs) self.deleted_registry_artifact_digests = deleted_registry_artifact_digests self.deleted_tags = deleted_tags @@ -476,7 +471,9 @@ def __init__( class ManifestAttributesBase(msrest.serialization.Model): """Manifest details. - :param digest: Manifest. + All required parameters must be populated in order to send to Azure. + + :param digest: Required. Manifest. :type digest: str :param size: Image size. :type size: long @@ -484,20 +481,27 @@ class ManifestAttributesBase(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Last update time. :type last_updated_on: ~datetime.datetime - :param cpu_architecture: CPU architecture. + :param cpu_architecture: Required. CPU architecture. :type cpu_architecture: str - :param operating_system: Operating system. + :param operating_system: Required. Operating system. :type operating_system: str :param manifest_media_type: Media type. :type manifest_media_type: str :param config_media_type: Config blob media type. :type config_media_type: str - :param tags: A set of tags. List of tags. + :param tags: Required. A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Changeable attributes. :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'digest': {'required': True}, + 'cpu_architecture': {'required': True}, + 'operating_system': {'required': True}, + 'tags': {'required': True}, + } + _attribute_map = { 'digest': {'key': 'digest', 'type': 'str'}, 'size': {'key': 'imageSize', 'type': 'long'}, @@ -514,15 +518,15 @@ class ManifestAttributesBase(msrest.serialization.Model): def __init__( self, *, - digest: Optional[str] = None, + digest: str, + cpu_architecture: str, + operating_system: str, + tags: List[str], size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, - cpu_architecture: Optional[str] = None, - operating_system: Optional[str] = None, manifest_media_type: Optional[str] = None, config_media_type: Optional[str] = None, - tags: Optional[List[str]] = None, manifest_properties: Optional["ContentProperties"] = None, **kwargs ): @@ -1028,9 +1032,9 @@ def __init__( class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. - :param registry: Registry name. - :type registry: str - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str :param digest: Manifest. :type digest: str @@ -1054,8 +1058,11 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'repository': {'required': True}, + } + _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, 'repository': {'key': 'imageName', 'type': 'str'}, 'digest': {'key': 'manifest.digest', 'type': 'str'}, 'size': {'key': 'manifest.imageSize', 'type': 'long'}, @@ -1072,8 +1079,7 @@ class RegistryArtifactProperties(msrest.serialization.Model): def __init__( self, *, - registry: Optional[str] = None, - repository: Optional[str] = None, + repository: str, digest: Optional[str] = None, size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, @@ -1087,7 +1093,6 @@ def __init__( **kwargs ): super(RegistryArtifactProperties, self).__init__(**kwargs) - self.registry = registry self.repository = repository self.digest = digest self.size = size @@ -1130,24 +1135,29 @@ def __init__( class RepositoryProperties(msrest.serialization.Model): """Repository attributes. - :param registry: Registry name. - :type registry: str + All required parameters must be populated in order to send to Azure. + :param name: Image name. :type name: str - :param created_on: Image created time. + :param created_on: Required. Image created time. :type created_on: ~datetime.datetime :param last_updated_on: Image last update time. :type last_updated_on: ~datetime.datetime - :param registry_artifact_count: Number of the manifests. + :param registry_artifact_count: Required. Number of the manifests. :type registry_artifact_count: int - :param tag_count: Number of the tags. + :param tag_count: Required. Number of the tags. :type tag_count: int :param writeable_properties: Changeable attributes. :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'created_on': {'required': True}, + 'registry_artifact_count': {'required': True}, + 'tag_count': {'required': True}, + } + _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, 'name': {'key': 'imageName', 'type': 'str'}, 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, @@ -1159,17 +1169,15 @@ class RepositoryProperties(msrest.serialization.Model): def __init__( self, *, - registry: Optional[str] = None, + created_on: datetime.datetime, + registry_artifact_count: int, + tag_count: int, name: Optional[str] = None, - created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, - registry_artifact_count: Optional[int] = None, - tag_count: Optional[int] = None, writeable_properties: Optional["ContentProperties"] = None, **kwargs ): super(RepositoryProperties, self).__init__(**kwargs) - self.registry = registry self.name = name self.created_on = created_on self.last_updated_on = last_updated_on @@ -1207,34 +1215,41 @@ def __init__( class TagAttributesBase(msrest.serialization.Model): """Tag attribute details. + All required parameters must be populated in order to send to Azure. + :param name: Tag name. :type name: str :param digest: Tag digest. :type digest: str - :param created_on: Tag created time. + :param created_on: Required. Tag created time. :type created_on: ~datetime.datetime - :param last_updated_on: Tag last update time. + :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime - :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ContentProperties + :param writeable_properties: Changeable attributes. + :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'created_on': {'required': True}, + 'last_updated_on': {'required': True}, + } + _attribute_map = { 'name': {'key': 'name', 'type': 'str'}, 'digest': {'key': 'digest', 'type': 'str'}, 'created_on': {'key': 'createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( self, *, + created_on: datetime.datetime, + last_updated_on: datetime.datetime, name: Optional[str] = None, digest: Optional[str] = None, - created_on: Optional[datetime.datetime] = None, - last_updated_on: Optional[datetime.datetime] = None, - modifiable_properties: Optional["ContentProperties"] = None, + writeable_properties: Optional["ContentProperties"] = None, **kwargs ): super(TagAttributesBase, self).__init__(**kwargs) @@ -1242,7 +1257,7 @@ def __init__( self.digest = digest self.created_on = created_on self.last_updated_on = last_updated_on - self.modifiable_properties = modifiable_properties + self.writeable_properties = writeable_properties class TagAttributesTag(msrest.serialization.Model): @@ -1269,10 +1284,8 @@ def __init__( class TagList(msrest.serialization.Model): """List of tag details. - :param registry: Registry name. - :type registry: str - :param image_name: Image name. - :type image_name: str + :param repository: Image name. + :type repository: str :param tags: A set of tags. List of tag attribute details. :type tags: list[~azure.containerregistry.models.TagAttributesBase] :param link: @@ -1280,8 +1293,7 @@ class TagList(msrest.serialization.Model): """ _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, - 'image_name': {'key': 'imageName', 'type': 'str'}, + 'repository': {'key': 'imageName', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -1289,15 +1301,13 @@ class TagList(msrest.serialization.Model): def __init__( self, *, - registry: Optional[str] = None, - image_name: Optional[str] = None, + repository: Optional[str] = None, tags: Optional[List["TagAttributesBase"]] = None, link: Optional[str] = None, **kwargs ): super(TagList, self).__init__(**kwargs) - self.registry = registry - self.image_name = image_name + self.repository = repository self.tags = tags self.link = link @@ -1305,8 +1315,6 @@ def __init__( class TagProperties(msrest.serialization.Model): """Tag attributes. - :param registry: Registry name. - :type registry: str :param repository: Image name. :type repository: str :param name: Tag name. @@ -1317,40 +1325,37 @@ class TagProperties(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Tag last update time. :type last_updated_on: ~datetime.datetime - :param modifiable_properties: Changeable attributes. - :type modifiable_properties: ~azure.containerregistry.models.ContentProperties + :param writeable_properties: Changeable attributes. + :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ _attribute_map = { - 'registry': {'key': 'registry', 'type': 'str'}, 'repository': {'key': 'imageName', 'type': 'str'}, 'name': {'key': 'tag.name', 'type': 'str'}, 'digest': {'key': 'tag.digest', 'type': 'str'}, 'created_on': {'key': 'tag.createdTime', 'type': 'iso-8601'}, 'last_updated_on': {'key': 'tag.lastUpdateTime', 'type': 'iso-8601'}, - 'modifiable_properties': {'key': 'tag.changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'tag.changeableAttributes', 'type': 'ContentProperties'}, } def __init__( self, *, - registry: Optional[str] = None, repository: Optional[str] = None, name: Optional[str] = None, digest: Optional[str] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, - modifiable_properties: Optional["ContentProperties"] = None, + writeable_properties: Optional["ContentProperties"] = None, **kwargs ): super(TagProperties, self).__init__(**kwargs) - self.registry = registry self.repository = repository self.name = name self.digest = digest self.created_on = created_on self.last_updated_on = last_updated_on - self.modifiable_properties = modifiable_properties + self.writeable_properties = writeable_properties class V1Manifest(Manifest): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py index 6e677bfca461..f4e0a4659c84 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py @@ -172,76 +172,22 @@ def get_next(next_link=None): ) get_repositories.metadata = {'url': '/acr/v1/_catalog'} # type: ignore - def get_repository_attributes( - self, - name, # type: str - **kwargs # type: Any - ): - # type: (...) -> "_models.RepositoryProperties" - """Get repository attributes. - - :param name: Name of the image (including the namespace). - :type name: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: RepositoryProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RepositoryProperties - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_repository_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('RepositoryProperties', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore - def delete_repository( self, name, # type: str **kwargs # type: Any ): - # type: (...) -> "_models.DeletedRepositoryResult" + # type: (...) -> "_models.DeleteRepositoryResult" """Delete the repository identified by ``name``. :param name: Name of the image (including the namespace). :type name: str :keyword callable cls: A custom type or function that will be passed the direct response - :return: DeletedRepositoryResult, or the result of cls(response) - :rtype: ~azure.containerregistry.models.DeletedRepositoryResult + :return: DeleteRepositoryResult, or the result of cls(response) + :rtype: ~azure.containerregistry.models.DeleteRepositoryResult :raises: ~azure.core.exceptions.HttpResponseError """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.DeletedRepositoryResult"] + cls = kwargs.pop('cls', None) # type: ClsType["_models.DeleteRepositoryResult"] error_map = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError } @@ -272,72 +218,10 @@ def delete_repository( error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) - deserialized = self._deserialize('DeletedRepositoryResult', pipeline_response) + deserialized = self._deserialize('DeleteRepositoryResult', pipeline_response) if cls: return cls(pipeline_response, deserialized, {}) return deserialized delete_repository.metadata = {'url': '/acr/v1/{name}'} # type: ignore - - def update_repository_attributes( - self, - name, # type: str - value=None, # type: Optional["_models.ContentProperties"] - **kwargs # type: Any - ): - # type: (...) -> None - """Update the attribute identified by ``name`` where ``reference`` is the name of the repository. - - :param name: Name of the image (including the namespace). - :type name: str - :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties - :keyword callable cls: A custom type or function that will be passed the direct response - :return: None, or the result of cls(response) - :rtype: None - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType[None] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/json") - accept = "application/json" - - # Construct URL - url = self.update_repository_attributes.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - 'name': self._serialize.url("name", name, 'str'), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - if value is not None: - body_content = self._serialize.body(value, 'ContentProperties') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - if cls: - return cls(pipeline_response, None, {}) - - update_repository_attributes.metadata = {'url': '/acr/v1/{name}'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index fafcf82b965b..ccbf34f38e89 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -192,7 +192,7 @@ def delete_manifest( :param name: Name of the image (including the namespace). :type name: str - :param reference: A tag or a digest, pointing to a specific image. + :param reference: Digest of a BLOB. :type reference: str :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) @@ -236,6 +236,122 @@ def delete_manifest( delete_manifest.metadata = {'url': '/v2/{name}/manifests/{reference}'} # type: ignore + def get_properties( + self, + name, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.RepositoryProperties" + """Get repository attributes. + + :param name: Name of the image (including the namespace). + :type name: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: RepositoryProperties, or the result of cls(response) + :rtype: ~azure.containerregistry.models.RepositoryProperties + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + accept = "application/json" + + # Construct URL + url = self.get_properties.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + request = self._client.get(url, query_parameters, header_parameters) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('RepositoryProperties', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + get_properties.metadata = {'url': '/acr/v1/{name}'} # type: ignore + + def set_properties( + self, + name, # type: str + value=None, # type: Optional["_models.ContentProperties"] + **kwargs # type: Any + ): + # type: (...) -> None + """Update the attribute identified by ``name`` where ``reference`` is the name of the repository. + + :param name: Name of the image (including the namespace). + :type name: str + :param value: Repository attribute value. + :type value: ~azure.containerregistry.models.ContentProperties + :keyword callable cls: A custom type or function that will be passed the direct response + :return: None, or the result of cls(response) + :rtype: None + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType[None] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/json") + accept = "application/json" + + # Construct URL + url = self.set_properties.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + 'name': self._serialize.url("name", name, 'str'), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + if value is not None: + body_content = self._serialize.body(value, 'ContentProperties') + else: + body_content = None + body_content_kwargs['content'] = body_content + request = self._client.patch(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + if cls: + return cls(pipeline_response, None, {}) + + set_properties.metadata = {'url': '/acr/v1/{name}'} # type: ignore + def get_tags( self, name, # type: str @@ -332,7 +448,7 @@ def get_next(next_link=None): ) get_tags.metadata = {'url': '/acr/v1/{name}/_tags'} # type: ignore - def get_tag_attributes( + def get_tag_properties( self, name, # type: str reference, # type: str @@ -358,7 +474,7 @@ def get_tag_attributes( accept = "application/json" # Construct URL - url = self.get_tag_attributes.metadata['url'] # type: ignore + url = self.get_tag_properties.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -388,7 +504,7 @@ def get_tag_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_tag_attributes.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore + get_tag_properties.metadata = {'url': '/acr/v1/{name}/_tags/{reference}'} # type: ignore def update_tag_attributes( self, @@ -602,7 +718,7 @@ def get_next(next_link=None): ) get_manifests.metadata = {'url': '/acr/v1/{name}/_manifests'} # type: ignore - def get_manifest_attributes( + def get_registry_artifact_properties( self, name, # type: str digest, # type: str @@ -628,7 +744,7 @@ def get_manifest_attributes( accept = "application/json" # Construct URL - url = self.get_manifest_attributes.metadata['url'] # type: ignore + url = self.get_registry_artifact_properties.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), 'name': self._serialize.url("name", name, 'str'), @@ -658,7 +774,7 @@ def get_manifest_attributes( return cls(pipeline_response, deserialized, {}) return deserialized - get_manifest_attributes.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore + get_registry_artifact_properties.metadata = {'url': '/acr/v1/{name}/_manifests/{digest}'} # type: ignore def update_manifest_attributes( self, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py index 366e8a430a68..a58dbf5af24a 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_version.py @@ -3,4 +3,4 @@ # Licensed under the MIT License. # ------------------------------------ -VERSION = "0.1.0" +VERSION = "0.0.1" diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index d3b751a58b7c..2b674ef08f6a 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -2,7 +2,7 @@ ### Settings ``` yaml -input-file: https://github.com/Azure/azure-sdk-for-js/blob/3760670d864e3334a800687f5b6deffce9ef78d3/sdk/containerregistry/container-registry/swagger/containerregistry.json +input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/4bdce8c1cce1303bbae0a52efd59085524d2d881/sdk/containerregistry/container-registry/swagger/containerregistry.json output-folder: "../azure/containerregistry/_generated" namespace: azure.containerregistry no-namespace-folders: true @@ -14,3 +14,6 @@ clear-output-folder: true enable-xml: true vanilla: true ``` + + + diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index b1bc6b946e1a..2be93b476245 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -19,7 +19,7 @@ from azure.core.paging import ItemPaged from azure.identity import DefaultAzureCredential -from _shared.testcase import ContainerRegistryTestClass +from testcase import ContainerRegistryTestClass acr_preparer = functools.partial( diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 075b253c262f..540aef4bc540 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -19,7 +19,7 @@ ) from azure.core.paging import ItemPaged -from _shared.testcase import ContainerRegistryTestClass +from testcase import ContainerRegistryTestClass acr_preparer = functools.partial( PowerShellPreparer, diff --git a/sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py similarity index 100% rename from sdk/containerregistry/azure-containerregistry/tests/_shared/testcase.py rename to sdk/containerregistry/azure-containerregistry/tests/testcase.py From cb9611b0abcbb7e3751b34ad029eeb0571dfe7f5 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 08:39:24 -0400 Subject: [PATCH 45/86] formatting --- .../containerregistry/_authentication_policy.py | 2 +- .../azure/containerregistry/_base_client.py | 7 +++---- .../_container_registry_client.py | 15 +++------------ .../_container_repository_client.py | 17 ++++------------- .../azure/containerregistry/_helpers.py | 3 +-- .../azure/containerregistry/_models.py | 17 ++++++----------- .../aio/_async_container_registry_client.py | 5 ++++- .../tests/test_container_registry_client.py | 3 +-- .../azure-containerregistry/tests/testcase.py | 2 +- 9 files changed, 24 insertions(+), 47 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index e3c4b8705277..23a14700d797 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -48,7 +48,7 @@ class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): """ BEARER = "Bearer" - AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile('(?:(\\w+)="([^""]*)")+') WWW_AUTHENTICATE = "WWW-Authenticate" SCOPE_PARAMETER = "scope" SERVICE_PARAMETER = "service" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 3b90280f97ab..32eb9b968fc5 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -18,7 +18,7 @@ class ContainerRegistryApiVersion(str, Enum): class ContainerRegistryBaseClient(object): - """ Base class for ContainerRegistryClient and ContainerRepositoryClient + """Base class for ContainerRegistryClient and ContainerRepositoryClient :param endpoint: Azure Container Registry endpoint :type endpoint: str @@ -26,6 +26,7 @@ class ContainerRegistryBaseClient(object): :type credential: :class:`azure.identity.DefaultTokenCredential` """ + def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-method-missing-type-annotations auth_policy = ContainerRegistryUserCredentialPolicy(credential=credential) self._client = ContainerRegistry( @@ -33,9 +34,7 @@ def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-met url=endpoint, sdk_moniker=USER_AGENT, authentication_policy=auth_policy, - credential_scopes=kwargs.pop( - "credential_scopes", ["https://management.core.windows.net/.default"] - ), + credential_scopes=kwargs.pop("credential_scopes", ["https://management.core.windows.net/.default"]), **kwargs ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index a2134cf1bb87..249e9674f49d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -25,9 +25,7 @@ def __init__(self, endpoint, credential, **kwargs): if not endpoint.startswith("https://"): endpoint = "https://" + endpoint self.credential = credential - super(ContainerRegistryClient, self).__init__( - endpoint=endpoint, credential=credential, **kwargs - ) + super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) def delete_repository(self, repository, **kwargs): # type: (str) -> DeletedRepositoryResult @@ -39,9 +37,7 @@ def delete_repository(self, repository, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # NOTE: DELETE `/acr/v1/{name}` - deleted_repository = self._client.container_registry.delete_repository( - repository, **kwargs - ) + deleted_repository = self._client.container_registry.delete_repository(repository, **kwargs) return DeletedRepositoryResult.from_generated(deleted_repository) def list_repositories(self, **kwargs): @@ -59,7 +55,6 @@ def list_repositories(self, **kwargs): last=kwargs.pop("last", None), n=kwargs.pop("max", None), **kwargs ) - def get_repository_client(self, repository, **kwargs): # type: (str) -> ContainerRepositoryClient """Get a repository client @@ -68,8 +63,4 @@ def get_repository_client(self, repository, **kwargs): :type repository: str :returns: :class:~azure.containerregistry.ContainerRepositoryClient """ - return ContainerRepositoryClient( - repository, - credential=self.credential, - **kwargs - ) + return ContainerRepositoryClient(repository, credential=self.credential, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 3edec77689a9..7d4b19f9c860 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -26,9 +26,7 @@ def __init__(self, endpoint, repository, credential, **kwargs): endpoint = "https://" + endpoint self.endpoint = endpoint self.repository = repository - super(ContainerRepositoryClient, self).__init__( - endpoint=self.endpoint, credential=credential, **kwargs - ) + super(ContainerRepositoryClient, self).__init__(endpoint=self.endpoint, credential=credential, **kwargs) def delete(self, **kwargs): # type: (...) -> None @@ -75,9 +73,7 @@ def get_properties(self): :returns: :class:~azure.containerregistry.RepositoryProperties :raises: None """ - resp = self._client.container_registry.get_repository_attributes( - self.repository - ) + resp = self._client.container_registry.get_repository_attributes(self.repository) return RepositoryProperties.from_generated(resp) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): @@ -95,9 +91,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): tag_or_digest = self.get_digest_from_tag(tag_or_digest) # TODO: The returned object from the generated code is not being deserialized properly return RegistryArtifactProperties.from_generated( - self._client.container_registry_repository.get_manifest_attributes( - self.repository, tag_or_digest, **kwargs - ) + self._client.container_registry_repository.get_manifest_attributes(self.repository, tag_or_digest, **kwargs) ) def get_tag_properties(self, tag, **kwargs): @@ -110,9 +104,7 @@ def get_tag_properties(self, tag, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ return TagProperties.from_generated( - self._client.container_registry_repository.get_tag_attributes( - self.repository, tag, **kwargs - ) + self._client.container_registry_repository.get_tag_attributes(self.repository, tag, **kwargs) ) def list_registry_artifacts(self, **kwargs): @@ -161,7 +153,6 @@ def list_tags(self, **kwargs): **kwargs ) - def set_manifest_properties(self, digest, value): # type: (str, ContentPermissions) -> None """Set the properties for a manifest diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py index 5a8f173ef8fb..71f3512086c8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py @@ -19,8 +19,7 @@ def get_authentication_policy(base_url, credential): authentication_policy = BearerTokenCredentialPolicy(credential, scope) else: raise TypeError( - "Please provide an instance from azure-identity " - "or a class that implement the 'get_token protocol" + "Please provide an instance from azure-identity " "or a class that implement the 'get_token protocol" ) return authentication_policy diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 7a293b5aade3..5483d8c8cb5e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -27,9 +27,7 @@ def from_generated(cls, generated): class DeletedRepositoryResult(object): def __init__(self, **kwargs): - self.deleted_registry_artifact_digests = kwargs.get( - "deleted_registry_artifact_digests", None - ) + self.deleted_registry_artifact_digests = kwargs.get("deleted_registry_artifact_digests", None) self.deleted_tags = kwargs.get("deleted_tags", None) @classmethod @@ -105,9 +103,7 @@ def __init__(self, **kwargs): self.manifest_count = kwargs.get("manifest_count", None) self.content_permissions = kwargs.get("content_permissions", None) if self.content_permissions: - self.content_permissions = ContentPermissions.from_generated( - self.content_permissions - ) + self.content_permissions = ContentPermissions.from_generated(self.content_permissions) @classmethod def from_generated(cls, generated): @@ -122,6 +118,7 @@ def from_generated(cls, generated): content_permissions=generated.writeable_properties, ) + class RegistryArtifactOrderBy(int, Enum): LastUpdateTimeDescending = 0 @@ -159,12 +156,10 @@ def __init__(self, **kwargs): self.last_updated_on = kwargs.get("last_updated_on", None) self.content_permissions = kwargs.get("content_permissions", None) if self.content_permissions: - self.content_permissions = ContentPermissions.from_generated( - self.content_permissions - ) + self.content_permissions = ContentPermissions.from_generated(self.content_permissions) self.name = kwargs.get("name", None) - self.signed = kwargs.get('signed', None) - self.quarantine_state = kwargs.get('quarantine_state', None) + self.signed = kwargs.get("signed", None) + self.quarantine_state = kwargs.get("quarantine_state", None) @classmethod def from_generated(cls, generated): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index ab51b8cd0326..1348e5c9479e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -13,8 +13,11 @@ if TYPE_CHECKING: from azure.core.credentials_async import AsyncTokenCredential + class ContainerRegistryClient(object): - def __init__(self, base_url: str, credential: "AsyncTokenCredential", **kwargs): # pylint: disable=client-method-missing-type-annotations + def __init__( + self, base_url: str, credential: "AsyncTokenCredential", **kwargs + ): # pylint: disable=client-method-missing-type-annotations pass def delete_repository(self, name: str, **kwargs) -> None: diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 2be93b476245..f016925d8db4 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -30,7 +30,6 @@ class TestContainerRegistryClient(AzureTestCase, ContainerRegistryTestClass): - @pytest.mark.live_test_only @acr_preparer() def test_list_repositories(self, containerregistry_baseurl): @@ -63,4 +62,4 @@ def test_delete_repository_does_not_exist(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) with pytest.raises(ResourceNotFoundError): - deleted_result = client.delete_repository("not_real_repo") \ No newline at end of file + deleted_result = client.delete_repository("not_real_repo") diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index 4e469668719c..b3eaeb25524e 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -74,4 +74,4 @@ def assert_tag( def assert_registry_artifact(self, tag_or_digest, expected_tag_or_digest): assert isinstance(tag_or_digest, RegistryArtifactProperties) - assert tag_or_digest == expected_tag_or_digest \ No newline at end of file + assert tag_or_digest == expected_tag_or_digest From cf02b85a058dccac8a217262c3e8f9ba4c87bf6a Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 11:32:47 -0400 Subject: [PATCH 46/86] fixed up all lint and mypy issues --- eng/tox/mypy_hard_failure_packages.py | 1 + .../azure-containerregistry/azure/__init__.py | 2 +- .../_authentication_policy.py | 3 ++ .../_container_registry_client.py | 15 ++++++--- .../_container_repository_client.py | 23 +++++++++---- .../azure/containerregistry/_helpers.py | 20 ------------ .../azure/containerregistry/_models.py | 32 +++++++++++-------- .../dev_requirements.txt | 1 - 8 files changed, 50 insertions(+), 47 deletions(-) diff --git a/eng/tox/mypy_hard_failure_packages.py b/eng/tox/mypy_hard_failure_packages.py index 8b5f6c93ac31..cdcb1cc09f1f 100644 --- a/eng/tox/mypy_hard_failure_packages.py +++ b/eng/tox/mypy_hard_failure_packages.py @@ -14,4 +14,5 @@ "azure-ai-formrecognizer", "azure-ai-metricsadvisor", "azure-eventgrid", + "azure-containerregistry", ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/__init__.py index 8db66d3d0f0f..d55ccad1f573 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/__init__.py @@ -1 +1 @@ -__path__ = __import__("pkgutil").extend_path(__path__, __name__) +__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index 23a14700d797..f7387d0f691e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -6,9 +6,12 @@ from base64 import b64encode import re +from typing import TYPE_CHECKING from azure.core.pipeline.policies import SansIOHTTPPolicy +if TYPE_CHECKING: + from azure.core.pipeline import PipelineRequest class ContainerRegistryUserCredential(object): """Credential used to authenticate with Container Registry service""" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 249e9674f49d..a4f2dcc768fe 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -3,16 +3,20 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from typing import TYPE_CHECKING from azure.core.paging import ItemPaged from ._base_client import ContainerRegistryBaseClient from ._container_repository_client import ContainerRepositoryClient from ._models import DeletedRepositoryResult +if TYPE_CHECKING: + from typing import Any, Dict + from azure.core.credentials import TokenCredential class ContainerRegistryClient(ContainerRegistryBaseClient): def __init__(self, endpoint, credential, **kwargs): - # type: (str, TokenCredential) -> None + # type: (str, TokenCredential, Dict[str, Any]) -> None """Create a ContainerRegistryClient from an ACR endpoint and a credential :param endpoint: An ACR endpoint @@ -24,11 +28,12 @@ def __init__(self, endpoint, credential, **kwargs): """ if not endpoint.startswith("https://"): endpoint = "https://" + endpoint + self.endpoint = endpoint self.credential = credential super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) def delete_repository(self, repository, **kwargs): - # type: (str) -> DeletedRepositoryResult + # type: (str, Dict[str, Any]) -> DeletedRepositoryResult """Delete a repository :param repository: The repository to delete @@ -41,7 +46,7 @@ def delete_repository(self, repository, **kwargs): return DeletedRepositoryResult.from_generated(deleted_repository) def list_repositories(self, **kwargs): - # type: (...) -> ItemPaged[str] + # type: (Dict[str, Any]) -> ItemPaged[str] """List all repositories :keyword max: Maximum number of repositories to return @@ -56,11 +61,11 @@ def list_repositories(self, **kwargs): ) def get_repository_client(self, repository, **kwargs): - # type: (str) -> ContainerRepositoryClient + # type: (str, Dict[str, Any]) -> ContainerRepositoryClient """Get a repository client :param repository: The repository to create a client for :type repository: str :returns: :class:~azure.containerregistry.ContainerRepositoryClient """ - return ContainerRepositoryClient(repository, credential=self.credential, **kwargs) + return ContainerRepositoryClient(self.endpoint, repository, credential=self.credential, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 7d4b19f9c860..9511dee05270 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -3,14 +3,20 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from typing import TYPE_CHECKING from ._base_client import ContainerRegistryBaseClient from ._models import RepositoryProperties, TagProperties, RegistryArtifactProperties +if TYPE_CHECKING: + from typing import Any, Dict + from azure.core.paging import ItemPaged + from azure.core.credentials import TokenCredential + from ._models import ContentPermissions class ContainerRepositoryClient(ContainerRegistryBaseClient): def __init__(self, endpoint, repository, credential, **kwargs): - # type: (str, str, TokenCredential) -> None + # type: (str, str, TokenCredential, Dict[str, Any]) -> None """Create a ContainerRepositoryClient from an endpoint, repository name, and credential :param endpoint: An ACR endpoint @@ -73,11 +79,12 @@ def get_properties(self): :returns: :class:~azure.containerregistry.RepositoryProperties :raises: None """ - resp = self._client.container_registry.get_repository_attributes(self.repository) + # GET '/acr/v1/{name}' + resp = self._client.container_registry_repository.get_properties(self.repository) return RepositoryProperties.from_generated(resp) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): - # type: (str) -> RegistryArtifactProperties + # type: (str, Dict[str, Any]) -> RegistryArtifactProperties """Get the properties of a registry artifact :param tag_or_digest: The tag/digest of a registry artifact @@ -85,17 +92,20 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :returns: :class:~azure.containerregistry.RegistryArtifactProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ + # GET '/acr/v1/{name}/_manifests/{digest}' # TODO: If `tag_or_digest` is a tag, need to do a get_tags to find the appropriate digest, # generated code only takes a digest if self._is_tag(tag_or_digest): tag_or_digest = self.get_digest_from_tag(tag_or_digest) # TODO: The returned object from the generated code is not being deserialized properly return RegistryArtifactProperties.from_generated( - self._client.container_registry_repository.get_manifest_attributes(self.repository, tag_or_digest, **kwargs) + self._client.container_registry_repository.get_registry_artifact_properties( + self.repository, tag_or_digest, **kwargs + ) ) def get_tag_properties(self, tag, **kwargs): - # type: (str) -> TagProperties + # type: (str, Dict[str, Any]) -> TagProperties """Get the properties for a tag :param tag: The tag to get properties for @@ -103,8 +113,9 @@ def get_tag_properties(self, tag, **kwargs): :returns: :class:~azure.containerregistry.TagProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ + # GET '/acr/v1/{name}/_tags/{reference}' return TagProperties.from_generated( - self._client.container_registry_repository.get_tag_attributes(self.repository, tag, **kwargs) + self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) ) def list_registry_artifacts(self, **kwargs): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py index 71f3512086c8..15227605df4f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py @@ -3,23 +3,3 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ - -from azure.core.pipeline.policies import ( - BearerTokenCredentialPolicy, -) - - -def get_authentication_policy(base_url, credential): - # type: (TokenCredential) -> SansIOHttpPolicy - authentication_policy = None - scope = base_url.strip("/") + "/.default" - if credential is None: - raise ValueError("Parameter 'credential' must not be None.") - if hasattr(credential, "get_token"): - authentication_policy = BearerTokenCredentialPolicy(credential, scope) - else: - raise TypeError( - "Please provide an instance from azure-identity " "or a class that implement the 'get_token protocol" - ) - - return authentication_policy diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 5483d8c8cb5e..d2ac3ac728e5 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -5,23 +5,27 @@ # ------------------------------------ from enum import Enum +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from ._generated.models import ManifestChangeableAttributes, ManifestAttributesBase + from ._generated.models import RepositoryProperties as GeneratedRepositoryProperties class ContentPermissions(object): def __init__(self, **kwargs): - self.can_delete = kwargs.get("can_delete") - self.can_list = kwargs.get("can_list") - self.can_read = kwargs.get("can_read") - self.can_write = kwargs.get("can_write") + self.delete_enabled = kwargs.get("delete_enabled") + self.list_enabled = kwargs.get("list_enabled") + self.read_enabled = kwargs.get("read_enabled") + self.write_enabled = kwargs.get("write_enabled") @classmethod def from_generated(cls, generated): - # type: (azure.containerregistry._generated.models.ChangeableAttributes) -> ContentPermissions + # type: (ManifestChangeableAttributes) -> ContentPermissions return cls( - delete=generated.can_delete, - list=generated.can_list, - read=generated.can_read, - write=generated.can_write, + delete_enabled=generated.delete_enabled, + list_enabled=generated.list_enabled, + read_enabled=generated.read_enabled, + write_enabled=generated.write_enabled, ) @@ -55,7 +59,7 @@ def __init__(self, **kwargs): @classmethod def from_generated(cls, generated): - # type: (azure.containerregistry._generated.models.ManfiestAttributestBase) -> RegistryArtifactProperties + # type: (ManifestAttributesBase) -> RegistryArtifactProperties return cls( config_media_type=generated.config_media_type, cpu_architecture=generated.cpu_architecture, @@ -65,8 +69,8 @@ def from_generated(cls, generated): manifest_media_type=generated.manifest_media_type, manifest_properties=generated.manifest_properties, operating_system=generated.operating_system, - registry=generated.registry, - repository=generated.repository, + # registry=generated.registry, + # repository=generated.repository, size=generated.size, tags=generated.tags, ) @@ -107,12 +111,12 @@ def __init__(self, **kwargs): @classmethod def from_generated(cls, generated): - # type: (azure.containerregistry._generated.models.RepositoryAttributes) -> RepositoryProperties + # type: (GeneratedRepositoryProperties) -> RepositoryProperties return cls( created_on=generated.created_on, last_updated_on=generated.last_updated_on, name=generated.name, - registry=generated.registry, + # registry=generated.registry, manifest_count=generated.registry_artifact_count, tag_count=generated.tag_count, content_permissions=generated.writeable_properties, diff --git a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt index e0e0792d9188..5f40d6f3e081 100644 --- a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt +++ b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt @@ -1,5 +1,4 @@ -e ../../../tools/azure-sdk-tools --e ../../../tools/azure-devtools ../../core/azure-core aiohttp>=3.0; python_version >= '3.5' azure-identity \ No newline at end of file From 544c9b75f84ebb6f896c93b61b5f366fafc869df Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 11:33:33 -0400 Subject: [PATCH 47/86] formatting --- .../azure/containerregistry/_authentication_policy.py | 1 + .../azure/containerregistry/_container_registry_client.py | 1 + .../azure/containerregistry/_container_repository_client.py | 1 + .../azure-containerregistry/azure/containerregistry/_models.py | 1 + 4 files changed, 4 insertions(+) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index f7387d0f691e..5f676270b748 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -13,6 +13,7 @@ if TYPE_CHECKING: from azure.core.pipeline import PipelineRequest + class ContainerRegistryUserCredential(object): """Credential used to authenticate with Container Registry service""" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index a4f2dcc768fe..324aaf86ae71 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -14,6 +14,7 @@ from typing import Any, Dict from azure.core.credentials import TokenCredential + class ContainerRegistryClient(ContainerRegistryBaseClient): def __init__(self, endpoint, credential, **kwargs): # type: (str, TokenCredential, Dict[str, Any]) -> None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 9511dee05270..67263eaeaaf8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -14,6 +14,7 @@ from azure.core.credentials import TokenCredential from ._models import ContentPermissions + class ContainerRepositoryClient(ContainerRegistryBaseClient): def __init__(self, endpoint, repository, credential, **kwargs): # type: (str, str, TokenCredential, Dict[str, Any]) -> None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index d2ac3ac728e5..84131ca37b99 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -11,6 +11,7 @@ from ._generated.models import ManifestChangeableAttributes, ManifestAttributesBase from ._generated.models import RepositoryProperties as GeneratedRepositoryProperties + class ContentPermissions(object): def __init__(self, **kwargs): self.delete_enabled = kwargs.get("delete_enabled") From 1f1eb4c65bb704c7551e6574fb66f246870c288e Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 12:00:38 -0400 Subject: [PATCH 48/86] adding devtools to dev_reqs --- .../azure-containerregistry/dev_requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt index 5f40d6f3e081..e0e0792d9188 100644 --- a/sdk/containerregistry/azure-containerregistry/dev_requirements.txt +++ b/sdk/containerregistry/azure-containerregistry/dev_requirements.txt @@ -1,4 +1,5 @@ -e ../../../tools/azure-sdk-tools +-e ../../../tools/azure-devtools ../../core/azure-core aiohttp>=3.0; python_version >= '3.5' azure-identity \ No newline at end of file From 643e9373a752173b4b7d132246b4ba84448f6dbf Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 13:59:44 -0400 Subject: [PATCH 49/86] including samples and license in manifest, thank you scbedd --- sdk/containerregistry/azure-containerregistry/MANIFEST.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/containerregistry/azure-containerregistry/MANIFEST.in b/sdk/containerregistry/azure-containerregistry/MANIFEST.in index dd20dd67408b..81d3dcd1770b 100644 --- a/sdk/containerregistry/azure-containerregistry/MANIFEST.in +++ b/sdk/containerregistry/azure-containerregistry/MANIFEST.in @@ -1,3 +1,5 @@ include *.md +include LICENSE.txt include azure/__init__.py -recursive-include tests *.py \ No newline at end of file +recursive-include tests *.py +recursive-include samples *.py *.md \ No newline at end of file From dfdbe82edafb952c3388b35d3d22cec4dceb7fbc Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 15:06:41 -0400 Subject: [PATCH 50/86] updating swagger --- .../_generated/models/_models.py | 114 +++++++++------- .../_generated/models/_models_py3.py | 124 ++++++++++-------- .../azure/containerregistry/_models.py | 22 +--- .../azure-containerregistry/swagger/README.md | 5 +- 4 files changed, 144 insertions(+), 121 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index dea33abbcdca..731ba96ec39c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -417,25 +417,23 @@ class ManifestAttributesBase(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Last update time. :type last_updated_on: ~datetime.datetime - :param cpu_architecture: Required. CPU architecture. + :param cpu_architecture: CPU architecture. :type cpu_architecture: str - :param operating_system: Required. Operating system. + :param operating_system: Operating system. :type operating_system: str - :param manifest_media_type: Media type. - :type manifest_media_type: str - :param config_media_type: Config blob media type. - :type config_media_type: str + :param registry_artifacts: List of manifest attributes details. + :type registry_artifacts: + list[~azure.containerregistry.models.ManifestAttributesManifestReferences] :param tags: Required. A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Changeable attributes. + :param manifest_properties: Required. Changeable attributes. :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ _validation = { 'digest': {'required': True}, - 'cpu_architecture': {'required': True}, - 'operating_system': {'required': True}, 'tags': {'required': True}, + 'manifest_properties': {'required': True}, } _attribute_map = { @@ -445,8 +443,7 @@ class ManifestAttributesBase(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, 'operating_system': {'key': 'os', 'type': 'str'}, - 'manifest_media_type': {'key': 'mediaType', 'type': 'str'}, - 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, + 'registry_artifacts': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'tags', 'type': '[str]'}, 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } @@ -460,12 +457,11 @@ def __init__( self.size = kwargs.get('size', None) self.created_on = kwargs.get('created_on', None) self.last_updated_on = kwargs.get('last_updated_on', None) - self.cpu_architecture = kwargs['cpu_architecture'] - self.operating_system = kwargs['operating_system'] - self.manifest_media_type = kwargs.get('manifest_media_type', None) - self.config_media_type = kwargs.get('config_media_type', None) + self.cpu_architecture = kwargs.get('cpu_architecture', None) + self.operating_system = kwargs.get('operating_system', None) + self.registry_artifacts = kwargs.get('registry_artifacts', None) self.tags = kwargs['tags'] - self.manifest_properties = kwargs.get('manifest_properties', None) + self.manifest_properties = kwargs['manifest_properties'] class ManifestAttributesManifest(msrest.serialization.Model): @@ -494,18 +490,26 @@ def __init__( class ManifestAttributesManifestReferences(msrest.serialization.Model): """Manifest attributes details. - :param digest: Manifest digest. + All required parameters must be populated in order to send to Azure. + + :param digest: Required. Manifest digest. :type digest: str - :param architecture: CPU architecture. - :type architecture: str - :param os: Operating system. - :type os: str + :param cpu_architecture: Required. CPU architecture. + :type cpu_architecture: str + :param operating_system: Required. Operating system. + :type operating_system: str """ + _validation = { + 'digest': {'required': True}, + 'cpu_architecture': {'required': True}, + 'operating_system': {'required': True}, + } + _attribute_map = { 'digest': {'key': 'digest', 'type': 'str'}, - 'architecture': {'key': 'architecture', 'type': 'str'}, - 'os': {'key': 'os', 'type': 'str'}, + 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, + 'operating_system': {'key': 'os', 'type': 'str'}, } def __init__( @@ -513,9 +517,9 @@ def __init__( **kwargs ): super(ManifestAttributesManifestReferences, self).__init__(**kwargs) - self.digest = kwargs.get('digest', None) - self.architecture = kwargs.get('architecture', None) - self.os = kwargs.get('os', None) + self.digest = kwargs['digest'] + self.cpu_architecture = kwargs['cpu_architecture'] + self.operating_system = kwargs['operating_system'] class ManifestChangeableAttributes(msrest.serialization.Model): @@ -897,7 +901,7 @@ class RegistryArtifactProperties(msrest.serialization.Model): :param repository: Required. Image name. :type repository: str - :param digest: Manifest. + :param digest: Required. Manifest. :type digest: str :param size: Image size. :type size: long @@ -909,18 +913,20 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type cpu_architecture: str :param operating_system: Operating system. :type operating_system: str - :param manifest_media_type: Media type. - :type manifest_media_type: str - :param config_media_type: Config blob media type. - :type config_media_type: str - :param tags: A set of tags. List of tags. + :param registry_artifacts: List of manifest attributes details. + :type registry_artifacts: + list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :param tags: Required. A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Changeable attributes. + :param manifest_properties: Required. Changeable attributes. :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ _validation = { 'repository': {'required': True}, + 'digest': {'required': True}, + 'tags': {'required': True}, + 'manifest_properties': {'required': True}, } _attribute_map = { @@ -931,8 +937,7 @@ class RegistryArtifactProperties(msrest.serialization.Model): 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, - 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, + 'registry_artifacts': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'manifest.tags', 'type': '[str]'}, 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, } @@ -943,16 +948,15 @@ def __init__( ): super(RegistryArtifactProperties, self).__init__(**kwargs) self.repository = kwargs['repository'] - self.digest = kwargs.get('digest', None) + self.digest = kwargs['digest'] self.size = kwargs.get('size', None) self.created_on = kwargs.get('created_on', None) self.last_updated_on = kwargs.get('last_updated_on', None) self.cpu_architecture = kwargs.get('cpu_architecture', None) self.operating_system = kwargs.get('operating_system', None) - self.manifest_media_type = kwargs.get('manifest_media_type', None) - self.config_media_type = kwargs.get('config_media_type', None) - self.tags = kwargs.get('tags', None) - self.manifest_properties = kwargs.get('manifest_properties', None) + self.registry_artifacts = kwargs.get('registry_artifacts', None) + self.tags = kwargs['tags'] + self.manifest_properties = kwargs['manifest_properties'] class Repositories(msrest.serialization.Model): @@ -1112,7 +1116,9 @@ def __init__( class TagList(msrest.serialization.Model): """List of tag details. - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str :param tags: A set of tags. List of tag attribute details. :type tags: list[~azure.containerregistry.models.TagAttributesBase] @@ -1120,6 +1126,10 @@ class TagList(msrest.serialization.Model): :type link: str """ + _validation = { + 'repository': {'required': True}, + } + _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, @@ -1131,7 +1141,7 @@ def __init__( **kwargs ): super(TagList, self).__init__(**kwargs) - self.repository = kwargs.get('repository', None) + self.repository = kwargs['repository'] self.tags = kwargs.get('tags', None) self.link = kwargs.get('link', None) @@ -1139,20 +1149,28 @@ def __init__( class TagProperties(msrest.serialization.Model): """Tag attributes. - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str :param name: Tag name. :type name: str :param digest: Tag digest. :type digest: str - :param created_on: Tag created time. + :param created_on: Required. Tag created time. :type created_on: ~datetime.datetime - :param last_updated_on: Tag last update time. + :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime :param writeable_properties: Changeable attributes. :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'repository': {'required': True}, + 'created_on': {'required': True}, + 'last_updated_on': {'required': True}, + } + _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'name': {'key': 'tag.name', 'type': 'str'}, @@ -1167,11 +1185,11 @@ def __init__( **kwargs ): super(TagProperties, self).__init__(**kwargs) - self.repository = kwargs.get('repository', None) + self.repository = kwargs['repository'] self.name = kwargs.get('name', None) self.digest = kwargs.get('digest', None) - self.created_on = kwargs.get('created_on', None) - self.last_updated_on = kwargs.get('last_updated_on', None) + self.created_on = kwargs['created_on'] + self.last_updated_on = kwargs['last_updated_on'] self.writeable_properties = kwargs.get('writeable_properties', None) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index ede8ef07e721..f278311ffffd 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -481,25 +481,23 @@ class ManifestAttributesBase(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Last update time. :type last_updated_on: ~datetime.datetime - :param cpu_architecture: Required. CPU architecture. + :param cpu_architecture: CPU architecture. :type cpu_architecture: str - :param operating_system: Required. Operating system. + :param operating_system: Operating system. :type operating_system: str - :param manifest_media_type: Media type. - :type manifest_media_type: str - :param config_media_type: Config blob media type. - :type config_media_type: str + :param registry_artifacts: List of manifest attributes details. + :type registry_artifacts: + list[~azure.containerregistry.models.ManifestAttributesManifestReferences] :param tags: Required. A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Changeable attributes. + :param manifest_properties: Required. Changeable attributes. :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ _validation = { 'digest': {'required': True}, - 'cpu_architecture': {'required': True}, - 'operating_system': {'required': True}, 'tags': {'required': True}, + 'manifest_properties': {'required': True}, } _attribute_map = { @@ -509,8 +507,7 @@ class ManifestAttributesBase(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, 'operating_system': {'key': 'os', 'type': 'str'}, - 'manifest_media_type': {'key': 'mediaType', 'type': 'str'}, - 'config_media_type': {'key': 'configMediaType', 'type': 'str'}, + 'registry_artifacts': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'tags', 'type': '[str]'}, 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } @@ -519,15 +516,14 @@ def __init__( self, *, digest: str, - cpu_architecture: str, - operating_system: str, tags: List[str], + manifest_properties: "ContentProperties", size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, - manifest_media_type: Optional[str] = None, - config_media_type: Optional[str] = None, - manifest_properties: Optional["ContentProperties"] = None, + cpu_architecture: Optional[str] = None, + operating_system: Optional[str] = None, + registry_artifacts: Optional[List["ManifestAttributesManifestReferences"]] = None, **kwargs ): super(ManifestAttributesBase, self).__init__(**kwargs) @@ -537,8 +533,7 @@ def __init__( self.last_updated_on = last_updated_on self.cpu_architecture = cpu_architecture self.operating_system = operating_system - self.manifest_media_type = manifest_media_type - self.config_media_type = config_media_type + self.registry_artifacts = registry_artifacts self.tags = tags self.manifest_properties = manifest_properties @@ -572,32 +567,40 @@ def __init__( class ManifestAttributesManifestReferences(msrest.serialization.Model): """Manifest attributes details. - :param digest: Manifest digest. + All required parameters must be populated in order to send to Azure. + + :param digest: Required. Manifest digest. :type digest: str - :param architecture: CPU architecture. - :type architecture: str - :param os: Operating system. - :type os: str + :param cpu_architecture: Required. CPU architecture. + :type cpu_architecture: str + :param operating_system: Required. Operating system. + :type operating_system: str """ + _validation = { + 'digest': {'required': True}, + 'cpu_architecture': {'required': True}, + 'operating_system': {'required': True}, + } + _attribute_map = { 'digest': {'key': 'digest', 'type': 'str'}, - 'architecture': {'key': 'architecture', 'type': 'str'}, - 'os': {'key': 'os', 'type': 'str'}, + 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, + 'operating_system': {'key': 'os', 'type': 'str'}, } def __init__( self, *, - digest: Optional[str] = None, - architecture: Optional[str] = None, - os: Optional[str] = None, + digest: str, + cpu_architecture: str, + operating_system: str, **kwargs ): super(ManifestAttributesManifestReferences, self).__init__(**kwargs) self.digest = digest - self.architecture = architecture - self.os = os + self.cpu_architecture = cpu_architecture + self.operating_system = operating_system class ManifestChangeableAttributes(msrest.serialization.Model): @@ -1036,7 +1039,7 @@ class RegistryArtifactProperties(msrest.serialization.Model): :param repository: Required. Image name. :type repository: str - :param digest: Manifest. + :param digest: Required. Manifest. :type digest: str :param size: Image size. :type size: long @@ -1048,18 +1051,20 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type cpu_architecture: str :param operating_system: Operating system. :type operating_system: str - :param manifest_media_type: Media type. - :type manifest_media_type: str - :param config_media_type: Config blob media type. - :type config_media_type: str - :param tags: A set of tags. List of tags. + :param registry_artifacts: List of manifest attributes details. + :type registry_artifacts: + list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :param tags: Required. A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Changeable attributes. + :param manifest_properties: Required. Changeable attributes. :type manifest_properties: ~azure.containerregistry.models.ContentProperties """ _validation = { 'repository': {'required': True}, + 'digest': {'required': True}, + 'tags': {'required': True}, + 'manifest_properties': {'required': True}, } _attribute_map = { @@ -1070,8 +1075,7 @@ class RegistryArtifactProperties(msrest.serialization.Model): 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'manifest_media_type': {'key': 'manifest.mediaType', 'type': 'str'}, - 'config_media_type': {'key': 'manifest.configMediaType', 'type': 'str'}, + 'registry_artifacts': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'manifest.tags', 'type': '[str]'}, 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, } @@ -1080,16 +1084,15 @@ def __init__( self, *, repository: str, - digest: Optional[str] = None, + digest: str, + tags: List[str], + manifest_properties: "ContentProperties", size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, cpu_architecture: Optional[str] = None, operating_system: Optional[str] = None, - manifest_media_type: Optional[str] = None, - config_media_type: Optional[str] = None, - tags: Optional[List[str]] = None, - manifest_properties: Optional["ContentProperties"] = None, + registry_artifacts: Optional[List["ManifestAttributesManifestReferences"]] = None, **kwargs ): super(RegistryArtifactProperties, self).__init__(**kwargs) @@ -1100,8 +1103,7 @@ def __init__( self.last_updated_on = last_updated_on self.cpu_architecture = cpu_architecture self.operating_system = operating_system - self.manifest_media_type = manifest_media_type - self.config_media_type = config_media_type + self.registry_artifacts = registry_artifacts self.tags = tags self.manifest_properties = manifest_properties @@ -1284,7 +1286,9 @@ def __init__( class TagList(msrest.serialization.Model): """List of tag details. - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str :param tags: A set of tags. List of tag attribute details. :type tags: list[~azure.containerregistry.models.TagAttributesBase] @@ -1292,6 +1296,10 @@ class TagList(msrest.serialization.Model): :type link: str """ + _validation = { + 'repository': {'required': True}, + } + _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, @@ -1301,7 +1309,7 @@ class TagList(msrest.serialization.Model): def __init__( self, *, - repository: Optional[str] = None, + repository: str, tags: Optional[List["TagAttributesBase"]] = None, link: Optional[str] = None, **kwargs @@ -1315,20 +1323,28 @@ def __init__( class TagProperties(msrest.serialization.Model): """Tag attributes. - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str :param name: Tag name. :type name: str :param digest: Tag digest. :type digest: str - :param created_on: Tag created time. + :param created_on: Required. Tag created time. :type created_on: ~datetime.datetime - :param last_updated_on: Tag last update time. + :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime :param writeable_properties: Changeable attributes. :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ + _validation = { + 'repository': {'required': True}, + 'created_on': {'required': True}, + 'last_updated_on': {'required': True}, + } + _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'name': {'key': 'tag.name', 'type': 'str'}, @@ -1341,11 +1357,11 @@ class TagProperties(msrest.serialization.Model): def __init__( self, *, - repository: Optional[str] = None, + repository: str, + created_on: datetime.datetime, + last_updated_on: datetime.datetime, name: Optional[str] = None, digest: Optional[str] = None, - created_on: Optional[datetime.datetime] = None, - last_updated_on: Optional[datetime.datetime] = None, writeable_properties: Optional["ContentProperties"] = None, **kwargs ): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 84131ca37b99..6eb438a1d297 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -45,33 +45,25 @@ def from_generated(cls, gen): class RegistryArtifactProperties(object): def __init__(self, **kwargs): + self.cpu_architecture = kwargs.get("cpu_architecture", None) self.created_on = kwargs.get("created_on", None) - self.registry = kwargs.get("registry", None) - # self.cpu_arch = kwargs.get("arch", None) - # self.digest = kwargs.get("digest", None) - # self.last_updated = kwargs.get("last_updated", None) - # self.manifest_properties = kwargs.get("manifest_properties", None) - # self.operating_system = kwargs.get("operating_system", None) - # self.registry = kwargs.get("registry", None) - # self.registry_artifacts = kwargs.get("registry_artifacts", None) - # self.repository = kwargs.get("repository", None) - # self.size = kwargs.get("size", None) - # self.tags = kwargs.get("tags", None) + self.digest = kwargs.get("digest", None) + self.last_updated_on = kwargs.get("last_updated_on", None) + self.manifest_properties = kwargs.get("manifest_properties", None) + self.operating_system = kwargs.get("operating_system", None) + self.size = kwargs.get("size", None) + self.tags = kwargs.get("tags", None) @classmethod def from_generated(cls, generated): # type: (ManifestAttributesBase) -> RegistryArtifactProperties return cls( - config_media_type=generated.config_media_type, cpu_architecture=generated.cpu_architecture, created_on=generated.created_on, digest=generated.digest, last_updated_on=generated.last_updated_on, - manifest_media_type=generated.manifest_media_type, manifest_properties=generated.manifest_properties, operating_system=generated.operating_system, - # registry=generated.registry, - # repository=generated.repository, size=generated.size, tags=generated.tags, ) diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index 2b674ef08f6a..55beeddb5c27 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -2,7 +2,7 @@ ### Settings ``` yaml -input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/4bdce8c1cce1303bbae0a52efd59085524d2d881/sdk/containerregistry/container-registry/swagger/containerregistry.json +input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/1138db4e60f389332df553686145356cce0b79ed/sdk/containerregistry/container-registry/swagger/containerregistry.json output-folder: "../azure/containerregistry/_generated" namespace: azure.containerregistry no-namespace-folders: true @@ -14,6 +14,3 @@ clear-output-folder: true enable-xml: true vanilla: true ``` - - - From 93ad7c498470c83b2155f4bc5eca161aa54cd237 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 22 Mar 2021 16:39:35 -0400 Subject: [PATCH 51/86] adding skeleton for auth flow --- .../azure/containerregistry/_helpers.py | 5 --- .../authentication/_access_token.py | 32 ++++++++++++++++++ .../authentication/_access_token_cache.py | 6 ++++ .../_container_registry_credential_policy.py | 33 +++++++++++++++++-- 4 files changed, 69 insertions(+), 7 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py deleted file mode 100644 index 15227605df4f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py +++ /dev/null @@ -1,5 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py new file mode 100644 index 000000000000..d532614f5a92 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py @@ -0,0 +1,32 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +class AccessToken(object): + """Base access token for ACR challenge based auth flow""" + + def __init__(self, url, pipeline): + # type: (str, HttpPipeline) -> None + self.reg_login_url = url + + # Exchange ACR Refresh token for an ACR Access Token + def get_access_token_with_response(self, grant_type, service_name, scope, refresh_token): + # type: (str, str, str, str) -> AccessToken + accept = "application/json" + return service.get_access_token( + self.reg_login_url, + grant_type, + service_name, + scope, + refresh_token, + accept, + context + ) + + def get_access_token(self, grant_type, service_name, scope, refresh_token): + # type: (str, str, str, str) -> AcrAccessToken + return "" + + \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py index e69de29bb2d1..287ce627d548 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py @@ -0,0 +1,6 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py index e0d4369dbd05..a5b87bec1871 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py @@ -4,8 +4,16 @@ # Licensed under the MIT License. # ------------------------------------ import re +from typing import TYPE_CHECKING + +from azure.core.pipeline.policies import ChallengeAuthenticationPolicy + +from ._container_registry_token_service import ContainerRegistryTokenService + +if TYPE_CHECKING: + from azure.core.credentials import TokenCredential + from typing import List -from azure.core.pipeline.policies import SansIOHTTPPolicy # Follows challenge based authorization scheme @@ -28,7 +36,7 @@ # Request Header: {Bearer acr acces token} -class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): +class ContainerRegistryCredentialPolicy(ChallengeAuthenticationPolicy): """Challenge based authentication policy for ACR. This policy is used for getting the AAD Token, refresh token, and access token before performing a call to service. @@ -44,12 +52,33 @@ class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): AUTHORIZATION = "Authorization" def __init__(self, credential, url, pipeline): + # type: (TokenCredential, str, HttpPipeline) -> None self.credential = credential self.url = url self.pipeline = pipeline + self.container_registry_token_service = ContainerRegistryTokenService( + credential, url, pipeline + ) + + @classmethod + def from_token_service(cls, token_service): + # type: (ContainerRegistryTokenService) -> ContainerRegistryCredentialPolicy + return cls(token_service.credential, token_service.url, token_service.pipeline) def process(self, context, next): # type: (HttpPipelineContext, HttpPipelinePolicy) -> HttpResponse + if not self.url.startswith("https"): + raise ValueError("Token Credentials require a URL using the HTTPS protocol scheme") + + def on_request(self, request): + # type: (PipelineRequest) -> None + """Called before the policy sends a request""" + pass + + def send(self, request): + # type: (PipelineRequest) -> PipelineResponse + """Authorizes a request with a bearer token, possibly handling an authentication challenge""" + pass def authorize_request(self, context, token_request_context): From c1f51983fbb27537ff7b95dd16d57e1ff18478e1 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 23 Mar 2021 10:19:02 -0400 Subject: [PATCH 52/86] more auth files --- ...ontainer_registry_token_request_context.py | 14 ++++++++ .../_container_registry_token_service.py | 25 +++++++++++++ .../authentication/_token_service_impl.py | 36 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py new file mode 100644 index 000000000000..73dbf28c6149 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py @@ -0,0 +1,14 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + + +class ContainerRegistryTokenRequestContext(object): + """A token request context associated with a given container registry token""" + + def __init__(self, service_name, scope): + # type: (str, str) -> None + self.service_name = service_name + self.scope = scope diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py index e69de29bb2d1..68ed6a15fbcc 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py @@ -0,0 +1,25 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from ._container_registry_token_request_context import ContainerRegistryTokenRequestContext + + +class ContainerRegistryTokenService(object): + """A token service for obtaining tokens to be used by the container registry service""" + + def __init__(self, token_credential, url, pipeline): + self.token_service = TokenService(url, pipeline) + self.refresh_cache = None # TODO: decide on cache + + def get_token(self, req_context): + # type: (ContainerRegistryTokenRequestContext) -> AccessToken + scope = req_context.scope + service_name = req_context.service_name + + refresh_token = self.refresh_cache.get_token(req_context) + return self.token_service.get_acr_access_token(refresh_token, scope, service_name) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py new file mode 100644 index 000000000000..d5b9c7f5d3ed --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py @@ -0,0 +1,36 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from ._container_registry_token_request_context import ContainerRegistryTokenRequestContext + + +class TokenServiceImpl(object): + """Token service implementation that wraps the authentication REST APIs for ACR""" + + def __init__(self, url, pipeline): + # type: (str, HttpPipeline) -> None + self._url = url + self.pipeline = pipeline + self.access_token_impl = AccessTokenImpl(url, pipeline) + self.refresh_token_impl = RefreshTokenImpl(url, pipeline) + + def get_acr_access_token(self, refresh_token, scope, service_name): + # type: (str, str, str) -> str + access_token = self.access_token_impl.get_acr_access_token("refresh_token", service_name, scope, refresh_token) + # Here is where caching would go if we implement it + return access_token + + def get_acr_refresh_token(self, aad_token, service_name): + # type: (str, str) -> str + # Here is where caching would go if we implement it + return self.refresh_token_impl( + "access_token", + aad_token, + None, + service_name + ) \ No newline at end of file From 166661efa12054c334789a18895c296e418e3dca Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 23 Mar 2021 16:23:13 -0400 Subject: [PATCH 53/86] committing for izy to take a look --- .../azure/containerregistry/__init__.py | 2 + .../_generated/_container_registry.py | 13 +- .../_generated/aio/_container_registry.py | 13 +- .../_generated/aio/operations/__init__.py | 6 +- .../operations/_access_tokens_operations.py | 165 ----------------- .../operations/_refresh_tokens_operations.py | 112 ------------ .../_generated/models/__init__.py | 17 +- .../models/_container_registry_enums.py | 35 ---- .../_generated/models/_models.py | 98 +++++----- .../_generated/models/_models_py3.py | 112 ++++++------ .../_generated/operations/__init__.py | 6 +- .../operations/_access_tokens_operations.py | 171 ------------------ .../operations/_refresh_tokens_operations.py | 117 ------------ .../authentication/_access_token.py | 32 ---- .../authentication/_access_token_cache.py | 50 +++++ .../_container_registry_credential_policy.py | 16 +- .../azure-containerregistry/swagger/README.md | 2 +- 17 files changed, 188 insertions(+), 779 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index e4f5065f9462..8d774b70270a 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -8,6 +8,7 @@ from ._container_registry_client import ContainerRegistryClient from ._container_repository_client import ContainerRepositoryClient +from ._exchange_client import ACRExchangeClient from ._models import ( ContentPermissions, DeletedRepositoryResult, @@ -26,6 +27,7 @@ __version__ = VERSION __all__ = [ + "ACRExchangeClient" "ContainerRegistryClient", "ContainerRepositoryClient", "ContentPermissions", diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py index 127f168e8ac3..fda89baf0d9b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py @@ -21,8 +21,7 @@ from .operations import ContainerRegistryOperations from .operations import ContainerRegistryRepositoryOperations from .operations import ContainerRegistryBlobOperations -from .operations import RefreshTokensOperations -from .operations import AccessTokensOperations +from .operations import AuthenticationOperations from . import models @@ -35,10 +34,8 @@ class ContainerRegistry(object): :vartype container_registry_repository: azure.containerregistry.operations.ContainerRegistryRepositoryOperations :ivar container_registry_blob: ContainerRegistryBlobOperations operations :vartype container_registry_blob: azure.containerregistry.operations.ContainerRegistryBlobOperations - :ivar refresh_tokens: RefreshTokensOperations operations - :vartype refresh_tokens: azure.containerregistry.operations.RefreshTokensOperations - :ivar access_tokens: AccessTokensOperations operations - :vartype access_tokens: azure.containerregistry.operations.AccessTokensOperations + :ivar authentication: AuthenticationOperations operations + :vartype authentication: azure.containerregistry.operations.AuthenticationOperations :param url: Registry login URL. :type url: str """ @@ -64,9 +61,7 @@ def __init__( self._client, self._config, self._serialize, self._deserialize) self.container_registry_blob = ContainerRegistryBlobOperations( self._client, self._config, self._serialize, self._deserialize) - self.refresh_tokens = RefreshTokensOperations( - self._client, self._config, self._serialize, self._deserialize) - self.access_tokens = AccessTokensOperations( + self.authentication = AuthenticationOperations( self._client, self._config, self._serialize, self._deserialize) def _send_request(self, http_request, **kwargs): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py index a344b66b5a8e..fb867d402c3b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py @@ -16,8 +16,7 @@ from .operations import ContainerRegistryOperations from .operations import ContainerRegistryRepositoryOperations from .operations import ContainerRegistryBlobOperations -from .operations import RefreshTokensOperations -from .operations import AccessTokensOperations +from .operations import AuthenticationOperations from .. import models @@ -30,10 +29,8 @@ class ContainerRegistry(object): :vartype container_registry_repository: azure.containerregistry.aio.operations.ContainerRegistryRepositoryOperations :ivar container_registry_blob: ContainerRegistryBlobOperations operations :vartype container_registry_blob: azure.containerregistry.aio.operations.ContainerRegistryBlobOperations - :ivar refresh_tokens: RefreshTokensOperations operations - :vartype refresh_tokens: azure.containerregistry.aio.operations.RefreshTokensOperations - :ivar access_tokens: AccessTokensOperations operations - :vartype access_tokens: azure.containerregistry.aio.operations.AccessTokensOperations + :ivar authentication: AuthenticationOperations operations + :vartype authentication: azure.containerregistry.aio.operations.AuthenticationOperations :param url: Registry login URL. :type url: str """ @@ -58,9 +55,7 @@ def __init__( self._client, self._config, self._serialize, self._deserialize) self.container_registry_blob = ContainerRegistryBlobOperations( self._client, self._config, self._serialize, self._deserialize) - self.refresh_tokens = RefreshTokensOperations( - self._client, self._config, self._serialize, self._deserialize) - self.access_tokens = AccessTokensOperations( + self.authentication = AuthenticationOperations( self._client, self._config, self._serialize, self._deserialize) async def _send_request(self, http_request: HttpRequest, **kwargs: Any) -> AsyncHttpResponse: diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py index 95b29f5d1bda..c07914265cd0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py @@ -9,13 +9,11 @@ from ._container_registry_operations import ContainerRegistryOperations from ._container_registry_repository_operations import ContainerRegistryRepositoryOperations from ._container_registry_blob_operations import ContainerRegistryBlobOperations -from ._refresh_tokens_operations import RefreshTokensOperations -from ._access_tokens_operations import AccessTokensOperations +from ._authentication_operations import AuthenticationOperations __all__ = [ 'ContainerRegistryOperations', 'ContainerRegistryRepositoryOperations', 'ContainerRegistryBlobOperations', - 'RefreshTokensOperations', - 'AccessTokensOperations', + 'AuthenticationOperations', ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py deleted file mode 100644 index 81a047426fb2..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_access_tokens_operations.py +++ /dev/null @@ -1,165 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import Any, Callable, Dict, Generic, Optional, TypeVar -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest - -from ... import models as _models - -T = TypeVar('T') -ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] - -class AccessTokensOperations: - """AccessTokensOperations async operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer) -> None: - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - async def get( - self, - service: str, - scope: str, - refresh_token: str, - **kwargs - ) -> "_models.AccessToken": - """Exchange ACR Refresh token for an ACR Access Token. - - :param service: Indicates the name of your Azure container registry. - :type service: str - :param scope: Which is expected to be a valid scope, and can be specified more than once for - multiple scope requests. You obtained this from the Www-Authenticate response header from the - challenge. - :type scope: str - :param refresh_token: Must be a valid ACR refresh token. - :type refresh_token: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: AccessToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AccessToken - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - grant_type = "refresh_token" - accept = "application/json" - - # Construct URL - url = self.get.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('AccessToken', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get.metadata = {'url': '/oauth2/token'} # type: ignore - - async def get_from_login( - self, - service: str, - scope: str, - **kwargs - ) -> "_models.AccessToken": - """Exchange Username, Password and Scope an ACR Access Token. - - :param service: Indicates the name of your Azure container registry. - :type service: str - :param scope: Expected to be a valid scope, and can be specified more than once for multiple - scope requests. You can obtain this from the Www-Authenticate response header from the - challenge. - :type scope: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: AccessToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AccessToken - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_from_login.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - query_parameters['service'] = self._serialize.query("service", service, 'str') - query_parameters['scope'] = self._serialize.query("scope", scope, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('AccessToken', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_from_login.metadata = {'url': '/oauth2/token'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py deleted file mode 100644 index 4f599817601f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_refresh_tokens_operations.py +++ /dev/null @@ -1,112 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import Any, Callable, Dict, Generic, Optional, TypeVar, Union -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest - -from ... import models as _models - -T = TypeVar('T') -ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] - -class RefreshTokensOperations: - """RefreshTokensOperations async operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer) -> None: - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - async def get_from_exchange( - self, - grant_type: Union[str, "_models.PostContentSchemaGrantType"], - service: str, - tenant: Optional[str] = None, - refresh_token: Optional[str] = None, - access_token: Optional[str] = None, - **kwargs - ) -> "_models.RefreshToken": - """Exchange AAD tokens for an ACR refresh Token. - - :param grant_type: Can take a value of access_token_refresh_token, or access_token, or - refresh_token. - :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType - :param service: Indicates the name of your Azure container registry. - :type service: str - :param tenant: AAD tenant associated to the AAD credentials. - :type tenant: str - :param refresh_token: AAD refresh token, mandatory when grant_type is - access_token_refresh_token or refresh_token. - :type refresh_token: str - :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token - or access_token. - :type access_token: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: RefreshToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RefreshToken - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.RefreshToken"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - accept = "application/json" - - # Construct URL - url = self.get_from_exchange.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('RefreshToken', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_from_exchange.metadata = {'url': '/oauth2/exchange'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py index 9c0366b04520..79172e17ea39 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py @@ -7,10 +7,11 @@ # -------------------------------------------------------------------------- try: - from ._models_py3 import AccessToken + from ._models_py3 import AcrAccessToken from ._models_py3 import AcrErrorInfo from ._models_py3 import AcrErrors from ._models_py3 import AcrManifests + from ._models_py3 import AcrRefreshToken from ._models_py3 import Annotations from ._models_py3 import ContentProperties from ._models_py3 import DeleteRepositoryResult @@ -33,7 +34,6 @@ from ._models_py3 import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema from ._models_py3 import PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema from ._models_py3 import Platform - from ._models_py3 import RefreshToken from ._models_py3 import RegistryArtifactProperties from ._models_py3 import Repositories from ._models_py3 import RepositoryProperties @@ -45,10 +45,11 @@ from ._models_py3 import V1Manifest from ._models_py3 import V2Manifest except (SyntaxError, ImportError): - from ._models import AccessToken # type: ignore + from ._models import AcrAccessToken # type: ignore from ._models import AcrErrorInfo # type: ignore from ._models import AcrErrors # type: ignore from ._models import AcrManifests # type: ignore + from ._models import AcrRefreshToken # type: ignore from ._models import Annotations # type: ignore from ._models import ContentProperties # type: ignore from ._models import DeleteRepositoryResult # type: ignore @@ -71,7 +72,6 @@ from ._models import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema # type: ignore from ._models import PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema # type: ignore from ._models import Platform # type: ignore - from ._models import RefreshToken # type: ignore from ._models import RegistryArtifactProperties # type: ignore from ._models import Repositories # type: ignore from ._models import RepositoryProperties # type: ignore @@ -83,15 +83,12 @@ from ._models import V1Manifest # type: ignore from ._models import V2Manifest # type: ignore -from ._container_registry_enums import ( - PostContentSchemaGrantType, -) - __all__ = [ - 'AccessToken', + 'AcrAccessToken', 'AcrErrorInfo', 'AcrErrors', 'AcrManifests', + 'AcrRefreshToken', 'Annotations', 'ContentProperties', 'DeleteRepositoryResult', @@ -114,7 +111,6 @@ 'Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema', 'PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema', 'Platform', - 'RefreshToken', 'RegistryArtifactProperties', 'Repositories', 'RepositoryProperties', @@ -125,5 +121,4 @@ 'TagProperties', 'V1Manifest', 'V2Manifest', - 'PostContentSchemaGrantType', ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py deleted file mode 100644 index 4f9b6bfb490f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py +++ /dev/null @@ -1,35 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- - -from enum import Enum, EnumMeta -from six import with_metaclass - -class _CaseInsensitiveEnumMeta(EnumMeta): - def __getitem__(self, name): - return super().__getitem__(name.upper()) - - def __getattr__(cls, name): - """Return the enum member matching `name` - We use __getattr__ instead of descriptors or inserting into the enum - class' __dict__ in order to support `name` and `value` being both - properties for enum members (which live in the class' __dict__) and - enum members themselves. - """ - try: - return cls._member_map_[name.upper()] - except KeyError: - raise AttributeError(name) - - -class PostContentSchemaGrantType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): - """Can take a value of access_token_refresh_token, or access_token, or refresh_token - """ - - ACCESS_TOKEN_REFRESH_TOKEN = "access_token_refresh_token" - ACCESS_TOKEN = "access_token" - REFRESH_TOKEN = "refresh_token" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 731ba96ec39c..125c967698f0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -10,8 +10,8 @@ import msrest.serialization -class AccessToken(msrest.serialization.Model): - """AccessToken. +class AcrAccessToken(msrest.serialization.Model): + """AcrAccessToken. :param access_token: The access token for performing authenticated requests. :type access_token: str @@ -25,7 +25,7 @@ def __init__( self, **kwargs ): - super(AccessToken, self).__init__(**kwargs) + super(AcrAccessToken, self).__init__(**kwargs) self.access_token = kwargs.get('access_token', None) @@ -102,6 +102,25 @@ def __init__( self.link = kwargs.get('link', None) +class AcrRefreshToken(msrest.serialization.Model): + """AcrRefreshToken. + + :param refresh_token: The refresh token to be used for generating access tokens. + :type refresh_token: str + """ + + _attribute_map = { + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + } + + def __init__( + self, + **kwargs + ): + super(AcrRefreshToken, self).__init__(**kwargs) + self.refresh_token = kwargs.get('refresh_token', None) + + class Annotations(msrest.serialization.Model): """Additional information provided through arbitrary metadata. @@ -743,47 +762,45 @@ def __init__( class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): """Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema. + Variables are only populated by the server, and will be ignored when sending a request. + All required parameters must be populated in order to send to Azure. - :param grant_type: Required. Can take a value of access_token_refresh_token, or access_token, - or refresh_token. Possible values include: "access_token_refresh_token", "access_token", - "refresh_token". - :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType + :ivar grant_type: Required. Can take a value of access_token. Default value: "access_token". + :vartype grant_type: str :param service: Required. Indicates the name of your Azure container registry. :type service: str - :param tenant: AAD tenant associated to the AAD credentials. + :param tenant: Required. AAD tenant associated to the AAD credentials. :type tenant: str - :param refresh_token: AAD refresh token, mandatory when grant_type is - access_token_refresh_token or refresh_token. - :type refresh_token: str - :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token - or access_token. - :type access_token: str + :param aad_accesstoken: Required. AAD access token, mandatory when grant_type is + access_token_refresh_token or access_token. + :type aad_accesstoken: str """ _validation = { - 'grant_type': {'required': True}, + 'grant_type': {'required': True, 'constant': True}, 'service': {'required': True}, + 'tenant': {'required': True}, + 'aad_accesstoken': {'required': True}, } _attribute_map = { 'grant_type': {'key': 'grant_type', 'type': 'str'}, 'service': {'key': 'service', 'type': 'str'}, 'tenant': {'key': 'tenant', 'type': 'str'}, - 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, - 'access_token': {'key': 'access_token', 'type': 'str'}, + 'aad_accesstoken': {'key': 'access_token', 'type': 'str'}, } + grant_type = "access_token" + def __init__( self, **kwargs ): super(Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) - self.grant_type = kwargs['grant_type'] self.service = kwargs['service'] - self.tenant = kwargs.get('tenant', None) - self.refresh_token = kwargs.get('refresh_token', None) - self.access_token = kwargs.get('access_token', None) + self.tenant = kwargs['tenant'] + self.aad_accesstoken = kwargs['aad_accesstoken'] class PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): @@ -802,22 +819,22 @@ class PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedS once for multiple scope requests. You obtained this from the Www-Authenticate response header from the challenge. :type scope: str - :param refresh_token: Required. Must be a valid ACR refresh token. - :type refresh_token: str + :param acr_refresh_token: Required. Must be a valid ACR refresh token. + :type acr_refresh_token: str """ _validation = { 'grant_type': {'required': True, 'constant': True}, 'service': {'required': True}, 'scope': {'required': True}, - 'refresh_token': {'required': True}, + 'acr_refresh_token': {'required': True}, } _attribute_map = { 'grant_type': {'key': 'grant_type', 'type': 'str'}, 'service': {'key': 'service', 'type': 'str'}, 'scope': {'key': 'scope', 'type': 'str'}, - 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + 'acr_refresh_token': {'key': 'refresh_token', 'type': 'str'}, } grant_type = "refresh_token" @@ -829,7 +846,7 @@ def __init__( super(PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) self.service = kwargs['service'] self.scope = kwargs['scope'] - self.refresh_token = kwargs['refresh_token'] + self.acr_refresh_token = kwargs['acr_refresh_token'] class Platform(msrest.serialization.Model): @@ -875,25 +892,6 @@ def __init__( self.features = kwargs.get('features', None) -class RefreshToken(msrest.serialization.Model): - """RefreshToken. - - :param refresh_token: The refresh token to be used for generating access tokens. - :type refresh_token: str - """ - - _attribute_map = { - 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, - } - - def __init__( - self, - **kwargs - ): - super(RefreshToken, self).__init__(**kwargs) - self.refresh_token = kwargs.get('refresh_token', None) - - class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. @@ -987,7 +985,7 @@ class RepositoryProperties(msrest.serialization.Model): All required parameters must be populated in order to send to Azure. - :param name: Image name. + :param name: Required. Image name. :type name: str :param created_on: Required. Image created time. :type created_on: ~datetime.datetime @@ -997,14 +995,16 @@ class RepositoryProperties(msrest.serialization.Model): :type registry_artifact_count: int :param tag_count: Required. Number of the tags. :type tag_count: int - :param writeable_properties: Changeable attributes. + :param writeable_properties: Required. Changeable attributes. :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ _validation = { + 'name': {'required': True}, 'created_on': {'required': True}, 'registry_artifact_count': {'required': True}, 'tag_count': {'required': True}, + 'writeable_properties': {'required': True}, } _attribute_map = { @@ -1021,12 +1021,12 @@ def __init__( **kwargs ): super(RepositoryProperties, self).__init__(**kwargs) - self.name = kwargs.get('name', None) + self.name = kwargs['name'] self.created_on = kwargs['created_on'] self.last_updated_on = kwargs.get('last_updated_on', None) self.registry_artifact_count = kwargs['registry_artifact_count'] self.tag_count = kwargs['tag_count'] - self.writeable_properties = kwargs.get('writeable_properties', None) + self.writeable_properties = kwargs['writeable_properties'] class RepositoryTags(msrest.serialization.Model): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index f278311ffffd..8ac1d4a86a0b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -7,16 +7,14 @@ # -------------------------------------------------------------------------- import datetime -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional from azure.core.exceptions import HttpResponseError import msrest.serialization -from ._container_registry_enums import * - -class AccessToken(msrest.serialization.Model): - """AccessToken. +class AcrAccessToken(msrest.serialization.Model): + """AcrAccessToken. :param access_token: The access token for performing authenticated requests. :type access_token: str @@ -32,7 +30,7 @@ def __init__( access_token: Optional[str] = None, **kwargs ): - super(AccessToken, self).__init__(**kwargs) + super(AcrAccessToken, self).__init__(**kwargs) self.access_token = access_token @@ -119,6 +117,27 @@ def __init__( self.link = link +class AcrRefreshToken(msrest.serialization.Model): + """AcrRefreshToken. + + :param refresh_token: The refresh token to be used for generating access tokens. + :type refresh_token: str + """ + + _attribute_map = { + 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + } + + def __init__( + self, + *, + refresh_token: Optional[str] = None, + **kwargs + ): + super(AcrRefreshToken, self).__init__(**kwargs) + self.refresh_token = refresh_token + + class Annotations(msrest.serialization.Model): """Additional information provided through arbitrary metadata. @@ -862,53 +881,49 @@ def __init__( class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): """Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema. + Variables are only populated by the server, and will be ignored when sending a request. + All required parameters must be populated in order to send to Azure. - :param grant_type: Required. Can take a value of access_token_refresh_token, or access_token, - or refresh_token. Possible values include: "access_token_refresh_token", "access_token", - "refresh_token". - :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType + :ivar grant_type: Required. Can take a value of access_token. Default value: "access_token". + :vartype grant_type: str :param service: Required. Indicates the name of your Azure container registry. :type service: str - :param tenant: AAD tenant associated to the AAD credentials. + :param tenant: Required. AAD tenant associated to the AAD credentials. :type tenant: str - :param refresh_token: AAD refresh token, mandatory when grant_type is - access_token_refresh_token or refresh_token. - :type refresh_token: str - :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token - or access_token. - :type access_token: str + :param aad_accesstoken: Required. AAD access token, mandatory when grant_type is + access_token_refresh_token or access_token. + :type aad_accesstoken: str """ _validation = { - 'grant_type': {'required': True}, + 'grant_type': {'required': True, 'constant': True}, 'service': {'required': True}, + 'tenant': {'required': True}, + 'aad_accesstoken': {'required': True}, } _attribute_map = { 'grant_type': {'key': 'grant_type', 'type': 'str'}, 'service': {'key': 'service', 'type': 'str'}, 'tenant': {'key': 'tenant', 'type': 'str'}, - 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, - 'access_token': {'key': 'access_token', 'type': 'str'}, + 'aad_accesstoken': {'key': 'access_token', 'type': 'str'}, } + grant_type = "access_token" + def __init__( self, *, - grant_type: Union[str, "PostContentSchemaGrantType"], service: str, - tenant: Optional[str] = None, - refresh_token: Optional[str] = None, - access_token: Optional[str] = None, + tenant: str, + aad_accesstoken: str, **kwargs ): super(Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) - self.grant_type = grant_type self.service = service self.tenant = tenant - self.refresh_token = refresh_token - self.access_token = access_token + self.aad_accesstoken = aad_accesstoken class PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema(msrest.serialization.Model): @@ -927,22 +942,22 @@ class PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedS once for multiple scope requests. You obtained this from the Www-Authenticate response header from the challenge. :type scope: str - :param refresh_token: Required. Must be a valid ACR refresh token. - :type refresh_token: str + :param acr_refresh_token: Required. Must be a valid ACR refresh token. + :type acr_refresh_token: str """ _validation = { 'grant_type': {'required': True, 'constant': True}, 'service': {'required': True}, 'scope': {'required': True}, - 'refresh_token': {'required': True}, + 'acr_refresh_token': {'required': True}, } _attribute_map = { 'grant_type': {'key': 'grant_type', 'type': 'str'}, 'service': {'key': 'service', 'type': 'str'}, 'scope': {'key': 'scope', 'type': 'str'}, - 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, + 'acr_refresh_token': {'key': 'refresh_token', 'type': 'str'}, } grant_type = "refresh_token" @@ -952,13 +967,13 @@ def __init__( *, service: str, scope: str, - refresh_token: str, + acr_refresh_token: str, **kwargs ): super(PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) self.service = service self.scope = scope - self.refresh_token = refresh_token + self.acr_refresh_token = acr_refresh_token class Platform(msrest.serialization.Model): @@ -1011,27 +1026,6 @@ def __init__( self.features = features -class RefreshToken(msrest.serialization.Model): - """RefreshToken. - - :param refresh_token: The refresh token to be used for generating access tokens. - :type refresh_token: str - """ - - _attribute_map = { - 'refresh_token': {'key': 'refresh_token', 'type': 'str'}, - } - - def __init__( - self, - *, - refresh_token: Optional[str] = None, - **kwargs - ): - super(RefreshToken, self).__init__(**kwargs) - self.refresh_token = refresh_token - - class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. @@ -1139,7 +1133,7 @@ class RepositoryProperties(msrest.serialization.Model): All required parameters must be populated in order to send to Azure. - :param name: Image name. + :param name: Required. Image name. :type name: str :param created_on: Required. Image created time. :type created_on: ~datetime.datetime @@ -1149,14 +1143,16 @@ class RepositoryProperties(msrest.serialization.Model): :type registry_artifact_count: int :param tag_count: Required. Number of the tags. :type tag_count: int - :param writeable_properties: Changeable attributes. + :param writeable_properties: Required. Changeable attributes. :type writeable_properties: ~azure.containerregistry.models.ContentProperties """ _validation = { + 'name': {'required': True}, 'created_on': {'required': True}, 'registry_artifact_count': {'required': True}, 'tag_count': {'required': True}, + 'writeable_properties': {'required': True}, } _attribute_map = { @@ -1171,12 +1167,12 @@ class RepositoryProperties(msrest.serialization.Model): def __init__( self, *, + name: str, created_on: datetime.datetime, registry_artifact_count: int, tag_count: int, - name: Optional[str] = None, + writeable_properties: "ContentProperties", last_updated_on: Optional[datetime.datetime] = None, - writeable_properties: Optional["ContentProperties"] = None, **kwargs ): super(RepositoryProperties, self).__init__(**kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py index 95b29f5d1bda..c07914265cd0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py @@ -9,13 +9,11 @@ from ._container_registry_operations import ContainerRegistryOperations from ._container_registry_repository_operations import ContainerRegistryRepositoryOperations from ._container_registry_blob_operations import ContainerRegistryBlobOperations -from ._refresh_tokens_operations import RefreshTokensOperations -from ._access_tokens_operations import AccessTokensOperations +from ._authentication_operations import AuthenticationOperations __all__ = [ 'ContainerRegistryOperations', 'ContainerRegistryRepositoryOperations', 'ContainerRegistryBlobOperations', - 'RefreshTokensOperations', - 'AccessTokensOperations', + 'AuthenticationOperations', ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py deleted file mode 100644 index 5b11a2fb1de9..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_access_tokens_operations.py +++ /dev/null @@ -1,171 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import TYPE_CHECKING -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import HttpRequest, HttpResponse - -from .. import models as _models - -if TYPE_CHECKING: - # pylint: disable=unused-import,ungrouped-imports - from typing import Any, Callable, Dict, Generic, Optional, TypeVar - - T = TypeVar('T') - ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] - -class AccessTokensOperations(object): - """AccessTokensOperations operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer): - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - def get( - self, - service, # type: str - scope, # type: str - refresh_token, # type: str - **kwargs # type: Any - ): - # type: (...) -> "_models.AccessToken" - """Exchange ACR Refresh token for an ACR Access Token. - - :param service: Indicates the name of your Azure container registry. - :type service: str - :param scope: Which is expected to be a valid scope, and can be specified more than once for - multiple scope requests. You obtained this from the Www-Authenticate response header from the - challenge. - :type scope: str - :param refresh_token: Must be a valid ACR refresh token. - :type refresh_token: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: AccessToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AccessToken - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - grant_type = "refresh_token" - accept = "application/json" - - # Construct URL - url = self.get.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('AccessToken', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get.metadata = {'url': '/oauth2/token'} # type: ignore - - def get_from_login( - self, - service, # type: str - scope, # type: str - **kwargs # type: Any - ): - # type: (...) -> "_models.AccessToken" - """Exchange Username, Password and Scope an ACR Access Token. - - :param service: Indicates the name of your Azure container registry. - :type service: str - :param scope: Expected to be a valid scope, and can be specified more than once for multiple - scope requests. You can obtain this from the Www-Authenticate response header from the - challenge. - :type scope: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: AccessToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AccessToken - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.AccessToken"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - accept = "application/json" - - # Construct URL - url = self.get_from_login.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - query_parameters['service'] = self._serialize.query("service", service, 'str') - query_parameters['scope'] = self._serialize.query("scope", scope, 'str') - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - request = self._client.get(url, query_parameters, header_parameters) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('AccessToken', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_from_login.metadata = {'url': '/oauth2/token'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py deleted file mode 100644 index 77f400b22aad..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_refresh_tokens_operations.py +++ /dev/null @@ -1,117 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from typing import TYPE_CHECKING -import warnings - -from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error -from azure.core.pipeline import PipelineResponse -from azure.core.pipeline.transport import HttpRequest, HttpResponse - -from .. import models as _models - -if TYPE_CHECKING: - # pylint: disable=unused-import,ungrouped-imports - from typing import Any, Callable, Dict, Generic, Optional, TypeVar, Union - - T = TypeVar('T') - ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] - -class RefreshTokensOperations(object): - """RefreshTokensOperations operations. - - You should not instantiate this class directly. Instead, you should create a Client instance that - instantiates it for you and attaches it as an attribute. - - :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models - :param client: Client for service requests. - :param config: Configuration of service client. - :param serializer: An object model serializer. - :param deserializer: An object model deserializer. - """ - - models = _models - - def __init__(self, client, config, serializer, deserializer): - self._client = client - self._serialize = serializer - self._deserialize = deserializer - self._config = config - - def get_from_exchange( - self, - grant_type, # type: Union[str, "_models.PostContentSchemaGrantType"] - service, # type: str - tenant=None, # type: Optional[str] - refresh_token=None, # type: Optional[str] - access_token=None, # type: Optional[str] - **kwargs # type: Any - ): - # type: (...) -> "_models.RefreshToken" - """Exchange AAD tokens for an ACR refresh Token. - - :param grant_type: Can take a value of access_token_refresh_token, or access_token, or - refresh_token. - :type grant_type: str or ~azure.containerregistry.models.PostContentSchemaGrantType - :param service: Indicates the name of your Azure container registry. - :type service: str - :param tenant: AAD tenant associated to the AAD credentials. - :type tenant: str - :param refresh_token: AAD refresh token, mandatory when grant_type is - access_token_refresh_token or refresh_token. - :type refresh_token: str - :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token - or access_token. - :type access_token: str - :keyword callable cls: A custom type or function that will be passed the direct response - :return: RefreshToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RefreshToken - :raises: ~azure.core.exceptions.HttpResponseError - """ - cls = kwargs.pop('cls', None) # type: ClsType["_models.RefreshToken"] - error_map = { - 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError - } - error_map.update(kwargs.pop('error_map', {})) - content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - accept = "application/json" - - # Construct URL - url = self.get_from_exchange.metadata['url'] # type: ignore - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - url = self._client.format_url(url, **path_format_arguments) - - # Construct parameters - query_parameters = {} # type: Dict[str, Any] - - # Construct headers - header_parameters = {} # type: Dict[str, Any] - header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') - header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - - body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) - pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) - response = pipeline_response.http_response - - if response.status_code not in [200]: - map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) - raise HttpResponseError(response=response, model=error) - - deserialized = self._deserialize('RefreshToken', pipeline_response) - - if cls: - return cls(pipeline_response, deserialized, {}) - - return deserialized - get_from_exchange.metadata = {'url': '/oauth2/exchange'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py deleted file mode 100644 index d532614f5a92..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token.py +++ /dev/null @@ -1,32 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - -class AccessToken(object): - """Base access token for ACR challenge based auth flow""" - - def __init__(self, url, pipeline): - # type: (str, HttpPipeline) -> None - self.reg_login_url = url - - # Exchange ACR Refresh token for an ACR Access Token - def get_access_token_with_response(self, grant_type, service_name, scope, refresh_token): - # type: (str, str, str, str) -> AccessToken - accept = "application/json" - return service.get_access_token( - self.reg_login_url, - grant_type, - service_name, - scope, - refresh_token, - accept, - context - ) - - def get_access_token(self, grant_type, service_name, scope, refresh_token): - # type: (str, str, str, str) -> AcrAccessToken - return "" - - \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py index 287ce627d548..f38c17e25040 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py @@ -3,4 +3,54 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from datetime import datetime +import logging +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from ._access_token import AccessToken + from ._container_registry_token_credential import ContainerRegistryTokenCredential + from ._container_registry_token_request_context import ContainerRegistryTokenRequestContext + +logger = logging.getLogger() + + +class AccessTokenCacheImpl(object): + """An access token cache that supports caching and refreshing a token""" + + # Delay after a refresh to attempt another refresh token + _refresh_delay = 30 + # Offset before token expiry to attempt proactive token refresh + _refresh_offset = 300 + + def __init__(self, token_credential): + # type: (ContainerRegistryTokenCredential) -> None + self._token_credential = token_credential + self.should_refresh = True + + def get_token(self, token_request_context): + # type: (ContainerRegistryTokenContext) -> AccessToken + self.retrieve_token(token_request_context) + + def retrieve_token(self, token_request_context): + # type: (ContainerRegistryTokenContext) -> AccessToken + # Caching implementation will go here + + token_refresh = self._token_credential.get_token(token_request_context) + + return token_refresh + + def _check_if_force_refresh(self, token_request_context): + # type: (ContainerRegistryTokenContext) -> bool + # TODO: Add caching in later previews + return True + + def _process_token_refresh(self, now, fallback): + # type: (datetime, AccessToken) -> AccessToken + return fallback + + def refresh_log(self, cache, now, log): + # type: (AccessToken, datetime, str) -> str + if not cache: + return "." + return "Retry may be attempted after {} seconds.".format(self._refresh_delay) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py index a5b87bec1871..333b811a752c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py @@ -40,8 +40,8 @@ class ContainerRegistryCredentialPolicy(ChallengeAuthenticationPolicy): """Challenge based authentication policy for ACR. This policy is used for getting the AAD Token, refresh token, and access token before performing a call to service. - :param credential: Azure Token Credential for authenticating with Azure - :type credential: TokenCredential + :param TokenCredential credential: Azure Token Credential for authenticating with Azure + :param str url: base URL for ACR account """ BEARER = "Bearer" @@ -70,6 +70,18 @@ def process(self, context, next): if not self.url.startswith("https"): raise ValueError("Token Credentials require a URL using the HTTPS protocol scheme") + http_response = next.process() + auth_header = http_response.headers[self.WWW_AUTHENTICATE] + if http_response.status_code == 401 and auth_header is not None: + return None + + def authorize_request(self, context, token_request_context): + # type: (HttpPipelineContext, ContainerRegistryTokenRequestContext) -> None + context.http_request.headers[self.AUTHORIZATION] = "{} {}".format( + self.BEARER, + self.token_service.get_token() + ) + def on_request(self, request): # type: (PipelineRequest) -> None """Called before the policy sends a request""" diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index 55beeddb5c27..c1f86407e69d 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -2,7 +2,7 @@ ### Settings ``` yaml -input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/1138db4e60f389332df553686145356cce0b79ed/sdk/containerregistry/container-registry/swagger/containerregistry.json +input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/aa5edc4d4cb0298bde52c939a7c948692f3285e1/sdk/containerregistry/container-registry/swagger/containerregistry.json output-folder: "../azure/containerregistry/_generated" namespace: azure.containerregistry no-namespace-folders: true From b14a81ba85c522d2564f10272389279ab07e3fa5 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 23 Mar 2021 16:24:49 -0400 Subject: [PATCH 54/86] forgot new files --- .../containerregistry/_exchange_client.py | 73 ++++++++ .../operations/_authentication_operations.py | 171 +++++++++++++++++ .../operations/_authentication_operations.py | 177 ++++++++++++++++++ .../authentication/_access_tokens_impl.py | 27 +++ .../authentication/_json_web_token.py | 5 + .../authentication/_refresh_token_impl.py | 5 + .../tests/test_exchange_client.py | 53 ++++++ 7 files changed, 511 insertions(+) create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py create mode 100644 sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py new file mode 100644 index 000000000000..6dd5e6624fb4 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -0,0 +1,73 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +import os + +from azure.core.pipeline.policies import SansIOHTTPPolicy + +from ._generated import ContainerRegistry +from ._user_agent import USER_AGENT + + +class ExchangeClientAuthenticationPolicy(SansIOHTTPPolicy): + """Authentication policy for exchange client that does not modify the request""" + + def on_request(self, request): + # type: (PipelineRequest) -> None + pass + + def on_response(self, request, response): + # type: (PipelineRequest, PipelineResponse) -> None + pass + + +class ACRExchangeClient(object): + """Class for handling oauth authentication requests + + :param endpoint: Azure Container Registry endpoint + :type endpoint: str + :param credential: AAD Token for authenticating requests with Azure + :type credential: :class:`azure.identity.DefaultTokenCredential` + + """ + + def __init__(self, endpoint, credential, **kwargs): + if not endpoint.startswith("https://"): + endpoint = "https://" + endpoint + self._credential_scopes = "https://management.core.windows.net/.default" + self._client = ContainerRegistry( + credential=credential, + url=endpoint, + sdk_moniker=USER_AGENT, + authentication_policy=ExchangeClientAuthenticationPolicy(), + credential_scopes=kwargs.pop("credential_scopes", self._credential_scopes), + **kwargs + ) + self._credential = credential + + def get_refresh_token(self, service, tenant): + return self._client.authentication.exchange_aad_token_for_acr_refresh_token( + service=service, + tenant=os.environ["AZURE_TENANT_ID"], + access_token=self._credential.get_token(self._credential_scopes) + ) + + def get_acr_access_token(self, service, scope, refresh_token): + return self.authentication.access_tokens.get(service, scope, refresh_token) + + def __enter__(self): + self._client.__enter__() + return self + + def __exit__(self, *args): + self._client.__exit__(*args) + + def close(self): + # type: () -> None + """Close sockets opened by the client. + Calling this method is unnecessary when using the client as a context manager. + """ + self._client.close() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py new file mode 100644 index 000000000000..34fd69b567e2 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py @@ -0,0 +1,171 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import Any, Callable, Dict, Generic, Optional, TypeVar +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest + +from ... import models as _models + +T = TypeVar('T') +ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] + +class AuthenticationOperations: + """AuthenticationOperations async operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer) -> None: + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + async def exchange_aad_token_for_acr_refresh_token( + self, + service: str, + tenant: str, + access_token: str, + **kwargs + ) -> "_models.AcrRefreshToken": + """Exchange AAD tokens for an ACR refresh Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param tenant: AAD tenant associated to the AAD credentials. + :type tenant: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AcrRefreshToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AcrRefreshToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrRefreshToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "access_token" + accept = "application/json" + + # Construct URL + url = self.exchange_aad_token_for_acr_refresh_token.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AcrRefreshToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + exchange_aad_token_for_acr_refresh_token.metadata = {'url': '/oauth2/exchange'} # type: ignore + + async def exchange_acr_refresh_token_for_acr_access_token( + self, + service: str, + scope: str, + refresh_token: str, + **kwargs + ) -> "_models.AcrAccessToken": + """Exchange ACR Refresh token for an ACR Access Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Which is expected to be a valid scope, and can be specified more than once for + multiple scope requests. You obtained this from the Www-Authenticate response header from the + challenge. + :type scope: str + :param refresh_token: Must be a valid ACR refresh token. + :type refresh_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AcrAccessToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AcrAccessToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrAccessToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "refresh_token" + accept = "application/json" + + # Construct URL + url = self.exchange_acr_refresh_token_for_acr_access_token.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AcrAccessToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + exchange_acr_refresh_token_for_acr_access_token.metadata = {'url': '/oauth2/token'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py new file mode 100644 index 000000000000..b32026f9e4f3 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py @@ -0,0 +1,177 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from typing import TYPE_CHECKING +import warnings + +from azure.core.exceptions import ClientAuthenticationError, HttpResponseError, ResourceExistsError, ResourceNotFoundError, map_error +from azure.core.pipeline import PipelineResponse +from azure.core.pipeline.transport import HttpRequest, HttpResponse + +from .. import models as _models + +if TYPE_CHECKING: + # pylint: disable=unused-import,ungrouped-imports + from typing import Any, Callable, Dict, Generic, Optional, TypeVar + + T = TypeVar('T') + ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] + +class AuthenticationOperations(object): + """AuthenticationOperations operations. + + You should not instantiate this class directly. Instead, you should create a Client instance that + instantiates it for you and attaches it as an attribute. + + :ivar models: Alias to model classes used in this operation group. + :type models: ~azure.containerregistry.models + :param client: Client for service requests. + :param config: Configuration of service client. + :param serializer: An object model serializer. + :param deserializer: An object model deserializer. + """ + + models = _models + + def __init__(self, client, config, serializer, deserializer): + self._client = client + self._serialize = serializer + self._deserialize = deserializer + self._config = config + + def exchange_aad_token_for_acr_refresh_token( + self, + service, # type: str + tenant, # type: str + access_token, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.AcrRefreshToken" + """Exchange AAD tokens for an ACR refresh Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param tenant: AAD tenant associated to the AAD credentials. + :type tenant: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AcrRefreshToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AcrRefreshToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrRefreshToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "access_token" + accept = "application/json" + + # Construct URL + url = self.exchange_aad_token_for_acr_refresh_token.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AcrRefreshToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + exchange_aad_token_for_acr_refresh_token.metadata = {'url': '/oauth2/exchange'} # type: ignore + + def exchange_acr_refresh_token_for_acr_access_token( + self, + service, # type: str + scope, # type: str + refresh_token, # type: str + **kwargs # type: Any + ): + # type: (...) -> "_models.AcrAccessToken" + """Exchange ACR Refresh token for an ACR Access Token. + + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Which is expected to be a valid scope, and can be specified more than once for + multiple scope requests. You obtained this from the Www-Authenticate response header from the + challenge. + :type scope: str + :param refresh_token: Must be a valid ACR refresh token. + :type refresh_token: str + :keyword callable cls: A custom type or function that will be passed the direct response + :return: AcrAccessToken, or the result of cls(response) + :rtype: ~azure.containerregistry.models.AcrAccessToken + :raises: ~azure.core.exceptions.HttpResponseError + """ + cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrAccessToken"] + error_map = { + 401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError + } + error_map.update(kwargs.pop('error_map', {})) + content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "refresh_token" + accept = "application/json" + + # Construct URL + url = self.exchange_acr_refresh_token_for_acr_access_token.metadata['url'] # type: ignore + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + url = self._client.format_url(url, **path_format_arguments) + + # Construct parameters + query_parameters = {} # type: Dict[str, Any] + + # Construct headers + header_parameters = {} # type: Dict[str, Any] + header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') + header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') + + body_content_kwargs = {} # type: Dict[str, Any] + body_content = self._serialize.body(grant_type, 'str') + body_content_kwargs['content'] = body_content + request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + raise HttpResponseError(response=response, model=error) + + deserialized = self._deserialize('AcrAccessToken', pipeline_response) + + if cls: + return cls(pipeline_response, deserialized, {}) + + return deserialized + exchange_acr_refresh_token_for_acr_access_token.metadata = {'url': '/oauth2/token'} # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py new file mode 100644 index 000000000000..e22043bd6dba --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py @@ -0,0 +1,27 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + + +class AccessTokensImpl(object): + """Provides access to all the operations defined in AcessTokensService""" + + def __init__(self, url, pipeline, client): + # type: (str, HttpPipeline, ContainerRegistry) -> None + self.url = url + self.service = pipeline + + def get_access_token_with_response(self, grant_type, service_name, scope, refresh_token): + # type: (str, str, str, str) -> AcrAccessToken + return self.service.get_access_token(self.url, grant_type, service_name, scope, refresh_token) + + def get_access_token(self, grant_type, service_name, scope, refresh_token): + # type: (str, str, str, str) -> AccessToken + return self.get_access_token_with_response(grant_type, service_name, scope, refresh_token) + + def get_access_token(self, url, grant_type, service, scope, refresh_token): + # type: (str, str, str, str, str) -> AcrAccessToken + _models_access_token = self._client.access_tokens.get(service, scope, refresh_token) + return AcrAccessToken._from_generated(_models_access_token) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py new file mode 100644 index 000000000000..15227605df4f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py @@ -0,0 +1,5 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py new file mode 100644 index 000000000000..15227605df4f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py @@ -0,0 +1,5 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py new file mode 100644 index 000000000000..1c9c6b867601 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py @@ -0,0 +1,53 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools +import os +import pytest +import six + +from devtools_testutils import AzureTestCase, PowerShellPreparer + +from azure.containerregistry import ( + ContainerRegistryClient, + ContainerRegistryUserCredential, + DeletedRepositoryResult, + ACRExchangeClient +) +from azure.core.exceptions import ResourceNotFoundError +from azure.core.paging import ItemPaged +from azure.identity import DefaultAzureCredential + +from testcase import ContainerRegistryTestClass + + +acr_preparer = functools.partial( + PowerShellPreparer, + "containerregistry", + containerregistry_baseurl="fake_url.azurecr.io", +) + + +class TestContainerRegistryClient(AzureTestCase, ContainerRegistryTestClass): + + def create_exchange_client(self, endpoint): + return self.create_client_from_credential( + ACRExchangeClient, + credential=self.get_credential(ACRExchangeClient), + endpoint=endpoint, + ) + + @pytest.mark.live_test_only + @acr_preparer() + def test_exchange_client(self, containerregistry_baseurl): + client = self.create_exchange_client(containerregistry_baseurl) + + service = "seankane.azurecr.io" + scope = "repository:hello-world:metadata_read" + + refresh = client.get_refresh_token(service, os.environ["AZURE_TENANT_ID"]) + + assert refresh is not None + print(refresh) From fc88483fa1807b057cdba4aad6f490c0d3ce7320 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 08:58:50 -0400 Subject: [PATCH 55/86] working auth policy using challenge --- .../_authentication_policy.py | 89 +++++++++ .../azure/containerregistry/_base_client.py | 5 +- .../containerregistry/_exchange_client.py | 76 +++++++- .../containerregistry/_generated/__init__.py | 4 +- .../_generated/_configuration.py | 4 +- .../_generated/_container_registry.py | 12 +- .../_generated/aio/__init__.py | 4 +- .../_generated/aio/_configuration.py | 4 +- .../_generated/aio/_container_registry.py | 12 +- .../_generated/aio/operations/__init__.py | 4 +- .../operations/_authentication_operations.py | 49 ++--- .../_container_registry_blob_operations.py | 6 +- .../_container_registry_operations.py | 10 +- ...ontainer_registry_repository_operations.py | 26 ++- .../_generated/models/__init__.py | 4 +- .../_generated/models/_models.py | 72 ++++---- .../_generated/models/_models_py3.py | 72 ++++---- .../_generated/operations/__init__.py | 4 +- .../operations/_authentication_operations.py | 51 ++---- .../_container_registry_blob_operations.py | 6 +- .../_container_registry_operations.py | 10 +- ...ontainer_registry_repository_operations.py | 26 ++- .../azure-containerregistry/swagger/README.md | 12 +- ...nge_client.test_auth_policy_in_action.yaml | 169 ++++++++++++++++++ .../tests/test_exchange_client.py | 36 +++- 25 files changed, 519 insertions(+), 248 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index 5f676270b748..f35353936d21 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -9,11 +9,34 @@ from typing import TYPE_CHECKING from azure.core.pipeline.policies import SansIOHTTPPolicy +from azure.core.pipeline.policies import HTTPPolicy + +from ._exchange_client import ACRExchangeClient if TYPE_CHECKING: from azure.core.pipeline import PipelineRequest +def _enforce_https(request): + # type: (PipelineRequest) -> None + """Raise ServiceRequestError if the request URL is non-HTTPS and the sender did not specify "enforce_https=False" + """ + + # move 'enforce_https' from options to context so it persists + # across retries but isn't passed to a transport implementation + option = request.context.options.pop("enforce_https", None) + + # True is the default setting; we needn't preserve an explicit opt in to the default behavior + if option is False: + request.context["enforce_https"] = option + + enforce_https = request.context.get("enforce_https", True) + if enforce_https and not request.http_request.url.lower().startswith("https"): + raise ServiceRequestError( + "Bearer token authentication is not permitted for non-TLS protected (non-https) URLs." + ) + + class ContainerRegistryUserCredential(object): """Credential used to authenticate with Container Registry service""" @@ -62,3 +85,69 @@ def __init__(self, credential, url, pipeline): self.credential = credential self.url = url self.pipeline = pipeline + + +class ContainerRegistryChallengePolicy(HTTPPolicy): + """Authentication policy for ACR which accepts a challenge""" + + def __init__(self, credential, *scopes, **kwargs): + # type: (TokenCredential, *str, **Any) -> None + super(HTTPPolicy, self).__init__() + self._scopes = ["https://management.core.windows.net/.default"] + self._credential = credential + self._token = None # type: Optional[AccessToken] + self._exchange_client = ACRExchangeClient("seankane.azurecr.io", self._credential) + + def need_new_token(self): + # type: () -> bool + return True + + def on_request(self, request): + # type: (PipelineRequest) -> None + """Called before the policy sends a request. + The base implementation authorizes the request with a bearer token. + :param ~azure.core.pipeline.PipelineRequest request: the request + """ + + if self._token is None or self._need_new_token(): + self._token = self._credential.get_token(*self._scopes) + try: + self._token = self._token.token + except AttributeError: + pass + request.http_request.headers["Authorization"] = "Bearer " + self._token + + def send(self, request): + # type: (PipelineRequest) -> PipelineResponse + """Authorizes a request with a bearer token, possibly handling an authentication challenge + :param ~azure.core.pipeline.PipelineRequest request: the request + """ + _enforce_https(request) + + self.on_request(request) + + response = self.next.send(request) + + if response.http_response.status_code == 401: + self._token = None # any cached token is invalid + challenge = response.http_response.headers.get("WWW-Authenticate") + if challenge and self.on_challenge(request, response, challenge): + response = self.next.send(request) + + return response + + def on_challenge(self, request, response, challenge): + # type: (PipelineRequest, PipelineResponse, str) -> bool + """Authorize request according to an authentication challenge + This method is called when the resource provider responds 401 with a WWW-Authenticate header. + :param ~azure.core.pipeline.PipelineRequest request: the request which elicited an authentication challenge + :param ~azure.core.pipeline.PipelineResponse response: the resource provider's response + :param str challenge: response's WWW-Authenticate header, unparsed. It may contain multiple challenges. + :returns: a bool indicating whether the policy should send the request + """ + # pylint:disable=unused-argument,no-self-use + + access_token = self._exchange_client.get_acr_access_token(challenge) + self._token = access_token + request.http_request.headers["Authorization"] = "Bearer " + self._token + return access_token is not None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 32eb9b968fc5..ea42f2adf696 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -6,7 +6,7 @@ from enum import Enum -from ._authentication_policy import ContainerRegistryUserCredentialPolicy +from ._authentication_policy import ContainerRegistryUserCredentialPolicy, ContainerRegistryChallengePolicy from ._generated import ContainerRegistry from ._user_agent import USER_AGENT @@ -28,7 +28,8 @@ class ContainerRegistryBaseClient(object): """ def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-method-missing-type-annotations - auth_policy = ContainerRegistryUserCredentialPolicy(credential=credential) + # auth_policy = ContainerRegistryUserCredentialPolicy(credential=credential) + auth_policy = ContainerRegistryChallengePolicy(credential) self._client = ContainerRegistry( credential=credential, url=endpoint, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py index 6dd5e6624fb4..3312b7facb63 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -3,12 +3,15 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ - +import json import os +import re from azure.core.pipeline.policies import SansIOHTTPPolicy +from azure.core.pipeline.transport import HttpRequest from ._generated import ContainerRegistry +from ._generated.models import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema from ._user_agent import USER_AGENT @@ -34,9 +37,17 @@ class ACRExchangeClient(object): """ + BEARER = "Bearer" + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + WWW_AUTHENTICATE = "WWW-Authenticate" + SCOPE_PARAMETER = "scope" + SERVICE_PARAMETER = "service" + AUTHORIZATION = "Authorization" + def __init__(self, endpoint, credential, **kwargs): if not endpoint.startswith("https://"): endpoint = "https://" + endpoint + self._endpoint = endpoint self._credential_scopes = "https://management.core.windows.net/.default" self._client = ContainerRegistry( credential=credential, @@ -48,15 +59,48 @@ def __init__(self, endpoint, credential, **kwargs): ) self._credential = credential - def get_refresh_token(self, service, tenant): - return self._client.authentication.exchange_aad_token_for_acr_refresh_token( - service=service, - tenant=os.environ["AZURE_TENANT_ID"], - access_token=self._credential.get_token(self._credential_scopes) - ) + def get_acr_access_token(self, challenge): + parsed_challenge = self._parse_challenge(challenge) + refresh_token = self.exchange_aad_token_for_refresh_token(**parsed_challenge) + return self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) + + def exchange_aad_token_for_refresh_token(self, service=None, scope=None, **kwargs): + + body = """grant_type=access_token&service={}&access_token={}""".format(service, self._credential.get_token(self._credential_scopes).token) + + headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} + request = HttpRequest("POST", self._endpoint + "/oauth2/exchange", headers=headers, data=body) + + resp = self._client._client._pipeline.run(request) + refresh_token = resp.http_response.internal_response.content + return json.loads(refresh_token)["refresh_token"] + + def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): - def get_acr_access_token(self, service, scope, refresh_token): - return self.authentication.access_tokens.get(service, scope, refresh_token) + body = """grant_type=refresh_token&service={}&scope={}&refresh_token={}""".format( + service, scope, refresh_token) + + headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} + request = HttpRequest("POST", self._endpoint + "/oauth2/token", headers=headers, data=body) + + resp = self._client._client._pipeline.run(request) + + access_token = resp.http_response.internal_response.content + return json.loads(access_token)["access_token"] + + def _parse_challenge(self, header): + # type: (str) -> Dict[str, Any] + """Parse challenge header into service and scope""" + if header.startswith(self.BEARER): + challenge_params = header[len(self.BEARER)+1:] + + matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) + self._clean(matches) + ret = {} + for i in range(0, len(matches), 2): + ret[matches[i]] = matches[i+1] + + return ret def __enter__(self): self._client.__enter__() @@ -71,3 +115,17 @@ def close(self): Calling this method is unnecessary when using the client as a context manager. """ self._client.close() + + def _clean(self, matches): + # type: (List[str]) -> None + while True: + try: + matches.remove('') + except ValueError: + break + + while True: + try: + matches.remove(',') + except ValueError: + return diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py index 930c62f8adda..f8de90df3085 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/__init__.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py index 0a03c9b6323b..b653ee26f06c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_configuration.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py index fda89baf0d9b..e25449264e14 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- @@ -29,13 +27,13 @@ class ContainerRegistry(object): """Metadata API definition for the Azure Container Registry runtime. :ivar container_registry: ContainerRegistryOperations operations - :vartype container_registry: azure.containerregistry.operations.ContainerRegistryOperations + :vartype container_registry: container_registry.operations.ContainerRegistryOperations :ivar container_registry_repository: ContainerRegistryRepositoryOperations operations - :vartype container_registry_repository: azure.containerregistry.operations.ContainerRegistryRepositoryOperations + :vartype container_registry_repository: container_registry.operations.ContainerRegistryRepositoryOperations :ivar container_registry_blob: ContainerRegistryBlobOperations operations - :vartype container_registry_blob: azure.containerregistry.operations.ContainerRegistryBlobOperations + :vartype container_registry_blob: container_registry.operations.ContainerRegistryBlobOperations :ivar authentication: AuthenticationOperations operations - :vartype authentication: azure.containerregistry.operations.AuthenticationOperations + :vartype authentication: container_registry.operations.AuthenticationOperations :param url: Registry login URL. :type url: str """ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py index 00c3ae0ed2bb..4f2f507e46a7 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/__init__.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py index d54574b49de1..165093e7dccd 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_configuration.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py index fb867d402c3b..ed0014488c0f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- @@ -24,13 +22,13 @@ class ContainerRegistry(object): """Metadata API definition for the Azure Container Registry runtime. :ivar container_registry: ContainerRegistryOperations operations - :vartype container_registry: azure.containerregistry.aio.operations.ContainerRegistryOperations + :vartype container_registry: container_registry.aio.operations.ContainerRegistryOperations :ivar container_registry_repository: ContainerRegistryRepositoryOperations operations - :vartype container_registry_repository: azure.containerregistry.aio.operations.ContainerRegistryRepositoryOperations + :vartype container_registry_repository: container_registry.aio.operations.ContainerRegistryRepositoryOperations :ivar container_registry_blob: ContainerRegistryBlobOperations operations - :vartype container_registry_blob: azure.containerregistry.aio.operations.ContainerRegistryBlobOperations + :vartype container_registry_blob: container_registry.aio.operations.ContainerRegistryBlobOperations :ivar authentication: AuthenticationOperations operations - :vartype authentication: azure.containerregistry.aio.operations.AuthenticationOperations + :vartype authentication: container_registry.aio.operations.AuthenticationOperations :param url: Registry login URL. :type url: str """ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py index c07914265cd0..94b714e4118b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/__init__.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py index 34fd69b567e2..27f0c12f8146 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import Any, Callable, Dict, Generic, Optional, TypeVar @@ -24,7 +22,7 @@ class AuthenticationOperations: instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. @@ -41,23 +39,16 @@ def __init__(self, client, config, serializer, deserializer) -> None: async def exchange_aad_token_for_acr_refresh_token( self, - service: str, - tenant: str, - access_token: str, + aad_accesstoken: Optional["_models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] = None, **kwargs ) -> "_models.AcrRefreshToken": """Exchange AAD tokens for an ACR refresh Token. - :param service: Indicates the name of your Azure container registry. - :type service: str - :param tenant: AAD tenant associated to the AAD credentials. - :type tenant: str - :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token - or access_token. - :type access_token: str + :param aad_accesstoken: + :type aad_accesstoken: ~container_registry.models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrRefreshToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AcrRefreshToken + :rtype: ~container_registry.models.AcrRefreshToken :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrRefreshToken"] @@ -66,7 +57,6 @@ async def exchange_aad_token_for_acr_refresh_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - grant_type = "access_token" accept = "application/json" # Construct URL @@ -85,7 +75,10 @@ async def exchange_aad_token_for_acr_refresh_token( header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') + if aad_accesstoken is not None: + body_content = self._serialize.body(aad_accesstoken, 'Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema') + else: + body_content = None body_content_kwargs['content'] = body_content request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) @@ -106,24 +99,16 @@ async def exchange_aad_token_for_acr_refresh_token( async def exchange_acr_refresh_token_for_acr_access_token( self, - service: str, - scope: str, - refresh_token: str, + acr_refresh_token: Optional["_models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] = None, **kwargs ) -> "_models.AcrAccessToken": """Exchange ACR Refresh token for an ACR Access Token. - :param service: Indicates the name of your Azure container registry. - :type service: str - :param scope: Which is expected to be a valid scope, and can be specified more than once for - multiple scope requests. You obtained this from the Www-Authenticate response header from the - challenge. - :type scope: str - :param refresh_token: Must be a valid ACR refresh token. - :type refresh_token: str + :param acr_refresh_token: + :type acr_refresh_token: ~container_registry.models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrAccessToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AcrAccessToken + :rtype: ~container_registry.models.AcrAccessToken :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrAccessToken"] @@ -132,7 +117,6 @@ async def exchange_acr_refresh_token_for_acr_access_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - grant_type = "refresh_token" accept = "application/json" # Construct URL @@ -151,7 +135,10 @@ async def exchange_acr_refresh_token_for_acr_access_token( header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') + if acr_refresh_token is not None: + body_content = self._serialize.body(acr_refresh_token, 'PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema') + else: + body_content = None body_content_kwargs['content'] = body_content request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py index 3afa8d85d4b0..21b1b334411c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import Any, Callable, Dict, Generic, IO, Optional, TypeVar @@ -24,7 +22,7 @@ class ContainerRegistryBlobOperations: instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py index ac829d331718..539ca7ae23af 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar @@ -25,7 +23,7 @@ class ContainerRegistryOperations: instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. @@ -101,7 +99,7 @@ def get_repositories( :type n: int :keyword callable cls: A custom type or function that will be passed the direct response :return: An iterator like instance of either Repositories or the result of cls(response) - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.containerregistry.models.Repositories] + :rtype: ~azure.core.async_paging.AsyncItemPaged[~container_registry.models.Repositories] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.Repositories"] @@ -177,7 +175,7 @@ async def delete_repository( :type name: str :keyword callable cls: A custom type or function that will be passed the direct response :return: DeleteRepositoryResult, or the result of cls(response) - :rtype: ~azure.containerregistry.models.DeleteRepositoryResult + :rtype: ~container_registry.models.DeleteRepositoryResult :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.DeleteRepositoryResult"] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index 514fe201861b..a5e395308f25 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import Any, AsyncIterable, Callable, Dict, Generic, Optional, TypeVar @@ -25,7 +23,7 @@ class ContainerRegistryRepositoryOperations: instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. @@ -59,7 +57,7 @@ async def get_manifest( :type accept: str :keyword callable cls: A custom type or function that will be passed the direct response :return: Manifest, or the result of cls(response) - :rtype: ~azure.containerregistry.models.Manifest + :rtype: ~container_registry.models.Manifest :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.Manifest"] @@ -119,7 +117,7 @@ async def create_manifest( :param reference: A tag or a digest, pointing to a specific image. :type reference: str :param payload: Manifest body, can take v1 or v2 values depending on accept header. - :type payload: ~azure.containerregistry.models.Manifest + :type payload: ~container_registry.models.Manifest :keyword callable cls: A custom type or function that will be passed the direct response :return: object, or the result of cls(response) :rtype: object @@ -240,7 +238,7 @@ async def get_properties( :type name: str :keyword callable cls: A custom type or function that will be passed the direct response :return: RepositoryProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RepositoryProperties + :rtype: ~container_registry.models.RepositoryProperties :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] @@ -293,7 +291,7 @@ async def set_properties( :param name: Name of the image (including the namespace). :type name: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties + :type value: ~container_registry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -367,7 +365,7 @@ def get_tags( :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response :return: An iterator like instance of either TagList or the result of cls(response) - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.containerregistry.models.TagList] + :rtype: ~azure.core.async_paging.AsyncItemPaged[~container_registry.models.TagList] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] @@ -452,7 +450,7 @@ async def get_tag_properties( :type reference: str :keyword callable cls: A custom type or function that will be passed the direct response :return: TagProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagProperties + :rtype: ~container_registry.models.TagProperties :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.TagProperties"] @@ -509,7 +507,7 @@ async def update_tag_attributes( :param reference: Tag name. :type reference: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties + :type value: ~container_registry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -635,7 +633,7 @@ def get_manifests( :type orderby: str :keyword callable cls: A custom type or function that will be passed the direct response :return: An iterator like instance of either AcrManifests or the result of cls(response) - :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.containerregistry.models.AcrManifests] + :rtype: ~azure.core.async_paging.AsyncItemPaged[~container_registry.models.AcrManifests] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrManifests"] @@ -718,7 +716,7 @@ async def get_registry_artifact_properties( :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response :return: RegistryArtifactProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RegistryArtifactProperties + :rtype: ~container_registry.models.RegistryArtifactProperties :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.RegistryArtifactProperties"] @@ -775,7 +773,7 @@ async def update_manifest_attributes( :param digest: Digest of a BLOB. :type digest: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties + :type value: ~container_registry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py index 79172e17ea39..fb30b2eeac5e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 125c967698f0..7dddb2d55637 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- @@ -60,7 +58,7 @@ class AcrErrors(msrest.serialization.Model): """Acr error response describing why the operation failed. :param errors: Array of detailed error. - :type errors: list[~azure.containerregistry.models.AcrErrorInfo] + :type errors: list[~container_registry.models.AcrErrorInfo] """ _attribute_map = { @@ -81,7 +79,7 @@ class AcrManifests(msrest.serialization.Model): :param repository: Image name. :type repository: str :param manifests: List of manifests. - :type manifests: list[~azure.containerregistry.models.ManifestAttributesBase] + :type manifests: list[~container_registry.models.ManifestAttributesBase] :param link: :type link: str """ @@ -258,7 +256,7 @@ class Descriptor(msrest.serialization.Model): :param urls: Specifies a list of URIs from which this object may be downloaded. :type urls: list[str] :param annotations: Additional information provided through arbitrary metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations """ _attribute_map = { @@ -323,7 +321,7 @@ class ImageSignature(msrest.serialization.Model): """Signature of a signed manifest. :param header: A JSON web signature. - :type header: ~azure.containerregistry.models.JWK + :type header: ~container_registry.models.JWK :param signature: A signature for the image manifest, signed by a libtrust private key. :type signature: str :param protected: The signed protected header. @@ -350,7 +348,7 @@ class JWK(msrest.serialization.Model): """A JSON web signature. :param jwk: JSON web key parameter. - :type jwk: ~azure.containerregistry.models.JWKHeader + :type jwk: ~container_registry.models.JWKHeader :param alg: The algorithm used to sign or encrypt the JWT. :type alg: str """ @@ -441,12 +439,11 @@ class ManifestAttributesBase(msrest.serialization.Model): :param operating_system: Operating system. :type operating_system: str :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: - list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] :param tags: Required. A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ContentProperties + :type manifest_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -487,7 +484,7 @@ class ManifestAttributesManifest(msrest.serialization.Model): """List of manifest attributes. :param references: List of manifest attributes details. - :type references: list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :type references: list[~container_registry.models.ManifestAttributesManifestReferences] :param quarantine_tag: Quarantine tag name. :type quarantine_tag: str """ @@ -588,7 +585,7 @@ class ManifestList(Manifest): :param media_type: Media type for this Manifest. :type media_type: str :param manifests: List of V2 image layer information. - :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :type manifests: list[~container_registry.models.ManifestListAttributes] """ _attribute_map = { @@ -620,7 +617,7 @@ class ManifestListAttributes(msrest.serialization.Model): :param platform: The platform object describes the platform which the image in the manifest runs on. A full list of valid operating system and architecture values are listed in the Go language documentation for $GOOS and $GOARCH. - :type platform: ~azure.containerregistry.models.Platform + :type platform: ~container_registry.models.Platform """ _attribute_map = { @@ -649,13 +646,13 @@ class ManifestWrapper(Manifest): :param media_type: Media type for this Manifest. :type media_type: str :param manifests: (ManifestList, OCIIndex) List of V2 image layer information. - :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :type manifests: list[~container_registry.models.ManifestListAttributes] :param config: (V2, OCI) Image config descriptor. - :type config: ~azure.containerregistry.models.Descriptor + :type config: ~container_registry.models.Descriptor :param layers: (V2, OCI) List of V2 image layer information. - :type layers: list[~azure.containerregistry.models.Descriptor] + :type layers: list[~container_registry.models.Descriptor] :param annotations: (OCI, OCIIndex) Additional metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations :param architecture: (V1) CPU architecture. :type architecture: str :param name: (V1) Image name. @@ -663,11 +660,11 @@ class ManifestWrapper(Manifest): :param tag: (V1) Image tag. :type tag: str :param fs_layers: (V1) List of layer information. - :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :type fs_layers: list[~container_registry.models.FsLayer] :param history: (V1) Image history. - :type history: list[~azure.containerregistry.models.History] + :type history: list[~container_registry.models.History] :param signatures: (V1) Image signature. - :type signatures: list[~azure.containerregistry.models.ImageSignature] + :type signatures: list[~container_registry.models.ImageSignature] """ _attribute_map = { @@ -709,9 +706,9 @@ class OCIIndex(Manifest): :param schema_version: Schema version. :type schema_version: int :param manifests: List of OCI image layer information. - :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :type manifests: list[~container_registry.models.ManifestListAttributes] :param annotations: Additional information provided through arbitrary metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations """ _attribute_map = { @@ -735,11 +732,11 @@ class OCIManifest(Manifest): :param schema_version: Schema version. :type schema_version: int :param config: V2 image config descriptor. - :type config: ~azure.containerregistry.models.Descriptor + :type config: ~container_registry.models.Descriptor :param layers: List of V2 image layer information. - :type layers: list[~azure.containerregistry.models.Descriptor] + :type layers: list[~container_registry.models.Descriptor] :param annotations: Additional information provided through arbitrary metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations """ _attribute_map = { @@ -912,12 +909,11 @@ class RegistryArtifactProperties(msrest.serialization.Model): :param operating_system: Operating system. :type operating_system: str :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: - list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] :param tags: Required. A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ContentProperties + :type manifest_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -996,7 +992,7 @@ class RepositoryProperties(msrest.serialization.Model): :param tag_count: Required. Number of the tags. :type tag_count: int :param writeable_properties: Required. Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ContentProperties + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -1066,7 +1062,7 @@ class TagAttributesBase(msrest.serialization.Model): :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime :param writeable_properties: Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ContentProperties + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -1121,7 +1117,7 @@ class TagList(msrest.serialization.Model): :param repository: Required. Image name. :type repository: str :param tags: A set of tags. List of tag attribute details. - :type tags: list[~azure.containerregistry.models.TagAttributesBase] + :type tags: list[~container_registry.models.TagAttributesBase] :param link: :type link: str """ @@ -1162,7 +1158,7 @@ class TagProperties(msrest.serialization.Model): :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime :param writeable_properties: Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ContentProperties + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -1205,11 +1201,11 @@ class V1Manifest(Manifest): :param tag: Image tag. :type tag: str :param fs_layers: List of layer information. - :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :type fs_layers: list[~container_registry.models.FsLayer] :param history: Image history. - :type history: list[~azure.containerregistry.models.History] + :type history: list[~container_registry.models.History] :param signatures: Image signature. - :type signatures: list[~azure.containerregistry.models.ImageSignature] + :type signatures: list[~container_registry.models.ImageSignature] """ _attribute_map = { @@ -1243,9 +1239,9 @@ class V2Manifest(Manifest): :param media_type: Media type for this Manifest. :type media_type: str :param config: V2 image config descriptor. - :type config: ~azure.containerregistry.models.Descriptor + :type config: ~container_registry.models.Descriptor :param layers: List of V2 image layer information. - :type layers: list[~azure.containerregistry.models.Descriptor] + :type layers: list[~container_registry.models.Descriptor] """ _attribute_map = { diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index 8ac1d4a86a0b..d9bd66c77216 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- @@ -69,7 +67,7 @@ class AcrErrors(msrest.serialization.Model): """Acr error response describing why the operation failed. :param errors: Array of detailed error. - :type errors: list[~azure.containerregistry.models.AcrErrorInfo] + :type errors: list[~container_registry.models.AcrErrorInfo] """ _attribute_map = { @@ -92,7 +90,7 @@ class AcrManifests(msrest.serialization.Model): :param repository: Image name. :type repository: str :param manifests: List of manifests. - :type manifests: list[~azure.containerregistry.models.ManifestAttributesBase] + :type manifests: list[~container_registry.models.ManifestAttributesBase] :param link: :type link: str """ @@ -297,7 +295,7 @@ class Descriptor(msrest.serialization.Model): :param urls: Specifies a list of URIs from which this object may be downloaded. :type urls: list[str] :param annotations: Additional information provided through arbitrary metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations """ _attribute_map = { @@ -372,7 +370,7 @@ class ImageSignature(msrest.serialization.Model): """Signature of a signed manifest. :param header: A JSON web signature. - :type header: ~azure.containerregistry.models.JWK + :type header: ~container_registry.models.JWK :param signature: A signature for the image manifest, signed by a libtrust private key. :type signature: str :param protected: The signed protected header. @@ -403,7 +401,7 @@ class JWK(msrest.serialization.Model): """A JSON web signature. :param jwk: JSON web key parameter. - :type jwk: ~azure.containerregistry.models.JWKHeader + :type jwk: ~container_registry.models.JWKHeader :param alg: The algorithm used to sign or encrypt the JWT. :type alg: str """ @@ -505,12 +503,11 @@ class ManifestAttributesBase(msrest.serialization.Model): :param operating_system: Operating system. :type operating_system: str :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: - list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] :param tags: Required. A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ContentProperties + :type manifest_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -561,7 +558,7 @@ class ManifestAttributesManifest(msrest.serialization.Model): """List of manifest attributes. :param references: List of manifest attributes details. - :type references: list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :type references: list[~container_registry.models.ManifestAttributesManifestReferences] :param quarantine_tag: Quarantine tag name. :type quarantine_tag: str """ @@ -676,7 +673,7 @@ class ManifestList(Manifest): :param media_type: Media type for this Manifest. :type media_type: str :param manifests: List of V2 image layer information. - :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :type manifests: list[~container_registry.models.ManifestListAttributes] """ _attribute_map = { @@ -712,7 +709,7 @@ class ManifestListAttributes(msrest.serialization.Model): :param platform: The platform object describes the platform which the image in the manifest runs on. A full list of valid operating system and architecture values are listed in the Go language documentation for $GOOS and $GOARCH. - :type platform: ~azure.containerregistry.models.Platform + :type platform: ~container_registry.models.Platform """ _attribute_map = { @@ -746,13 +743,13 @@ class ManifestWrapper(Manifest): :param media_type: Media type for this Manifest. :type media_type: str :param manifests: (ManifestList, OCIIndex) List of V2 image layer information. - :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :type manifests: list[~container_registry.models.ManifestListAttributes] :param config: (V2, OCI) Image config descriptor. - :type config: ~azure.containerregistry.models.Descriptor + :type config: ~container_registry.models.Descriptor :param layers: (V2, OCI) List of V2 image layer information. - :type layers: list[~azure.containerregistry.models.Descriptor] + :type layers: list[~container_registry.models.Descriptor] :param annotations: (OCI, OCIIndex) Additional metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations :param architecture: (V1) CPU architecture. :type architecture: str :param name: (V1) Image name. @@ -760,11 +757,11 @@ class ManifestWrapper(Manifest): :param tag: (V1) Image tag. :type tag: str :param fs_layers: (V1) List of layer information. - :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :type fs_layers: list[~container_registry.models.FsLayer] :param history: (V1) Image history. - :type history: list[~azure.containerregistry.models.History] + :type history: list[~container_registry.models.History] :param signatures: (V1) Image signature. - :type signatures: list[~azure.containerregistry.models.ImageSignature] + :type signatures: list[~container_registry.models.ImageSignature] """ _attribute_map = { @@ -819,9 +816,9 @@ class OCIIndex(Manifest): :param schema_version: Schema version. :type schema_version: int :param manifests: List of OCI image layer information. - :type manifests: list[~azure.containerregistry.models.ManifestListAttributes] + :type manifests: list[~container_registry.models.ManifestListAttributes] :param annotations: Additional information provided through arbitrary metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations """ _attribute_map = { @@ -849,11 +846,11 @@ class OCIManifest(Manifest): :param schema_version: Schema version. :type schema_version: int :param config: V2 image config descriptor. - :type config: ~azure.containerregistry.models.Descriptor + :type config: ~container_registry.models.Descriptor :param layers: List of V2 image layer information. - :type layers: list[~azure.containerregistry.models.Descriptor] + :type layers: list[~container_registry.models.Descriptor] :param annotations: Additional information provided through arbitrary metadata. - :type annotations: ~azure.containerregistry.models.Annotations + :type annotations: ~container_registry.models.Annotations """ _attribute_map = { @@ -1046,12 +1043,11 @@ class RegistryArtifactProperties(msrest.serialization.Model): :param operating_system: Operating system. :type operating_system: str :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: - list[~azure.containerregistry.models.ManifestAttributesManifestReferences] + :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] :param tags: Required. A set of tags. List of tags. :type tags: list[str] :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~azure.containerregistry.models.ContentProperties + :type manifest_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -1144,7 +1140,7 @@ class RepositoryProperties(msrest.serialization.Model): :param tag_count: Required. Number of the tags. :type tag_count: int :param writeable_properties: Required. Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ContentProperties + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -1224,7 +1220,7 @@ class TagAttributesBase(msrest.serialization.Model): :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime :param writeable_properties: Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ContentProperties + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -1287,7 +1283,7 @@ class TagList(msrest.serialization.Model): :param repository: Required. Image name. :type repository: str :param tags: A set of tags. List of tag attribute details. - :type tags: list[~azure.containerregistry.models.TagAttributesBase] + :type tags: list[~container_registry.models.TagAttributesBase] :param link: :type link: str """ @@ -1332,7 +1328,7 @@ class TagProperties(msrest.serialization.Model): :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime :param writeable_properties: Changeable attributes. - :type writeable_properties: ~azure.containerregistry.models.ContentProperties + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { @@ -1382,11 +1378,11 @@ class V1Manifest(Manifest): :param tag: Image tag. :type tag: str :param fs_layers: List of layer information. - :type fs_layers: list[~azure.containerregistry.models.FsLayer] + :type fs_layers: list[~container_registry.models.FsLayer] :param history: Image history. - :type history: list[~azure.containerregistry.models.History] + :type history: list[~container_registry.models.History] :param signatures: Image signature. - :type signatures: list[~azure.containerregistry.models.ImageSignature] + :type signatures: list[~container_registry.models.ImageSignature] """ _attribute_map = { @@ -1428,9 +1424,9 @@ class V2Manifest(Manifest): :param media_type: Media type for this Manifest. :type media_type: str :param config: V2 image config descriptor. - :type config: ~azure.containerregistry.models.Descriptor + :type config: ~container_registry.models.Descriptor :param layers: List of V2 image layer information. - :type layers: list[~azure.containerregistry.models.Descriptor] + :type layers: list[~container_registry.models.Descriptor] """ _attribute_map = { diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py index c07914265cd0..94b714e4118b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/__init__.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py index b32026f9e4f3..4abf8f4a1f82 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import TYPE_CHECKING @@ -28,7 +26,7 @@ class AuthenticationOperations(object): instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. @@ -45,24 +43,17 @@ def __init__(self, client, config, serializer, deserializer): def exchange_aad_token_for_acr_refresh_token( self, - service, # type: str - tenant, # type: str - access_token, # type: str + aad_accesstoken=None, # type: Optional["_models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] **kwargs # type: Any ): # type: (...) -> "_models.AcrRefreshToken" """Exchange AAD tokens for an ACR refresh Token. - :param service: Indicates the name of your Azure container registry. - :type service: str - :param tenant: AAD tenant associated to the AAD credentials. - :type tenant: str - :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token - or access_token. - :type access_token: str + :param aad_accesstoken: + :type aad_accesstoken: ~container_registry.models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrRefreshToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AcrRefreshToken + :rtype: ~container_registry.models.AcrRefreshToken :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrRefreshToken"] @@ -71,7 +62,6 @@ def exchange_aad_token_for_acr_refresh_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - grant_type = "access_token" accept = "application/json" # Construct URL @@ -90,8 +80,11 @@ def exchange_aad_token_for_acr_refresh_token( header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') - body_content_kwargs['content'] = body_content + if aad_accesstoken is not None: + body_content = self._serialize.body(aad_accesstoken, 'Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema') + else: + body_content = None + body_content_kwargs['form_content'] = body_content request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response @@ -111,25 +104,17 @@ def exchange_aad_token_for_acr_refresh_token( def exchange_acr_refresh_token_for_acr_access_token( self, - service, # type: str - scope, # type: str - refresh_token, # type: str + acr_refresh_token=None, # type: Optional["_models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] **kwargs # type: Any ): # type: (...) -> "_models.AcrAccessToken" """Exchange ACR Refresh token for an ACR Access Token. - :param service: Indicates the name of your Azure container registry. - :type service: str - :param scope: Which is expected to be a valid scope, and can be specified more than once for - multiple scope requests. You obtained this from the Www-Authenticate response header from the - challenge. - :type scope: str - :param refresh_token: Must be a valid ACR refresh token. - :type refresh_token: str + :param acr_refresh_token: + :type acr_refresh_token: ~container_registry.models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrAccessToken, or the result of cls(response) - :rtype: ~azure.containerregistry.models.AcrAccessToken + :rtype: ~container_registry.models.AcrAccessToken :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrAccessToken"] @@ -138,7 +123,6 @@ def exchange_acr_refresh_token_for_acr_access_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") - grant_type = "refresh_token" accept = "application/json" # Construct URL @@ -157,7 +141,10 @@ def exchange_acr_refresh_token_for_acr_access_token( header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') body_content_kwargs = {} # type: Dict[str, Any] - body_content = self._serialize.body(grant_type, 'str') + if acr_refresh_token is not None: + body_content = self._serialize.body(acr_refresh_token, 'PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema') + else: + body_content = None body_content_kwargs['content'] = body_content request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py index c20df3d43b5a..b10afab300ba 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import TYPE_CHECKING @@ -28,7 +26,7 @@ class ContainerRegistryBlobOperations(object): instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py index f4e0a4659c84..c994d5627f59 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import TYPE_CHECKING @@ -29,7 +27,7 @@ class ContainerRegistryOperations(object): instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. @@ -107,7 +105,7 @@ def get_repositories( :type n: int :keyword callable cls: A custom type or function that will be passed the direct response :return: An iterator like instance of either Repositories or the result of cls(response) - :rtype: ~azure.core.paging.ItemPaged[~azure.containerregistry.models.Repositories] + :rtype: ~azure.core.paging.ItemPaged[~container_registry.models.Repositories] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.Repositories"] @@ -184,7 +182,7 @@ def delete_repository( :type name: str :keyword callable cls: A custom type or function that will be passed the direct response :return: DeleteRepositoryResult, or the result of cls(response) - :rtype: ~azure.containerregistry.models.DeleteRepositoryResult + :rtype: ~container_registry.models.DeleteRepositoryResult :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.DeleteRepositoryResult"] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index ccbf34f38e89..36968b545726 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- from typing import TYPE_CHECKING @@ -29,7 +27,7 @@ class ContainerRegistryRepositoryOperations(object): instantiates it for you and attaches it as an attribute. :ivar models: Alias to model classes used in this operation group. - :type models: ~azure.containerregistry.models + :type models: ~container_registry.models :param client: Client for service requests. :param config: Configuration of service client. :param serializer: An object model serializer. @@ -64,7 +62,7 @@ def get_manifest( :type accept: str :keyword callable cls: A custom type or function that will be passed the direct response :return: Manifest, or the result of cls(response) - :rtype: ~azure.containerregistry.models.Manifest + :rtype: ~container_registry.models.Manifest :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.Manifest"] @@ -125,7 +123,7 @@ def create_manifest( :param reference: A tag or a digest, pointing to a specific image. :type reference: str :param payload: Manifest body, can take v1 or v2 values depending on accept header. - :type payload: ~azure.containerregistry.models.Manifest + :type payload: ~container_registry.models.Manifest :keyword callable cls: A custom type or function that will be passed the direct response :return: object, or the result of cls(response) :rtype: object @@ -248,7 +246,7 @@ def get_properties( :type name: str :keyword callable cls: A custom type or function that will be passed the direct response :return: RepositoryProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RepositoryProperties + :rtype: ~container_registry.models.RepositoryProperties :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.RepositoryProperties"] @@ -302,7 +300,7 @@ def set_properties( :param name: Name of the image (including the namespace). :type name: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties + :type value: ~container_registry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -377,7 +375,7 @@ def get_tags( :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response :return: An iterator like instance of either TagList or the result of cls(response) - :rtype: ~azure.core.paging.ItemPaged[~azure.containerregistry.models.TagList] + :rtype: ~azure.core.paging.ItemPaged[~container_registry.models.TagList] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.TagList"] @@ -463,7 +461,7 @@ def get_tag_properties( :type reference: str :keyword callable cls: A custom type or function that will be passed the direct response :return: TagProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.TagProperties + :rtype: ~container_registry.models.TagProperties :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.TagProperties"] @@ -521,7 +519,7 @@ def update_tag_attributes( :param reference: Tag name. :type reference: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties + :type value: ~container_registry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None @@ -649,7 +647,7 @@ def get_manifests( :type orderby: str :keyword callable cls: A custom type or function that will be passed the direct response :return: An iterator like instance of either AcrManifests or the result of cls(response) - :rtype: ~azure.core.paging.ItemPaged[~azure.containerregistry.models.AcrManifests] + :rtype: ~azure.core.paging.ItemPaged[~container_registry.models.AcrManifests] :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.AcrManifests"] @@ -733,7 +731,7 @@ def get_registry_artifact_properties( :type digest: str :keyword callable cls: A custom type or function that will be passed the direct response :return: RegistryArtifactProperties, or the result of cls(response) - :rtype: ~azure.containerregistry.models.RegistryArtifactProperties + :rtype: ~container_registry.models.RegistryArtifactProperties :raises: ~azure.core.exceptions.HttpResponseError """ cls = kwargs.pop('cls', None) # type: ClsType["_models.RegistryArtifactProperties"] @@ -791,7 +789,7 @@ def update_manifest_attributes( :param digest: Digest of a BLOB. :type digest: str :param value: Repository attribute value. - :type value: ~azure.containerregistry.models.ContentProperties + :type value: ~container_registry.models.ContentProperties :keyword callable cls: A custom type or function that will be passed the direct response :return: None, or the result of cls(response) :rtype: None diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index c1f86407e69d..049a82248395 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -3,14 +3,4 @@ ### Settings ``` yaml input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/aa5edc4d4cb0298bde52c939a7c948692f3285e1/sdk/containerregistry/container-registry/swagger/containerregistry.json -output-folder: "../azure/containerregistry/_generated" -namespace: azure.containerregistry -no-namespace-folders: true -python: true -python-mode: create -license-header: MICROSOFT_MIT_NO_VERSION -package-name: azure-containerregistry -clear-output-folder: true -enable-xml: true -vanilla: true -``` +``` \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml new file mode 100644 index 000000000000..f6442fa4b342 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml @@ -0,0 +1,169 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '196' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 12:58:35 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTA0MTQsIm5iZiI6MTYxNjU5MDQxNCwiZXhwIjoxNjE2Njc3MTE0LCJhaW8iOiJFMlpnWVBDU25WUHN0KzM2YnQyL1Q5Nm1hTnlkQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoicC1TR01nLUZzRWlyX0tzMmM4d3lBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.ff66r-Lz0TrvDdUXq1zsbwGAyrK7aFoMcXUBecYutkgaGNvVtOjOLhQqqeZDcS4X9tmYCDXqCkpttchJUYWr8qZkYC20JvvPpdiFLtPgBvZ0yiR_DDyvg-jHZPdHGoNN6FufDI3PQ4R_g9JEGsf-VV3LlQAbzfenoMDcv1RlsIoF7EAJFBlYmk2MIFOnJl3_EPKPI0ARwyj-n2tp7gCc4gk90WaEzb4kWWNuWj8DsWSgnwWJrjz7BJtg0Qw-FnDLjvHq-ESTmYj0PAS4wRQ4ayevUhI8D1pZJmHwiLoKQi2DkIHv74ZXG9QJNMlRaLKkXgtWXjDVmYjbX8Qkdgn3mQ + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4MmJmOTMzNy1hYzIyLTQyZjEtOWUzMC0zZTJjM2U1YTI3NTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1ODk4MTYsImV4cCI6MTYxNjYwMTUxNiwiaWF0IjoxNjE2NTg5ODE2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e9-Br9N1MYCz2xju6TxeqItFKVWMziIc8EO0BcX4Xsec1DrUx9yA28060r5mCB4nv041AMHEy3JkY_d8mu-4jacXS325bF1oJG3CsOviJM47R_qTNcE2bLdAyPXYZpJ0gsXr-a9xnqetL86yLRfQCFUDGyEfxX0YWC471gvuiqDKTwCZAy1a-QiyzHLxoT2DqpLEDUJvrtTYXXvenuio3KvOqz-HLos4dSwbsNUyd77qjlRPHOi-MDs7RTTKMoAD4EhBvj_gQjFQmLEycTe0KxikbFMNA37l-ie2JoY-bQfiJdCWNIY7b4lNzfZ0fF80hv_BHGb91CXJaOxFM3d79Q"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 12:58:36 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry:catalog:*&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4MmJmOTMzNy1hYzIyLTQyZjEtOWUzMC0zZTJjM2U1YTI3NTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1ODk4MTYsImV4cCI6MTYxNjYwMTUxNiwiaWF0IjoxNjE2NTg5ODE2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e9-Br9N1MYCz2xju6TxeqItFKVWMziIc8EO0BcX4Xsec1DrUx9yA28060r5mCB4nv041AMHEy3JkY_d8mu-4jacXS325bF1oJG3CsOviJM47R_qTNcE2bLdAyPXYZpJ0gsXr-a9xnqetL86yLRfQCFUDGyEfxX0YWC471gvuiqDKTwCZAy1a-QiyzHLxoT2DqpLEDUJvrtTYXXvenuio3KvOqz-HLos4dSwbsNUyd77qjlRPHOi-MDs7RTTKMoAD4EhBvj_gQjFQmLEycTe0KxikbFMNA37l-ie2JoY-bQfiJdCWNIY7b4lNzfZ0fF80hv_BHGb91CXJaOxFM3d79Q + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1057' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1YmZjYWQ3NS0xYTVlLTQ5OGEtOTIzYy1hY2U0Mjk2YmU3MmIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1ODk4MTYsImV4cCI6MTYxNjU5NDMxNiwiaWF0IjoxNjE2NTg5ODE2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.EkjUVOfHTXswuvFfSQDC3BYhu23RLwtqEirYtclB4xbS_DBO5YUEthgtwAvaRzaU9RXGB7hutGrFdBvOl6mUw0ZH-xJ6SIGCT1HTQPTqPU6RaXCtv80ErWKDvEmPxxiRpjlo6nVwp3RB91YlVPjmw5MEVU0RXHSbhwZJeRFLBjkfYd0jeaPBjQMNLaDkzWSYROQf6mPsMo_7NYpUo4zYM94711xnvACg_7TfwxwnAt5aoRPt2vi0OLUt6CcQleXa9qByGAXQYduJJ2UhhAzXH6JXPcLB8QF-iXh4WbBKVOfECUJArmWrfx2Pliui6l8UKfbtl3ec7Tl6GYlMB_p3Og"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 12:58:36 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '125' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 12:58:36 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py index 1c9c6b867601..b43844e7b6a3 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py @@ -13,6 +13,7 @@ from azure.containerregistry import ( ContainerRegistryClient, ContainerRegistryUserCredential, + ContainerRepositoryClient, DeletedRepositoryResult, ACRExchangeClient ) @@ -30,7 +31,7 @@ ) -class TestContainerRegistryClient(AzureTestCase, ContainerRegistryTestClass): +class TestExchangeClient(AzureTestCase, ContainerRegistryTestClass): def create_exchange_client(self, endpoint): return self.create_client_from_credential( @@ -47,7 +48,34 @@ def test_exchange_client(self, containerregistry_baseurl): service = "seankane.azurecr.io" scope = "repository:hello-world:metadata_read" - refresh = client.get_refresh_token(service, os.environ["AZURE_TENANT_ID"]) + refresh_token = client.exchange_aad_token_for_refresh_token(service, scope) + assert refresh_token is not None + assert len(refresh_token) > 100 + print(refresh_token) - assert refresh is not None - print(refresh) + + access_token = client.exchange_refresh_token_for_access_token(service, scope, refresh_token) + assert access_token is not None + assert len(access_token) > 100 + print(access_token) + + # access_token = client.get_acr_access_token(service, scope) + # assert access_token is not None + # assert len(access_token) > 100 + # print(access_token) + + + @pytest.mark.live_test_only + @acr_preparer() + def test_auth_policy_in_action(self, containerregistry_baseurl): + client = ContainerRegistryClient( + endpoint=containerregistry_baseurl, + credential=DefaultAzureCredential(), + ) + + prev = None + for repo in client.list_repositories(): + assert repo is not None + assert repo != prev + prev = repo + print(repo) \ No newline at end of file From da18b29b54c24d4148e2ba4d8f55d4734e7a0ef1 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 11:16:34 -0400 Subject: [PATCH 56/86] working tests --- .../azure/containerregistry/__init__.py | 6 - .../_authentication_policy.py | 53 +------ .../azure/containerregistry/_base_client.py | 3 +- .../azure/containerregistry/_models.py | 40 +++--- ...test_delete_repository_does_not_exist.yaml | 128 ++++++++++++++++- ...egistry_client.test_list_repositories.yaml | 130 +++++++++++++++++- ...repository_client.test_get_attributes.yaml | 126 ++++++++++++++++- ...repository_client.test_get_properties.yaml | 126 ++++++++++++++++- ...tainer_repository_client.test_get_tag.yaml | 126 ++++++++++++++++- ...y_client.test_list_registry_artifacts.yaml | 47 ------- ...iner_repository_client.test_list_tags.yaml | 126 ++++++++++++++++- ...tory_client.test_list_tags_descending.yaml | 126 ++++++++++++++++- ...nge_client.test_auth_policy_in_action.yaml | 16 +-- ..._exchange_client.test_exchange_client.yaml | 74 ++++++++++ .../tests/test_container_registry_client.py | 1 - .../tests/test_container_repository_client.py | 20 +-- .../tests/test_exchange_client.py | 12 +- .../azure-containerregistry/tests/testcase.py | 15 +- 18 files changed, 991 insertions(+), 184 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 8d774b70270a..82ab1b769a97 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -18,10 +18,6 @@ TagOrderBy, TagProperties, ) -from ._authentication_policy import ( - ContainerRegistryUserCredential, - ContainerRegistryUserCredentialPolicy, -) from ._version import VERSION __version__ = VERSION @@ -37,6 +33,4 @@ "RepositoryProperties", "TagOrderBy", "TagProperties", - "ContainerRegistryUserCredential", - "ContainerRegistryUserCredentialPolicy", ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index f35353936d21..6ace4394cbe4 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -8,8 +8,7 @@ import re from typing import TYPE_CHECKING -from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.core.pipeline.policies import HTTPPolicy +from azure.core.pipeline.policies import SansIOHTTPPolicy, HTTPPolicy from ._exchange_client import ACRExchangeClient @@ -37,56 +36,6 @@ def _enforce_https(request): ) -class ContainerRegistryUserCredential(object): - """Credential used to authenticate with Container Registry service""" - - def __init__(self, username, password): - self._user = username - self._password = password - - def get_token(self): - token_str = "{}:{}".format(self._user, self._password) - token_bytes = token_str.encode("ascii") - b64_bytes = b64encode(token_bytes) - return b64_bytes.decode("ascii") - - -class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): - """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" - - def __init__(self, credential): - self.credential = credential - - @staticmethod - def _update_headers(headers, token): - headers["Authorization"] = "Basic {}".format(token) - - def on_request(self, request): - # type: (PipelineRequest) -> None - self._update_headers(request.http_request.headers, self.credential.get_token()) - - -class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): - """Challenge based authentication policy for ACR. This policy is used for getting - the AAD Token, refresh token, and access token before performing a call to service. - - :param credential: Azure Token Credential for authenticating with Azure - :type credential: TokenCredential - """ - - BEARER = "Bearer" - AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile('(?:(\\w+)="([^""]*)")+') - WWW_AUTHENTICATE = "WWW-Authenticate" - SCOPE_PARAMETER = "scope" - SERVICE_PARAMETER = "service" - AUTHORIZATION = "Authorization" - - def __init__(self, credential, url, pipeline): - self.credential = credential - self.url = url - self.pipeline = pipeline - - class ContainerRegistryChallengePolicy(HTTPPolicy): """Authentication policy for ACR which accepts a challenge""" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index ea42f2adf696..035b66d08bbc 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -6,7 +6,7 @@ from enum import Enum -from ._authentication_policy import ContainerRegistryUserCredentialPolicy, ContainerRegistryChallengePolicy +from ._authentication_policy import ContainerRegistryChallengePolicy from ._generated import ContainerRegistry from ._user_agent import USER_AGENT @@ -28,7 +28,6 @@ class ContainerRegistryBaseClient(object): """ def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-method-missing-type-annotations - # auth_policy = ContainerRegistryUserCredentialPolicy(credential=credential) auth_policy = ContainerRegistryChallengePolicy(credential) self._client = ContainerRegistry( credential=credential, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 6eb438a1d297..be90104e7021 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -8,25 +8,25 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from ._generated.models import ManifestChangeableAttributes, ManifestAttributesBase + from ._generated.models import ContentProperties, ManifestAttributesBase from ._generated.models import RepositoryProperties as GeneratedRepositoryProperties - + from ._generated.models import TagProperties as GeneratedTagProperties class ContentPermissions(object): def __init__(self, **kwargs): - self.delete_enabled = kwargs.get("delete_enabled") - self.list_enabled = kwargs.get("list_enabled") - self.read_enabled = kwargs.get("read_enabled") - self.write_enabled = kwargs.get("write_enabled") + self.can_delete = kwargs.get("can_delete") + self.can_list = kwargs.get("can_list") + self.can_read = kwargs.get("can_read") + self.can_write = kwargs.get("can_write") @classmethod def from_generated(cls, generated): - # type: (ManifestChangeableAttributes) -> ContentPermissions + # type: (ContentProperties) -> ContentPermissions return cls( - delete_enabled=generated.delete_enabled, - list_enabled=generated.list_enabled, - read_enabled=generated.read_enabled, - write_enabled=generated.write_enabled, + can_delete=generated.can_delete, + can_list=generated.can_list, + can_read=generated.can_read, + can_write=generated.can_write, ) @@ -93,11 +93,10 @@ class RepositoryProperties(object): def __init__(self, **kwargs): self.created_on = kwargs.get("created_on", None) self.last_updated_on = kwargs.get("last_updated_on", None) - self.modifiable_properties = kwargs.get("modifiable_properties", None) self.name = kwargs.get("name", None) self.registry = kwargs.get("registry", None) - self.tag_count = kwargs.get("tag_count", None) self.manifest_count = kwargs.get("manifest_count", None) + self.tag_count = kwargs.get("tag_count", None) self.content_permissions = kwargs.get("content_permissions", None) if self.content_permissions: self.content_permissions = ContentPermissions.from_generated(self.content_permissions) @@ -109,10 +108,10 @@ def from_generated(cls, generated): created_on=generated.created_on, last_updated_on=generated.last_updated_on, name=generated.name, - # registry=generated.registry, manifest_count=generated.registry_artifact_count, tag_count=generated.tag_count, content_permissions=generated.writeable_properties, + registry=generated.additional_properties.get("registry", None) ) @@ -151,21 +150,18 @@ def __init__(self, **kwargs): self.created_on = kwargs.get("created_on", None) self.digest = kwargs.get("digest", None) self.last_updated_on = kwargs.get("last_updated_on", None) - self.content_permissions = kwargs.get("content_permissions", None) - if self.content_permissions: - self.content_permissions = ContentPermissions.from_generated(self.content_permissions) + self.writeable_properties = kwargs.get("writeable_properties", None) + if self.writeable_properties: + self.writeable_properties = ContentPermissions.from_generated(self.writeable_properties) self.name = kwargs.get("name", None) - self.signed = kwargs.get("signed", None) - self.quarantine_state = kwargs.get("quarantine_state", None) @classmethod def from_generated(cls, generated): + # type: (GeneratedTagProperties) -> TagProperties return cls( created_on=generated.created_on, digest=generated.digest, last_updated_on=generated.last_updated_on, - content_permissions=generated.modifiable_properties, name=generated.name, - signed=generated.additional_properties.get("signed", None), - quarantine_state=generated.additional_properties.get("quarantineState", None), + writeable_properties=generated.writeable_properties, ) diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml index 31cb09c2945f..e5c5d4a5acf3 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml @@ -11,7 +11,131 @@ interactions: Content-Length: - '0' User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '209' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:37 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:not_real_repo:delete",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNTYsIm5iZiI6MTYxNjU5NzI1NiwiZXhwIjoxNjE2NjgzOTU2LCJhaW8iOiJFMlpnWUZCYWFGTE5rbWVmbnBKMzgzTHRJMWxIQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRkgxdi1zWnJSa083alBhM1FYazlBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.b0WiVDarwGEItqLvydUyOR47TBzt2Ss2UTn3O4DqFyRrStDiZW5vIk_K-wXnOvxHO2nC08NjhyweMht0BQYueORdaxlP5345-5Z3POu0ONrKM6L9IGHQ3bUOslFtJgUUzgc_M1_eEKwUuDy0hbDfbCmTRfQJIcl5HqX_dKNjlLYsZwbX-Fejg3tXefh2ldgqqvPS8UJ6rbQ4gzg8V_nCC48GpneWota6Okdn9DxNLlx9K_ZGgxZBWDnEUk6vYDc6BLVNZZMl1mMaVADkhwKVWk0N2AAQs_WBgep5E1jd_vhcNgK0mFg__YL4HvIHgPCbKiP7-6aztoMTzZMnUodKDA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3MGY4YmEzYi1iMmM4LTQ4NGMtYTExMi03YTRmNzZjNTg5N2YiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NTgsImV4cCI6MTYxNjYwODM1OCwiaWF0IjoxNjE2NTk2NjU4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.jsr6b2GTW75zWkoTwUTFKV7D0GWf-pU443qPYhctCOCfp9Y1q24HuLyfK7a4SfhocOOQ-tJ8Q3ccWOKBT_1AI05aecTTOKEn1rzNBnXIrI2W-juQSiQp5B_muL4195itqPOlq7FoqAsqFputSL4zf8_tBBtK_Bt-03cwq5-TU_SrKXXzdrwBf-klCFkX7_tJfIBhqWaKylEULi6NZfVaiZu0ZatowrwIgD-XWFr1IJyIl2l_hGv0HPS1x8ZEActR6-i5F-qf0PvVL_3ihRndeknF9mcRPDBdqWYvDd_AFdMZE6HDJOgLM8evXn0HgJ6Um2GCbE14JGBa9Jr9mXOE6g"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:38 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:not_real_repo:delete&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3MGY4YmEzYi1iMmM4LTQ4NGMtYTExMi03YTRmNzZjNTg5N2YiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NTgsImV4cCI6MTYxNjYwODM1OCwiaWF0IjoxNjE2NTk2NjU4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.jsr6b2GTW75zWkoTwUTFKV7D0GWf-pU443qPYhctCOCfp9Y1q24HuLyfK7a4SfhocOOQ-tJ8Q3ccWOKBT_1AI05aecTTOKEn1rzNBnXIrI2W-juQSiQp5B_muL4195itqPOlq7FoqAsqFputSL4zf8_tBBtK_Bt-03cwq5-TU_SrKXXzdrwBf-klCFkX7_tJfIBhqWaKylEULi6NZfVaiZu0ZatowrwIgD-XWFr1IJyIl2l_hGv0HPS1x8ZEActR6-i5F-qf0PvVL_3ihRndeknF9mcRPDBdqWYvDd_AFdMZE6HDJOgLM8evXn0HgJ6Um2GCbE14JGBa9Jr9mXOE6g + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1070' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5MmUxOTNiZC1mYjRkLTQ4MTktYjI0Yi0zMzJlNzE5NmM4N2EiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NTgsImV4cCI6MTYxNjYwMTE1OCwiaWF0IjoxNjE2NTk2NjU4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJub3RfcmVhbF9yZXBvIiwiYWN0aW9ucyI6WyJkZWxldGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.HNEXAHBCyubysC0z_Ywm8Gefp3E1AZaPcP_8i-5ncj9Zao7qBCPIjts2IfN3Z4SHrJUcT4sIpgy7FkBe7PAZoTXMCIZK-H7CdeLx2G8hZsLmiqdUJ8T_Otv7xlbXe5MMRkIOtTxjPiqSdhE-vJHX_UZ52bUdBcqUty7HoyMpkuoRqa9R-yJN9vYbDZq4clZmTfDH4ih0ZBhmyeKSPE8t8g3wnKBjPS8-xeuD9IQTFJ1tB1BIeLjsEae76HmIrUeossJkHPFGv6ygV3tQu4AkvspDSwlnTNZQq5gdz4DMLYs68Dv_1dXMe4xVE5iYorTExYfU8o9SFQ2Xct9r-emrjw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:38 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: DELETE uri: https://fake_url.azurecr.io/acr/v1/not_real_repo @@ -34,7 +158,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 15:58:46 GMT + - Wed, 24 Mar 2021 14:52:38 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index 7f82320be48d..61d6dba93055 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -9,13 +9,14 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"repositories":["hello-world"]} + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} ' headers: @@ -27,11 +28,132 @@ interactions: connection: - keep-alive content-length: - - '33' + - '196' content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 22:12:59 GMT + - Wed, 24 Mar 2021 14:52:40 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNTksIm5iZiI6MTYxNjU5NzI1OSwiZXhwIjoxNjE2NjgzOTU5LCJhaW8iOiJFMlpnWVBpOHZ2WDN1NDRRTzRaQ2tZZ3ZoaXhOQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiTFJTRWk0dkpORXFoWjBpXy00RXdBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.chHqHOLx4lnmIKpXa35d8bgKvQT7HnXhWqheMgaX2N8_-gmXd7yU_FZAmFSHqmXY-p6qfEs_h4f7btM8LWy-9NaP5che0Ux8kho0Pa-uFTyxZbIdwOiqQ9SmsjAqj4l7CiSDhwTMJe1-DGcGRIPFshgGxqmFWqll8ac-p16L3b3qc2Rh5IxOy5c7_7EIYHtKoUm0tAxtuGjHK5t02SrBDLqm730r9Pc2RuVsagUfTOIr1TqphhvXx5ileM5uXa1hENSM055crIdw0H2q47gSqfz0l0zd0g18drJtVBblWzK8KP86DimqXKimycTIUPG97h8qN_91NBUtKluIJJSV8A + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0YzQyM2FmNi0yN2UyLTQ1NzQtYWVjYy00ZGE0MDQyNmVlMGMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjEsImV4cCI6MTYxNjYwODM2MSwiaWF0IjoxNjE2NTk2NjYxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.SqQUVh3H5-YmHzcqOf4qZ4j9FNSthKtRPCjMfxD77IEsrHeeSzqVYvOXbYU34j0bL5b4WwxaEWeY-MX-561pl6oVi30HbquNEUQw5gvJoNJnpVsbV9-KmPo3C_puSFSrh8h_0sTuuPYI2jX0WsQuIqFptGtHsvzqL1dqtvnQubT53ci8hUD7zpHLYoXGEGGM-DtdHmXY8eToRKqqyUFM-6kiWapY2WpxXtu6tLzPKMhAh9UlVkEi9y2ezKx4JlE8ZZQv9eNtRuvRlT3bomBNLWlhuUDGf7svBLhPx2JLrsv-5j3_VsNHu5oWly5Fb2wACfppjgKzwYyg_HZFUOBjog"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:41 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry:catalog:*&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0YzQyM2FmNi0yN2UyLTQ1NzQtYWVjYy00ZGE0MDQyNmVlMGMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjEsImV4cCI6MTYxNjYwODM2MSwiaWF0IjoxNjE2NTk2NjYxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.SqQUVh3H5-YmHzcqOf4qZ4j9FNSthKtRPCjMfxD77IEsrHeeSzqVYvOXbYU34j0bL5b4WwxaEWeY-MX-561pl6oVi30HbquNEUQw5gvJoNJnpVsbV9-KmPo3C_puSFSrh8h_0sTuuPYI2jX0WsQuIqFptGtHsvzqL1dqtvnQubT53ci8hUD7zpHLYoXGEGGM-DtdHmXY8eToRKqqyUFM-6kiWapY2WpxXtu6tLzPKMhAh9UlVkEi9y2ezKx4JlE8ZZQv9eNtRuvRlT3bomBNLWlhuUDGf7svBLhPx2JLrsv-5j3_VsNHu5oWly5Fb2wACfppjgKzwYyg_HZFUOBjog + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1057' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhZGI0Y2JkMy04ZDA4LTRkYTUtYmVkZi04OGY0MjhlOTYwNGMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjEsImV4cCI6MTYxNjYwMTE2MSwiaWF0IjoxNjE2NTk2NjYxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.jzAZSWImjrFuU_QCPn5kmf624sLrftc7bcxoP_xeutgUmlEUolx_4jzDN9dut5zHnt1uxSdFGv85odjwNsn7KGW8o3dwUu-597Tr31N_W9m11IpwqKbudZbUMn_wXRW9BHc8khYyXHR5diQezU6s_vub8zMGguZtFFDQWjleKi5PhhA95CFfzWzNNKUmTdoU5u44r63YMywz26ic2iqxt6p822WRBfQLi--k_jS-XapDmp90HlaEBZBYMnrQC1Ate4hF1fexRI8jNEhmElU2kF27CdZb5y47f2-d18BwQtJl9WxQMLddYhzP6VRj6Z2s_4wNkaCBpj7bD8OvHL_nIw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:41 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '125' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:42 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml index 92b820121aa9..e6a581c5e27b 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -9,7 +9,129 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:43 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNjIsIm5iZiI6MTYxNjU5NzI2MiwiZXhwIjoxNjE2NjgzOTYyLCJhaW8iOiJFMlpnWUtneUZUcHkzK3YzNHlkcW43bWZUQy8zQndBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibjc5eFVFT1VTMGVZdVlRXzdfSk1BQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.HPp1dIWySftlZwhkCVqD-Lz6DVa185aOCKCDF1CiGWOJDDQ30mxEmFxj7sC1X0ZoXLuNwUZpZfsZLK9TzCuQORkLWKl6W6l4-qJVlAAygr21XS7BWBdztWbV5JTn0HFETj4hoa-dpta5QKW5mZvlRLd7H8cxsHRCne9vXGjC4DSw-u_8EQGR-hCNvi3W2z0QFDB6Z5i3MplDkIXMkhxk70JMccobwyfdbTBFilF8kZgUcjOaKhqGZkG4zkxKrs6M1WXQZ1r7PznZbZlhwzFWCCycfqvkFJ3rD3KDybGESgvAB5JJ7wqhjXMi5Y-BAzHud6txhs_q4OEZTVNbod8jGg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5OWI0NmU0ZC00MjgzLTQ2MTItYTBlNy00NGRiNmRlMWYzNWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjQsImV4cCI6MTYxNjYwODM2NCwiaWF0IjoxNjE2NTk2NjY0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.DocYXlucsuYp59eWsNUTtZJc0nUFivsBd_nr3y4TT622Eru31nDEsb922-75Ioy4qPmI_7GL_6eKp3d7TJlzoy4s77CxdEmKcRfdYdw4H9NVVXgiqL0f8dUDDHAKp123LgQvJ2KXHiV1i3J8-yZeOvSoKNiy5Uk8EzzZig7CmrKSG1yETiP3S1XBTJhoMeEmHuNzOfe3jLnYhQEZtggTO0zNvLNgQSjDPTUr_n2lovCBMVVCEnL8HL8KiE_XpaCkKJI7PXruhXDAjE-i5zYbdVub6W4BEI7sv-u5PMMRehgLc8BXYyP-J--5OK09MwZGS8TmvW_3cKtzCv8Y6VBixg"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:44 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5OWI0NmU0ZC00MjgzLTQ2MTItYTBlNy00NGRiNmRlMWYzNWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjQsImV4cCI6MTYxNjYwODM2NCwiaWF0IjoxNjE2NTk2NjY0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.DocYXlucsuYp59eWsNUTtZJc0nUFivsBd_nr3y4TT622Eru31nDEsb922-75Ioy4qPmI_7GL_6eKp3d7TJlzoy4s77CxdEmKcRfdYdw4H9NVVXgiqL0f8dUDDHAKp123LgQvJ2KXHiV1i3J8-yZeOvSoKNiy5Uk8EzzZig7CmrKSG1yETiP3S1XBTJhoMeEmHuNzOfe3jLnYhQEZtggTO0zNvLNgQSjDPTUr_n2lovCBMVVCEnL8HL8KiE_XpaCkKJI7PXruhXDAjE-i5zYbdVub6W4BEI7sv-u5PMMRehgLc8BXYyP-J--5OK09MwZGS8TmvW_3cKtzCv8Y6VBixg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1075' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2ZjhiZjE1MS02YWM3LTRjYjQtYWI4Zi1lNjBmOTE5ZmM0Y2QiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjQsImV4cCI6MTYxNjYwMTE2NCwiaWF0IjoxNjE2NTk2NjY0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Kb7hq32WI_KwUXBnAdu1N7XLoe3juA0X3n4Qtcgb1myk6xX7e6Xlb9dbpr1LqboAR1Jl-pmr1uXVWC3uhVcYrKnsR5eO5pM5ABOwp1gNkNmFevJYucZz73Bb_2YrIld4nRNMysabs3iRaSDu3Mh2OujXE3z7S2Mmh1puip05gziUSUWAOwd5t-IuTzEQBhsHOsrWweCghHjR1W0qiMSd-5UbHUhd-aueXZ6CHqGrnxji-pVZtAUet0UrSH8ddYIJ6BGkr4lltXEXlQCFgvgiXjiWr7-4Jw1mPo4E3CpGaC_EcnCPsDA7HvlczYVMDM0Kaiq8SBbP41KdXChTNjOEdg"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:44 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET uri: https://fake_url.azurecr.io/acr/v1/hello-world @@ -31,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 17 Mar 2021 15:00:58 GMT + - Wed, 24 Mar 2021 14:52:45 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml index 0dfa210dfcc0..7d50f17a576d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -9,7 +9,129 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:46 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNjYsIm5iZiI6MTYxNjU5NzI2NiwiZXhwIjoxNjE2NjgzOTY2LCJhaW8iOiJFMlpnWVBDZGMyaCtVK3FYdUsrdGY0UXFHTnFmQWdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2J0WkRBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.a9EqIfAYmMzqdlAd4ufV3ebsxFjMwNFwwQ64PVKNtxz1zZ478S0pbXFqbMA4I_250RAJbjRd5bB7rnSqJFO7HfJ2CWtDkehrTiKrkiCxA9PngNPjs3uTOMM-doaJFuORO8dzGfyvmiNpS4bi0VBpgdN1sFGHEdmIz91-qj8MIRNfmJV5_-3yakJnFlj7bjVEI-35_HNT7LuMW9qmroel-ijsLg5si6vJ5ntiXTPwX4ob3si4kSIH18METXZGit0i00UqXk3Zh0BRXJWIguV06jkazFurlaciq81VLNBnxboZNYfNbaHZLgtjCMaRzqxgi6bruFTHv-kJaZys71Czow + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5ODYzYjY5YS00YzM2LTQ5NWUtOTg4OS04ZTcyZGM2YzgwNTgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjcsImV4cCI6MTYxNjYwODM2NywiaWF0IjoxNjE2NTk2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VjHgVZbEEbUetEu9DmM64aWPs6YQkQx8CVFQSoqLrHvryWTsFU3qvbuUq5Z5SNvk3ZH8gEAOT8bNJ52m4T84EiFoUOKlZZaS7mmIdf92SYWQao00d9nxDqWMYra3Y6Woe04gUFAvJz_ZFQGdL1paHAyFpJtMbrOtBAKD2EjDLidgd6bCfQ0cSyRA0kVg7_LfYdrmhFE6f4c-FasUR9pgHyPAd12l-FYwPIpb6uS-_lKuMoh5HG8unQBAn3W1eEYLrAfqj2ZV8CCUKMhIoqW3kbDg3hikoL5PD-exXsB-qG9QxDGRncZhnCR6v8KE5_wnOEgcFGRb0DlI9dI_OKaz6A"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:47 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5ODYzYjY5YS00YzM2LTQ5NWUtOTg4OS04ZTcyZGM2YzgwNTgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjcsImV4cCI6MTYxNjYwODM2NywiaWF0IjoxNjE2NTk2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VjHgVZbEEbUetEu9DmM64aWPs6YQkQx8CVFQSoqLrHvryWTsFU3qvbuUq5Z5SNvk3ZH8gEAOT8bNJ52m4T84EiFoUOKlZZaS7mmIdf92SYWQao00d9nxDqWMYra3Y6Woe04gUFAvJz_ZFQGdL1paHAyFpJtMbrOtBAKD2EjDLidgd6bCfQ0cSyRA0kVg7_LfYdrmhFE6f4c-FasUR9pgHyPAd12l-FYwPIpb6uS-_lKuMoh5HG8unQBAn3W1eEYLrAfqj2ZV8CCUKMhIoqW3kbDg3hikoL5PD-exXsB-qG9QxDGRncZhnCR6v8KE5_wnOEgcFGRb0DlI9dI_OKaz6A + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1075' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIxMTQ5YmVjMy0xZmIxLTQ2ZmEtOTIxNi1hYWI2NzQxN2Q5OTQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjcsImV4cCI6MTYxNjYwMTE2NywiaWF0IjoxNjE2NTk2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.ZLs8UNXciEAc17kbh4Fix0i01dYqDvr4HmvmJkgFOOKkWmNrX-CvTkIkngEh8ghedq0HCDzNkp79EmZdckFmPsvd_7xFVQTGl9DcJ5QcNydOST1mOVaJ8laMIid-Zjw60kUZj8CWtQxGQMluvhN_4yqKlHJt_RSdlyhNhGJrRmmzyNVYWsoZMcZt49T1ONAx9WiKNZb-Ns5hgn-MuOOxepgeKJD1hNCDWfStARCluviF-XLqk8Nya7iKtX1Dgj0vsMvGU-xvmzKcGJ5xJTAOCZc3l-az5k8r4UXGVvBNPeptTHVyQkukELQt0BvGXm-j-arWfw9PbLD97C1VuaBVew"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:47 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET uri: https://fake_url.azurecr.io/acr/v1/hello-world @@ -31,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 17 Mar 2021 15:00:59 GMT + - Wed, 24 Mar 2021 14:52:48 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml index f9f3c9d66fba..b0d5f7f435cd 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml @@ -9,7 +9,129 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:49 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNjksIm5iZiI6MTYxNjU5NzI2OSwiZXhwIjoxNjE2NjgzOTY5LCJhaW8iOiJFMlpnWUZpU3NUVG13U1VYaHlmYVdldVhQdGN1QVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZDFfZ2Z6ZGU0RTJnbHFWeHlfd3lBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.G77ErPwUhYK0OZ4AHtaHG3dvLkEJm8L6Zn2YL55GHLOMo-G5eNqhv7Vk1UXNxz8677tflVOtrR2plFsi0Aa4qxhVeykrfSEWtxiyMnklcO2LAXNsOFMvLFiitJ8OKZ7CmRUgzZqi4PnRTUEtX4Ym5U1Xlzmfu5qs0kPnFVxO9bxim1DL4eQopfrfk25wB5cXLu1t3TgjvxSCnIu5BfIQVUvGkvKuuwVxVh2ERSXtJsfmJ5Z6z3Z6aa4rqzUzrUSbP9WbzMdcSAh_YKI2sjq0G7sbzOZ_Z7iMz_EOTk_4nIkviv_0sha6t2yzhT3BabfvXZCWPa1S5LW14-jPkG7AvA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1NWEyNDM2My1mMTA0LTQ0MDItYWE5Mi0yYTgzMWE4NmU2MjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzAsImV4cCI6MTYxNjYwODM3MCwiaWF0IjoxNjE2NTk2NjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Rp8FSyec4_Ynl-48D4wrr1-xFqBr-r8mtx_2vhAvF-lM4VP1J7ogTVMqOnfdwf7BGQBSaIcEpMfjT5Z2TONuchsnZqw5oBDc96cMWEKQD4qs5ovNZhVZycssJboEsOjtOIY9uJnRvSXKSaAfbHJzpT_giKC8sFUM5WoO_S_z7Kms3DlxkHsEmV9gt9ahW3F0pvmGlCBw-ntbprAp7RzqBAIzMtAGbyIOweSboOmn05OPoFu-QfbUJozYTGQCUB7-Yh9pQtXT3T8ovZwt6ZCQv1PTVxOb9JQnOoqhIbx4b1DrsDWV999Iec4R-1kfOnzdohVNExDJplz8tmNNaJWFUQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:50 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1NWEyNDM2My1mMTA0LTQ0MDItYWE5Mi0yYTgzMWE4NmU2MjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzAsImV4cCI6MTYxNjYwODM3MCwiaWF0IjoxNjE2NTk2NjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Rp8FSyec4_Ynl-48D4wrr1-xFqBr-r8mtx_2vhAvF-lM4VP1J7ogTVMqOnfdwf7BGQBSaIcEpMfjT5Z2TONuchsnZqw5oBDc96cMWEKQD4qs5ovNZhVZycssJboEsOjtOIY9uJnRvSXKSaAfbHJzpT_giKC8sFUM5WoO_S_z7Kms3DlxkHsEmV9gt9ahW3F0pvmGlCBw-ntbprAp7RzqBAIzMtAGbyIOweSboOmn05OPoFu-QfbUJozYTGQCUB7-Yh9pQtXT3T8ovZwt6ZCQv1PTVxOb9JQnOoqhIbx4b1DrsDWV999Iec4R-1kfOnzdohVNExDJplz8tmNNaJWFUQ + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1075' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OTk2ZjlmNS0wOWQ2LTRlYWItYjY1Yi1mMjY4MzZjM2E3OTYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzAsImV4cCI6MTYxNjYwMTE3MCwiaWF0IjoxNjE2NTk2NjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Yhdp6P4vAtlqmChdOi4QCXFRkQhR9Rmqba_8ds02prbln4Pl7rKTqZjfqF-RIErkn3mCP3GIXXfjdpKKozLzimeINRtCemp1pepGNvc4YFeroLJZ4txNhYufurvKbmH75BSyW7Trnbgm30RLc0kRkOyBZIn0GkteeZwq0zonX0nrU3pNUS2jIusiYQk2jt9MAmGS5lOotpYqOdQ-D2gXhf-Np0CAXSfWraX02_oDF1LVYz3IlEaaWA0FrDLUuKQgW0-O4uTBRaGvmbarITnZx5d6LE685EO2Ynx8LQHsrdRJ9kCqWChOWSBnhVTJmPP0woPzmin119XslBk6sNRdgQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:52:50 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest @@ -31,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 18:59:31 GMT + - Wed, 24 Mar 2021 14:52:51 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml deleted file mode 100644 index 21f6714348b8..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '597' - content-type: - - application/json; charset=utf-8 - date: - - Tue, 16 Mar 2021 16:28:33 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index df994523904e..ae748419016b 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -9,7 +9,129 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:56:18 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTc0NzcsIm5iZiI6MTYxNjU5NzQ3NywiZXhwIjoxNjE2Njg0MTc3LCJhaW8iOiJFMlpnWU5DdmRMNDl4ZG9wam52cTdlZWFmUEhhQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiaVBrbXhwb3RwMEtFMVg2YjlJa2hBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.BuBjj0q5wsbd9WzlJeclHk9r8gokRU5GY41fH4M0InBjYixHnmtD5EDSCjflztZyrnGALb8UjsAjMlIlwk0y8RPMeTvD2m6BfxPsbVUWXGU6dquWsmet22A_i4RVaTD9NoFj7ywtYTKTHaNyHbIJA1ByGJUoVYn1qyhNPIsIBsvam-P2LkfVTlgDQqMleTlJbck89vzv2PGGvZbN_W_aHoudE1ve1DxUI0yOjM6RpmUmM1SJCS6yWBd48fIUgxDoYjvYu8yGUHLoQGWuNHBudBfOkSxnlIitdePlujorvsvJQCd-oOO6tGnKkFacpt92FT-X2SIcxEGvvTQc6bmdug + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwY2EzYTM5NS03Yzg3LTRhMTktYjM2OS1kNWU1NDk0MmJiZWIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4NzksImV4cCI6MTYxNjYwODU3OSwiaWF0IjoxNjE2NTk2ODc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VhrorgnBXNuxg0cyIM8uXNb04f6O3U442WdScOpcfEJ6l3j5DcfYFrVL5dsyRZjd5cyVjhiJ7PWv0_A0CE6Z9RVclLDAOqSPZ_8S5OoCldJZx8-Z71bj8nwUsgvHJYNsXrY-Tr9DqwYdi4Jxp-uEEiSuE726DY5IbQYCzv5ec0NbV_-24Li9Tot0Vmk3Ei_Lv-m6tGHw_ox8AUV-Q_HTnxBwOzRZNehEXPXwqndvRvRg8BXWTCNzk18b49M94gnaiRbd5U3u6gI9IBpr_adVHJFWwzQwQ-3n1VY_aAJwXSVkJum6bt_GNjmYBia2KB5IDVBeWYAKa-U_xhRRF9rcKw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:56:19 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwY2EzYTM5NS03Yzg3LTRhMTktYjM2OS1kNWU1NDk0MmJiZWIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4NzksImV4cCI6MTYxNjYwODU3OSwiaWF0IjoxNjE2NTk2ODc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VhrorgnBXNuxg0cyIM8uXNb04f6O3U442WdScOpcfEJ6l3j5DcfYFrVL5dsyRZjd5cyVjhiJ7PWv0_A0CE6Z9RVclLDAOqSPZ_8S5OoCldJZx8-Z71bj8nwUsgvHJYNsXrY-Tr9DqwYdi4Jxp-uEEiSuE726DY5IbQYCzv5ec0NbV_-24Li9Tot0Vmk3Ei_Lv-m6tGHw_ox8AUV-Q_HTnxBwOzRZNehEXPXwqndvRvRg8BXWTCNzk18b49M94gnaiRbd5U3u6gI9IBpr_adVHJFWwzQwQ-3n1VY_aAJwXSVkJum6bt_GNjmYBia2KB5IDVBeWYAKa-U_xhRRF9rcKw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1075' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwNGMyNzVlMy1iYTA5LTQwNDMtOTkzNy1hZWZjYzMwYzExNTIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4NzksImV4cCI6MTYxNjYwMTM3OSwiaWF0IjoxNjE2NTk2ODc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Nv4dTh617m6UTelV9wieRk1xXzOI3OEABVAsR-6FTHjfNgmus5V_CVwgxObpyCFbgoWjrMatI_dQUuXjM3Sa-aRKu4yfEOF3iPPKDDXDD5IhkcntbzXPnwFkbF-MBoZLCfELewmTheg1l3KcpbpO3QtUEcqf3QMVlT78g0QL2hOTR4C_E23abiudL9M5yldzclajcApfy6e56Vdugntwbaw_Mjs9qfRJgiweSWIuKQHXN03_grp_vWudF5QbiczHzbbPdHLiGNV5u6lWnwflg76o0tOqzgSqOFbV05SKwCZ9W4fYUXk__mDfNGR64sSuNiH_OB7yYKr10IkDWNQcaw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:56:19 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags @@ -31,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 22:13:00 GMT + - Wed, 24 Mar 2021 14:56:20 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml index 277f34bad509..a2852b160be2 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml @@ -9,7 +9,129 @@ interactions: Connection: - keep-alive User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:56:22 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTc0ODEsIm5iZiI6MTYxNjU5NzQ4MSwiZXhwIjoxNjE2Njg0MTgxLCJhaW8iOiJFMlpnWUxqNmMvUGYyeWxKbWFLYXdjeVZmQ2xKQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZVh1TjlUZE9zMDZIMHZFMVpGSTZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.Q7CGXRpqs6Oumv-agkYDr78LhiwMiwUdVDd21MNCgRE8xsbEdndQ6Chmg1VkVneT5qPzhyp3JhE4NwBKSYKLuNqlsP0_1aYY2Wc59VvGEHW2X-ztEuemQAeZCUsHYDko5v_MNXtiRqqAlrqUwhSjz2jobh-7BQNKmX0TSm2T4DVt2z3N64PydCkpMsyrJWaEbeeoVwjAZ4LPMb-tv9fmbLa6TZR0zGBhQcLhGmXSB9HSC0cOlE66gKn0fXCJmlfUPe8Tw7Szh0jM2IgdELM4gHhUL6p0F2BLHYTmJ5VZ22Ky1AijqIKNHCgy37p4E1gpp8Jq_pet6_AkDms7jUWukw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJlZTY3YmI3NC1lZjk4LTRmODItOTkzMC03NjU4ZTY0NzQ5ODciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4ODMsImV4cCI6MTYxNjYwODU4MywiaWF0IjoxNjE2NTk2ODgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.JwngldsRwkjGfhpGOTrZ5o4MU4IeqSCOI4LZT53UMcVHgSYlc8YYI-agwFrNFzX2y62sy7U9XJ1xPBCVSy3SUKH7F0ngZ6ViXa5MGFNQ_4h-DLnvP61Ni8oW2TuVczwVsVaGaKHqSIWSONEKxUse1dHqapevwZ9NoiOb0Tn05K_r1axDMsc0U7Pwqr7eulUYtdzj_NMh67FTYNNeHgfLUYQehRzvCOM_S8kV6TOioj-vtsPtvPPKzcScQElPCyD66DNTULPlurNrr8VnnHUlbFn_WrDZAS--sji8E6pyCMyiknrQd7Jl2So-3IFcqMshCyEVPu0JcfhAXuRXWXKlbA"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:56:23 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJlZTY3YmI3NC1lZjk4LTRmODItOTkzMC03NjU4ZTY0NzQ5ODciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4ODMsImV4cCI6MTYxNjYwODU4MywiaWF0IjoxNjE2NTk2ODgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.JwngldsRwkjGfhpGOTrZ5o4MU4IeqSCOI4LZT53UMcVHgSYlc8YYI-agwFrNFzX2y62sy7U9XJ1xPBCVSy3SUKH7F0ngZ6ViXa5MGFNQ_4h-DLnvP61Ni8oW2TuVczwVsVaGaKHqSIWSONEKxUse1dHqapevwZ9NoiOb0Tn05K_r1axDMsc0U7Pwqr7eulUYtdzj_NMh67FTYNNeHgfLUYQehRzvCOM_S8kV6TOioj-vtsPtvPPKzcScQElPCyD66DNTULPlurNrr8VnnHUlbFn_WrDZAS--sji8E6pyCMyiknrQd7Jl2So-3IFcqMshCyEVPu0JcfhAXuRXWXKlbA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1075' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwZjQ5YmRhNS0yNmZhLTQ0ZWYtYWRiNy0yZTA0MTUxZjVjNmQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4ODMsImV4cCI6MTYxNjYwMTM4MywiaWF0IjoxNjE2NTk2ODgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.gvbZHWpFXOsTMthgCIAe4MufwLDB7VzQNu51pc2pFp_ZknU2cxSUh2fZXwR-vqtktvNIXJxUhArEGMt-5VDj5WKlybzICtDXkN1cRCWl6o8aLJ4PpxRzoN2al9H__8ipQmk2G9FFDdHDmoVfEslr8G6LtM0Mb8R-P6pjpdKt8P0NhjaHGGz6Omu5992ElQFChrxpU-lsfoTYnyvjlRvhk0fwhCGxOGeagqfQKjSKr3Ov6CF9mkjt4xHZiZn4KUHKzQFUCkmIDoh3GL6eA83xyn0C8MmZANEWOwoMCMXNavZl-XVDJmHDlcDdxfIZytuKenoNh8hpQBJo0mJqu2XANw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:56:23 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 @@ -31,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 18 Mar 2021 22:13:01 GMT + - Wed, 24 Mar 2021 14:56:23 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml index f6442fa4b342..139e60199d66 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml @@ -32,7 +32,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 24 Mar 2021 12:58:35 GMT + - Wed, 24 Mar 2021 14:52:59 GMT docker-distribution-api-version: - registry/2.0 server: @@ -48,7 +48,7 @@ interactions: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTA0MTQsIm5iZiI6MTYxNjU5MDQxNCwiZXhwIjoxNjE2Njc3MTE0LCJhaW8iOiJFMlpnWVBDU25WUHN0KzM2YnQyL1Q5Nm1hTnlkQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoicC1TR01nLUZzRWlyX0tzMmM4d3lBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.ff66r-Lz0TrvDdUXq1zsbwGAyrK7aFoMcXUBecYutkgaGNvVtOjOLhQqqeZDcS4X9tmYCDXqCkpttchJUYWr8qZkYC20JvvPpdiFLtPgBvZ0yiR_DDyvg-jHZPdHGoNN6FufDI3PQ4R_g9JEGsf-VV3LlQAbzfenoMDcv1RlsIoF7EAJFBlYmk2MIFOnJl3_EPKPI0ARwyj-n2tp7gCc4gk90WaEzb4kWWNuWj8DsWSgnwWJrjz7BJtg0Qw-FnDLjvHq-ESTmYj0PAS4wRQ4ayevUhI8D1pZJmHwiLoKQi2DkIHv74ZXG9QJNMlRaLKkXgtWXjDVmYjbX8Qkdgn3mQ + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNzgsIm5iZiI6MTYxNjU5NzI3OCwiZXhwIjoxNjE2NjgzOTc4LCJhaW8iOiJFMlpnWUZpdkpOOHBJZmx4ei9YVG9Wd2x1cmF6QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiWWk4NkJQUEp6MEtzSXlURDZUUkFBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.LLtjtpI_e-KTpvx6KL3pyQQYzOz-ObQErYzIPbJ-NgOdZY080xcjhCJunrTA4ThdxCSTcMiCBgPRrT4hn7pnC_6ykzwP1z20G4UpommcWSZC7np7uIsSvregagFhI6qNrmWIuGPB0ZtQFnvVzdu-IBDP1-9n63htZ1DKZLCS2Kctte1ToTpGQADhtXwpPUBsfKXhftPMVyg4Wxf8RMlGZjWcp-cdXXVpCcg9yWDGFUhI8nmDi7-dPCIbX5H1RNvRGKxDmx97WVe-tuAbudGbGzqB_VnzyusOkmdzVbwt5If_12YiNUFENnPYoVfMSQYX7xarswhTWZeWuBLIJ6MWmg headers: Accept: - application/json @@ -67,14 +67,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4MmJmOTMzNy1hYzIyLTQyZjEtOWUzMC0zZTJjM2U1YTI3NTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1ODk4MTYsImV4cCI6MTYxNjYwMTUxNiwiaWF0IjoxNjE2NTg5ODE2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e9-Br9N1MYCz2xju6TxeqItFKVWMziIc8EO0BcX4Xsec1DrUx9yA28060r5mCB4nv041AMHEy3JkY_d8mu-4jacXS325bF1oJG3CsOviJM47R_qTNcE2bLdAyPXYZpJ0gsXr-a9xnqetL86yLRfQCFUDGyEfxX0YWC471gvuiqDKTwCZAy1a-QiyzHLxoT2DqpLEDUJvrtTYXXvenuio3KvOqz-HLos4dSwbsNUyd77qjlRPHOi-MDs7RTTKMoAD4EhBvj_gQjFQmLEycTe0KxikbFMNA37l-ie2JoY-bQfiJdCWNIY7b4lNzfZ0fF80hv_BHGb91CXJaOxFM3d79Q"}' + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzMjllOTIyZC1jMTA0LTRjMDgtOTQzMS01MzIwZTU2ZTJjZWMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzksImV4cCI6MTYxNjYwODM3OSwiaWF0IjoxNjE2NTk2Njc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.OFcwQH0sUco1vreSpPMa2_5xEhk1nMAj263CEny3laj97NuRCvK44915ivYQd03GlMblPacqDtumWMWzl1096xoCceLEyM95l4kpb-HrdDLLrarZI1oo9x10TnTMgc4T7SBvET_ft56gPt0jhGO7qMrywMePr1ACQyABSCovKZ2wFsILawKnBgpdtv9zIDjl9DX6uO-6khTFsWD3qVQV7lnsHEFEyZ8vckbSxMcpC_Hj1HD24MgrgvPLbZTuWf4ThOaWOwh5V6jcI29jaKeUyC0wXSDfx4md1F2LEYMZFgB0abErSzLl81EWt6FgGlN5S41guFhJTlJcfOWku0krNQ"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Wed, 24 Mar 2021 12:58:36 GMT + - Wed, 24 Mar 2021 14:52:59 GMT server: - openresty strict-transport-security: @@ -85,7 +85,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry:catalog:*&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4MmJmOTMzNy1hYzIyLTQyZjEtOWUzMC0zZTJjM2U1YTI3NTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1ODk4MTYsImV4cCI6MTYxNjYwMTUxNiwiaWF0IjoxNjE2NTg5ODE2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e9-Br9N1MYCz2xju6TxeqItFKVWMziIc8EO0BcX4Xsec1DrUx9yA28060r5mCB4nv041AMHEy3JkY_d8mu-4jacXS325bF1oJG3CsOviJM47R_qTNcE2bLdAyPXYZpJ0gsXr-a9xnqetL86yLRfQCFUDGyEfxX0YWC471gvuiqDKTwCZAy1a-QiyzHLxoT2DqpLEDUJvrtTYXXvenuio3KvOqz-HLos4dSwbsNUyd77qjlRPHOi-MDs7RTTKMoAD4EhBvj_gQjFQmLEycTe0KxikbFMNA37l-ie2JoY-bQfiJdCWNIY7b4lNzfZ0fF80hv_BHGb91CXJaOxFM3d79Q + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry:catalog:*&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzMjllOTIyZC1jMTA0LTRjMDgtOTQzMS01MzIwZTU2ZTJjZWMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzksImV4cCI6MTYxNjYwODM3OSwiaWF0IjoxNjE2NTk2Njc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.OFcwQH0sUco1vreSpPMa2_5xEhk1nMAj263CEny3laj97NuRCvK44915ivYQd03GlMblPacqDtumWMWzl1096xoCceLEyM95l4kpb-HrdDLLrarZI1oo9x10TnTMgc4T7SBvET_ft56gPt0jhGO7qMrywMePr1ACQyABSCovKZ2wFsILawKnBgpdtv9zIDjl9DX6uO-6khTFsWD3qVQV7lnsHEFEyZ8vckbSxMcpC_Hj1HD24MgrgvPLbZTuWf4ThOaWOwh5V6jcI29jaKeUyC0wXSDfx4md1F2LEYMZFgB0abErSzLl81EWt6FgGlN5S41guFhJTlJcfOWku0krNQ headers: Accept: - application/json @@ -104,14 +104,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1YmZjYWQ3NS0xYTVlLTQ5OGEtOTIzYy1hY2U0Mjk2YmU3MmIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1ODk4MTYsImV4cCI6MTYxNjU5NDMxNiwiaWF0IjoxNjE2NTg5ODE2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.EkjUVOfHTXswuvFfSQDC3BYhu23RLwtqEirYtclB4xbS_DBO5YUEthgtwAvaRzaU9RXGB7hutGrFdBvOl6mUw0ZH-xJ6SIGCT1HTQPTqPU6RaXCtv80ErWKDvEmPxxiRpjlo6nVwp3RB91YlVPjmw5MEVU0RXHSbhwZJeRFLBjkfYd0jeaPBjQMNLaDkzWSYROQf6mPsMo_7NYpUo4zYM94711xnvACg_7TfwxwnAt5aoRPt2vi0OLUt6CcQleXa9qByGAXQYduJJ2UhhAzXH6JXPcLB8QF-iXh4WbBKVOfECUJArmWrfx2Pliui6l8UKfbtl3ec7Tl6GYlMB_p3Og"}' + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiYjYwMWVlMi0wMjM5LTQ3YjEtYmNkZC0zYzk2MzM0ODcwYTgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2ODAsImV4cCI6MTYxNjYwMTE4MCwiaWF0IjoxNjE2NTk2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Zor6a4_ekZTUF4EDcykNI65x7tEWPjy19Op_5A6FeeFA944diel4k9VVLDyPmTME1NQQYhmWDC1FPdMfFAIGdjQpo1QOR8TXtSOzHk6Iwlyt7BsyE3MUu8-A__P16U6FCYgPQA69DwmwhInJMpwSKaNGEBl-GnA1U1j_iYMlInQHWiAFuPhjw232lHYeFXcSIJzEQSVugOfJ46AFVYZQ1HGwgAxQXonocfGWvZySE_JX4Wv4BJD_iA_fksR5rxO1A3jFWdSkvCm3SabKZV6ePtzrxsTOXk1p9nHr6QCzAeiRC9UC93COsq5s_v_PGVDJqKd2SJ59tkDhRWNKkCbFTA"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Wed, 24 Mar 2021 12:58:36 GMT + - Wed, 24 Mar 2021 14:53:00 GMT server: - openresty strict-transport-security: @@ -153,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Wed, 24 Mar 2021 12:58:36 GMT + - Wed, 24 Mar 2021 14:53:00 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml new file mode 100644 index 000000000000..3ffc42a07c7a --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml @@ -0,0 +1,74 @@ +interactions: +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTY2NTAsIm5iZiI6MTYxNjU5NjY1MCwiZXhwIjoxNjE2NjgzMzUwLCJhaW8iOiJFMlpnWURqMElNTjFvNkF0bzlzMEg3MFNsWk9DQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiY2k5T3ZOMk5ia3UtVFRBTlZYV0xBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.SZHTpt2ueoYQkI_IaFpndsrpQIgfWOAkYKnOJ0-unpN2ETrK7s_kvJu69VjZRggnRikqHchdULA1EBDgQt456lqREszVwoOnKvb1n_N78IDu1Z7GzhiguHNkXfV4Qq4T_g1LwO1rYpHTyIe0t2Upz9za6hWecxl94YR9mZ0PJuuQXO2qJ74LjxRVKdY6OyHzvcv1kQJDsJJsXCssRN2j7NQUsRHoxKsbhu2TMKwe4IxcbFahv3tom7YkNvs2f-9srqsC3zAj2fqHAqgQwEPcQEjuKcy1MKdFqoRe5iXlRqo5uDixAImMqCk_oxM4W9nHPKw2h3JA4KO5TtCcqbtLUw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzNWUxMzk1MC0wMTBjLTQyNDAtYWQ5MS04MGFlMTU1NDg2OTkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTYwNTAsImV4cCI6MTYxNjYwNzc1MCwiaWF0IjoxNjE2NTk2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZDM8Tlokj2sX5KMIcRmq-J_mh1ZAQxgkDE2FPT2qT8B9z4dTTkPjKbljaZQfjyDF_SrD1zzS8yDYB0LA4N6PjrWZYo6GrJMS7d5dd06mbvhOzUiITOuo2nGJg74L_M88VX4D2Cruq5h3UOBHKIzG1cc9ru7j3lxdNci8HCV37ipDOUJlOhJmzmovQj9YH-VUdrWPRIcMgiDHUN7ITmTxoK3uwEN4h1K-mu8Wt_JNpWXjciDuki3Hky6sgb902rKNrJZMP0K9rwLgwhrdypE-RxQSMDH-k-2EmQfno5XWIC1XRKZrTi6iyYsp_u9HkQNCx4ANtMrVptZFwO9AlTYgfQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Wed, 24 Mar 2021 14:42:30 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=repository:hello-world:metadata_read&scope=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzNWUxMzk1MC0wMTBjLTQyNDAtYWQ5MS04MGFlMTU1NDg2OTkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTYwNTAsImV4cCI6MTYxNjYwNzc1MCwiaWF0IjoxNjE2NTk2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZDM8Tlokj2sX5KMIcRmq-J_mh1ZAQxgkDE2FPT2qT8B9z4dTTkPjKbljaZQfjyDF_SrD1zzS8yDYB0LA4N6PjrWZYo6GrJMS7d5dd06mbvhOzUiITOuo2nGJg74L_M88VX4D2Cruq5h3UOBHKIzG1cc9ru7j3lxdNci8HCV37ipDOUJlOhJmzmovQj9YH-VUdrWPRIcMgiDHUN7ITmTxoK3uwEN4h1K-mu8Wt_JNpWXjciDuki3Hky6sgb902rKNrJZMP0K9rwLgwhrdypE-RxQSMDH-k-2EmQfno5XWIC1XRKZrTi6iyYsp_u9HkQNCx4ANtMrVptZFwO9AlTYgfQ&refresh_token=seankane.azurecr.io + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1075' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, + Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '' + headers: + connection: + - keep-alive + content-length: + - '0' + date: + - Wed, 24 Mar 2021 14:42:31 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + status: + code: 400 + message: Bad Request +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index f016925d8db4..cbaa44b48736 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -12,7 +12,6 @@ from azure.containerregistry import ( ContainerRegistryClient, - ContainerRegistryUserCredential, DeletedRepositoryResult, ) from azure.core.exceptions import ResourceNotFoundError diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 540aef4bc540..b591cbfc1ded 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -45,9 +45,9 @@ def test_get_attributes(self, containerregistry_baseurl): @pytest.mark.live_test_only @acr_preparer() def test_get_properties(self, containerregistry_baseurl): - reg_client = self.create_repository_client(containerregistry_baseurl, "hello-world") + repo_client = self.create_repository_client(containerregistry_baseurl, "hello-world") - properties = reg_client.get_properties() + properties = repo_client.get_properties() assert isinstance(properties, RepositoryProperties) assert properties.name == "hello-world" @@ -58,13 +58,13 @@ def test_get_properties(self, containerregistry_baseurl): @pytest.mark.skip("Pending") @acr_preparer() def test_get_registry_artifact_properties(self, containerregistry_baseurl): - reg_client = self.create_repository_client(containerregistry_baseurl, "hello-world") + repo_client = self.create_repository_client(containerregistry_baseurl, "hello-world") digest = "sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042" tag = "first" - properties = reg_client.get_registry_artifact_properties(digest) - first_properties = reg_client.get_registry_artifact_properties(tag) + properties = repo_client.get_registry_artifact_properties(digest) + first_properties = repo_client.get_registry_artifact_properties(tag) self.assert_registry_artifact(properties, digest) self.assert_registry_artifact(first_properties, tag) @@ -76,7 +76,8 @@ def test_get_tag(self, containerregistry_baseurl): tag = client.get_tag_properties("latest") - self.assert_tag(tag) + assert tag is not None + assert isinstance(tag, TagProperties) @pytest.mark.live_test_only @acr_preparer() @@ -108,11 +109,10 @@ def test_list_tags_descending(self, containerregistry_baseurl): # assert tag.last_updated_on < last_updated_on last_updated_on = tag.last_updated_on count += 1 - # print(tag) assert count > 0 - @pytest.mark.skip("List pending") + @pytest.mark.xfail @acr_preparer() def test_list_registry_artifacts(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -127,10 +127,10 @@ def test_delete_repository(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) client.delete() - reg_client = self.create_registry_client(containerregistry_baseurl) + repo_client = self.create_registry_client(containerregistry_baseurl) repo_count = 0 - for repo in reg_client.list_repositories(): + for repo in repo_client.list_repositories(): repo_count += 1 assert repo_count == 0 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py index b43844e7b6a3..7d4628a3d5be 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py @@ -12,7 +12,6 @@ from azure.containerregistry import ( ContainerRegistryClient, - ContainerRegistryUserCredential, ContainerRepositoryClient, DeletedRepositoryResult, ACRExchangeClient @@ -40,7 +39,7 @@ def create_exchange_client(self, endpoint): endpoint=endpoint, ) - @pytest.mark.live_test_only + @pytest.mark.skip("not needed") @acr_preparer() def test_exchange_client(self, containerregistry_baseurl): client = self.create_exchange_client(containerregistry_baseurl) @@ -59,12 +58,6 @@ def test_exchange_client(self, containerregistry_baseurl): assert len(access_token) > 100 print(access_token) - # access_token = client.get_acr_access_token(service, scope) - # assert access_token is not None - # assert len(access_token) > 100 - # print(access_token) - - @pytest.mark.live_test_only @acr_preparer() def test_auth_policy_in_action(self, containerregistry_baseurl): @@ -77,5 +70,4 @@ def test_auth_policy_in_action(self, containerregistry_baseurl): for repo in client.list_repositories(): assert repo is not None assert repo != prev - prev = repo - print(repo) \ No newline at end of file + prev = repo \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index b3eaeb25524e..0732e8bd0955 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -9,31 +9,26 @@ from azure.containerregistry import ( ContainerRepositoryClient, ContainerRegistryClient, - ContainerRegistryUserCredential, TagProperties, ContentPermissions, RegistryArtifactProperties, ) +from azure.identity import DefaultAzureCredential + class ContainerRegistryTestClass(object): def create_registry_client(self, endpoint): return ContainerRegistryClient( endpoint=endpoint, - credential=ContainerRegistryUserCredential( - username=os.environ["CONTAINERREGISTRY_USERNAME"], - password=os.environ["CONTAINERREGISTRY_PASSWORD"], - ), + credential=DefaultAzureCredential(), ) def create_repository_client(self, endpoint, name): return ContainerRepositoryClient( endpoint=endpoint, repository=name, - credential=ContainerRegistryUserCredential( - username=os.environ["CONTAINERREGISTRY_USERNAME"], - password=os.environ["CONTAINERREGISTRY_PASSWORD"], - ), + credential=DefaultAzureCredential(), ) def assert_content_permission(self, content_perm, content_perm2): @@ -56,7 +51,7 @@ def assert_tag( repository=None, ): assert isinstance(tag, TagProperties) - assert isinstance(tag.content_permissions, ContentPermissions) + assert isinstance(tag.writeable_permissions, ContentPermissions) assert isinstance(tag.created_on, datetime) assert isinstance(tag.last_updated_on, datetime) if content_permission: From f3dc7464e6150aff9c25ac2fe74cc452bf5e952a Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 11:16:59 -0400 Subject: [PATCH 57/86] deleting recordings --- ...test_delete_repository_does_not_exist.yaml | 174 ------------------ ...egistry_client.test_list_repositories.yaml | 169 ----------------- ...gistry_client.test_list_repositories2.yaml | 47 ----- ...repository_client.test_get_attributes.yaml | 169 ----------------- ...repository_client.test_get_properties.yaml | 169 ----------------- ...test_get_registry_artifact_properties.yaml | 89 --------- ...tainer_repository_client.test_get_tag.yaml | 169 ----------------- ...iner_repository_client.test_list_tags.yaml | 169 ----------------- ...tory_client.test_list_tags_descending.yaml | 169 ----------------- ...nge_client.test_auth_policy_in_action.yaml | 169 ----------------- ..._exchange_client.test_exchange_client.yaml | 74 -------- 11 files changed, 1567 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml deleted file mode 100644 index e5c5d4a5acf3..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml +++ /dev/null @@ -1,174 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '0' - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE - uri: https://fake_url.azurecr.io/acr/v1/not_real_repo - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '209' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:37 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:not_real_repo:delete",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNTYsIm5iZiI6MTYxNjU5NzI1NiwiZXhwIjoxNjE2NjgzOTU2LCJhaW8iOiJFMlpnWUZCYWFGTE5rbWVmbnBKMzgzTHRJMWxIQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRkgxdi1zWnJSa083alBhM1FYazlBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.b0WiVDarwGEItqLvydUyOR47TBzt2Ss2UTn3O4DqFyRrStDiZW5vIk_K-wXnOvxHO2nC08NjhyweMht0BQYueORdaxlP5345-5Z3POu0ONrKM6L9IGHQ3bUOslFtJgUUzgc_M1_eEKwUuDy0hbDfbCmTRfQJIcl5HqX_dKNjlLYsZwbX-Fejg3tXefh2ldgqqvPS8UJ6rbQ4gzg8V_nCC48GpneWota6Okdn9DxNLlx9K_ZGgxZBWDnEUk6vYDc6BLVNZZMl1mMaVADkhwKVWk0N2AAQs_WBgep5E1jd_vhcNgK0mFg__YL4HvIHgPCbKiP7-6aztoMTzZMnUodKDA - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3MGY4YmEzYi1iMmM4LTQ4NGMtYTExMi03YTRmNzZjNTg5N2YiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NTgsImV4cCI6MTYxNjYwODM1OCwiaWF0IjoxNjE2NTk2NjU4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.jsr6b2GTW75zWkoTwUTFKV7D0GWf-pU443qPYhctCOCfp9Y1q24HuLyfK7a4SfhocOOQ-tJ8Q3ccWOKBT_1AI05aecTTOKEn1rzNBnXIrI2W-juQSiQp5B_muL4195itqPOlq7FoqAsqFputSL4zf8_tBBtK_Bt-03cwq5-TU_SrKXXzdrwBf-klCFkX7_tJfIBhqWaKylEULi6NZfVaiZu0ZatowrwIgD-XWFr1IJyIl2l_hGv0HPS1x8ZEActR6-i5F-qf0PvVL_3ihRndeknF9mcRPDBdqWYvDd_AFdMZE6HDJOgLM8evXn0HgJ6Um2GCbE14JGBa9Jr9mXOE6g"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:38 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:not_real_repo:delete&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3MGY4YmEzYi1iMmM4LTQ4NGMtYTExMi03YTRmNzZjNTg5N2YiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NTgsImV4cCI6MTYxNjYwODM1OCwiaWF0IjoxNjE2NTk2NjU4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.jsr6b2GTW75zWkoTwUTFKV7D0GWf-pU443qPYhctCOCfp9Y1q24HuLyfK7a4SfhocOOQ-tJ8Q3ccWOKBT_1AI05aecTTOKEn1rzNBnXIrI2W-juQSiQp5B_muL4195itqPOlq7FoqAsqFputSL4zf8_tBBtK_Bt-03cwq5-TU_SrKXXzdrwBf-klCFkX7_tJfIBhqWaKylEULi6NZfVaiZu0ZatowrwIgD-XWFr1IJyIl2l_hGv0HPS1x8ZEActR6-i5F-qf0PvVL_3ihRndeknF9mcRPDBdqWYvDd_AFdMZE6HDJOgLM8evXn0HgJ6Um2GCbE14JGBa9Jr9mXOE6g - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1070' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5MmUxOTNiZC1mYjRkLTQ4MTktYjI0Yi0zMzJlNzE5NmM4N2EiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NTgsImV4cCI6MTYxNjYwMTE1OCwiaWF0IjoxNjE2NTk2NjU4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJub3RfcmVhbF9yZXBvIiwiYWN0aW9ucyI6WyJkZWxldGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.HNEXAHBCyubysC0z_Ywm8Gefp3E1AZaPcP_8i-5ncj9Zao7qBCPIjts2IfN3Z4SHrJUcT4sIpgy7FkBe7PAZoTXMCIZK-H7CdeLx2G8hZsLmiqdUJ8T_Otv7xlbXe5MMRkIOtTxjPiqSdhE-vJHX_UZ52bUdBcqUty7HoyMpkuoRqa9R-yJN9vYbDZq4clZmTfDH4ih0ZBhmyeKSPE8t8g3wnKBjPS8-xeuD9IQTFJ1tB1BIeLjsEae76HmIrUeossJkHPFGv6ygV3tQu4AkvspDSwlnTNZQq5gdz4DMLYs68Dv_1dXMe4xVE5iYorTExYfU8o9SFQ2Xct9r-emrjw"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:38 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '0' - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE - uri: https://fake_url.azurecr.io/acr/v1/not_real_repo - response: - body: - string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known - to registry","detail":{"name":"not_real_repo"}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '121' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:38 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 404 - message: Not Found -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml deleted file mode 100644 index 61d6dba93055..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ /dev/null @@ -1,169 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '196' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:40 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNTksIm5iZiI6MTYxNjU5NzI1OSwiZXhwIjoxNjE2NjgzOTU5LCJhaW8iOiJFMlpnWVBpOHZ2WDN1NDRRTzRaQ2tZZ3ZoaXhOQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiTFJTRWk0dkpORXFoWjBpXy00RXdBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.chHqHOLx4lnmIKpXa35d8bgKvQT7HnXhWqheMgaX2N8_-gmXd7yU_FZAmFSHqmXY-p6qfEs_h4f7btM8LWy-9NaP5che0Ux8kho0Pa-uFTyxZbIdwOiqQ9SmsjAqj4l7CiSDhwTMJe1-DGcGRIPFshgGxqmFWqll8ac-p16L3b3qc2Rh5IxOy5c7_7EIYHtKoUm0tAxtuGjHK5t02SrBDLqm730r9Pc2RuVsagUfTOIr1TqphhvXx5ileM5uXa1hENSM055crIdw0H2q47gSqfz0l0zd0g18drJtVBblWzK8KP86DimqXKimycTIUPG97h8qN_91NBUtKluIJJSV8A - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0YzQyM2FmNi0yN2UyLTQ1NzQtYWVjYy00ZGE0MDQyNmVlMGMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjEsImV4cCI6MTYxNjYwODM2MSwiaWF0IjoxNjE2NTk2NjYxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.SqQUVh3H5-YmHzcqOf4qZ4j9FNSthKtRPCjMfxD77IEsrHeeSzqVYvOXbYU34j0bL5b4WwxaEWeY-MX-561pl6oVi30HbquNEUQw5gvJoNJnpVsbV9-KmPo3C_puSFSrh8h_0sTuuPYI2jX0WsQuIqFptGtHsvzqL1dqtvnQubT53ci8hUD7zpHLYoXGEGGM-DtdHmXY8eToRKqqyUFM-6kiWapY2WpxXtu6tLzPKMhAh9UlVkEi9y2ezKx4JlE8ZZQv9eNtRuvRlT3bomBNLWlhuUDGf7svBLhPx2JLrsv-5j3_VsNHu5oWly5Fb2wACfppjgKzwYyg_HZFUOBjog"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:41 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry:catalog:*&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0YzQyM2FmNi0yN2UyLTQ1NzQtYWVjYy00ZGE0MDQyNmVlMGMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjEsImV4cCI6MTYxNjYwODM2MSwiaWF0IjoxNjE2NTk2NjYxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.SqQUVh3H5-YmHzcqOf4qZ4j9FNSthKtRPCjMfxD77IEsrHeeSzqVYvOXbYU34j0bL5b4WwxaEWeY-MX-561pl6oVi30HbquNEUQw5gvJoNJnpVsbV9-KmPo3C_puSFSrh8h_0sTuuPYI2jX0WsQuIqFptGtHsvzqL1dqtvnQubT53ci8hUD7zpHLYoXGEGGM-DtdHmXY8eToRKqqyUFM-6kiWapY2WpxXtu6tLzPKMhAh9UlVkEi9y2ezKx4JlE8ZZQv9eNtRuvRlT3bomBNLWlhuUDGf7svBLhPx2JLrsv-5j3_VsNHu5oWly5Fb2wACfppjgKzwYyg_HZFUOBjog - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1057' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhZGI0Y2JkMy04ZDA4LTRkYTUtYmVkZi04OGY0MjhlOTYwNGMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjEsImV4cCI6MTYxNjYwMTE2MSwiaWF0IjoxNjE2NTk2NjYxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.jzAZSWImjrFuU_QCPn5kmf624sLrftc7bcxoP_xeutgUmlEUolx_4jzDN9dut5zHnt1uxSdFGv85odjwNsn7KGW8o3dwUu-597Tr31N_W9m11IpwqKbudZbUMn_wXRW9BHc8khYyXHR5diQezU6s_vub8zMGguZtFFDQWjleKi5PhhA95CFfzWzNNKUmTdoU5u44r63YMywz26ic2iqxt6p822WRBfQLi--k_jS-XapDmp90HlaEBZBYMnrQC1Ate4hF1fexRI8jNEhmElU2kF27CdZb5y47f2-d18BwQtJl9WxQMLddYhzP6VRj6Z2s_4wNkaCBpj7bD8OvHL_nIw"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:41 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '125' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:42 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml deleted file mode 100644 index 5000163caa3c..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["hello-world"]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '33' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 15:54:32 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml deleted file mode 100644 index e6a581c5e27b..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ /dev/null @@ -1,169 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '214' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:43 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNjIsIm5iZiI6MTYxNjU5NzI2MiwiZXhwIjoxNjE2NjgzOTYyLCJhaW8iOiJFMlpnWUtneUZUcHkzK3YzNHlkcW43bWZUQy8zQndBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibjc5eFVFT1VTMGVZdVlRXzdfSk1BQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.HPp1dIWySftlZwhkCVqD-Lz6DVa185aOCKCDF1CiGWOJDDQ30mxEmFxj7sC1X0ZoXLuNwUZpZfsZLK9TzCuQORkLWKl6W6l4-qJVlAAygr21XS7BWBdztWbV5JTn0HFETj4hoa-dpta5QKW5mZvlRLd7H8cxsHRCne9vXGjC4DSw-u_8EQGR-hCNvi3W2z0QFDB6Z5i3MplDkIXMkhxk70JMccobwyfdbTBFilF8kZgUcjOaKhqGZkG4zkxKrs6M1WXQZ1r7PznZbZlhwzFWCCycfqvkFJ3rD3KDybGESgvAB5JJ7wqhjXMi5Y-BAzHud6txhs_q4OEZTVNbod8jGg - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5OWI0NmU0ZC00MjgzLTQ2MTItYTBlNy00NGRiNmRlMWYzNWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjQsImV4cCI6MTYxNjYwODM2NCwiaWF0IjoxNjE2NTk2NjY0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.DocYXlucsuYp59eWsNUTtZJc0nUFivsBd_nr3y4TT622Eru31nDEsb922-75Ioy4qPmI_7GL_6eKp3d7TJlzoy4s77CxdEmKcRfdYdw4H9NVVXgiqL0f8dUDDHAKp123LgQvJ2KXHiV1i3J8-yZeOvSoKNiy5Uk8EzzZig7CmrKSG1yETiP3S1XBTJhoMeEmHuNzOfe3jLnYhQEZtggTO0zNvLNgQSjDPTUr_n2lovCBMVVCEnL8HL8KiE_XpaCkKJI7PXruhXDAjE-i5zYbdVub6W4BEI7sv-u5PMMRehgLc8BXYyP-J--5OK09MwZGS8TmvW_3cKtzCv8Y6VBixg"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:44 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5OWI0NmU0ZC00MjgzLTQ2MTItYTBlNy00NGRiNmRlMWYzNWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjQsImV4cCI6MTYxNjYwODM2NCwiaWF0IjoxNjE2NTk2NjY0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.DocYXlucsuYp59eWsNUTtZJc0nUFivsBd_nr3y4TT622Eru31nDEsb922-75Ioy4qPmI_7GL_6eKp3d7TJlzoy4s77CxdEmKcRfdYdw4H9NVVXgiqL0f8dUDDHAKp123LgQvJ2KXHiV1i3J8-yZeOvSoKNiy5Uk8EzzZig7CmrKSG1yETiP3S1XBTJhoMeEmHuNzOfe3jLnYhQEZtggTO0zNvLNgQSjDPTUr_n2lovCBMVVCEnL8HL8KiE_XpaCkKJI7PXruhXDAjE-i5zYbdVub6W4BEI7sv-u5PMMRehgLc8BXYyP-J--5OK09MwZGS8TmvW_3cKtzCv8Y6VBixg - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1075' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2ZjhiZjE1MS02YWM3LTRjYjQtYWI4Zi1lNjBmOTE5ZmM0Y2QiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjQsImV4cCI6MTYxNjYwMTE2NCwiaWF0IjoxNjE2NTk2NjY0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Kb7hq32WI_KwUXBnAdu1N7XLoe3juA0X3n4Qtcgb1myk6xX7e6Xlb9dbpr1LqboAR1Jl-pmr1uXVWC3uhVcYrKnsR5eO5pM5ABOwp1gNkNmFevJYucZz73Bb_2YrIld4nRNMysabs3iRaSDu3Mh2OujXE3z7S2Mmh1puip05gziUSUWAOwd5t-IuTzEQBhsHOsrWweCghHjR1W0qiMSd-5UbHUhd-aueXZ6CHqGrnxji-pVZtAUet0UrSH8ddYIJ6BGkr4lltXEXlQCFgvgiXjiWr7-4Jw1mPo4E3CpGaC_EcnCPsDA7HvlczYVMDM0Kaiq8SBbP41KdXChTNjOEdg"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:44 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '289' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:45 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml deleted file mode 100644 index 7d50f17a576d..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ /dev/null @@ -1,169 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '214' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:46 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNjYsIm5iZiI6MTYxNjU5NzI2NiwiZXhwIjoxNjE2NjgzOTY2LCJhaW8iOiJFMlpnWVBDZGMyaCtVK3FYdUsrdGY0UXFHTnFmQWdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2J0WkRBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.a9EqIfAYmMzqdlAd4ufV3ebsxFjMwNFwwQ64PVKNtxz1zZ478S0pbXFqbMA4I_250RAJbjRd5bB7rnSqJFO7HfJ2CWtDkehrTiKrkiCxA9PngNPjs3uTOMM-doaJFuORO8dzGfyvmiNpS4bi0VBpgdN1sFGHEdmIz91-qj8MIRNfmJV5_-3yakJnFlj7bjVEI-35_HNT7LuMW9qmroel-ijsLg5si6vJ5ntiXTPwX4ob3si4kSIH18METXZGit0i00UqXk3Zh0BRXJWIguV06jkazFurlaciq81VLNBnxboZNYfNbaHZLgtjCMaRzqxgi6bruFTHv-kJaZys71Czow - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5ODYzYjY5YS00YzM2LTQ5NWUtOTg4OS04ZTcyZGM2YzgwNTgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjcsImV4cCI6MTYxNjYwODM2NywiaWF0IjoxNjE2NTk2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VjHgVZbEEbUetEu9DmM64aWPs6YQkQx8CVFQSoqLrHvryWTsFU3qvbuUq5Z5SNvk3ZH8gEAOT8bNJ52m4T84EiFoUOKlZZaS7mmIdf92SYWQao00d9nxDqWMYra3Y6Woe04gUFAvJz_ZFQGdL1paHAyFpJtMbrOtBAKD2EjDLidgd6bCfQ0cSyRA0kVg7_LfYdrmhFE6f4c-FasUR9pgHyPAd12l-FYwPIpb6uS-_lKuMoh5HG8unQBAn3W1eEYLrAfqj2ZV8CCUKMhIoqW3kbDg3hikoL5PD-exXsB-qG9QxDGRncZhnCR6v8KE5_wnOEgcFGRb0DlI9dI_OKaz6A"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:47 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5ODYzYjY5YS00YzM2LTQ5NWUtOTg4OS04ZTcyZGM2YzgwNTgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjcsImV4cCI6MTYxNjYwODM2NywiaWF0IjoxNjE2NTk2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VjHgVZbEEbUetEu9DmM64aWPs6YQkQx8CVFQSoqLrHvryWTsFU3qvbuUq5Z5SNvk3ZH8gEAOT8bNJ52m4T84EiFoUOKlZZaS7mmIdf92SYWQao00d9nxDqWMYra3Y6Woe04gUFAvJz_ZFQGdL1paHAyFpJtMbrOtBAKD2EjDLidgd6bCfQ0cSyRA0kVg7_LfYdrmhFE6f4c-FasUR9pgHyPAd12l-FYwPIpb6uS-_lKuMoh5HG8unQBAn3W1eEYLrAfqj2ZV8CCUKMhIoqW3kbDg3hikoL5PD-exXsB-qG9QxDGRncZhnCR6v8KE5_wnOEgcFGRb0DlI9dI_OKaz6A - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1075' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIxMTQ5YmVjMy0xZmIxLTQ2ZmEtOTIxNi1hYWI2NzQxN2Q5OTQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NjcsImV4cCI6MTYxNjYwMTE2NywiaWF0IjoxNjE2NTk2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.ZLs8UNXciEAc17kbh4Fix0i01dYqDvr4HmvmJkgFOOKkWmNrX-CvTkIkngEh8ghedq0HCDzNkp79EmZdckFmPsvd_7xFVQTGl9DcJ5QcNydOST1mOVaJ8laMIid-Zjw60kUZj8CWtQxGQMluvhN_4yqKlHJt_RSdlyhNhGJrRmmzyNVYWsoZMcZt49T1ONAx9WiKNZb-Ns5hgn-MuOOxepgeKJD1hNCDWfStARCluviF-XLqk8Nya7iKtX1Dgj0vsMvGU-xvmzKcGJ5xJTAOCZc3l-az5k8r4UXGVvBNPeptTHVyQkukELQt0BvGXm-j-arWfw9PbLD97C1VuaBVew"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:47 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '289' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:48 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml deleted file mode 100644 index a1fee822f8a6..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml +++ /dev/null @@ -1,89 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security - Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/18/2021 8:35:38 AM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '911' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 18:59:43 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/first - response: - body: - string: '404 page not found - - ' - headers: - connection: - - keep-alive - content-length: - - '19' - content-type: - - text/plain; charset=utf-8 - date: - - Thu, 18 Mar 2021 18:59:43 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 404 - message: Not Found -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml deleted file mode 100644 index b0d5f7f435cd..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml +++ /dev/null @@ -1,169 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '214' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:49 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNjksIm5iZiI6MTYxNjU5NzI2OSwiZXhwIjoxNjE2NjgzOTY5LCJhaW8iOiJFMlpnWUZpU3NUVG13U1VYaHlmYVdldVhQdGN1QVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZDFfZ2Z6ZGU0RTJnbHFWeHlfd3lBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.G77ErPwUhYK0OZ4AHtaHG3dvLkEJm8L6Zn2YL55GHLOMo-G5eNqhv7Vk1UXNxz8677tflVOtrR2plFsi0Aa4qxhVeykrfSEWtxiyMnklcO2LAXNsOFMvLFiitJ8OKZ7CmRUgzZqi4PnRTUEtX4Ym5U1Xlzmfu5qs0kPnFVxO9bxim1DL4eQopfrfk25wB5cXLu1t3TgjvxSCnIu5BfIQVUvGkvKuuwVxVh2ERSXtJsfmJ5Z6z3Z6aa4rqzUzrUSbP9WbzMdcSAh_YKI2sjq0G7sbzOZ_Z7iMz_EOTk_4nIkviv_0sha6t2yzhT3BabfvXZCWPa1S5LW14-jPkG7AvA - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1NWEyNDM2My1mMTA0LTQ0MDItYWE5Mi0yYTgzMWE4NmU2MjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzAsImV4cCI6MTYxNjYwODM3MCwiaWF0IjoxNjE2NTk2NjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Rp8FSyec4_Ynl-48D4wrr1-xFqBr-r8mtx_2vhAvF-lM4VP1J7ogTVMqOnfdwf7BGQBSaIcEpMfjT5Z2TONuchsnZqw5oBDc96cMWEKQD4qs5ovNZhVZycssJboEsOjtOIY9uJnRvSXKSaAfbHJzpT_giKC8sFUM5WoO_S_z7Kms3DlxkHsEmV9gt9ahW3F0pvmGlCBw-ntbprAp7RzqBAIzMtAGbyIOweSboOmn05OPoFu-QfbUJozYTGQCUB7-Yh9pQtXT3T8ovZwt6ZCQv1PTVxOb9JQnOoqhIbx4b1DrsDWV999Iec4R-1kfOnzdohVNExDJplz8tmNNaJWFUQ"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:50 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1NWEyNDM2My1mMTA0LTQ0MDItYWE5Mi0yYTgzMWE4NmU2MjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzAsImV4cCI6MTYxNjYwODM3MCwiaWF0IjoxNjE2NTk2NjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Rp8FSyec4_Ynl-48D4wrr1-xFqBr-r8mtx_2vhAvF-lM4VP1J7ogTVMqOnfdwf7BGQBSaIcEpMfjT5Z2TONuchsnZqw5oBDc96cMWEKQD4qs5ovNZhVZycssJboEsOjtOIY9uJnRvSXKSaAfbHJzpT_giKC8sFUM5WoO_S_z7Kms3DlxkHsEmV9gt9ahW3F0pvmGlCBw-ntbprAp7RzqBAIzMtAGbyIOweSboOmn05OPoFu-QfbUJozYTGQCUB7-Yh9pQtXT3T8ovZwt6ZCQv1PTVxOb9JQnOoqhIbx4b1DrsDWV999Iec4R-1kfOnzdohVNExDJplz8tmNNaJWFUQ - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1075' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OTk2ZjlmNS0wOWQ2LTRlYWItYjY1Yi1mMjY4MzZjM2E3OTYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzAsImV4cCI6MTYxNjYwMTE3MCwiaWF0IjoxNjE2NTk2NjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Yhdp6P4vAtlqmChdOi4QCXFRkQhR9Rmqba_8ds02prbln4Pl7rKTqZjfqF-RIErkn3mCP3GIXXfjdpKKozLzimeINRtCemp1pepGNvc4YFeroLJZ4txNhYufurvKbmH75BSyW7Trnbgm30RLc0kRkOyBZIn0GkteeZwq0zonX0nrU3pNUS2jIusiYQk2jt9MAmGS5lOotpYqOdQ-D2gXhf-Np0CAXSfWraX02_oDF1LVYz3IlEaaWA0FrDLUuKQgW0-O4uTBRaGvmbarITnZx5d6LE685EO2Ynx8LQHsrdRJ9kCqWChOWSBnhVTJmPP0woPzmin119XslBk6sNRdgQ"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:50 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '380' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:51 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml deleted file mode 100644 index ae748419016b..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ /dev/null @@ -1,169 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '214' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:18 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTc0NzcsIm5iZiI6MTYxNjU5NzQ3NywiZXhwIjoxNjE2Njg0MTc3LCJhaW8iOiJFMlpnWU5DdmRMNDl4ZG9wam52cTdlZWFmUEhhQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiaVBrbXhwb3RwMEtFMVg2YjlJa2hBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.BuBjj0q5wsbd9WzlJeclHk9r8gokRU5GY41fH4M0InBjYixHnmtD5EDSCjflztZyrnGALb8UjsAjMlIlwk0y8RPMeTvD2m6BfxPsbVUWXGU6dquWsmet22A_i4RVaTD9NoFj7ywtYTKTHaNyHbIJA1ByGJUoVYn1qyhNPIsIBsvam-P2LkfVTlgDQqMleTlJbck89vzv2PGGvZbN_W_aHoudE1ve1DxUI0yOjM6RpmUmM1SJCS6yWBd48fIUgxDoYjvYu8yGUHLoQGWuNHBudBfOkSxnlIitdePlujorvsvJQCd-oOO6tGnKkFacpt92FT-X2SIcxEGvvTQc6bmdug - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwY2EzYTM5NS03Yzg3LTRhMTktYjM2OS1kNWU1NDk0MmJiZWIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4NzksImV4cCI6MTYxNjYwODU3OSwiaWF0IjoxNjE2NTk2ODc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VhrorgnBXNuxg0cyIM8uXNb04f6O3U442WdScOpcfEJ6l3j5DcfYFrVL5dsyRZjd5cyVjhiJ7PWv0_A0CE6Z9RVclLDAOqSPZ_8S5OoCldJZx8-Z71bj8nwUsgvHJYNsXrY-Tr9DqwYdi4Jxp-uEEiSuE726DY5IbQYCzv5ec0NbV_-24Li9Tot0Vmk3Ei_Lv-m6tGHw_ox8AUV-Q_HTnxBwOzRZNehEXPXwqndvRvRg8BXWTCNzk18b49M94gnaiRbd5U3u6gI9IBpr_adVHJFWwzQwQ-3n1VY_aAJwXSVkJum6bt_GNjmYBia2KB5IDVBeWYAKa-U_xhRRF9rcKw"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:19 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwY2EzYTM5NS03Yzg3LTRhMTktYjM2OS1kNWU1NDk0MmJiZWIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4NzksImV4cCI6MTYxNjYwODU3OSwiaWF0IjoxNjE2NTk2ODc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.VhrorgnBXNuxg0cyIM8uXNb04f6O3U442WdScOpcfEJ6l3j5DcfYFrVL5dsyRZjd5cyVjhiJ7PWv0_A0CE6Z9RVclLDAOqSPZ_8S5OoCldJZx8-Z71bj8nwUsgvHJYNsXrY-Tr9DqwYdi4Jxp-uEEiSuE726DY5IbQYCzv5ec0NbV_-24Li9Tot0Vmk3Ei_Lv-m6tGHw_ox8AUV-Q_HTnxBwOzRZNehEXPXwqndvRvRg8BXWTCNzk18b49M94gnaiRbd5U3u6gI9IBpr_adVHJFWwzQwQ-3n1VY_aAJwXSVkJum6bt_GNjmYBia2KB5IDVBeWYAKa-U_xhRRF9rcKw - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1075' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwNGMyNzVlMy1iYTA5LTQwNDMtOTkzNy1hZWZjYzMwYzExNTIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4NzksImV4cCI6MTYxNjYwMTM3OSwiaWF0IjoxNjE2NTk2ODc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Nv4dTh617m6UTelV9wieRk1xXzOI3OEABVAsR-6FTHjfNgmus5V_CVwgxObpyCFbgoWjrMatI_dQUuXjM3Sa-aRKu4yfEOF3iPPKDDXDD5IhkcntbzXPnwFkbF-MBoZLCfELewmTheg1l3KcpbpO3QtUEcqf3QMVlT78g0QL2hOTR4C_E23abiudL9M5yldzclajcApfy6e56Vdugntwbaw_Mjs9qfRJgiweSWIuKQHXN03_grp_vWudF5QbiczHzbbPdHLiGNV5u6lWnwflg76o0tOqzgSqOFbV05SKwCZ9W4fYUXk__mDfNGR64sSuNiH_OB7yYKr10IkDWNQcaw"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:19 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '722' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:20 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml deleted file mode 100644 index a2852b160be2..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml +++ /dev/null @@ -1,169 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '214' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:22 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTc0ODEsIm5iZiI6MTYxNjU5NzQ4MSwiZXhwIjoxNjE2Njg0MTgxLCJhaW8iOiJFMlpnWUxqNmMvUGYyeWxKbWFLYXdjeVZmQ2xKQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZVh1TjlUZE9zMDZIMHZFMVpGSTZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.Q7CGXRpqs6Oumv-agkYDr78LhiwMiwUdVDd21MNCgRE8xsbEdndQ6Chmg1VkVneT5qPzhyp3JhE4NwBKSYKLuNqlsP0_1aYY2Wc59VvGEHW2X-ztEuemQAeZCUsHYDko5v_MNXtiRqqAlrqUwhSjz2jobh-7BQNKmX0TSm2T4DVt2z3N64PydCkpMsyrJWaEbeeoVwjAZ4LPMb-tv9fmbLa6TZR0zGBhQcLhGmXSB9HSC0cOlE66gKn0fXCJmlfUPe8Tw7Szh0jM2IgdELM4gHhUL6p0F2BLHYTmJ5VZ22Ky1AijqIKNHCgy37p4E1gpp8Jq_pet6_AkDms7jUWukw - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJlZTY3YmI3NC1lZjk4LTRmODItOTkzMC03NjU4ZTY0NzQ5ODciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4ODMsImV4cCI6MTYxNjYwODU4MywiaWF0IjoxNjE2NTk2ODgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.JwngldsRwkjGfhpGOTrZ5o4MU4IeqSCOI4LZT53UMcVHgSYlc8YYI-agwFrNFzX2y62sy7U9XJ1xPBCVSy3SUKH7F0ngZ6ViXa5MGFNQ_4h-DLnvP61Ni8oW2TuVczwVsVaGaKHqSIWSONEKxUse1dHqapevwZ9NoiOb0Tn05K_r1axDMsc0U7Pwqr7eulUYtdzj_NMh67FTYNNeHgfLUYQehRzvCOM_S8kV6TOioj-vtsPtvPPKzcScQElPCyD66DNTULPlurNrr8VnnHUlbFn_WrDZAS--sji8E6pyCMyiknrQd7Jl2So-3IFcqMshCyEVPu0JcfhAXuRXWXKlbA"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:23 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository:hello-world:metadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJlZTY3YmI3NC1lZjk4LTRmODItOTkzMC03NjU4ZTY0NzQ5ODciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4ODMsImV4cCI6MTYxNjYwODU4MywiaWF0IjoxNjE2NTk2ODgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.JwngldsRwkjGfhpGOTrZ5o4MU4IeqSCOI4LZT53UMcVHgSYlc8YYI-agwFrNFzX2y62sy7U9XJ1xPBCVSy3SUKH7F0ngZ6ViXa5MGFNQ_4h-DLnvP61Ni8oW2TuVczwVsVaGaKHqSIWSONEKxUse1dHqapevwZ9NoiOb0Tn05K_r1axDMsc0U7Pwqr7eulUYtdzj_NMh67FTYNNeHgfLUYQehRzvCOM_S8kV6TOioj-vtsPtvPPKzcScQElPCyD66DNTULPlurNrr8VnnHUlbFn_WrDZAS--sji8E6pyCMyiknrQd7Jl2So-3IFcqMshCyEVPu0JcfhAXuRXWXKlbA - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1075' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwZjQ5YmRhNS0yNmZhLTQ0ZWYtYWRiNy0yZTA0MTUxZjVjNmQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY4ODMsImV4cCI6MTYxNjYwMTM4MywiaWF0IjoxNjE2NTk2ODgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.gvbZHWpFXOsTMthgCIAe4MufwLDB7VzQNu51pc2pFp_ZknU2cxSUh2fZXwR-vqtktvNIXJxUhArEGMt-5VDj5WKlybzICtDXkN1cRCWl6o8aLJ4PpxRzoN2al9H__8ipQmk2G9FFDdHDmoVfEslr8G6LtM0Mb8R-P6pjpdKt8P0NhjaHGGz6Omu5992ElQFChrxpU-lsfoTYnyvjlRvhk0fwhCGxOGeagqfQKjSKr3Ov6CF9mkjt4xHZiZn4KUHKzQFUCkmIDoh3GL6eA83xyn0C8MmZANEWOwoMCMXNavZl-XVDJmHDlcDdxfIZytuKenoNh8hpQBJo0mJqu2XANw"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:23 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '722' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:56:23 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml deleted file mode 100644 index 139e60199d66..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml +++ /dev/null @@ -1,169 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '196' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:59 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTcyNzgsIm5iZiI6MTYxNjU5NzI3OCwiZXhwIjoxNjE2NjgzOTc4LCJhaW8iOiJFMlpnWUZpdkpOOHBJZmx4ei9YVG9Wd2x1cmF6QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiWWk4NkJQUEp6MEtzSXlURDZUUkFBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.LLtjtpI_e-KTpvx6KL3pyQQYzOz-ObQErYzIPbJ-NgOdZY080xcjhCJunrTA4ThdxCSTcMiCBgPRrT4hn7pnC_6ykzwP1z20G4UpommcWSZC7np7uIsSvregagFhI6qNrmWIuGPB0ZtQFnvVzdu-IBDP1-9n63htZ1DKZLCS2Kctte1ToTpGQADhtXwpPUBsfKXhftPMVyg4Wxf8RMlGZjWcp-cdXXVpCcg9yWDGFUhI8nmDi7-dPCIbX5H1RNvRGKxDmx97WVe-tuAbudGbGzqB_VnzyusOkmdzVbwt5If_12YiNUFENnPYoVfMSQYX7xarswhTWZeWuBLIJ6MWmg - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzMjllOTIyZC1jMTA0LTRjMDgtOTQzMS01MzIwZTU2ZTJjZWMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzksImV4cCI6MTYxNjYwODM3OSwiaWF0IjoxNjE2NTk2Njc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.OFcwQH0sUco1vreSpPMa2_5xEhk1nMAj263CEny3laj97NuRCvK44915ivYQd03GlMblPacqDtumWMWzl1096xoCceLEyM95l4kpb-HrdDLLrarZI1oo9x10TnTMgc4T7SBvET_ft56gPt0jhGO7qMrywMePr1ACQyABSCovKZ2wFsILawKnBgpdtv9zIDjl9DX6uO-6khTFsWD3qVQV7lnsHEFEyZ8vckbSxMcpC_Hj1HD24MgrgvPLbZTuWf4ThOaWOwh5V6jcI29jaKeUyC0wXSDfx4md1F2LEYMZFgB0abErSzLl81EWt6FgGlN5S41guFhJTlJcfOWku0krNQ"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:52:59 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry:catalog:*&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzMjllOTIyZC1jMTA0LTRjMDgtOTQzMS01MzIwZTU2ZTJjZWMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2NzksImV4cCI6MTYxNjYwODM3OSwiaWF0IjoxNjE2NTk2Njc5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.OFcwQH0sUco1vreSpPMa2_5xEhk1nMAj263CEny3laj97NuRCvK44915ivYQd03GlMblPacqDtumWMWzl1096xoCceLEyM95l4kpb-HrdDLLrarZI1oo9x10TnTMgc4T7SBvET_ft56gPt0jhGO7qMrywMePr1ACQyABSCovKZ2wFsILawKnBgpdtv9zIDjl9DX6uO-6khTFsWD3qVQV7lnsHEFEyZ8vckbSxMcpC_Hj1HD24MgrgvPLbZTuWf4ThOaWOwh5V6jcI29jaKeUyC0wXSDfx4md1F2LEYMZFgB0abErSzLl81EWt6FgGlN5S41guFhJTlJcfOWku0krNQ - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1057' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiYjYwMWVlMi0wMjM5LTQ3YjEtYmNkZC0zYzk2MzM0ODcwYTgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTY2ODAsImV4cCI6MTYxNjYwMTE4MCwiaWF0IjoxNjE2NTk2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.Zor6a4_ekZTUF4EDcykNI65x7tEWPjy19Op_5A6FeeFA944diel4k9VVLDyPmTME1NQQYhmWDC1FPdMfFAIGdjQpo1QOR8TXtSOzHk6Iwlyt7BsyE3MUu8-A__P16U6FCYgPQA69DwmwhInJMpwSKaNGEBl-GnA1U1j_iYMlInQHWiAFuPhjw232lHYeFXcSIJzEQSVugOfJ46AFVYZQ1HGwgAxQXonocfGWvZySE_JX4Wv4BJD_iA_fksR5rxO1A3jFWdSkvCm3SabKZV6ePtzrxsTOXk1p9nHr6QCzAeiRC9UC93COsq5s_v_PGVDJqKd2SJ59tkDhRWNKkCbFTA"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:53:00 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '125' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:53:00 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml deleted file mode 100644 index 3ffc42a07c7a..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_exchange_client.yaml +++ /dev/null @@ -1,74 +0,0 @@ -interactions: -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY1OTY2NTAsIm5iZiI6MTYxNjU5NjY1MCwiZXhwIjoxNjE2NjgzMzUwLCJhaW8iOiJFMlpnWURqMElNTjFvNkF0bzlzMEg3MFNsWk9DQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiY2k5T3ZOMk5ia3UtVFRBTlZYV0xBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.SZHTpt2ueoYQkI_IaFpndsrpQIgfWOAkYKnOJ0-unpN2ETrK7s_kvJu69VjZRggnRikqHchdULA1EBDgQt456lqREszVwoOnKvb1n_N78IDu1Z7GzhiguHNkXfV4Qq4T_g1LwO1rYpHTyIe0t2Upz9za6hWecxl94YR9mZ0PJuuQXO2qJ74LjxRVKdY6OyHzvcv1kQJDsJJsXCssRN2j7NQUsRHoxKsbhu2TMKwe4IxcbFahv3tom7YkNvs2f-9srqsC3zAj2fqHAqgQwEPcQEjuKcy1MKdFqoRe5iXlRqo5uDixAImMqCk_oxM4W9nHPKw2h3JA4KO5TtCcqbtLUw - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzNWUxMzk1MC0wMTBjLTQyNDAtYWQ5MS04MGFlMTU1NDg2OTkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTYwNTAsImV4cCI6MTYxNjYwNzc1MCwiaWF0IjoxNjE2NTk2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZDM8Tlokj2sX5KMIcRmq-J_mh1ZAQxgkDE2FPT2qT8B9z4dTTkPjKbljaZQfjyDF_SrD1zzS8yDYB0LA4N6PjrWZYo6GrJMS7d5dd06mbvhOzUiITOuo2nGJg74L_M88VX4D2Cruq5h3UOBHKIzG1cc9ru7j3lxdNci8HCV37ipDOUJlOhJmzmovQj9YH-VUdrWPRIcMgiDHUN7ITmTxoK3uwEN4h1K-mu8Wt_JNpWXjciDuki3Hky6sgb902rKNrJZMP0K9rwLgwhrdypE-RxQSMDH-k-2EmQfno5XWIC1XRKZrTi6iyYsp_u9HkQNCx4ANtMrVptZFwO9AlTYgfQ"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Wed, 24 Mar 2021 14:42:30 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=repository:hello-world:metadata_read&scope=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzNWUxMzk1MC0wMTBjLTQyNDAtYWQ5MS04MGFlMTU1NDg2OTkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY1OTYwNTAsImV4cCI6MTYxNjYwNzc1MCwiaWF0IjoxNjE2NTk2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZDM8Tlokj2sX5KMIcRmq-J_mh1ZAQxgkDE2FPT2qT8B9z4dTTkPjKbljaZQfjyDF_SrD1zzS8yDYB0LA4N6PjrWZYo6GrJMS7d5dd06mbvhOzUiITOuo2nGJg74L_M88VX4D2Cruq5h3UOBHKIzG1cc9ru7j3lxdNci8HCV37ipDOUJlOhJmzmovQj9YH-VUdrWPRIcMgiDHUN7ITmTxoK3uwEN4h1K-mu8Wt_JNpWXjciDuki3Hky6sgb902rKNrJZMP0K9rwLgwhrdypE-RxQSMDH-k-2EmQfno5XWIC1XRKZrTi6iyYsp_u9HkQNCx4ANtMrVptZFwO9AlTYgfQ&refresh_token=seankane.azurecr.io - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1075' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '' - headers: - connection: - - keep-alive - content-length: - - '0' - date: - - Wed, 24 Mar 2021 14:42:31 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - status: - code: 400 - message: Bad Request -version: 1 From aef65bd4fb4d93963eb50cf31a6d74d21a7a4c3b Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 11:25:57 -0400 Subject: [PATCH 58/86] authentication flow test --- .../tests/test_auth_flow.py | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py b/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py new file mode 100644 index 000000000000..69c56e0a767a --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py @@ -0,0 +1,63 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools +import os +import pytest + +from devtools_testutils import AzureTestCase, PowerShellPreparer + +from azure.containerregistry import ( + ContainerRepositoryClient, + ContainerRegistryClient, + RepositoryProperties, + ContentPermissions, + TagProperties, + TagOrderBy, +) +from azure.core.paging import ItemPaged +from azure.identity import DefaultAzureCredential + +from testcase import ContainerRegistryTestClass + +acr_preparer = functools.partial( + PowerShellPreparer, + "containerregistry", + containerregistry_baseurl="fake_url.azurecr.io", +) + + +class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): + + repository = "hello-world" + + @pytest.mark.live_test_only + @acr_preparer() + def test_get_refresh_token(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + + service = "seankane.azurecr.io" + scope = "repository:hello-world:metadata_read" + + d = DefaultAzureCredential() + + token = d.get_token("https://management.core.windows.net/.default").token + print(token) + + m = Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema( + service=service, + scope=scope, + aad_accesstoken=token, + ) + + refresh = client._client.authentication.exchange_aad_token_for_acr_refresh_token(m) + + m = PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema( + service=service, + scope=scope, + acr_refresh_token=refresh.refresh_token, + ) + + assert m.access_token \ No newline at end of file From 6304e3790f7c4288f11411ef207d546afc6fd922 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 11:36:14 -0400 Subject: [PATCH 59/86] regenerated --- .../_generated/_container_registry.py | 20 ---------------- .../_generated/aio/_container_registry.py | 18 -------------- .../operations/_authentication_operations.py | 10 ++++---- .../_container_registry_blob_operations.py | 18 +++++++------- .../_container_registry_operations.py | 6 ++--- ...ontainer_registry_repository_operations.py | 24 +++++++++---------- .../_generated/models/_models.py | 5 ---- .../_generated/models/_models_py3.py | 6 ----- .../operations/_authentication_operations.py | 12 +++++----- .../_container_registry_blob_operations.py | 18 +++++++------- .../_container_registry_operations.py | 6 ++--- ...ontainer_registry_repository_operations.py | 24 +++++++++---------- .../azure-containerregistry/swagger/README.md | 2 +- 13 files changed, 60 insertions(+), 109 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py index e25449264e14..412246dce869 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py @@ -13,8 +13,6 @@ # pylint: disable=unused-import,ungrouped-imports from typing import Any - from azure.core.pipeline.transport import HttpRequest, HttpResponse - from ._configuration import ContainerRegistryConfiguration from .operations import ContainerRegistryOperations from .operations import ContainerRegistryRepositoryOperations @@ -62,24 +60,6 @@ def __init__( self.authentication = AuthenticationOperations( self._client, self._config, self._serialize, self._deserialize) - def _send_request(self, http_request, **kwargs): - # type: (HttpRequest, Any) -> HttpResponse - """Runs the network request through the client's chained policies. - - :param http_request: The network request you want to make. Required. - :type http_request: ~azure.core.pipeline.transport.HttpRequest - :keyword bool stream: Whether the response payload will be streamed. Defaults to True. - :return: The response of your network call. Does not do error handling on your response. - :rtype: ~azure.core.pipeline.transport.HttpResponse - """ - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - http_request.url = self._client.format_url(http_request.url, **path_format_arguments) - stream = kwargs.pop("stream", True) - pipeline_response = self._client._pipeline.run(http_request, stream=stream, **kwargs) - return pipeline_response.http_response - def close(self): # type: () -> None self._client.close() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py index ed0014488c0f..0a9c67e71803 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py @@ -7,7 +7,6 @@ from typing import Any from azure.core import AsyncPipelineClient -from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest from msrest import Deserializer, Serializer from ._configuration import ContainerRegistryConfiguration @@ -56,23 +55,6 @@ def __init__( self.authentication = AuthenticationOperations( self._client, self._config, self._serialize, self._deserialize) - async def _send_request(self, http_request: HttpRequest, **kwargs: Any) -> AsyncHttpResponse: - """Runs the network request through the client's chained policies. - - :param http_request: The network request you want to make. Required. - :type http_request: ~azure.core.pipeline.transport.HttpRequest - :keyword bool stream: Whether the response payload will be streamed. Defaults to True. - :return: The response of your network call. Does not do error handling on your response. - :rtype: ~azure.core.pipeline.transport.AsyncHttpResponse - """ - path_format_arguments = { - 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), - } - http_request.url = self._client.format_url(http_request.url, **path_format_arguments) - stream = kwargs.pop("stream", True) - pipeline_response = await self._client._pipeline.run(http_request, stream=stream, **kwargs) - return pipeline_response.http_response - async def close(self) -> None: await self._client.close() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py index 27f0c12f8146..fe3b4ac65b9b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py @@ -37,7 +37,7 @@ def __init__(self, client, config, serializer, deserializer) -> None: self._deserialize = deserializer self._config = config - async def exchange_aad_token_for_acr_refresh_token( + async def exchange_aad_access_token_for_acr_refresh_token( self, aad_accesstoken: Optional["_models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] = None, **kwargs @@ -60,7 +60,7 @@ async def exchange_aad_token_for_acr_refresh_token( accept = "application/json" # Construct URL - url = self.exchange_aad_token_for_acr_refresh_token.metadata['url'] # type: ignore + url = self.exchange_aad_access_token_for_acr_refresh_token.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), } @@ -86,7 +86,7 @@ async def exchange_aad_token_for_acr_refresh_token( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrRefreshToken', pipeline_response) @@ -95,7 +95,7 @@ async def exchange_aad_token_for_acr_refresh_token( return cls(pipeline_response, deserialized, {}) return deserialized - exchange_aad_token_for_acr_refresh_token.metadata = {'url': '/oauth2/exchange'} # type: ignore + exchange_aad_access_token_for_acr_refresh_token.metadata = {'url': '/oauth2/exchange'} # type: ignore async def exchange_acr_refresh_token_for_acr_access_token( self, @@ -146,7 +146,7 @@ async def exchange_acr_refresh_token_for_acr_access_token( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrAccessToken', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py index 21b1b334411c..6ea47ff442fa 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py @@ -147,7 +147,7 @@ async def check_blob_exists( if response.status_code not in [200, 307]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -271,7 +271,7 @@ async def mount_blob( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -328,7 +328,7 @@ async def get_upload_status( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -390,7 +390,7 @@ async def upload_chunk( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -407,7 +407,7 @@ async def complete_upload( self, digest: str, location: str, - value: Optional[IO] = None, + value: IO, **kwargs ) -> None: """Complete the upload, providing all the data in the body, if necessary. A request without a body @@ -458,7 +458,7 @@ async def complete_upload( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -515,7 +515,7 @@ async def cancel_upload( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -565,7 +565,7 @@ async def start_upload( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -696,7 +696,7 @@ async def check_chunk_exists( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py index 539ca7ae23af..09b4addc2975 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py @@ -76,7 +76,7 @@ async def check_docker_v2_support( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -153,7 +153,7 @@ async def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -206,7 +206,7 @@ async def delete_repository( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('DeleteRepositoryResult', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index a5e395308f25..84c40d58ad53 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -91,7 +91,7 @@ async def get_manifest( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('Manifest', pipeline_response) @@ -157,7 +157,7 @@ async def create_manifest( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -219,7 +219,7 @@ async def delete_manifest( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -269,7 +269,7 @@ async def get_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RepositoryProperties', pipeline_response) @@ -333,7 +333,7 @@ async def set_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -425,7 +425,7 @@ async def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -482,7 +482,7 @@ async def get_tag_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('TagProperties', pipeline_response) @@ -550,7 +550,7 @@ async def update_tag_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -604,7 +604,7 @@ async def delete_tag( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -691,7 +691,7 @@ async def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -748,7 +748,7 @@ async def get_registry_artifact_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RegistryArtifactProperties', pipeline_response) @@ -816,7 +816,7 @@ async def update_manifest_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 7dddb2d55637..81934d82941b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -767,8 +767,6 @@ class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlenco :vartype grant_type: str :param service: Required. Indicates the name of your Azure container registry. :type service: str - :param tenant: Required. AAD tenant associated to the AAD credentials. - :type tenant: str :param aad_accesstoken: Required. AAD access token, mandatory when grant_type is access_token_refresh_token or access_token. :type aad_accesstoken: str @@ -777,14 +775,12 @@ class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlenco _validation = { 'grant_type': {'required': True, 'constant': True}, 'service': {'required': True}, - 'tenant': {'required': True}, 'aad_accesstoken': {'required': True}, } _attribute_map = { 'grant_type': {'key': 'grant_type', 'type': 'str'}, 'service': {'key': 'service', 'type': 'str'}, - 'tenant': {'key': 'tenant', 'type': 'str'}, 'aad_accesstoken': {'key': 'access_token', 'type': 'str'}, } @@ -796,7 +792,6 @@ def __init__( ): super(Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) self.service = kwargs['service'] - self.tenant = kwargs['tenant'] self.aad_accesstoken = kwargs['aad_accesstoken'] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index d9bd66c77216..8fe23c8756ef 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -886,8 +886,6 @@ class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlenco :vartype grant_type: str :param service: Required. Indicates the name of your Azure container registry. :type service: str - :param tenant: Required. AAD tenant associated to the AAD credentials. - :type tenant: str :param aad_accesstoken: Required. AAD access token, mandatory when grant_type is access_token_refresh_token or access_token. :type aad_accesstoken: str @@ -896,14 +894,12 @@ class Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlenco _validation = { 'grant_type': {'required': True, 'constant': True}, 'service': {'required': True}, - 'tenant': {'required': True}, 'aad_accesstoken': {'required': True}, } _attribute_map = { 'grant_type': {'key': 'grant_type', 'type': 'str'}, 'service': {'key': 'service', 'type': 'str'}, - 'tenant': {'key': 'tenant', 'type': 'str'}, 'aad_accesstoken': {'key': 'access_token', 'type': 'str'}, } @@ -913,13 +909,11 @@ def __init__( self, *, service: str, - tenant: str, aad_accesstoken: str, **kwargs ): super(Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema, self).__init__(**kwargs) self.service = service - self.tenant = tenant self.aad_accesstoken = aad_accesstoken diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py index 4abf8f4a1f82..9c82246fd6f2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py @@ -41,7 +41,7 @@ def __init__(self, client, config, serializer, deserializer): self._deserialize = deserializer self._config = config - def exchange_aad_token_for_acr_refresh_token( + def exchange_aad_access_token_for_acr_refresh_token( self, aad_accesstoken=None, # type: Optional["_models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] **kwargs # type: Any @@ -65,7 +65,7 @@ def exchange_aad_token_for_acr_refresh_token( accept = "application/json" # Construct URL - url = self.exchange_aad_token_for_acr_refresh_token.metadata['url'] # type: ignore + url = self.exchange_aad_access_token_for_acr_refresh_token.metadata['url'] # type: ignore path_format_arguments = { 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), } @@ -84,14 +84,14 @@ def exchange_aad_token_for_acr_refresh_token( body_content = self._serialize.body(aad_accesstoken, 'Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema') else: body_content = None - body_content_kwargs['form_content'] = body_content + body_content_kwargs['content'] = body_content request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrRefreshToken', pipeline_response) @@ -100,7 +100,7 @@ def exchange_aad_token_for_acr_refresh_token( return cls(pipeline_response, deserialized, {}) return deserialized - exchange_aad_token_for_acr_refresh_token.metadata = {'url': '/oauth2/exchange'} # type: ignore + exchange_aad_access_token_for_acr_refresh_token.metadata = {'url': '/oauth2/exchange'} # type: ignore def exchange_acr_refresh_token_for_acr_access_token( self, @@ -152,7 +152,7 @@ def exchange_acr_refresh_token_for_acr_access_token( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrAccessToken', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py index b10afab300ba..3c680cd2311f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py @@ -153,7 +153,7 @@ def check_blob_exists( if response.status_code not in [200, 307]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -279,7 +279,7 @@ def mount_blob( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -337,7 +337,7 @@ def get_upload_status( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -400,7 +400,7 @@ def upload_chunk( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -417,7 +417,7 @@ def complete_upload( self, digest, # type: str location, # type: str - value=None, # type: Optional[IO] + value, # type: IO **kwargs # type: Any ): # type: (...) -> None @@ -469,7 +469,7 @@ def complete_upload( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -527,7 +527,7 @@ def cancel_upload( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -578,7 +578,7 @@ def start_upload( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -711,7 +711,7 @@ def check_chunk_exists( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py index c994d5627f59..8f3532ede045 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py @@ -81,7 +81,7 @@ def check_docker_v2_support( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -159,7 +159,7 @@ def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -213,7 +213,7 @@ def delete_repository( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('DeleteRepositoryResult', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index 36968b545726..a244957e7e13 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -96,7 +96,7 @@ def get_manifest( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('Manifest', pipeline_response) @@ -163,7 +163,7 @@ def create_manifest( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -226,7 +226,7 @@ def delete_manifest( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -277,7 +277,7 @@ def get_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RepositoryProperties', pipeline_response) @@ -342,7 +342,7 @@ def set_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -435,7 +435,7 @@ def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -493,7 +493,7 @@ def get_tag_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('TagProperties', pipeline_response) @@ -562,7 +562,7 @@ def update_tag_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -617,7 +617,7 @@ def delete_tag( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -705,7 +705,7 @@ def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -763,7 +763,7 @@ def get_registry_artifact_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RegistryArtifactProperties', pipeline_response) @@ -832,7 +832,7 @@ def update_manifest_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) + error = self._deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index 049a82248395..ce31c501855c 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -2,5 +2,5 @@ ### Settings ``` yaml -input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/aa5edc4d4cb0298bde52c939a7c948692f3285e1/sdk/containerregistry/container-registry/swagger/containerregistry.json +input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/e40f55d5fa64d177c0267b52129c77aa353f95d8/sdk/containerregistry/container-registry/swagger/containerregistry.json ``` \ No newline at end of file From 17a1a0793bd271c902bf60c65fc93eb889425201 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 11:41:50 -0400 Subject: [PATCH 60/86] fixing up test --- .../azure-containerregistry/tests/test_auth_flow.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py b/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py index 69c56e0a767a..73cc799add17 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py @@ -48,11 +48,10 @@ def test_get_refresh_token(self, containerregistry_baseurl): m = Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema( service=service, - scope=scope, aad_accesstoken=token, ) - refresh = client._client.authentication.exchange_aad_token_for_acr_refresh_token(m) + refresh = client._client.authentication.exchange_aad_access_token_for_acr_refresh_token(m) m = PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema( service=service, From 7465c81ca0f8d4cce4145872eb9865e4516d8c66 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 15:50:33 -0400 Subject: [PATCH 61/86] new generated code, fixed user agent, passing tests --- .../_authentication_policy.py | 2 +- .../azure/containerregistry/_base_client.py | 2 +- .../_container_registry_client.py | 9 +- .../_container_repository_client.py | 66 +++++++------- .../containerregistry/_exchange_client.py | 35 +++++--- .../_generated/_container_registry.py | 20 +++++ .../_generated/aio/_container_registry.py | 18 ++++ .../operations/_authentication_operations.py | 59 ++++++++----- .../_container_registry_blob_operations.py | 18 ++-- .../_container_registry_operations.py | 6 +- ...ontainer_registry_repository_operations.py | 24 ++--- .../operations/_authentication_operations.py | 59 ++++++++----- .../_container_registry_blob_operations.py | 18 ++-- .../_container_registry_operations.py | 6 +- ...ontainer_registry_repository_operations.py | 24 ++--- .../azure/containerregistry/_models.py | 31 ++++--- .../azure/containerregistry/_user_agent.py | 4 +- .../authentication/_authentication_policy.py | 6 +- .../_container_registry_credential_policy.py | 2 +- .../azure-containerregistry/swagger/README.md | 1 + .../tests/test_auth_flow.py | 19 ++-- .../tests/test_container_repository_client.py | 88 +++++++++++++++---- 22 files changed, 332 insertions(+), 185 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index 6ace4394cbe4..89dfaa3379b8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -47,7 +47,7 @@ def __init__(self, credential, *scopes, **kwargs): self._token = None # type: Optional[AccessToken] self._exchange_client = ACRExchangeClient("seankane.azurecr.io", self._credential) - def need_new_token(self): + def _need_new_token(self): # type: () -> bool return True diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 035b66d08bbc..9261f4dcc170 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -54,4 +54,4 @@ def close(self): def _is_tag(self, tag_or_digest): # pylint: disable=no-self-use tag = tag_or_digest.split(":") - return len(tag) == 2 and tag[0] == u"sha" + return not (len(tag) == 2 and tag[0].startswith(u"sha")) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 324aaf86ae71..59231507dead 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -29,8 +29,8 @@ def __init__(self, endpoint, credential, **kwargs): """ if not endpoint.startswith("https://"): endpoint = "https://" + endpoint - self.endpoint = endpoint - self.credential = credential + self._endpoint = endpoint + self._credential = credential super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) def delete_repository(self, repository, **kwargs): @@ -43,8 +43,7 @@ def delete_repository(self, repository, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # NOTE: DELETE `/acr/v1/{name}` - deleted_repository = self._client.container_registry.delete_repository(repository, **kwargs) - return DeletedRepositoryResult.from_generated(deleted_repository) + return DeletedRepositoryResult._from_generated(self._client.container_registry.delete_repository(repository, **kwargs)) def list_repositories(self, **kwargs): # type: (Dict[str, Any]) -> ItemPaged[str] @@ -69,4 +68,4 @@ def get_repository_client(self, repository, **kwargs): :type repository: str :returns: :class:~azure.containerregistry.ContainerRepositoryClient """ - return ContainerRepositoryClient(self.endpoint, repository, credential=self.credential, **kwargs) + return ContainerRepositoryClient(self._endpoint, repository, credential=self._credential, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 67263eaeaaf8..4ff863924f3e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -31,9 +31,9 @@ def __init__(self, endpoint, repository, credential, **kwargs): """ if not endpoint.startswith("https://"): endpoint = "https://" + endpoint - self.endpoint = endpoint + self._endpoint = endpoint self.repository = repository - super(ContainerRepositoryClient, self).__init__(endpoint=self.endpoint, credential=credential, **kwargs) + super(ContainerRepositoryClient, self).__init__(endpoint=self._endpoint, credential=credential, **kwargs) def delete(self, **kwargs): # type: (...) -> None @@ -69,9 +69,9 @@ def delete_tag(self, tag): def get_digest_from_tag(self, tag): # type: (str) -> str for t in self.list_tags(): - if t.tag == tag: + if t.name == tag: return t.digest - return "" + raise ValueError("Could not find a digest for tag {}".format(tag)) def get_properties(self): # type: (...) -> RepositoryProperties @@ -81,8 +81,7 @@ def get_properties(self): :raises: None """ # GET '/acr/v1/{name}' - resp = self._client.container_registry_repository.get_properties(self.repository) - return RepositoryProperties.from_generated(resp) + return RepositoryProperties._from_generated(self._client.container_registry_repository.get_properties(self.repository)) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): # type: (str, Dict[str, Any]) -> RegistryArtifactProperties @@ -94,12 +93,10 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # GET '/acr/v1/{name}/_manifests/{digest}' - # TODO: If `tag_or_digest` is a tag, need to do a get_tags to find the appropriate digest, - # generated code only takes a digest if self._is_tag(tag_or_digest): tag_or_digest = self.get_digest_from_tag(tag_or_digest) - # TODO: The returned object from the generated code is not being deserialized properly - return RegistryArtifactProperties.from_generated( + + return RegistryArtifactProperties._from_generated( self._client.container_registry_repository.get_registry_artifact_properties( self.repository, tag_or_digest, **kwargs ) @@ -115,13 +112,13 @@ def get_tag_properties(self, tag, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # GET '/acr/v1/{name}/_tags/{reference}' - return TagProperties.from_generated( + return TagProperties._from_generated( self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) ) def list_registry_artifacts(self, **kwargs): # type: (...) -> ItemPaged[RegistryArtifactProperties] - """List the registry artifacts for a repository + """List the artifacts for a repository :keyword last: Query parameter for the last item in the previous query :type last: str @@ -132,17 +129,14 @@ def list_registry_artifacts(self, **kwargs): :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] :raises: None """ - raise NotImplementedError("Not implemented") - # TODO: turn this into an ItemPaged - # artifacts = self._client.manifests.get_list( - # self.repository, - # last=kwargs.get("last", None), - # n=kwargs.get("n", None), - # orderby=kwargs.get("orderby"), - # ) # , - # # cls=lambda objs: [RegistryArtifacts.from_generated(x) for x in objs]) - - # return RegistryArtifactProperties.from_generated(artifacts) + # GET /acr/v1/{name}/_manifests + last = kwargs.pop("last", None) + n = kwargs.pop("top", None) + orderby = kwargs.pop("order_by", None) + return self._client.container_registry_repository.get_manifests( + self.repository, last=last, n=n, orderby=orderby, + cls=lambda objs: [RegistryArtifactProperties._from_generated(x) for x in objs] + ) def list_tags(self, **kwargs): # type: (...) -> ItemPaged[TagProperties] @@ -161,32 +155,40 @@ def list_tags(self, **kwargs): n=kwargs.pop("top", None), orderby=kwargs.pop("order_by", None), digest=kwargs.pop("digest", None), - cls=lambda objs: [TagProperties.from_generated(o) for o in objs], + cls=lambda objs: [TagProperties._from_generated(o) for o in objs], **kwargs ) - def set_manifest_properties(self, digest, value): + def set_manifest_properties(self, digest, permissions): # type: (str, ContentPermissions) -> None """Set the properties for a manifest :param digest: Digest of a manifest :type digest: str - :param value: The property's values to be set - :type value: ContentPermissions + :param permissions: The property's values to be set + :type permissions: ContentPermissions :returns: ~azure.core.paging.ItemPaged[TagProperties] :raises: None """ - raise NotImplementedError("Has not been implemented") - def set_tag_properties(self, tag, permissions): + self._client.container_registry_repository.update_manifest_attributes( + self.repository, digest, permissions.to_generated() + ) + + def set_tag_properties(self, tag_or_digest, permissions): # type: (str, ContentPermissions) -> None """Set the properties for a tag :param tag: Tag to set properties for :type tag: str - :param value: The property's values to be set - :type value: ContentPermissions + :param permissions: The property's values to be set + :type permissions: ContentPermissions :returns: ~azure.core.paging.ItemPaged[TagProperties] :raises: None """ - raise NotImplementedError("Has not been implemented") + if self._is_tag(tag_or_digest): + tag_or_digest = self.get_digest_from_tag(tag_or_digest) + + self._client.container_registry_repository.update_manifest_attributes( + self.repository, tag_or_digest, permissions.to_generated() + ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py index 3312b7facb63..a97626056b29 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -66,27 +66,36 @@ def get_acr_access_token(self, challenge): def exchange_aad_token_for_refresh_token(self, service=None, scope=None, **kwargs): - body = """grant_type=access_token&service={}&access_token={}""".format(service, self._credential.get_token(self._credential_scopes).token) + # body = """grant_type=access_token&service={}&access_token={}""".format(service, self._credential.get_token(self._credential_scopes).token) - headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} - request = HttpRequest("POST", self._endpoint + "/oauth2/exchange", headers=headers, data=body) + # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} + # request = HttpRequest("POST", self._endpoint + "/oauth2/exchange", headers=headers, data=body) - resp = self._client._client._pipeline.run(request) - refresh_token = resp.http_response.internal_response.content - return json.loads(refresh_token)["refresh_token"] + # resp = self._client._client._pipeline.run(request) + # refresh_token = resp.http_response.internal_response.content + + # return json.loads(refresh_token)["refresh_token"] + + refresh_token = self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( + service, self._credential.get_token(self._credential_scopes).token) + return refresh_token.refresh_token def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): - body = """grant_type=refresh_token&service={}&scope={}&refresh_token={}""".format( - service, scope, refresh_token) + # body = """grant_type=refresh_token&service={}&scope={}&refresh_token={}""".format( + # service, scope, refresh_token) - headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} - request = HttpRequest("POST", self._endpoint + "/oauth2/token", headers=headers, data=body) + # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} + # request = HttpRequest("POST", self._endpoint + "/oauth2/token", headers=headers, data=body) - resp = self._client._client._pipeline.run(request) + # resp = self._client._client._pipeline.run(request) - access_token = resp.http_response.internal_response.content - return json.loads(access_token)["access_token"] + # access_token = resp.http_response.internal_response.content + # return json.loads(access_token)["access_token"] + + access_token = self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( + service, scope, refresh_token) + return access_token.access_token def _parse_challenge(self, header): # type: (str) -> Dict[str, Any] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py index 412246dce869..e25449264e14 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/_container_registry.py @@ -13,6 +13,8 @@ # pylint: disable=unused-import,ungrouped-imports from typing import Any + from azure.core.pipeline.transport import HttpRequest, HttpResponse + from ._configuration import ContainerRegistryConfiguration from .operations import ContainerRegistryOperations from .operations import ContainerRegistryRepositoryOperations @@ -60,6 +62,24 @@ def __init__( self.authentication = AuthenticationOperations( self._client, self._config, self._serialize, self._deserialize) + def _send_request(self, http_request, **kwargs): + # type: (HttpRequest, Any) -> HttpResponse + """Runs the network request through the client's chained policies. + + :param http_request: The network request you want to make. Required. + :type http_request: ~azure.core.pipeline.transport.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to True. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.pipeline.transport.HttpResponse + """ + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + http_request.url = self._client.format_url(http_request.url, **path_format_arguments) + stream = kwargs.pop("stream", True) + pipeline_response = self._client._pipeline.run(http_request, stream=stream, **kwargs) + return pipeline_response.http_response + def close(self): # type: () -> None self._client.close() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py index 0a9c67e71803..ed0014488c0f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/_container_registry.py @@ -7,6 +7,7 @@ from typing import Any from azure.core import AsyncPipelineClient +from azure.core.pipeline.transport import AsyncHttpResponse, HttpRequest from msrest import Deserializer, Serializer from ._configuration import ContainerRegistryConfiguration @@ -55,6 +56,23 @@ def __init__( self.authentication = AuthenticationOperations( self._client, self._config, self._serialize, self._deserialize) + async def _send_request(self, http_request: HttpRequest, **kwargs: Any) -> AsyncHttpResponse: + """Runs the network request through the client's chained policies. + + :param http_request: The network request you want to make. Required. + :type http_request: ~azure.core.pipeline.transport.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to True. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.pipeline.transport.AsyncHttpResponse + """ + path_format_arguments = { + 'url': self._serialize.url("self._config.url", self._config.url, 'str', skip_quote=True), + } + http_request.url = self._client.format_url(http_request.url, **path_format_arguments) + stream = kwargs.pop("stream", True) + pipeline_response = await self._client._pipeline.run(http_request, stream=stream, **kwargs) + return pipeline_response.http_response + async def close(self) -> None: await self._client.close() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py index fe3b4ac65b9b..c63c725fb81f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_authentication_operations.py @@ -39,13 +39,17 @@ def __init__(self, client, config, serializer, deserializer) -> None: async def exchange_aad_access_token_for_acr_refresh_token( self, - aad_accesstoken: Optional["_models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] = None, + service: str, + access_token: str, **kwargs ) -> "_models.AcrRefreshToken": """Exchange AAD tokens for an ACR refresh Token. - :param aad_accesstoken: - :type aad_accesstoken: ~container_registry.models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema + :param service: Indicates the name of your Azure container registry. + :type service: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrRefreshToken, or the result of cls(response) :rtype: ~container_registry.models.AcrRefreshToken @@ -57,6 +61,7 @@ async def exchange_aad_access_token_for_acr_refresh_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "access_token" accept = "application/json" # Construct URL @@ -74,19 +79,19 @@ async def exchange_aad_access_token_for_acr_refresh_token( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - body_content_kwargs = {} # type: Dict[str, Any] - if aad_accesstoken is not None: - body_content = self._serialize.body(aad_accesstoken, 'Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + # Construct form data + _form_content = { + 'grant_type': grant_type, + 'service': service, + 'access_token': access_token, + } + request = self._client.post(url, query_parameters, header_parameters, form_content=_form_content) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrRefreshToken', pipeline_response) @@ -99,13 +104,21 @@ async def exchange_aad_access_token_for_acr_refresh_token( async def exchange_acr_refresh_token_for_acr_access_token( self, - acr_refresh_token: Optional["_models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] = None, + service: str, + scope: str, + refresh_token: str, **kwargs ) -> "_models.AcrAccessToken": """Exchange ACR Refresh token for an ACR Access Token. - :param acr_refresh_token: - :type acr_refresh_token: ~container_registry.models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Which is expected to be a valid scope, and can be specified more than once for + multiple scope requests. You obtained this from the Www-Authenticate response header from the + challenge. + :type scope: str + :param refresh_token: Must be a valid ACR refresh token. + :type refresh_token: str :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrAccessToken, or the result of cls(response) :rtype: ~container_registry.models.AcrAccessToken @@ -117,6 +130,7 @@ async def exchange_acr_refresh_token_for_acr_access_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "refresh_token" accept = "application/json" # Construct URL @@ -134,19 +148,20 @@ async def exchange_acr_refresh_token_for_acr_access_token( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - body_content_kwargs = {} # type: Dict[str, Any] - if acr_refresh_token is not None: - body_content = self._serialize.body(acr_refresh_token, 'PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + # Construct form data + _form_content = { + 'grant_type': grant_type, + 'service': service, + 'scope': scope, + 'refresh_token': refresh_token, + } + request = self._client.post(url, query_parameters, header_parameters, form_content=_form_content) pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrAccessToken', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py index 6ea47ff442fa..21b1b334411c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_blob_operations.py @@ -147,7 +147,7 @@ async def check_blob_exists( if response.status_code not in [200, 307]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -271,7 +271,7 @@ async def mount_blob( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -328,7 +328,7 @@ async def get_upload_status( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -390,7 +390,7 @@ async def upload_chunk( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -407,7 +407,7 @@ async def complete_upload( self, digest: str, location: str, - value: IO, + value: Optional[IO] = None, **kwargs ) -> None: """Complete the upload, providing all the data in the body, if necessary. A request without a body @@ -458,7 +458,7 @@ async def complete_upload( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -515,7 +515,7 @@ async def cancel_upload( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -565,7 +565,7 @@ async def start_upload( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -696,7 +696,7 @@ async def check_chunk_exists( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py index 09b4addc2975..539ca7ae23af 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_operations.py @@ -76,7 +76,7 @@ async def check_docker_v2_support( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -153,7 +153,7 @@ async def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -206,7 +206,7 @@ async def delete_repository( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('DeleteRepositoryResult', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index 84c40d58ad53..a5e395308f25 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -91,7 +91,7 @@ async def get_manifest( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('Manifest', pipeline_response) @@ -157,7 +157,7 @@ async def create_manifest( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -219,7 +219,7 @@ async def delete_manifest( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -269,7 +269,7 @@ async def get_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RepositoryProperties', pipeline_response) @@ -333,7 +333,7 @@ async def set_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -425,7 +425,7 @@ async def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -482,7 +482,7 @@ async def get_tag_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('TagProperties', pipeline_response) @@ -550,7 +550,7 @@ async def update_tag_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -604,7 +604,7 @@ async def delete_tag( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -691,7 +691,7 @@ async def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -748,7 +748,7 @@ async def get_registry_artifact_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RegistryArtifactProperties', pipeline_response) @@ -816,7 +816,7 @@ async def update_manifest_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py index 9c82246fd6f2..4d347034a24d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_authentication_operations.py @@ -43,14 +43,18 @@ def __init__(self, client, config, serializer, deserializer): def exchange_aad_access_token_for_acr_refresh_token( self, - aad_accesstoken=None, # type: Optional["_models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] + service, # type: str + access_token, # type: str **kwargs # type: Any ): # type: (...) -> "_models.AcrRefreshToken" """Exchange AAD tokens for an ACR refresh Token. - :param aad_accesstoken: - :type aad_accesstoken: ~container_registry.models.Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema + :param service: Indicates the name of your Azure container registry. + :type service: str + :param access_token: AAD access token, mandatory when grant_type is access_token_refresh_token + or access_token. + :type access_token: str :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrRefreshToken, or the result of cls(response) :rtype: ~container_registry.models.AcrRefreshToken @@ -62,6 +66,7 @@ def exchange_aad_access_token_for_acr_refresh_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "access_token" accept = "application/json" # Construct URL @@ -79,19 +84,19 @@ def exchange_aad_access_token_for_acr_refresh_token( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - body_content_kwargs = {} # type: Dict[str, Any] - if aad_accesstoken is not None: - body_content = self._serialize.body(aad_accesstoken, 'Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + # Construct form data + _form_content = { + 'grant_type': grant_type, + 'service': service, + 'access_token': access_token, + } + request = self._client.post(url, query_parameters, header_parameters, form_content=_form_content) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrRefreshToken', pipeline_response) @@ -104,14 +109,22 @@ def exchange_aad_access_token_for_acr_refresh_token( def exchange_acr_refresh_token_for_acr_access_token( self, - acr_refresh_token=None, # type: Optional["_models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema"] + service, # type: str + scope, # type: str + refresh_token, # type: str **kwargs # type: Any ): # type: (...) -> "_models.AcrAccessToken" """Exchange ACR Refresh token for an ACR Access Token. - :param acr_refresh_token: - :type acr_refresh_token: ~container_registry.models.PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema + :param service: Indicates the name of your Azure container registry. + :type service: str + :param scope: Which is expected to be a valid scope, and can be specified more than once for + multiple scope requests. You obtained this from the Www-Authenticate response header from the + challenge. + :type scope: str + :param refresh_token: Must be a valid ACR refresh token. + :type refresh_token: str :keyword callable cls: A custom type or function that will be passed the direct response :return: AcrAccessToken, or the result of cls(response) :rtype: ~container_registry.models.AcrAccessToken @@ -123,6 +136,7 @@ def exchange_acr_refresh_token_for_acr_access_token( } error_map.update(kwargs.pop('error_map', {})) content_type = kwargs.pop("content_type", "application/x-www-form-urlencoded") + grant_type = "refresh_token" accept = "application/json" # Construct URL @@ -140,19 +154,20 @@ def exchange_acr_refresh_token_for_acr_access_token( header_parameters['Content-Type'] = self._serialize.header("content_type", content_type, 'str') header_parameters['Accept'] = self._serialize.header("accept", accept, 'str') - body_content_kwargs = {} # type: Dict[str, Any] - if acr_refresh_token is not None: - body_content = self._serialize.body(acr_refresh_token, 'PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema') - else: - body_content = None - body_content_kwargs['content'] = body_content - request = self._client.post(url, query_parameters, header_parameters, **body_content_kwargs) + # Construct form data + _form_content = { + 'grant_type': grant_type, + 'service': service, + 'scope': scope, + 'refresh_token': refresh_token, + } + request = self._client.post(url, query_parameters, header_parameters, form_content=_form_content) pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs) response = pipeline_response.http_response if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('AcrAccessToken', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py index 3c680cd2311f..b10afab300ba 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_blob_operations.py @@ -153,7 +153,7 @@ def check_blob_exists( if response.status_code not in [200, 307]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -279,7 +279,7 @@ def mount_blob( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -337,7 +337,7 @@ def get_upload_status( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -400,7 +400,7 @@ def upload_chunk( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -417,7 +417,7 @@ def complete_upload( self, digest, # type: str location, # type: str - value, # type: IO + value=None, # type: Optional[IO] **kwargs # type: Any ): # type: (...) -> None @@ -469,7 +469,7 @@ def complete_upload( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -527,7 +527,7 @@ def cancel_upload( if response.status_code not in [204]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -578,7 +578,7 @@ def start_upload( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -711,7 +711,7 @@ def check_chunk_exists( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py index 8f3532ede045..c994d5627f59 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_operations.py @@ -81,7 +81,7 @@ def check_docker_v2_support( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -159,7 +159,7 @@ def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -213,7 +213,7 @@ def delete_repository( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('DeleteRepositoryResult', pipeline_response) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index a244957e7e13..36968b545726 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -96,7 +96,7 @@ def get_manifest( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('Manifest', pipeline_response) @@ -163,7 +163,7 @@ def create_manifest( if response.status_code not in [201]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) response_headers = {} @@ -226,7 +226,7 @@ def delete_manifest( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -277,7 +277,7 @@ def get_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RepositoryProperties', pipeline_response) @@ -342,7 +342,7 @@ def set_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -435,7 +435,7 @@ def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -493,7 +493,7 @@ def get_tag_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('TagProperties', pipeline_response) @@ -562,7 +562,7 @@ def update_tag_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -617,7 +617,7 @@ def delete_tag( if response.status_code not in [202]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: @@ -705,7 +705,7 @@ def get_next(next_link=None): response = pipeline_response.http_response if response.status_code not in [200]: - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) map_error(status_code=response.status_code, response=response, error_map=error_map) raise HttpResponseError(response=response, model=error) @@ -763,7 +763,7 @@ def get_registry_artifact_properties( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) deserialized = self._deserialize('RegistryArtifactProperties', pipeline_response) @@ -832,7 +832,7 @@ def update_manifest_attributes( if response.status_code not in [200]: map_error(status_code=response.status_code, response=response, error_map=error_map) - error = self._deserialize(_models.AcrErrors, response) + error = self._deserialize.failsafe_deserialize(_models.AcrErrors, response) raise HttpResponseError(response=response, model=error) if cls: diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index be90104e7021..6d905d812c0f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -6,9 +6,10 @@ from enum import Enum from typing import TYPE_CHECKING +from ._generated.models import ContentProperties if TYPE_CHECKING: - from ._generated.models import ContentProperties, ManifestAttributesBase + from ._generated.models import ManifestAttributesBase from ._generated.models import RepositoryProperties as GeneratedRepositoryProperties from ._generated.models import TagProperties as GeneratedTagProperties @@ -20,7 +21,7 @@ def __init__(self, **kwargs): self.can_write = kwargs.get("can_write") @classmethod - def from_generated(cls, generated): + def _from_generated(cls, generated): # type: (ContentProperties) -> ContentPermissions return cls( can_delete=generated.can_delete, @@ -29,6 +30,14 @@ def from_generated(cls, generated): can_write=generated.can_write, ) + def to_generated(self): + # type: () -> ContentProperties + return ContentProperties( + can_delete=self.can_delete, + can_list=self.can_list, + can_read=self.can_read, + can_write=self.can_write, + ) class DeletedRepositoryResult(object): def __init__(self, **kwargs): @@ -36,7 +45,7 @@ def __init__(self, **kwargs): self.deleted_tags = kwargs.get("deleted_tags", None) @classmethod - def from_generated(cls, gen): + def _from_generated(cls, gen): return cls( deleted_tags=gen.deleted_tags, deleted_registry_artifact_digests=gen.deleted_registry_artifact_digests, @@ -51,11 +60,12 @@ def __init__(self, **kwargs): self.last_updated_on = kwargs.get("last_updated_on", None) self.manifest_properties = kwargs.get("manifest_properties", None) self.operating_system = kwargs.get("operating_system", None) + self.registry_artifacts = kwargs.get("registry_artifacts", None) self.size = kwargs.get("size", None) self.tags = kwargs.get("tags", None) @classmethod - def from_generated(cls, generated): + def _from_generated(cls, generated): # type: (ManifestAttributesBase) -> RegistryArtifactProperties return cls( cpu_architecture=generated.cpu_architecture, @@ -64,6 +74,7 @@ def from_generated(cls, generated): last_updated_on=generated.last_updated_on, manifest_properties=generated.manifest_properties, operating_system=generated.operating_system, + registry_artifacts=generated.registry_artifacts, size=generated.size, tags=generated.tags, ) @@ -99,10 +110,10 @@ def __init__(self, **kwargs): self.tag_count = kwargs.get("tag_count", None) self.content_permissions = kwargs.get("content_permissions", None) if self.content_permissions: - self.content_permissions = ContentPermissions.from_generated(self.content_permissions) + self.content_permissions = ContentPermissions._from_generated(self.content_permissions) @classmethod - def from_generated(cls, generated): + def _from_generated(cls, generated): # type: (GeneratedRepositoryProperties) -> RepositoryProperties return cls( created_on=generated.created_on, @@ -150,13 +161,13 @@ def __init__(self, **kwargs): self.created_on = kwargs.get("created_on", None) self.digest = kwargs.get("digest", None) self.last_updated_on = kwargs.get("last_updated_on", None) - self.writeable_properties = kwargs.get("writeable_properties", None) - if self.writeable_properties: - self.writeable_properties = ContentPermissions.from_generated(self.writeable_properties) + self.content_permissions = kwargs.get("writeable_properties", None) + if self.content_permissions: + self.content_permissions = ContentPermissions._from_generated(self.content_permissions) self.name = kwargs.get("name", None) @classmethod - def from_generated(cls, generated): + def _from_generated(cls, generated): # type: (GeneratedTagProperties) -> TagProperties return cls( created_on=generated.created_on, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py index 2eb77068ff86..bcc9a0c59445 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_user_agent.py @@ -3,8 +3,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -import sys - from ._version import VERSION -USER_AGENT = "azure-containerregistry/{}/{}".format(VERSION, sys.version) +USER_AGENT = "azure-containerregistry/{}".format(VERSION) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py index 5a66b8549949..a5f2546e1ebd 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py @@ -28,7 +28,7 @@ class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" def __init__(self, credential): - self.credential = credential + self._credential = credential @staticmethod def _update_headers(headers, token): @@ -36,7 +36,7 @@ def _update_headers(headers, token): def on_request(self, request): # type: (PipelineRequest) -> None - self._update_headers(request.http_request.headers, self.credential.get_token()) + self._update_headers(request.http_request.headers, self._credential.get_token()) class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): @@ -55,6 +55,6 @@ class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): AUTHORIZATION = "Authorization" def __init__(self, credential, url, pipeline): - self.credential = credential + self._credential = credential self.url = url self.pipeline = pipeline \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py index 333b811a752c..0939dd3c58cb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py @@ -53,7 +53,7 @@ class ContainerRegistryCredentialPolicy(ChallengeAuthenticationPolicy): def __init__(self, credential, url, pipeline): # type: (TokenCredential, str, HttpPipeline) -> None - self.credential = credential + self._credential = credential self.url = url self.pipeline = pipeline self.container_registry_token_service = ContainerRegistryTokenService( diff --git a/sdk/containerregistry/azure-containerregistry/swagger/README.md b/sdk/containerregistry/azure-containerregistry/swagger/README.md index ce31c501855c..1abfd60b6f9b 100644 --- a/sdk/containerregistry/azure-containerregistry/swagger/README.md +++ b/sdk/containerregistry/azure-containerregistry/swagger/README.md @@ -3,4 +3,5 @@ ### Settings ``` yaml input-file: https://raw.githubusercontent.com/Azure/azure-sdk-for-js/e40f55d5fa64d177c0267b52129c77aa353f95d8/sdk/containerregistry/container-registry/swagger/containerregistry.json +output-folder: "../azure/containerregistry/_generated" ``` \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py b/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py index 73cc799add17..42582412c27f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py @@ -17,6 +17,7 @@ TagProperties, TagOrderBy, ) +from azure.containerregistry._generated.models import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema from azure.core.paging import ItemPaged from azure.identity import DefaultAzureCredential @@ -51,12 +52,18 @@ def test_get_refresh_token(self, containerregistry_baseurl): aad_accesstoken=token, ) - refresh = client._client.authentication.exchange_aad_access_token_for_acr_refresh_token(m) + refresh = client._client.authentication.exchange_aad_access_token_for_acr_refresh_token( + service, token) + print(refresh.refresh_token) - m = PathsV3R3RxOauth2TokenPostRequestbodyContentApplicationXWwwFormUrlencodedSchema( - service=service, - scope=scope, - acr_refresh_token=refresh.refresh_token, + assert refresh is not None + assert refresh.refresh_token is not None + + access_token = client._client.authentication.exchange_acr_refresh_token_for_acr_access_token( + service, scope, refresh.refresh_token ) - assert m.access_token \ No newline at end of file + assert access_token is not None + assert access_token.access_token is not None + + # assert m.access_token \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index b591cbfc1ded..411a5cc0e8ce 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -3,6 +3,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +from datetime import datetime import functools import os import pytest @@ -12,8 +13,9 @@ from azure.containerregistry import ( ContainerRepositoryClient, ContainerRegistryClient, - RepositoryProperties, ContentPermissions, + RepositoryProperties, + RegistryArtifactProperties, TagProperties, TagOrderBy, ) @@ -55,29 +57,42 @@ def test_get_properties(self, containerregistry_baseurl): assert properties.content_permissions is not None assert isinstance(properties.content_permissions, ContentPermissions) - @pytest.mark.skip("Pending") + @pytest.mark.live_test_only @acr_preparer() - def test_get_registry_artifact_properties(self, containerregistry_baseurl): - repo_client = self.create_repository_client(containerregistry_baseurl, "hello-world") + def test_get_tag(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) - digest = "sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042" - tag = "first" + tag = client.get_tag_properties("latest") - properties = repo_client.get_registry_artifact_properties(digest) - first_properties = repo_client.get_registry_artifact_properties(tag) + assert tag is not None + assert isinstance(tag, TagProperties) - self.assert_registry_artifact(properties, digest) - self.assert_registry_artifact(first_properties, tag) + @pytest.mark.live_test_only + @acr_preparer() + def test_list_registry_artifacts(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + + for artifact in client.list_registry_artifacts(): + assert artifact is not None + assert isinstance(artifact, RegistryArtifactProperties) + assert artifact.created_on is not None + assert isinstance(artifact.created_on, datetime) + assert artifact.last_updated_on is not None + assert isinstance(artifact.last_updated_on, datetime) + assert artifact.tags is not None + assert isinstance(artifact.tags, list) @pytest.mark.live_test_only @acr_preparer() - def test_get_tag(self, containerregistry_baseurl): + def test_get_registry_artifact_properties(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) - tag = client.get_tag_properties("latest") + properties = client.get_registry_artifact_properties("latest") - assert tag is not None - assert isinstance(tag, TagProperties) + assert properties is not None + assert isinstance(properties, RegistryArtifactProperties) + assert isinstance(properties.created_on, datetime) + assert isinstance(properties.last_updated_on, datetime) @pytest.mark.live_test_only @acr_preparer() @@ -112,14 +127,51 @@ def test_list_tags_descending(self, containerregistry_baseurl): assert count > 0 - @pytest.mark.xfail + @pytest.mark.live_test_only @acr_preparer() - def test_list_registry_artifacts(self, containerregistry_baseurl): + def test_set_manifest_properties(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) - repo_attribs = client.list_registry_artifacts() + for manifest in client.list_registry_artifacts(): + + permissions = manifest.content_permissions + permissions.can_write = not permissions.can_write + + client.set_manifest_properties(manifest.digest, permissions) + + received = client.get_registry_artifact_properties(manifest.digest) + + assert received.content_permissions.can_write == permissions.can_write + assert received.content_permissions.can_read == permissions.can_read + assert received.content_permissions.can_list == permissions.can_list + assert received.content_permissions.can_delete == permissions.can_delete + + break + + tags = client.set_manifest_properties() + + @pytest.mark.live_test_only + @acr_preparer() + def test_set_tag_properties(self, containerregistry_baseurl): + client = self.create_repository_client(containerregistry_baseurl, self.repository) + + for tag in client.list_tags(): + + permissions = tag.content_permissions + permissions.can_write = not permissions.can_write + + client.set_tag_properties(tag.digest, permissions) + + received = client.get_tag_properties(tag.name) + + assert received.content_permissions.can_write == permissions.can_write + assert received.content_permissions.can_read == permissions.can_read + assert received.content_permissions.can_list == permissions.can_list + assert received.content_permissions.can_delete == permissions.can_delete + + break - print(repo_attribs) + tags = client.set_manifest_properties() @pytest.mark.skip("Don't want to delete right now") @acr_preparer() From 340d12865a5510771c782d1ed81e58e326035485 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 16:23:39 -0400 Subject: [PATCH 62/86] fixing up a few tests --- .../azure/containerregistry/_models.py | 4 +- ...test_delete_repository_does_not_exist.yaml | 50 ----------- ...egistry_client.test_list_repositories.yaml | 47 ---------- ...gistry_client.test_list_repositories2.yaml | 47 ---------- ...repository_client.test_get_attributes.yaml | 47 ---------- ...repository_client.test_get_properties.yaml | 47 ---------- ...test_get_registry_artifact_properties.yaml | 89 ------------------- ...tainer_repository_client.test_get_tag.yaml | 47 ---------- ...y_client.test_list_registry_artifacts.yaml | 47 ---------- ...iner_repository_client.test_list_tags.yaml | 47 ---------- ...tory_client.test_list_tags_descending.yaml | 47 ---------- .../tests/test_container_registry_client.py | 1 + .../tests/test_container_repository_client.py | 3 +- 13 files changed, 5 insertions(+), 518 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 4c09ba76d3d1..0d8613d44efc 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -58,11 +58,13 @@ def __init__(self, **kwargs): self.created_on = kwargs.get("created_on", None) self.digest = kwargs.get("digest", None) self.last_updated_on = kwargs.get("last_updated_on", None) - self.manifest_properties = kwargs.get("manifest_properties", None) self.operating_system = kwargs.get("operating_system", None) self.registry_artifacts = kwargs.get("registry_artifacts", None) self.size = kwargs.get("size", None) self.tags = kwargs.get("tags", None) + self.content_permissions = kwargs.get("manifest_properties", None) + if self.content_permissions: + self.content_permissions = ContentPermissions._from_generated(self.content_permissions) @classmethod def _from_generated(cls, generated): diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml deleted file mode 100644 index 31cb09c2945f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml +++ /dev/null @@ -1,50 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '0' - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE - uri: https://fake_url.azurecr.io/acr/v1/not_real_repo - response: - body: - string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known - to registry","detail":{"name":"not_real_repo"}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '121' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 15:58:46 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 404 - message: Not Found -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml deleted file mode 100644 index 8208988eafeb..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["busybox","hello-world","library/hello-world"]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '65' - content-type: - - application/json; charset=utf-8 - date: - - Mon, 22 Mar 2021 20:58:53 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml deleted file mode 100644 index 5000163caa3c..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories2.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["hello-world"]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '33' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 15:54:32 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml deleted file mode 100644 index 92b820121aa9..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '289' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 17 Mar 2021 15:00:58 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml deleted file mode 100644 index 0dfa210dfcc0..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '289' - content-type: - - application/json; charset=utf-8 - date: - - Wed, 17 Mar 2021 15:00:59 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml deleted file mode 100644 index a1fee822f8a6..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml +++ /dev/null @@ -1,89 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security - Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/18/2021 8:35:38 AM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '911' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 18:59:43 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/first - response: - body: - string: '404 page not found - - ' - headers: - connection: - - keep-alive - content-length: - - '19' - content-type: - - text/plain; charset=utf-8 - date: - - Thu, 18 Mar 2021 18:59:43 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 404 - message: Not Found -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml deleted file mode 100644 index f9f3c9d66fba..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '380' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 18:59:31 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml deleted file mode 100644 index 21f6714348b8..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '597' - content-type: - - application/json; charset=utf-8 - date: - - Tue, 16 Mar 2021 16:28:33 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml deleted file mode 100644 index df994523904e..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '722' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 22:13:00 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml deleted file mode 100644 index 277f34bad509..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml +++ /dev/null @@ -1,47 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.1.0/3.9.0rc1 (tags/v3.9.0rc1:439c93d, - Aug 11 2020, 19:19:43) [MSC v.1924 64 bit (AMD64)] Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '722' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 18 Mar 2021 22:13:01 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 15da4f0fd3d4..8064f936324e 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -38,6 +38,7 @@ def test_list_repositories(self, containerregistry_baseurl): assert isinstance(repositories, ItemPaged) count = 0 + prev = None for repo in repositories: count += 1 assert isinstance(repo, six.string_types) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index ef7bf263779c..48877e3481df 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -143,8 +143,7 @@ def test_set_manifest_properties(self, containerregistry_baseurl): break - tags = client.set_manifest_properties() - + @pytest.mark.xfail @pytest.mark.live_test_only @acr_preparer() def test_set_tag_properties(self, containerregistry_baseurl): From 76b8ca0686e328e0ab8fb7c20adb1228a0dc12ea Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 16:42:55 -0400 Subject: [PATCH 63/86] changing a test slightly --- .../tests/test_container_repository_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 48877e3481df..78d1302cc247 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -130,7 +130,7 @@ def test_set_manifest_properties(self, containerregistry_baseurl): for manifest in client.list_registry_artifacts(): permissions = manifest.content_permissions - permissions.can_write = not permissions.can_write + permissions.can_delete = not permissions.can_delete client.set_manifest_properties(manifest.digest, permissions) From ac6352b207ba83e0d65d6aafa4833849ad2b8333 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Wed, 24 Mar 2021 19:35:30 -0400 Subject: [PATCH 64/86] async policy almost working, problem with the same url encoding --- .../_authentication_policy.py | 4 +- .../azure/containerregistry/_base_client.py | 2 +- .../_container_registry_authentication.py | 24 --- .../containerregistry/_exchange_client.py | 1 - .../azure/containerregistry/aio/__init__.py | 2 + .../aio/_async_authentication_policy.py | 102 ++++++++++ .../aio/_async_base_client.py | 57 ++++++ .../aio/_async_container_registry_client.py | 23 ++- .../aio/_async_container_repository_client.py | 188 ++++++++++++++++++ .../aio/_async_exchange_client.py | 139 +++++++++++++ .../tests/async_tests/__init__.py | 1 + .../async_tests/test_container_registry.py | 91 +++++++++ .../tests/test_container_registry_client.py | 1 + 13 files changed, 599 insertions(+), 36 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index 89dfaa3379b8..f7be4a6de1c8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -39,13 +39,13 @@ def _enforce_https(request): class ContainerRegistryChallengePolicy(HTTPPolicy): """Authentication policy for ACR which accepts a challenge""" - def __init__(self, credential, *scopes, **kwargs): + def __init__(self, credential, endpoint, *scopes, **kwargs): # type: (TokenCredential, *str, **Any) -> None super(HTTPPolicy, self).__init__() self._scopes = ["https://management.core.windows.net/.default"] self._credential = credential self._token = None # type: Optional[AccessToken] - self._exchange_client = ACRExchangeClient("seankane.azurecr.io", self._credential) + self._exchange_client = ACRExchangeClient(endpoint, self._credential) def _need_new_token(self): # type: () -> bool diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 9261f4dcc170..2396763946ab 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -28,7 +28,7 @@ class ContainerRegistryBaseClient(object): """ def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-method-missing-type-annotations - auth_policy = ContainerRegistryChallengePolicy(credential) + auth_policy = ContainerRegistryChallengePolicy(credential, endpoint) self._client = ContainerRegistry( credential=credential, url=endpoint, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py deleted file mode 100644 index a95714a56549..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_authentication.py +++ /dev/null @@ -1,24 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - - -# class ContainerRegistryStsClient(object): -# def __init__(self, endpoint, credential, **kwargs): -# # type: (str, TokenCredential) -> None -# """Create a ContainerRepositoryStsClient from an endpoint and a credential - -# :param endpoint: An ACR endpoint -# :type endpoint: str -# :param credential: The credential with which to authenticate -# :type credential: TokenCredential -# :returns: None -# :raises: None -# """ -# pass - -# def get_access_token(self, **kwargs): -# # type: (...) -> None -# pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py index a97626056b29..9ce60045a920 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -11,7 +11,6 @@ from azure.core.pipeline.transport import HttpRequest from ._generated import ContainerRegistry -from ._generated.models import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema from ._user_agent import USER_AGENT diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py index ba3fbad75c27..75d8c6e33a3f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py @@ -1,5 +1,7 @@ from ._async_container_registry_client import ContainerRegistryClient +from ._async_container_repository_client import ContainerRepositoryClient __all__ = [ "ContainerRegistryClient", + "ContainerRepositoryClient", ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py new file mode 100644 index 000000000000..1091cae550ac --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py @@ -0,0 +1,102 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from base64 import b64encode +import re +from typing import TYPE_CHECKING + +from azure.core.pipeline.policies import AsyncHTTPPolicy + +from ._async_exchange_client import ACRExchangeClient + +if TYPE_CHECKING: + from azure.core.pipeline import PipelineRequest + + +def _enforce_https(request): + # type: (PipelineRequest) -> None + """Raise ServiceRequestError if the request URL is non-HTTPS and the sender did not specify "enforce_https=False" + """ + + # move 'enforce_https' from options to context so it persists + # across retries but isn't passed to a transport implementation + option = request.context.options.pop("enforce_https", None) + + # True is the default setting; we needn't preserve an explicit opt in to the default behavior + if option is False: + request.context["enforce_https"] = option + + enforce_https = request.context.get("enforce_https", True) + if enforce_https and not request.http_request.url.lower().startswith("https"): + raise ServiceRequestError( + "Bearer token authentication is not permitted for non-TLS protected (non-https) URLs." + ) + + +class ContainerRegistryChallengePolicy(AsyncHTTPPolicy): + """Authentication policy for ACR which accepts a challenge""" + + def __init__(self, credential, endpoint, *scopes, **kwargs): + # type: (TokenCredential, str, *str, **Any) -> None + super(AsyncHTTPPolicy, self).__init__() + self._scopes = "https://management.core.windows.net/.default" + self._credential = credential + self._token = None # type: Optional[AccessToken] + self._exchange_client = ACRExchangeClient(endpoint, self._credential) + + def _need_new_token(self): + # type: () -> bool + return True + + async def on_request(self, request): + # type: (PipelineRequest) -> None + """Called before the policy sends a request. + The base implementation authorizes the request with a bearer token. + :param ~azure.core.pipeline.PipelineRequest request: the request + """ + + if self._token is None or self._need_new_token(): + self._token = await self._credential.get_token(self._scopes) + try: + self._token = self._token.token + except AttributeError: + pass + request.http_request.headers["Authorization"] = "Bearer " + self._token + + async def send(self, request): + # type: (PipelineRequest) -> PipelineResponse + """Authorizes a request with a bearer token, possibly handling an authentication challenge + :param ~azure.core.pipeline.PipelineRequest request: the request + """ + _enforce_https(request) + + await self.on_request(request) + + response = await self.next.send(request) + + if response.http_response.status_code == 401: + self._token = None # any cached token is invalid + challenge = response.http_response.headers.get("WWW-Authenticate") + if challenge and await self.on_challenge(request, response, challenge): + response = self.next.send(request) + + return response + + async def on_challenge(self, request, response, challenge): + # type: (PipelineRequest, PipelineResponse, str) -> bool + """Authorize request according to an authentication challenge + This method is called when the resource provider responds 401 with a WWW-Authenticate header. + :param ~azure.core.pipeline.PipelineRequest request: the request which elicited an authentication challenge + :param ~azure.core.pipeline.PipelineResponse response: the resource provider's response + :param str challenge: response's WWW-Authenticate header, unparsed. It may contain multiple challenges. + :returns: a bool indicating whether the policy should send the request + """ + # pylint:disable=unused-argument,no-self-use + + access_token = await self._exchange_client.get_acr_access_token(challenge) + self._token = access_token + request.http_request.headers["Authorization"] = "Bearer " + self._token + return access_token is not None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py new file mode 100644 index 000000000000..d64a8efa93f0 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py @@ -0,0 +1,57 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from enum import Enum + +from ._async_authentication_policy import ContainerRegistryChallengePolicy +from .._generated.aio import ContainerRegistry +from .._user_agent import USER_AGENT + + +class ContainerRegistryApiVersion(str, Enum): + """Container Registry API version supported by this package""" + + V0_PREVIEW = "" + + +class ContainerRegistryBaseClient(object): + """Base class for ContainerRegistryClient and ContainerRepositoryClient + + :param endpoint: Azure Container Registry endpoint + :type endpoint: str + :param credential: AAD Token for authenticating requests with Azure + :type credential: :class:`azure.identity.DefaultTokenCredential` + + """ + + def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-method-missing-type-annotations + auth_policy = ContainerRegistryChallengePolicy(credential, endpoint) + self._client = ContainerRegistry( + credential=credential, + url=endpoint, + sdk_moniker=USER_AGENT, + authentication_policy=auth_policy, + credential_scopes=kwargs.pop("credential_scopes", ["https://management.core.windows.net/.default"]), + **kwargs + ) + + async def __enter__(self): + await self._client.__enter__() + return self + + async def __aexit__(self, *args): + await self._client.__aexit__(*args) + + def close(self): + # type: () -> None + """Close sockets opened by the client. + Calling this method is unnecessary when using the client as a context manager. + """ + self._client.close() + + def _is_tag(self, tag_or_digest): # pylint: disable=no-self-use + tag = tag_or_digest.split(":") + return not (len(tag) == 2 and tag[0].startswith(u"sha")) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index 1348e5c9479e..385984eb445d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -7,6 +7,7 @@ from azure.core.async_paging import AsyncItemPaged +from ._async_base_client import ContainerRegistryBaseClient from .._container_registry_client import ContainerRegistryClient as SyncContainerRegistryClient from .._models import RepositoryProperties @@ -14,20 +15,26 @@ from azure.core.credentials_async import AsyncTokenCredential -class ContainerRegistryClient(object): +class ContainerRegistryClient(ContainerRegistryBaseClient): def __init__( - self, base_url: str, credential: "AsyncTokenCredential", **kwargs + self, endpoint: str, credential: "AsyncTokenCredential", **kwargs ): # pylint: disable=client-method-missing-type-annotations - pass + if not endpoint.startswith("https://"): + endpoint = "https://" + endpoint + self._endpoint = endpoint + self._credential = credential + super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) + def delete_repository(self, name: str, **kwargs) -> None: pass def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: - pass - def get_repository_client(self, name: str, **kwargs) -> SyncContainerRegistryClient: - pass + return self._client.container_registry.get_repositories( + last=kwargs.pop("last", None), n=kwargs.pop("max", None), **kwargs + ) - def get_repository_attributes(self, name: str, **kwargs) -> RepositoryProperties: - pass + + def get_repository_client(self, name: str, **kwargs) -> SyncContainerRegistryClient: + pass \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py new file mode 100644 index 000000000000..e3ad9ceb1e63 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -0,0 +1,188 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from typing import TYPE_CHECKING + +from azure.core.async_paging import AsyncItemPaged + +from ._async_base_client import ContainerRegistryBaseClient +from .._container_registry_client import ContainerRegistryClient as SyncContainerRegistryClient +from .._models import RepositoryProperties + +if TYPE_CHECKING: + from azure.core.credentials_async import AsyncTokenCredential + + +class ContainerRepositoryClient(ContainerRegistryBaseClient): + def __init__( + self, endpoint: str, repository: str, credential: "AsyncTokenCredential", **kwargs + ): # pylint: disable=client-method-missing-type-annotations + if not endpoint.startswith("https://"): + endpoint = "https://" + endpoint + self._endpoint = endpoint + self._credential = credential + self.repository = repository + super(ContainerRepositoryClient, self).__init__(endpoint=self._endpoint, credential=credential, **kwargs) + + + def delete(self, **kwargs): + # type: (...) -> None + """Delete a repository + + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ + self._client.container_registry.delete_repository(self.repository, **kwargs) + + def delete_registry_artifact(self, digest): + # type: (str) -> None + """Delete a registry artifact + + :param digest: The digest of the artifact to be deleted + :type digest: str + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ + raise NotImplementedError("Has not been implemented") + + def delete_tag(self, tag): + # type: (str) -> None + """Delete a tag + + :param tag: The digest of the artifact to be deleted + :type tag: str + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ + raise NotImplementedError("Has not been implemented") + + def get_digest_from_tag(self, tag): + # type: (str) -> str + for t in self.list_tags(): + if t.name == tag: + return t.digest + raise ValueError("Could not find a digest for tag {}".format(tag)) + + async def get_properties(self): + # type: (...) -> RepositoryProperties + """Get the properties of a repository + + :returns: :class:~azure.containerregistry.RepositoryProperties + :raises: None + """ + # GET '/acr/v1/{name}' + return RepositoryProperties._from_generated( + await self._client.container_registry_repository.get_properties(self.repository) + ) + + def get_registry_artifact_properties(self, tag_or_digest, **kwargs): + # type: (str, Dict[str, Any]) -> RegistryArtifactProperties + """Get the properties of a registry artifact + + :param tag_or_digest: The tag/digest of a registry artifact + :type tag_or_digest: str + :returns: :class:~azure.containerregistry.RegistryArtifactProperties + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ + # GET '/acr/v1/{name}/_manifests/{digest}' + if self._is_tag(tag_or_digest): + tag_or_digest = self.get_digest_from_tag(tag_or_digest) + + return RegistryArtifactProperties._from_generated( + self._client.container_registry_repository.get_registry_artifact_properties( + self.repository, tag_or_digest, **kwargs + ) + ) + + def get_tag_properties(self, tag, **kwargs): + # type: (str, Dict[str, Any]) -> TagProperties + """Get the properties for a tag + + :param tag: The tag to get properties for + :type tag: str + :returns: :class:~azure.containerregistry.TagProperties + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ + # GET '/acr/v1/{name}/_tags/{reference}' + return TagProperties._from_generated( # pylint: disable=protected-access + self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) + ) + + def list_registry_artifacts(self, **kwargs): + # type: (...) -> ItemPaged[RegistryArtifactProperties] + """List the artifacts for a repository + + :keyword last: Query parameter for the last item in the previous query + :type last: str + :keyword n: Max number of items to be returned + :type n: int + :keyword orderby: Order by query parameter + :type orderby: :class:~azure.containerregistry.RegistryArtifactOrderBy + :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] + :raises: None + """ + # GET /acr/v1/{name}/_manifests + last = kwargs.pop("last", None) + n = kwargs.pop("top", None) + orderby = kwargs.pop("order_by", None) + return self._client.container_registry_repository.get_manifests( + self.repository, last=last, n=n, orderby=orderby, + cls=lambda objs: [RegistryArtifactProperties._from_generated(x) for x in objs] + ) + + def list_tags(self, **kwargs): + # type: (...) -> ItemPaged[TagProperties] + """List the tags for a repository + + :param last: Query parameter for the last item in the previous call. Ensuing + call will return values after last lexically + :type last: str + :param order_by: Query paramter for ordering by time ascending or descending + :returns: ~azure.core.paging.ItemPaged[TagProperties] + :raises: None + """ + return self._client.container_registry_repository.get_tags( + self.repository, + last=kwargs.pop("last", None), + n=kwargs.pop("top", None), + orderby=kwargs.pop("order_by", None), + digest=kwargs.pop("digest", None), + cls=lambda objs: [TagProperties._from_generated(o) for o in objs], + **kwargs + ) + + def set_manifest_properties(self, digest, permissions): + # type: (str, ContentPermissions) -> None + """Set the properties for a manifest + + :param digest: Digest of a manifest + :type digest: str + :param permissions: The property's values to be set + :type permissions: ContentPermissions + :returns: ~azure.core.paging.ItemPaged[TagProperties] + :raises: None + """ + + self._client.container_registry_repository.update_manifest_attributes( + self.repository, digest, permissions.to_generated() + ) + + def set_tag_properties(self, tag_or_digest, permissions): + # type: (str, ContentPermissions) -> None + """Set the properties for a tag + + :param tag: Tag to set properties for + :type tag: str + :param permissions: The property's values to be set + :type permissions: ContentPermissions + :returns: ~azure.core.paging.ItemPaged[TagProperties] + :raises: None + """ + if self._is_tag(tag_or_digest): + tag_or_digest = self.get_digest_from_tag(tag_or_digest) + + self._client.container_registry_repository.update_manifest_attributes( + self.repository, tag_or_digest, permissions.to_generated() + ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py new file mode 100644 index 000000000000..bac73b4e0c2a --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py @@ -0,0 +1,139 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import json +import os +import re + +from azure.core.pipeline.policies import SansIOHTTPPolicy +from azure.core.pipeline.transport import HttpRequest + +from .._generated.aio import ContainerRegistry +from .._user_agent import USER_AGENT + + +class ExchangeClientAuthenticationPolicy(SansIOHTTPPolicy): + """Authentication policy for exchange client that does not modify the request""" + + def on_request(self, request): + # type: (PipelineRequest) -> None + pass + + def on_response(self, request, response): + # type: (PipelineRequest, PipelineResponse) -> None + pass + + +class ACRExchangeClient(object): + """Class for handling oauth authentication requests + + :param endpoint: Azure Container Registry endpoint + :type endpoint: str + :param credential: AAD Token for authenticating requests with Azure + :type credential: :class:`azure.identity.DefaultTokenCredential` + + """ + + BEARER = "Bearer" + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + WWW_AUTHENTICATE = "WWW-Authenticate" + SCOPE_PARAMETER = "scope" + SERVICE_PARAMETER = "service" + AUTHORIZATION = "Authorization" + + def __init__(self, endpoint, credential, **kwargs): + if not endpoint.startswith("https://"): + endpoint = "https://" + endpoint + self._endpoint = endpoint + self._credential_scopes = "https://management.core.windows.net/.default" + self._client = ContainerRegistry( + credential=credential, + url=endpoint, + sdk_moniker=USER_AGENT, + authentication_policy=ExchangeClientAuthenticationPolicy(), + credential_scopes=kwargs.pop("credential_scopes", self._credential_scopes), + **kwargs + ) + self._credential = credential + + async def get_acr_access_token(self, challenge): + parsed_challenge = self._parse_challenge(challenge) + refresh_token = await self.exchange_aad_token_for_refresh_token(**parsed_challenge) + return await self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) + + async def exchange_aad_token_for_refresh_token(self, service=None, scope=None, **kwargs): + + # body = """grant_type=access_token&service={}&access_token={}""".format(service, self._credential.get_token(self._credential_scopes).token) + + # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} + # request = HttpRequest("POST", self._endpoint + "/oauth2/exchange", headers=headers, data=body) + + # resp = self._client._client._pipeline.run(request) + # refresh_token = resp.http_response.internal_response.content + + # return json.loads(refresh_token)["refresh_token"] + token = await self._credential.get_token(self._credential_scopes) + refresh_token = await self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( + service, token.token) + return refresh_token.refresh_token + + async def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): + + # body = """grant_type=refresh_token&service={}&scope={}&refresh_token={}""".format( + # service, scope, refresh_token) + + # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} + # request = HttpRequest("POST", self._endpoint + "/oauth2/token", headers=headers, data=body) + + # resp = self._client._client._pipeline.run(request) + + # access_token = resp.http_response.internal_response.content + # return json.loads(access_token)["access_token"] + + access_token = await self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( + service, scope, refresh_token) + return access_token.access_token + + def _parse_challenge(self, header): + # type: (str) -> Dict[str, Any] + """Parse challenge header into service and scope""" + if header.startswith(self.BEARER): + challenge_params = header[len(self.BEARER)+1:] + + matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) + self._clean(matches) + ret = {} + for i in range(0, len(matches), 2): + ret[matches[i]] = matches[i+1] + + return ret + + async def __aenter__(self): + self._client.__aenter__() + return self + + async def __aexit__(self, *args): + self._client.__aexit__(*args) + + def close(self): + # type: () -> None + """Close sockets opened by the client. + Calling this method is unnecessary when using the client as a context manager. + """ + self._client.close() + + def _clean(self, matches): + # type: (List[str]) -> None + while True: + try: + matches.remove('') + except ValueError: + break + + while True: + try: + matches.remove(',') + except ValueError: + return diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py new file mode 100644 index 000000000000..d55ccad1f573 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py @@ -0,0 +1 @@ +__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py new file mode 100644 index 000000000000..5ecb73033c8d --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py @@ -0,0 +1,91 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools +import os +import pytest +import six + +from devtools_testutils import AzureTestCase, PowerShellPreparer + +from azure.containerregistry import ( + DeletedRepositoryResult, + RepositoryProperties, +) +from azure.containerregistry.aio import ContainerRegistryClient, ContainerRepositoryClient +from azure.core.exceptions import ResourceNotFoundError +from azure.core.paging import ItemPaged +from azure.identity.aio import DefaultAzureCredential + +# from testcase import ContainerRegistryTestClass + + +acr_preparer = functools.partial( + PowerShellPreparer, + "containerregistry", + containerregistry_baseurl="fake_url.azurecr.io", +) + + +class TestContainerRegistryClient(AzureTestCase):#, ContainerRegistryTestClass): + + def create_registry_client(self, endpoint): + return ContainerRegistryClient( + endpoint=endpoint, + credential=DefaultAzureCredential() + ) + + @pytest.mark.live_test_only + @acr_preparer() + async def test_get(self, containerregistry_baseurl): + client = ContainerRepositoryClient( + endpoint=containerregistry_baseurl, + repository="hello-world", + credential=DefaultAzureCredential(), + ) + + repo = await client.get_properties() + + assert repo is not None + assert isinstance(repo, RepositoryProperties) + + + @pytest.mark.skip("abc") + @pytest.mark.live_test_only + @acr_preparer() + async def test_list_repositories(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + repositories = client.list_repositories() + + count = 0 + prev = None + async for repo in client.list_repositories(): + count += 1 + assert isinstance(repo, six.string_types) + assert prev != repo + prev = repo + + assert count > 0 + + @pytest.mark.skip("Don't want to delete for now") + @acr_preparer() + def test_delete_repository(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + deleted_result = client.delete_repository("debian") + + assert isinstance(deleted_result, DeletedRepositoryResult) + assert len(deleted_result.deleted_registry_artifact_digests) == 1 + assert len(deleted_result.deleted_tags) == 1 + + @pytest.mark.skip("Don't want to for now") + @pytest.mark.live_test_only + @acr_preparer() + def test_delete_repository_does_not_exist(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + with pytest.raises(ResourceNotFoundError): + deleted_result = client.delete_repository("not_real_repo") diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index 8064f936324e..cbbb373a738d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -58,6 +58,7 @@ def test_delete_repository(self, containerregistry_baseurl): assert len(deleted_result.deleted_registry_artifact_digests) == 1 assert len(deleted_result.deleted_tags) == 1 + @pytest.mark.skip("Don't want to for now") @pytest.mark.live_test_only @acr_preparer() def test_delete_repository_does_not_exist(self, containerregistry_baseurl): From ce532bcb4932ff726b8e3f2003938171f3c75c98 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 25 Mar 2021 13:46:52 -0400 Subject: [PATCH 65/86] more test fixes --- .../aio/_async_authentication_policy.py | 2 +- .../aio/_async_container_registry_client.py | 18 +- .../aio/_async_container_repository_client.py | 4 +- .../aio/_async_exchange_client.py | 22 - ...test_delete_repository_does_not_exist.yaml | 114 ++++ .../test_container_registry.test_get.yaml | 113 ++++ ...ainer_registry.test_list_repositories.yaml | 113 ++++ .../async_tests/test_container_registry.py | 29 +- ...test_auth_flow.test_get_refresh_token.yaml | 74 +++ ...egistry_client.test_list_repositories.yaml | 165 ++++++ ...repository_client.test_get_properties.yaml | 165 ++++++ ...test_get_registry_artifact_properties.yaml | 330 ++++++++++++ ...tainer_repository_client.test_get_tag.yaml | 165 ++++++ ...y_client.test_list_registry_artifacts.yaml | 165 ++++++ ...iner_repository_client.test_list_tags.yaml | 165 ++++++ ...tory_client.test_list_tags_descending.yaml | 165 ++++++ ...y_client.test_set_manifest_properties.yaml | 505 ++++++++++++++++++ ...sitory_client.test_set_tag_properties.yaml | 503 +++++++++++++++++ ...nge_client.test_auth_policy_in_action.yaml | 165 ++++++ .../tests/test_container_repository_client.py | 10 +- .../azure-containerregistry/tests/testcase.py | 82 ++- .../scenario_tests/recording_processors.py | 9 +- 22 files changed, 3020 insertions(+), 63 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py index 1091cae550ac..1c5b2f1b60b2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py @@ -81,7 +81,7 @@ async def send(self, request): self._token = None # any cached token is invalid challenge = response.http_response.headers.get("WWW-Authenticate") if challenge and await self.on_challenge(request, response, challenge): - response = self.next.send(request) + response = await self.next.send(request) return response diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index 385984eb445d..4e7e6dd12291 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -3,13 +3,13 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -from typing import TYPE_CHECKING +from typing import Any, Dict, TYPE_CHECKING from azure.core.async_paging import AsyncItemPaged from ._async_base_client import ContainerRegistryBaseClient from .._container_registry_client import ContainerRegistryClient as SyncContainerRegistryClient -from .._models import RepositoryProperties +from .._models import RepositoryProperties, DeletedRepositoryResult if TYPE_CHECKING: from azure.core.credentials_async import AsyncTokenCredential @@ -26,8 +26,18 @@ def __init__( super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) - def delete_repository(self, name: str, **kwargs) -> None: - pass + async def delete_repository(self, repository: str, **kwargs: Dict[str, Any]) -> DeletedRepositoryResult: + """Delete a repository + + :param repository: The repository to delete + :type repository: str + :returns: None + :raises: :class:~azure.core.exceptions.ResourceNotFoundError + """ + result = await self._client.container_registry.delete_repository(repository, **kwargs) + return DeletedRepositoryResult._from_generated(result) + + def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index e3ad9ceb1e63..98716522b9eb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -27,14 +27,14 @@ def __init__( super(ContainerRepositoryClient, self).__init__(endpoint=self._endpoint, credential=credential, **kwargs) - def delete(self, **kwargs): + async def delete(self, **kwargs): # type: (...) -> None """Delete a repository :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - self._client.container_registry.delete_repository(self.repository, **kwargs) + await self._client.container_registry.delete_repository(self.repository, **kwargs) def delete_registry_artifact(self, digest): # type: (str) -> None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py index bac73b4e0c2a..4fdf25ba4fae 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py @@ -64,34 +64,12 @@ async def get_acr_access_token(self, challenge): return await self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) async def exchange_aad_token_for_refresh_token(self, service=None, scope=None, **kwargs): - - # body = """grant_type=access_token&service={}&access_token={}""".format(service, self._credential.get_token(self._credential_scopes).token) - - # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} - # request = HttpRequest("POST", self._endpoint + "/oauth2/exchange", headers=headers, data=body) - - # resp = self._client._client._pipeline.run(request) - # refresh_token = resp.http_response.internal_response.content - - # return json.loads(refresh_token)["refresh_token"] token = await self._credential.get_token(self._credential_scopes) refresh_token = await self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( service, token.token) return refresh_token.refresh_token async def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): - - # body = """grant_type=refresh_token&service={}&scope={}&refresh_token={}""".format( - # service, scope, refresh_token) - - # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} - # request = HttpRequest("POST", self._endpoint + "/oauth2/token", headers=headers, data=body) - - # resp = self._client._client._pipeline.run(request) - - # access_token = resp.http_response.internal_response.content - # return json.loads(access_token)["access_token"] - access_token = await self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( service, scope, refresh_token) return access_token.access_token diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml new file mode 100644 index 000000000000..997b1bbc7a0f --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml @@ -0,0 +1,114 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '209' + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:46 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:not_real_repo:delete",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/not_real_repo +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODg1MjUsIm5iZiI6MTYxNjY4ODUyNSwiZXhwIjoxNjE2Nzc1MjI1LCJhaW8iOiJFMlpnWVBDNE5rdnF6em05OHRNVG1tTWVlT1dLQWdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoicE9ONTM4TU9Za0c2eEtZN2VFNWpBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.K4z8Y3OnXAXX9unFr66_FKvt0TRHxljiFTUVJg8l9nbsfp2x6G9NkjSDBzg2AlpsMjg2VcKPd_bNR7Eo-Sr1CxswX1azmaFDgPeFVqLmtK9cllRuwpngMNnlMNHPWRFvn3JnBiBvKn9SWM0d234RMMUmS_u96xNmri6ue-zxitJQg79qlDKrZungQTyoao3HJBdFkRry8hufIc-O6r2xNx1iHmchFZwoPM_RPdpZq0v07K7PzFdIYkNb5EEVB_U7LIMVmhksyhoAEzGq82T0EM8QotfeQTWBkd88_5gUCaJaJkiy081InwhQ1uSc5vX540d__LU-bvnW5u5aFitoCg + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZTQ0OTc1Mi00YWY5LTRjMDQtODYzNC0wMDIyYTBjMDE4NmYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjcsImV4cCI6MTYxNjY5OTYyNywiaWF0IjoxNjE2Njg3OTI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZB_fKjLcFgD2p-KiR2uOgXHkNHuRQfA1rV3gvJ4PxulC9e2UcbxArM6HGy_cTBOjXRg0pGT5HRYaPGOs4HzBHOowKnYajgx20f04FprTgJprIYKGCcp0rT8U_9GB6ZwPmY3KyCA3ScbkqAe8_GdjjqD6k-LCyYG3w00Z4WP3XaPJ-RaKTTrRBr2NinOkntmgDAauab8Q8S8hOTdLDlA1i5TIqXGkEq_JRsbr_P9Zq4PrXYcFPhNFwuobo-Dc3TboGDobInehNfjyOq99x6cZp2y15B9ltMF6lWVI9-0LYk5uXoVHJsvpsR_aWPf8rA14hxZ1XIn0C1PQQ4YeFvmV0g"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:47 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZTQ0OTc1Mi00YWY5LTRjMDQtODYzNC0wMDIyYTBjMDE4NmYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjcsImV4cCI6MTYxNjY5OTYyNywiaWF0IjoxNjE2Njg3OTI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZB_fKjLcFgD2p-KiR2uOgXHkNHuRQfA1rV3gvJ4PxulC9e2UcbxArM6HGy_cTBOjXRg0pGT5HRYaPGOs4HzBHOowKnYajgx20f04FprTgJprIYKGCcp0rT8U_9GB6ZwPmY3KyCA3ScbkqAe8_GdjjqD6k-LCyYG3w00Z4WP3XaPJ-RaKTTrRBr2NinOkntmgDAauab8Q8S8hOTdLDlA1i5TIqXGkEq_JRsbr_P9Zq4PrXYcFPhNFwuobo-Dc3TboGDobInehNfjyOq99x6cZp2y15B9ltMF6lWVI9-0LYk5uXoVHJsvpsR_aWPf8rA14hxZ1XIn0C1PQQ4YeFvmV0g + scope: repository:not_real_repo:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkYWFlMjE1NS05MzUxLTQ5YzktYmJkNy02MDMyMjkwMTUwZTkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjcsImV4cCI6MTYxNjY5MjQyNywiaWF0IjoxNjE2Njg3OTI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJub3RfcmVhbF9yZXBvIiwiYWN0aW9ucyI6WyJkZWxldGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.FkpNJr_GHPVSYd7KE2rTyRDfxu5zQjmMJWBa9rcz9VkHzOLySANrGgqp25Tz1BHBcKms8j29kkNh-6Soabo_fg8iGBrudWMfQgghnsKSRUmKsG33YrasJyczec3TZw0zdZO7FxeWTJupak3qAq8VhQbnbKcSY5vMDelOzP88BwYJ3ImTedrDhAPr88cwt0JoZ-4WNhuyUSInSM5S1CwggYbDE2jS1kti3UAwHhmULZApe3qMoXdpm9gcgLP-z2hntmGMYKelYok2M8xmc2plF8CspS8wz-EayC1dxpzCpCrWnk52cOUtBKJT57NsJYpO2fG3csayksaAeHfT5ruLEQ"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:47 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"not_real_repo"}}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '121' + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:47 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 404 + message: Not Found + url: https://seankane.azurecr.io/acr/v1/not_real_repo +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml new file mode 100644 index 000000000000..ef3c859c905d --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml @@ -0,0 +1,113 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '214' + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 15:42:28 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/hello-world +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODY2NDYsIm5iZiI6MTYxNjY4NjY0NiwiZXhwIjoxNjE2NzczMzQ2LCJhaW8iOiJFMlpnWU5EYktYMlI5L0oyWm5WdGMzblBUTFYwQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRFNKWGFkX1E4VXFMTWpEM2oyUnVBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.Cqc9CKfdMvjmxBml3J-hv-V-w6vU0vwyy7hNU6UlHe1inPFlEflcqN_XRX-wNcIKFVsmLUsoh5Kfw9r87A1DJS57gyRIE8YzNFIWiw2CRDrveFAW6TfPukbXwdaHUwDd_owpdnDbsOvTDrMISmls_q8ZEhdRvdJb3GtyjZiC9Z7q_CWus_HBEwx0I5SWF7nKzMXGYwncObKYpGo5TI6k9C6VOt-8nlnRvfAueU_aqlMzAB7fu4NZtVIRmkE_gK3u4UNf_FYZWWOZk_2X8CgM-o327pJ5HFR-EhqiL7fuot52uPlADNCjCQP5qX6ENzURPiJsblQcWHVRqB2Fg3nmjQ + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkN2M2NWM2ZC05OTM0LTQxYWYtOGJkYi02ZTU0Y2FkODI4ZjkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODYwNTAsImV4cCI6MTYxNjY5Nzc1MCwiaWF0IjoxNjE2Njg2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.hO0zLR6XtQB6hZZXMqgHPezRei8TDjQfJ1VFAW7qMQ2RiXQ0dT_nfWqHJlWbx6E0NS_P1k--N0d6gBhoDCAOG3FACc7hYtMyzHCJ76dGqVRdyYp44P6OwosYr19tdfDAVi8Wleo96IgPmeE-PBzaJIzOXvcXgDSWLbpvixZc_Jx2hDmHM2V7LlMB2thwerNUnj50m1SA6J7uVEiZNhHGQvNPIBVB5KIUE-i2AgcmLp22VazJ51o7wkWzodPVmXMkLEhhWqFjq6IUQC_GcYueZ6WEvTAhM2p23Wn8AqPU_VciO7CczTdvtpbiXeYknXIslyXLUWSsxyiKVfAI5GzJDw"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 15:42:30 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkN2M2NWM2ZC05OTM0LTQxYWYtOGJkYi02ZTU0Y2FkODI4ZjkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODYwNTAsImV4cCI6MTYxNjY5Nzc1MCwiaWF0IjoxNjE2Njg2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.hO0zLR6XtQB6hZZXMqgHPezRei8TDjQfJ1VFAW7qMQ2RiXQ0dT_nfWqHJlWbx6E0NS_P1k--N0d6gBhoDCAOG3FACc7hYtMyzHCJ76dGqVRdyYp44P6OwosYr19tdfDAVi8Wleo96IgPmeE-PBzaJIzOXvcXgDSWLbpvixZc_Jx2hDmHM2V7LlMB2thwerNUnj50m1SA6J7uVEiZNhHGQvNPIBVB5KIUE-i2AgcmLp22VazJ51o7wkWzodPVmXMkLEhhWqFjq6IUQC_GcYueZ6WEvTAhM2p23Wn8AqPU_VciO7CczTdvtpbiXeYknXIslyXLUWSsxyiKVfAI5GzJDw + scope: repository:hello-world:metadata_read + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1Y2NkNjM0MS0xMDhiLTQ3ZWItODczNC02NTU5NGIwYjkxMDEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODYwNTAsImV4cCI6MTYxNjY5MDU1MCwiaWF0IjoxNjE2Njg2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.e059O57qmQa3vMGk7LMr8HM2WzKTCzau4xOByi8MQjDe-p6mtYGuV6ownAqi1w-eybZqKAQX-ommpk15RXKbVkkrpFg5Tbz2-I5EcshkyR2ESFIo0DxvldlJXEWK9FyNuwTfWaWptU734xKY8GPdcsRzid5bl5JsQAD2oWFXxbJnDD9WP00U5r4wiqO0I0s6Q97Ce4AtNMEX87SXTWDQ4jMeMRCxsUV6L5a8P55Cd5NdpqEq2baHP9OZZEwysDhDlNhLIMPoQFfssHIz5b5IjOAwJ8gbPmzHz7HWLtwqYZyhOhpBYhTpawoZC0lVG6CTZ0lYyqk7AVYLv5gDAwTvzQ"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 15:42:30 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '289' + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 15:42:30 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/hello-world +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml new file mode 100644 index 000000000000..9580ef074ca4 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml @@ -0,0 +1,113 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '196' + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:48 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/_catalog +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODg1MjcsIm5iZiI6MTYxNjY4ODUyNywiZXhwIjoxNjE2Nzc1MjI3LCJhaW8iOiJFMlpnWUFpUVNmb1hWUmJ1dWxkSU41TjN0NG96QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT0V4eF9MVU9JMG1FUHVMNEo5RjBBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.kSFkot0f5ek0fy-AqLPjRRFWpWOVVrXSnN67klzZgrLi6do9zYvfXptJUkGkxu3Oyj1i3ea-gNpD6-VEcWG25zsK3w8lIKO9gpV0jebmj3aRB8jk_K9Tgk84mHAzzFSAF4fTFXkrFSbsdt4ntwlGuy_LNprtsJqUnpyF-OsR5s8pqF0Vkew-2_PO1ZVDixaxIzELHyLoqPPb2zC4F5TB0TYEjotB7Ds97rTzjPC-kKTILnsYbzi9zwZ4uWKQlfh03ZXvFO4zmOgceujP8LT-fyuOJCc_MB5PLyn7dW6UOa_Dl2BfK80mE0Ot_yDboNQMTJke9fJFT5kQRK1higtj8w + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMzE3MGMzNy04OGZhLTRhMTAtYTc3Ny0yYWNjZWQzZmQ0ZDAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjksImV4cCI6MTYxNjY5OTYyOSwiaWF0IjoxNjE2Njg3OTI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.afyBJmPJQA4hdbwvImWni_CSIw8rxtI6J6YBX82hDXmS9478jsO37ZfIpYgMfiewO3f0MY0p53rC3HhTVuH9yk5_qtM5UC0gMBkMovxxGvjsme77g9H356k2kdWl-hSsDm1Q3XAzYO5bAKrBET6Xo4pe6aROxN7sMMVBHSf7guDmXPbY4FMZxhKI8tWwH3RemAQQ4YTzPy2dc5sKAvriEju--a_mGvQUDMoHGecY1Qo6e2ZuzYqnANqopu0eSRjPFv8UwLR91YAEfrqWPOFMrXDdWqI7i_NCpc3MIauw3L-ytbUvifawCTBMr8g2nYTwWiNdR82y8Qyn28PJA9fnEg"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:49 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMzE3MGMzNy04OGZhLTRhMTAtYTc3Ny0yYWNjZWQzZmQ0ZDAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjksImV4cCI6MTYxNjY5OTYyOSwiaWF0IjoxNjE2Njg3OTI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.afyBJmPJQA4hdbwvImWni_CSIw8rxtI6J6YBX82hDXmS9478jsO37ZfIpYgMfiewO3f0MY0p53rC3HhTVuH9yk5_qtM5UC0gMBkMovxxGvjsme77g9H356k2kdWl-hSsDm1Q3XAzYO5bAKrBET6Xo4pe6aROxN7sMMVBHSf7guDmXPbY4FMZxhKI8tWwH3RemAQQ4YTzPy2dc5sKAvriEju--a_mGvQUDMoHGecY1Qo6e2ZuzYqnANqopu0eSRjPFv8UwLR91YAEfrqWPOFMrXDdWqI7i_NCpc3MIauw3L-ytbUvifawCTBMr8g2nYTwWiNdR82y8Qyn28PJA9fnEg + scope: registry:catalog:* + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3Y2I1MjVjZi1jODA1LTRiOTItYTA2NC1jZWI2MzczNjY4YTUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjksImV4cCI6MTYxNjY5MjQyOSwiaWF0IjoxNjE2Njg3OTI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.kj7B-g32r8lVjxkhJwq9_ucje6zGHXNFlxQduMG_YKwUnockoiRbAUZ_1xoWg9JCUnlcR1dkLt4uhIt6Zh5w5FspeUuuZrjeTsdmnbxO_XV055OphwRy1OcHPejNUHdQpb8hbSWtPKvjsUAm-7jsqFQnDv4QVfsPGPv69Afs65LDuCKFOxi175079sxXhtCr2yi5j1DPrZVTasRL9ydFjPPS50YSMG3xi_OQjJXsxqb-xcmfLaz17h_zFiCmBA_PzAnx1gDRQKPkHgjAUHj1W0S6MXHJOp4cFJfqim6lMij401d1Z1U4HSEH1eWvlOemYXuC4oOJHGgvtblD-kw9DQ"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:49 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '125' + content-type: application/json; charset=utf-8 + date: Thu, 25 Mar 2021 16:13:49 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/_catalog +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py index 5ecb73033c8d..93701f41f266 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py @@ -29,30 +29,10 @@ ) -class TestContainerRegistryClient(AzureTestCase):#, ContainerRegistryTestClass): - +class TestContainerRegistryClient(AzureTestCase): def create_registry_client(self, endpoint): - return ContainerRegistryClient( - endpoint=endpoint, - credential=DefaultAzureCredential() - ) - - @pytest.mark.live_test_only - @acr_preparer() - async def test_get(self, containerregistry_baseurl): - client = ContainerRepositoryClient( - endpoint=containerregistry_baseurl, - repository="hello-world", - credential=DefaultAzureCredential(), - ) - - repo = await client.get_properties() - - assert repo is not None - assert isinstance(repo, RepositoryProperties) - + return ContainerRegistryClient(endpoint=endpoint, credential=DefaultAzureCredential()) - @pytest.mark.skip("abc") @pytest.mark.live_test_only @acr_preparer() async def test_list_repositories(self, containerregistry_baseurl): @@ -81,11 +61,10 @@ def test_delete_repository(self, containerregistry_baseurl): assert len(deleted_result.deleted_registry_artifact_digests) == 1 assert len(deleted_result.deleted_tags) == 1 - @pytest.mark.skip("Don't want to for now") @pytest.mark.live_test_only @acr_preparer() - def test_delete_repository_does_not_exist(self, containerregistry_baseurl): + async def test_delete_repository_does_not_exist(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) with pytest.raises(ResourceNotFoundError): - deleted_result = client.delete_repository("not_real_repo") + deleted_result = await client.delete_repository("not_real_repo") diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml new file mode 100644 index 000000000000..71c0f25cba02 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml @@ -0,0 +1,74 @@ +interactions: +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNTQsIm5iZiI6MTYxNjY4NzI1NCwiZXhwIjoxNjE2NzczOTU0LCJhaW8iOiJFMlpnWU9oUlR0TDllT3RtYjUwbTY1elp2eHNUQVE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibWlVOEZXQklNVXk2eHJLX2pDNFJBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JvWpWhQByofdCAQ-UHPu6vuMAWuNo7ce6ceVvDjnXVaXye_8X5BS1O9poEJ2TphzXZJQ0vRBEkkwZaap6zneR5zi55MGChSX92tAPeLEq5z1gh6YCDfrQHX2nN6aB7jMFJWlpj8DojkAcMh9wNYww8PoPitTKyc0pD3aoHTWUXeuYnAg9JRGhIMwjdTNHuTc6mwFsTcDmpZJ1KLxCC3CJbtp6zZj86OiK4y_v4EORfr4_wmE-mpJojwBcCxIF-L_UPLVAnx-OJIjttJ779dZ679N13tsKgVdjXBxKGF3KfJ_V3mdyOalp4I1wBhBNzm3QUT6wsk70bckzCLESLFBgA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkNDAxMDY2Ny1mYjgyLTRhMDktYjZhZS1lOWMyODc2NzcwMzgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTYsImV4cCI6MTYxNjY5ODM1NiwiaWF0IjoxNjE2Njg2NjU2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.XgSJn0OtHEMBlxjqEaQ_h9a_T3fHIwgEsqBE1mfKq3DaK3HHMuWNoAhDbjsAcGrbRVqL7sw3q95hepDohgnw2WDelvHjACDP9xYwyRZQj9WT7xRwOcUrEsVd0o1OrUJKv0T__7p3aGGdf-Lml98n3uePzqWOlVbUv7sl1LHmWvq3iWi6UUhD_v3OlwE3LBlGX4uwhxVpKnQbDpSXn6GoSrlaxMz6cJES-I2Fd_iwd1hJqGPsQl2kLpuwo83vdGnGPl5FUOqC44fWNJcCGn8zMTPGKBKRr7bF_jAGCHZWgNhgbB9BqJL6Yf4XA_9HZO8lrfTVCIVKPV6x544VRvIM6w"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:36 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkNDAxMDY2Ny1mYjgyLTRhMDktYjZhZS1lOWMyODc2NzcwMzgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTYsImV4cCI6MTYxNjY5ODM1NiwiaWF0IjoxNjE2Njg2NjU2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.XgSJn0OtHEMBlxjqEaQ_h9a_T3fHIwgEsqBE1mfKq3DaK3HHMuWNoAhDbjsAcGrbRVqL7sw3q95hepDohgnw2WDelvHjACDP9xYwyRZQj9WT7xRwOcUrEsVd0o1OrUJKv0T__7p3aGGdf-Lml98n3uePzqWOlVbUv7sl1LHmWvq3iWi6UUhD_v3OlwE3LBlGX4uwhxVpKnQbDpSXn6GoSrlaxMz6cJES-I2Fd_iwd1hJqGPsQl2kLpuwo83vdGnGPl5FUOqC44fWNJcCGn8zMTPGKBKRr7bF_jAGCHZWgNhgbB9BqJL6Yf4XA_9HZO8lrfTVCIVKPV6x544VRvIM6w + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2ZDU5OWNlYy05M2MzLTQ4Y2MtYWVhMy00YmI4ZWMxM2IwNjIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTcsImV4cCI6MTYxNjY5MTE1NywiaWF0IjoxNjE2Njg2NjU3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.R-OkJ83W76DYOwUDtAwEn2RP3FBO587ggFSNyLRaPaUUSW7Ns3IA5jhIwqaU0soEQHoCYurY_FossxciFQU0BZYiCZ0VzUeuASsR00XBhqKPsoSaKdzZftj2wqIe8GNA2SkQNT_rfe6sKYfBJUchIXqoQV1b7jFiP-QhI8KBxeKtmsSTWxF4IqeckihxLh42ubdJygjhocNlFGk0VRjCDELiL4OJmNAjbYHQ08zKno1jamyptF6tM4-3owiVLjirWylDD0sBVJ7XdFVa4WXBmEBVR8_--bP5ZQg-Hgb-C0OcxECtDvfg_m-ZAp4aJJRIAjurTibQhk_cmU5Sf8yl6Q"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:37 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml new file mode 100644 index 000000000000..5861dde40863 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '196' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:38 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNTcsIm5iZiI6MTYxNjY4NzI1NywiZXhwIjoxNjE2NzczOTU3LCJhaW8iOiJFMlpnWU5qTEZiVC9oTm4yaDZxU0J3NjFMbjV6RmdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZVJScVpHRk5URW1wQmNhQVJUV1BBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.M_sTJByBEUU9Zr0CPIuhiS3sVJJLyW3NVwyRMyFFBt-7SthCcbrVX9LZcfdr6nafLCexkYC4WtPdJ4xt9fTxJs9BTLBPEXp7mtZFs3EYzuASoEVHJLaMeYd1BwzRvRNcaAQJaTRLvazYGdJCD1UCPhsBmc5ocYfKXfSHL64B0tWJY6aivBzof_8c1Xan27wGg9WrssabDQu6OeXVl0m1jtXFb2HUpqTnqTNo8b-QhSlUy5ehyojZmZtyZLf55IHf_mrQWiVzzHRH83q15o70eMqRukjwHBQ7rMIO_HNqKvk97qDREdlvDGguINacnT57FbvoMO7rRke96cR9z9XKGg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmNTY2ZTQxNy03NGJkLTRiMjAtYTgzZi0zMDQxMDFjNzQ1YzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTksImV4cCI6MTYxNjY5ODM1OSwiaWF0IjoxNjE2Njg2NjU5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.So0GO7Ge8zl-B6mZT-BTM4FwFNEKHUB1ScfeQT--TT6X-PQmr22jioIqhRHcIYebzxdTmzY61w1ecLTNnylKBrMTW1EBEqpt2lIcvfE9rz3k-z2GdYJjJOkdvnN5Fkf2sHXimk_EQahNLT1WfAr2tjr9AAMG8-IC0WVQbHsmVmynyQQPPcd5xvTQ1ftXjKoEzEjmTUOCCPJi_9o1Q0KMhQsRgSg9Vlr2PB_2NpS_xVPcoHCd69Z2bN5MUbzOAYRsCAit0Xfp9Yu4BdVmSYnotCEogGBSuQMv59tkLw4SIeLxYPla7UQdTOVduikKQ4-84ZaZfPHOUQk6EL-qQSLIRA"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:39 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry%3Acatalog%3A%2A&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmNTY2ZTQxNy03NGJkLTRiMjAtYTgzZi0zMDQxMDFjNzQ1YzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTksImV4cCI6MTYxNjY5ODM1OSwiaWF0IjoxNjE2Njg2NjU5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.So0GO7Ge8zl-B6mZT-BTM4FwFNEKHUB1ScfeQT--TT6X-PQmr22jioIqhRHcIYebzxdTmzY61w1ecLTNnylKBrMTW1EBEqpt2lIcvfE9rz3k-z2GdYJjJOkdvnN5Fkf2sHXimk_EQahNLT1WfAr2tjr9AAMG8-IC0WVQbHsmVmynyQQPPcd5xvTQ1ftXjKoEzEjmTUOCCPJi_9o1Q0KMhQsRgSg9Vlr2PB_2NpS_xVPcoHCd69Z2bN5MUbzOAYRsCAit0Xfp9Yu4BdVmSYnotCEogGBSuQMv59tkLw4SIeLxYPla7UQdTOVduikKQ4-84ZaZfPHOUQk6EL-qQSLIRA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1063' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2MGUxZjAzNS1jMjdjLTQ4ZDAtOTcwOS1kODdlOTQ4ODA3NjciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTksImV4cCI6MTYxNjY5MTE1OSwiaWF0IjoxNjE2Njg2NjU5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.I9ArX-GXS8FfMSbDYAvoeebZtKRbTMWWALUPhc64J0B1CcCBrl3ehcwAn5wQ4S_XQIyYa7nG9bmSeBN3fCZiw4Pm2F1Ynyhdu6nHvVSw4u5YwVT2DENdE_FlIcNkTQs8XNobKOC4X7vV8Sx6s4fc4dK4g7MTSCAGWlIeknUdykPeg7q4o8evMsZqzhRiUPD4YSDL2OB1d8RGeWkIJExoz0werbfVfu2YeKWwK7jipAGS-GKPNtLYifT2U1VlRPh7I1ONkb7fnfXCG-DdllpsJB39K9LD0Rpyjh0XJkVxvrlpyITtC7-13o1hEYzMEjx_xxSDF0GdF1kloU-RX0D5dA"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:39 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '125' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:39 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml new file mode 100644 index 000000000000..c6e3a9024dff --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:44 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNjMsIm5iZiI6MTYxNjY4NzI2MywiZXhwIjoxNjE2NzczOTYzLCJhaW8iOiJFMlpnWUpqVFAzMkoydm9ENjBLdVNZc3ZycDQwRVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRVNPRTlTR2hVa091Q1h4Tm95Z1BBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.iErbO5UQhtcgGznf11mC1Pw3QrVJqZuUPRIgl53cmAVKL2O8M5uZh0065gZ79hXzyLIJ6HekAFSIaY9VSobLAL0tctdXAg2IL-spmUjOZn30EoWQrMAPQ5oSX7r1udzfovyIO9uIdGBKW312jnfA3maiZkkCQy8eqOax44_ceEroih4x_5kMSWS_Tmk100EimKta2T6-t2qy_xcuyUftvtTZBDlCZAtFJPTR1V38n_iTFvkJYMUraXMSzKO6Tiw5TsB7pkURbLuzszwleuTnB4-IJVREUUxXLXtFCi9CRO-1yMrPMwBx9zhe0o11AGZ_T2pVEjZ2C7_4-0_6gqQPpg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMjk2NTI0OS0zNzAwLTQ5NWUtYmUxYy0wZTliMzAzZDE5MDkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjUsImV4cCI6MTYxNjY5ODM2NSwiaWF0IjoxNjE2Njg2NjY1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.TyriD1hq1OcG5uKwB3hq5SMaW5y56GQ6_msXw8zFJPTETnP70HcouFIHvJGzfFXFlF9xaNyfC1Er4WslQ2wlvx9ivgStmlFqS29fScZSDx2y5dzynvnnQY_w0947GkY26RI5zFVe_CQ3BUPhGsgFZXcV3l-mF4_crCuE5nCWqpZHlDWh-r3R7fw1R_xtMc--4znwDhyrg1Q5KdbgQGsT0ORAFRMtRHvjTtInjO4i0wLziDrhvYw55S9DLFnDwRTGcHOnF8HeGjvhv8ippsyNaLvR-v8eHGWFJV3TOrspecrE4dp4t_HJl2F4Y-rM-DxyPWMCykBR8OkumbmDFEFsmw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:45 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMjk2NTI0OS0zNzAwLTQ5NWUtYmUxYy0wZTliMzAzZDE5MDkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjUsImV4cCI6MTYxNjY5ODM2NSwiaWF0IjoxNjE2Njg2NjY1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.TyriD1hq1OcG5uKwB3hq5SMaW5y56GQ6_msXw8zFJPTETnP70HcouFIHvJGzfFXFlF9xaNyfC1Er4WslQ2wlvx9ivgStmlFqS29fScZSDx2y5dzynvnnQY_w0947GkY26RI5zFVe_CQ3BUPhGsgFZXcV3l-mF4_crCuE5nCWqpZHlDWh-r3R7fw1R_xtMc--4znwDhyrg1Q5KdbgQGsT0ORAFRMtRHvjTtInjO4i0wLziDrhvYw55S9DLFnDwRTGcHOnF8HeGjvhv8ippsyNaLvR-v8eHGWFJV3TOrspecrE4dp4t_HJl2F4Y-rM-DxyPWMCykBR8OkumbmDFEFsmw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0OWVmOTcwNS1lMTEwLTQ3N2UtYjhjMS1kZTA1MDUyYjMyMzQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjUsImV4cCI6MTYxNjY5MTE2NSwiaWF0IjoxNjE2Njg2NjY1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.EDfBShkfySbhHsVJHsXG4OLWycSA2ddp-Xp_m5k--gesNW23hRn_tHP7jggtdf33zDrhn7FMp4z6sA10Nl1c4aeFipOsDX3dAvim9mIU1s0jS9uenIhzzqm1nPDIL3sHS7YHnC6Z4xfKR4j1oqtmqIK_s_0nQq6qww2ae13HFDPgRhI2DqVXWP86eieBpNMG7jhK6wrO8U74BizzpkSlcqST5r8RYpdUr6UcHUFDwuVniwfttwYoMx3r4X2t4oTiszLR3Z9st5kxv6k5Vc6Z2bB3bTMyewuKEMiROcyJFavbHGjUdV516yseFlJmG02_k3jKKDwOR9X9-iGIk3fegQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:45 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '289' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:45 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml new file mode 100644 index 000000000000..dfddec445293 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml @@ -0,0 +1,330 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:47 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNjYsIm5iZiI6MTYxNjY4NzI2NiwiZXhwIjoxNjE2NzczOTY2LCJhaW8iOiJFMlpnWU5pOTZ5aHZaZzNIdDRjbnpyb2RGUEdlQ1FBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDVvaTZ0elZ3VXluWkEzNEdjZFZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.UrhZkKaCqLriAnO4wBlQfgnQSie3oUSeCteY1O3_HGG4ZnuOPsYxUDH_VvMBrpM8m9d1bQ9cygsp8apqBzYsP_tldBvKusiiOVSkU7A49lDirKx4DfijLPqvNYOYF19eOPwMhPMaRTAjM1vswICC87UfMe_OMUBNqd2XjfPeQ7YsD48opUxindvJHZ5p9GzEi9FrAj_6K2sk81tH7l3Cbs0yrJ3j9MfIk6zX18gFzCue26F25gEHf48GB6dpduAPRalMw7IgbX4FO3HeF33Y41HxmqmKfUkXlW5S1yTzgjrKtI4m39cr-jro98AYCOpFPL58COW6KDppPJemq64aSA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMDgyNjVlYy0xYzkyLTQwYjItYWJmMS1jOTQ3ODk2ZjU4MzciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjcsImV4cCI6MTYxNjY5ODM2NywiaWF0IjoxNjE2Njg2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.MMFFfCYja2TZQ86y4vVHulWUVI98SGx1VQ5GPQUnCPBzU1DdXJjPP60-StCxmI1adibyz1UE_DtOtecm4mSPmIFO3awDdELbcngZEnYeR8A5gyzy8xFXhDtTCxOK2ZIJ4gXalpAQazRvx4hCdL7IvQDEgFowNfZG1QDsZti3GyNIS-CEWcTxMQKxM6Ic8NGmgAwl8-O3d6YMIyleDghsEHIWYa-c_GyiDLHCFwsihETXRPbBLotwxB9yqW7xJEoLSqmOG0I8H0crFZR99Z8dz9S9qltxlxMTI20TYwqzgBRzJgi_3vhvlKTv5LQk7vXKfBcpc1ewYVMmhazm5LcF_w"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:47 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMDgyNjVlYy0xYzkyLTQwYjItYWJmMS1jOTQ3ODk2ZjU4MzciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjcsImV4cCI6MTYxNjY5ODM2NywiaWF0IjoxNjE2Njg2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.MMFFfCYja2TZQ86y4vVHulWUVI98SGx1VQ5GPQUnCPBzU1DdXJjPP60-StCxmI1adibyz1UE_DtOtecm4mSPmIFO3awDdELbcngZEnYeR8A5gyzy8xFXhDtTCxOK2ZIJ4gXalpAQazRvx4hCdL7IvQDEgFowNfZG1QDsZti3GyNIS-CEWcTxMQKxM6Ic8NGmgAwl8-O3d6YMIyleDghsEHIWYa-c_GyiDLHCFwsihETXRPbBLotwxB9yqW7xJEoLSqmOG0I8H0crFZR99Z8dz9S9qltxlxMTI20TYwqzgBRzJgi_3vhvlKTv5LQk7vXKfBcpc1ewYVMmhazm5LcF_w + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyYWYyNzI4MC00YTdlLTRiYTgtYTk2Zi1hM2IxOGUwNThkMDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjgsImV4cCI6MTYxNjY5MTE2OCwiaWF0IjoxNjE2Njg2NjY4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.ZsvarYmAXUucyCxdddmi240TvaiIX8DwdPhwEIaqyM_5o2_mg1wZK-ojF4F2T4fFOqiOKAwlg6i6x_DxFhMkBdizteapM07w-od2egsogoaosdR4O2cPI-qKNC71uZPMRps_3HBxDsgT10nbxjZgFazyOzccAuAjHi3vkuewvk5pItays5YAQ0PLribERK7yV-UebT2he80iHy8xCbEuxpHGD6RBsrckF5riBJ04dmmh3V6h8jC5P3LEC0Cyg075nygsfdGGGDBjxxgiHODvefzIG7DbXZ_76XK2yy33bBouiDzrfXo5gq5fMKLmN4cWqtKfd3cHgvDBF2I4hmUAmQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:48 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '722' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:48 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:48 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNjYsIm5iZiI6MTYxNjY4NzI2NiwiZXhwIjoxNjE2NzczOTY2LCJhaW8iOiJFMlpnWU5pOTZ5aHZaZzNIdDRjbnpyb2RGUEdlQ1FBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDVvaTZ0elZ3VXluWkEzNEdjZFZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.UrhZkKaCqLriAnO4wBlQfgnQSie3oUSeCteY1O3_HGG4ZnuOPsYxUDH_VvMBrpM8m9d1bQ9cygsp8apqBzYsP_tldBvKusiiOVSkU7A49lDirKx4DfijLPqvNYOYF19eOPwMhPMaRTAjM1vswICC87UfMe_OMUBNqd2XjfPeQ7YsD48opUxindvJHZ5p9GzEi9FrAj_6K2sk81tH7l3Cbs0yrJ3j9MfIk6zX18gFzCue26F25gEHf48GB6dpduAPRalMw7IgbX4FO3HeF33Y41HxmqmKfUkXlW5S1yTzgjrKtI4m39cr-jro98AYCOpFPL58COW6KDppPJemq64aSA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMWQxYzU0NS04MDBmLTQxYTItOGYyOS0zMDJlMWNlNzE5OWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjgsImV4cCI6MTYxNjY5ODM2OCwiaWF0IjoxNjE2Njg2NjY4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.NZFAQbMEBkSY25HOzDNlvaIGqvIg0xbl1R9HbWOCCvpGt0HBZA9UOnQZucVITQgBM2LD4JyRuB5sKqE_w1JKSyl5exPoHtPfTsMycZylwkDJnVttnmza3ufKHqyGGqUY14dxmOZFh1-quK-Fa-B4zOjjtkeuZHEfqsIOTrKZnPzFVVo2t-GiDjqHY5PVtPfzlcp8DSA_Vuuy6rsKcA434uVl7XflrBW1vWOxBmJPBUxORd4KVq3oVaJAOxRGRrVg0XbCdh8G1D3qVcH2AdXqYAn_Y5WWt3Z3JXDefAZKOFwonFtnWUieQiCQgjiAs8ugkqf0Dgge9q3-7tnEGFUZ5Q"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:48 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMWQxYzU0NS04MDBmLTQxYTItOGYyOS0zMDJlMWNlNzE5OWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjgsImV4cCI6MTYxNjY5ODM2OCwiaWF0IjoxNjE2Njg2NjY4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.NZFAQbMEBkSY25HOzDNlvaIGqvIg0xbl1R9HbWOCCvpGt0HBZA9UOnQZucVITQgBM2LD4JyRuB5sKqE_w1JKSyl5exPoHtPfTsMycZylwkDJnVttnmza3ufKHqyGGqUY14dxmOZFh1-quK-Fa-B4zOjjtkeuZHEfqsIOTrKZnPzFVVo2t-GiDjqHY5PVtPfzlcp8DSA_Vuuy6rsKcA434uVl7XflrBW1vWOxBmJPBUxORd4KVq3oVaJAOxRGRrVg0XbCdh8G1D3qVcH2AdXqYAn_Y5WWt3Z3JXDefAZKOFwonFtnWUieQiCQgjiAs8ugkqf0Dgge9q3-7tnEGFUZ5Q + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIxNjE5MDQ1OC1hNGM3LTQ4Y2YtYjYyOC05YTgzMTg0OGFkYWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjksImV4cCI6MTYxNjY5MTE2OSwiaWF0IjoxNjE2Njg2NjY5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.IxHcEftOeiCig867HcRMyNslh4ts349FhFt8uAVEw5H0as_1n5vWA6abkg1-xXSWWL4LhZ4YfOh0K0Tb6POKzjjNmLePNkYJdSlXB4O8U9xEPvHwDu3tVI0hefriUbQnbqKpBTJRcXIvE1S6Fb-v3ieys8JVaZ8JYGdcPO7mif27PJ-AvNiTVDEoYN9AUd4s3AEIk-3EkCx45FHWQP4PE0EShgsCCxy7VsK8OS9i5rW1_Cng06T5mooRmKj_Tb-tGdDr5CteO6VyaVcE4jaPzPuZARyHgLZG1-uJbV9e5AuNi5QFXy5BNoDjcgRSb6MuokijVYidg11RmeqlU1CJ_A"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:49 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security + Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '913' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:49 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml new file mode 100644 index 000000000000..6487accafe60 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:51 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzAsIm5iZiI6MTYxNjY4NzI3MCwiZXhwIjoxNjE2NzczOTcwLCJhaW8iOiJFMlpnWUdBTFdsSHptbG02OTl3TkEwWHJQWnY4QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiUjdTY1dnMlZVVTYwWmZnbjJCYVZBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.d9DiNZpvoxCKX271t_nMfFzEOBMhbCyXbhKnnbkFhfXO8WyMsZ77CGJefzWLAJQwL8Ia9C70SXTMU-yCPEuTsmPCISIHTEuWgXhrEbWWHHgsxMVCeFTPTirdIWb9kA92YzN2LNeiptPhGQyeH29rJRnKJHIf5K3bj9KPT9tFzOYXH1hHAKcrjLPoyukhDFL7GaehO1AXzsQ3DJZNGKmqe56P8LuJQsl1fEKq_RIfY5pOXB0VNAbIFnc61__6DMTkeoF9DEhZfWkqxwVp2qdNJbqi0lj1hWGj49pRd1fwXvqcaYIOD_bRVUNOQW5in1IDoXoJoGPUkstda7g3xQ7rBw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiNmQxY2MyYi1mZWNkLTRjYjgtYmQyMi03ZGZiMDE4ZTZjNDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzEsImV4cCI6MTYxNjY5ODM3MSwiaWF0IjoxNjE2Njg2NjcxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Fo9gR9mk2nGQ-NA2QEha61OX_pMftZwPQqmRMBrs4YFmSfIdmiS5mn9i7nMsCwyYFsEWAyBWN-NUuRJHYC4RiMZUn0CMg6FKm_Ik2EgCCHuBN7wbt4IvxZS1s5xnuOelCqHOkZjXgdn7NxBCl0fE6LV2aYZ80L1xcEeVy1tUMGPVtA7PuyX6Z_9mU2IeZbwjANzhZtLZgH3TClAG1tBkGlpjjL0Fwzb2YVGEV0kGCll9c55ASMRDhsMKnLo_QPOEISabqp2jmn6wUbh6184C4RASRTGkEW02H_Mpu-TV62IkFHgVPHtSfqwXkrQ0c0NwkXL_Wf5_8KZinDtdL2jL_Q"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:51 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiNmQxY2MyYi1mZWNkLTRjYjgtYmQyMi03ZGZiMDE4ZTZjNDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzEsImV4cCI6MTYxNjY5ODM3MSwiaWF0IjoxNjE2Njg2NjcxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Fo9gR9mk2nGQ-NA2QEha61OX_pMftZwPQqmRMBrs4YFmSfIdmiS5mn9i7nMsCwyYFsEWAyBWN-NUuRJHYC4RiMZUn0CMg6FKm_Ik2EgCCHuBN7wbt4IvxZS1s5xnuOelCqHOkZjXgdn7NxBCl0fE6LV2aYZ80L1xcEeVy1tUMGPVtA7PuyX6Z_9mU2IeZbwjANzhZtLZgH3TClAG1tBkGlpjjL0Fwzb2YVGEV0kGCll9c55ASMRDhsMKnLo_QPOEISabqp2jmn6wUbh6184C4RASRTGkEW02H_Mpu-TV62IkFHgVPHtSfqwXkrQ0c0NwkXL_Wf5_8KZinDtdL2jL_Q + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyY2M5MzZhYy02YTdiLTRjMGMtODQ3Mi01ODE4YjNmNDRhZTciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzIsImV4cCI6MTYxNjY5MTE3MiwiaWF0IjoxNjE2Njg2NjcyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.amZDrXRFPbqPNR3Su_5ktQFZxwqmmp_BRI0u8tQ7-GDHtyh7jQ7IQE3wKp-Q1-e8QJHpQ2b4bVXVveOsGZibmiSQHQgSEy1qs25wQHMetu_f36rx4uPWXb1NPaPPv7bMS0vO3pKd4rTWLDH_Z8lEEpfvp5bgGt3tjJCcwTCY5bBjEzVsIkVEj6ITzLS-z3-UW6hLgoXrLg_8GZiHVkFr3azN9Ddz176fJK6W36se1mX-XPAVo5MJ7Az1ZjqebHrxcsotjZkUaFJ8Jzk2CLVZo2vR0QJjY_1u9Gsr5pRdyaJju98OveHGSsHJhYohd8x8SdY9GVRYGyDSlyiJ23UZWw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:52 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '380' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:52 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml new file mode 100644 index 000000000000..f5e12c34bee7 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:53 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzMsIm5iZiI6MTYxNjY4NzI3MywiZXhwIjoxNjE2NzczOTczLCJhaW8iOiJFMlpnWUZqVmwxRmt6WE0yeCsvd2ZBa0ZoK3cwQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoia1duME0ySTZORS1jU3EyV2JpTVpBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.nCh79PRrK1viGXpl9gQVTMYYMrCwZk1Vk-JlenkSb4gLj9OLahIoz4oAeM7PdJ76QoCO20jR0fs8ZkS-ZqqgcyJkiTQ1yX1TtvhnHhPxTIiaEc8YdqUusm2OO1-SzXslZHS_jfevJ3Iw9ireevFN_mSQyeKs33mhwlmFV6Tp9Cat5VGtnlMqObvXUTBLbfmxSZwFD6qQeIdpxEO_pJFz9438wh_ZXxZ68EIBEY3Isrk_QQX1rxUkSYdusccxwww7v5EV-ysSj-jz_jbztv4N1Lqs4-TL5PEaG6q4Zsg9H1Tho9PwnGkzEFEuaFoSOr6zf26pKIxiCg5u4WRPfU0S_w + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmMjNmZWFiOC02YThmLTQzZDAtYjJlMi1lMTFjZmFhMWQ1YTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzQsImV4cCI6MTYxNjY5ODM3NCwiaWF0IjoxNjE2Njg2Njc0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gvqjbRSrrSdB0Hgl5srbb9_Zo9JWdp5Wvon4zprFrTfUc1lwzKTVc7ADXtkP7ChMLHMI0_oU92XG2n2OyYzPKXopekp4V05hglM8fwxt7jskXzAOzBykgGZiYa4YXRhCH-frs2hLgG_b76cdWYXQeoyaY_vaL4hYxwa3xL6CfCQQwdZ11cZeqCNE6sF_16EvHmHZIjiEGhM3rmeKHVrvn2-pOK_1m5_gKvlVYslo3-Gq35Jg77XyLhr1cmrCqYeS5VlwyA1LVAGbj-YpiodjUe4i4X61VD8tM81Y4oC9i90YGTxtbx3DasGBBhAcHVwBG4MxkZbi08HMAEXou1SLjQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:54 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmMjNmZWFiOC02YThmLTQzZDAtYjJlMi1lMTFjZmFhMWQ1YTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzQsImV4cCI6MTYxNjY5ODM3NCwiaWF0IjoxNjE2Njg2Njc0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gvqjbRSrrSdB0Hgl5srbb9_Zo9JWdp5Wvon4zprFrTfUc1lwzKTVc7ADXtkP7ChMLHMI0_oU92XG2n2OyYzPKXopekp4V05hglM8fwxt7jskXzAOzBykgGZiYa4YXRhCH-frs2hLgG_b76cdWYXQeoyaY_vaL4hYxwa3xL6CfCQQwdZ11cZeqCNE6sF_16EvHmHZIjiEGhM3rmeKHVrvn2-pOK_1m5_gKvlVYslo3-Gq35Jg77XyLhr1cmrCqYeS5VlwyA1LVAGbj-YpiodjUe4i4X61VD8tM81Y4oC9i90YGTxtbx3DasGBBhAcHVwBG4MxkZbi08HMAEXou1SLjQ + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjMzg3ZjM1OS0zZjhhLTQxOTQtYjEyMC05NzUxM2NmODIzZTIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzQsImV4cCI6MTYxNjY5MTE3NCwiaWF0IjoxNjE2Njg2Njc0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.DDgHxpqtbRT485lm2oblRbAoDKOIzBh93HFR53f-lsVV21kIQ7LC-wymNoT5I8vsE_6Qd_TFo5kUFZBPY8w--NezAMs-ImmiuvqIJ-CWSMsJ72OSUL26bXULhGwRa-UhmOig9b6QkDJ-u4PZ-Tcx1FYkVzA0YvZqCm7rh43RsQk09GlddIaXCILTJraKUzgKjHz2qphxmhL6aX31z-7bsFLTXTMHLZ6BUWPbNEUL-4V_OXgIO25xmHCNjWYqC6EggA4y3VzUTskyQVzbLmzSXtcZ7U34YGU4VnJ2Ofjqr0_0qRoGv1H9YJ9WypWKxo3d7JtfRkAL03FUA4UoMPWmcg"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:54 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '599' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:54 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml new file mode 100644 index 000000000000..d1e9ee9c8c74 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:56 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzUsIm5iZiI6MTYxNjY4NzI3NSwiZXhwIjoxNjE2NzczOTc1LCJhaW8iOiJFMlpnWURCd0xWajdKakZyaDZ1UDRNcHB2cGFhQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQlBOX1RFeW16RWUzbjBkZzlQY1ZBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.VfCCMSfCfKp0rncwTfxcRvnL1k671J2wF1qGcMCWJbvY6etjAPPetdHA9QKe86McYDN-lVuHn_QcEAcJG7meUyQy21sFyCgx5GTJZKoSbE75D1S2wYZGdhercubifBCBny-uUsaEahpJpH3Uf_OSeSwf3ladYntOFepQR9iMbwqJjoqu5DD6fJvukp9-3fiE5G3z85UqJPa4Jk_a9bN1tIOagHFO4ATcQZh1YQnIjADhBxpklMlpUubGdvabVjPcDWQEgcRSvRwlnQLbK4G3PJW85cowRtFLHwJwNUWpWlJDHFdT5feh5f0htZEXLM5RSdEenkzJdU1lmtV8vnl4xA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjOTZkZmRiNC05ZmY5LTRhYTEtODE0Mi0wMTIyNTIwMTE3MmMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzcsImV4cCI6MTYxNjY5ODM3NywiaWF0IjoxNjE2Njg2Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e0YNV0UAB8ufCo0baIF1AOEl1r0gEOSQEh4pz2n16oQuK5jUyFnfYUNCsgToAOiwu-ho_ZVpFJjIkkB3BpS6wLxg-26JPAbvIl7YOnDH9eCTra4UuKyfOXC52lFvkh2K5G-rOiajO-dI8-V8M0ziuUmHU5wFNZYJZMA2bsqjAiE57Pk2j-If4RYSDlRz_tM1VFIFck1LMXHjnTIREpS5RfaByo-nEMkAtzQFxNnvqTkbCvODkIceKx3UhQmFDmpEMhL26Bgef7fK5aY5hf5Y3ikh6CxEWOprfCaKh9LBfriP29UzRqxYa2Vxr9qzOKceqeLeBoaX9nPFTgo6hPPj1Q"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:57 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjOTZkZmRiNC05ZmY5LTRhYTEtODE0Mi0wMTIyNTIwMTE3MmMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzcsImV4cCI6MTYxNjY5ODM3NywiaWF0IjoxNjE2Njg2Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e0YNV0UAB8ufCo0baIF1AOEl1r0gEOSQEh4pz2n16oQuK5jUyFnfYUNCsgToAOiwu-ho_ZVpFJjIkkB3BpS6wLxg-26JPAbvIl7YOnDH9eCTra4UuKyfOXC52lFvkh2K5G-rOiajO-dI8-V8M0ziuUmHU5wFNZYJZMA2bsqjAiE57Pk2j-If4RYSDlRz_tM1VFIFck1LMXHjnTIREpS5RfaByo-nEMkAtzQFxNnvqTkbCvODkIceKx3UhQmFDmpEMhL26Bgef7fK5aY5hf5Y3ikh6CxEWOprfCaKh9LBfriP29UzRqxYa2Vxr9qzOKceqeLeBoaX9nPFTgo6hPPj1Q + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiMDMxMWJiNi1kMDYyLTQ1ZTgtODRhOC1lNGM0N2E3NDBlMjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzcsImV4cCI6MTYxNjY5MTE3NywiaWF0IjoxNjE2Njg2Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.JtI-gZZ7oL8wHuAsNLrkJX-RIAqZolwM4OXXc7OmAKDGI4Gokks7bvv4k4YkppzU1z2omrzVcRbVOoDq60IlBUbUF6cSYmpeo0eCVYQMfQ-Co5hBOix84554DXqr-rit_mB7kkXtOwmNIb2seJg81OUpgK497vGF1O7X7m2y1ACcu2f7enVqD-yoL75W50f5HTBHiStLSxeXLGBOa9EB1quBJWy2xGJcnhPXXy0FueGjT2f9DshBiL5-aghn2huJ9Gbd1FfwgFqlukBbTqRqoZnKx4115E1PmNn4Sqss3sMYYgQUboJ4yw1Qb4PRlXT6aUNukeItSEYTAtV_PmDDTQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:57 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '722' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:57 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml new file mode 100644 index 000000000000..674822015882 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:52:59 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzgsIm5iZiI6MTYxNjY4NzI3OCwiZXhwIjoxNjE2NzczOTc4LCJhaW8iOiJFMlpnWUdpcXRZMnBTODFaa2VheXh1K05aeWtQQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiekFzMkF1bXkzMGFCTnpxNDJsMlRBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.fxtnDcPLe6FLlBHg-a2Y-szSKkXA77Rz2jRBgTP49kLS61HWxt8Vg8XsTw4GPq22IrQfxoB4RhRUzEic5M-gt2_I9vatcMaHmZtR9zxbIiiAyMyUYQTU-jSzbhT-xujlwE_57hBvAdl9xvKaVsNWA3iCt7lxIr3E6JnKO_09p4YjuG7t4JkNLO8gvPinFz7YVvp37gWLhPWiKmV6FlKkhNrgVqmghjEECmsrZoczUAS-LUiHvzTt_ARp1hnVhoyxAqF6sniLJBkWYKtm63krXrnp_iWwORryFayJbGPSjWWa1dWEf7Aa6YayjlR1-8RF603QWSZehL4T4G2iAR1twg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmZTU3MDE0NC0xYzYzLTRhYWQtYjRjYy1jNGRhY2FmZWU5MTYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODAsImV4cCI6MTYxNjY5ODM4MCwiaWF0IjoxNjE2Njg2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Gucl0Bvy-WzRnHFr8QXoSfyifY0IgvD5fnWsHwdfw47vY9PfqR0mz0Z3snzLA8zQEB3oCfTWdQYf3ZwwyJcmVxRCshaG-Qw5f6gQuEL9pk-mlwWJmWUdPPooqqtmjwnd7pyJ8y9iPTGGLBuFOtu_sE7YCl4omOjYpDk2avyTC9fl1KMTDP97TEa8gI1qDkOEshIxcgxN57b0N-83z3at6eZsNjAAKagBXIVUVuxFOPaA2Lg8OfruQq16Z3uiyLYpA8BpI-Y_TzO9ol8xjgKgP_qvUcFbziVWZsk7HzfSQocx21teXgz94v4glaT1_83tc6jd8gO1Kk2xJ0vlmIkVUw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:00 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmZTU3MDE0NC0xYzYzLTRhYWQtYjRjYy1jNGRhY2FmZWU5MTYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODAsImV4cCI6MTYxNjY5ODM4MCwiaWF0IjoxNjE2Njg2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Gucl0Bvy-WzRnHFr8QXoSfyifY0IgvD5fnWsHwdfw47vY9PfqR0mz0Z3snzLA8zQEB3oCfTWdQYf3ZwwyJcmVxRCshaG-Qw5f6gQuEL9pk-mlwWJmWUdPPooqqtmjwnd7pyJ8y9iPTGGLBuFOtu_sE7YCl4omOjYpDk2avyTC9fl1KMTDP97TEa8gI1qDkOEshIxcgxN57b0N-83z3at6eZsNjAAKagBXIVUVuxFOPaA2Lg8OfruQq16Z3uiyLYpA8BpI-Y_TzO9ol8xjgKgP_qvUcFbziVWZsk7HzfSQocx21teXgz94v4glaT1_83tc6jd8gO1Kk2xJ0vlmIkVUw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3MTQ3ZmVmOS0wNjhlLTQ1YTgtOTJjYy0xMzllZmNjNTgwNzMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODAsImV4cCI6MTYxNjY5MTE4MCwiaWF0IjoxNjE2Njg2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.dZS5ftdS25i4awSxm-l09EKR3jOiNtW6bfxFJC7f5AIo_1zLHmC3_me9_VF75NmKOrMOwQrd1HjCqbroCF39i4aurRstw2ptAianSBiz0PBxCWiVV4OqYpxL0kvwzyHzXnR-IPdSuS2kkritErv4EPeLNYvpF4LkdBlC87wCQxDqExoTL33ttqiZMlVc59bv_hDa9_YdSRiad45jIfBdSPDyUEAVYJZ2fnBhKLZMrGqM-kBAeiyXS1g7FvawPgvoq_N5zjGCcFnUrekGDqto5BcqQ79kJUknkE33ADq32HtZZSGwFcq9l3lUlTT8_aWCRmpc8_jL-QT0bsA0oOJGLg"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:00 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '722' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:00 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml new file mode 100644 index 000000000000..cd2b074239fb --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml @@ -0,0 +1,505 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:02 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODEsIm5iZiI6MTYxNjY4NzI4MSwiZXhwIjoxNjE2NzczOTgxLCJhaW8iOiJFMlpnWURoNlNOS1lkL3MwRll0N3k3ZytzbnZPQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYlU0R2x5WmptVUMzRFJUN2lJSmZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NLtmKZXYAPW4sDYSanx9hO95le8c6IvZTNytaoWO3JKN0ztHI3-qkLCRBUKvZmA28feYbuLgp_yzusctE25OntuW10s3njXUovWoRpAvtCZXvqjZnVtKt4aBCAM0xbAYw-2OFm_RQcVnqVPo3oHR6z13B7nfuA7LH884Prr7QzmEPu4sYs7AqSm5pY2ESSZRUYdh_gt8X-S34KgJBFxDmBRfQfC_rRQx6KYHprL9PJCUFL2dH0WP70AmxxnT5vaLwr9zDhn8o_sCQOrv8G6puYNLK82NeT8SKOjLHrNTKagfO3c8gLrnDwOePHnCWnvGSXomGtb6Tqk7bbF6b5MfDQ + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZjQzMWE0Ny05YzQwLTRkMWQtOTdhNy04NzViNzZiNDBiYzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODMsImV4cCI6MTYxNjY5ODM4MywiaWF0IjoxNjE2Njg2NjgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.V2lnkzCK17R4woVIYURzWFDjyzakX_CiyPdAjaLcdlxa3SVvvmENLE3OAJTf7yDvikdw45UnDO_ZxZuynJUSKDPvb-fuMRZJoGHPwLh-cfV6GUnyQ3C39K5YQNY5ZHQsRL7qSowaAHQu55FpTxkKQrWPV82ERX3V8-MQiE85LIoQjNeR3au_KTK_6E-StTI2GDVN_KiR0q_ZDXvDBUKUy1Wuazz-fpmDOBno_uODqLZXiXbndDoODhS8mRZSyj295GadyShPvkPTz1uflL30vrOvHdT9nrEFVDjbaP_e9MWNbZclEDcJQBmcuj7Lr2yVvVuAtCo02xpq8588lfmgBA"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:03 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZjQzMWE0Ny05YzQwLTRkMWQtOTdhNy04NzViNzZiNDBiYzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODMsImV4cCI6MTYxNjY5ODM4MywiaWF0IjoxNjE2Njg2NjgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.V2lnkzCK17R4woVIYURzWFDjyzakX_CiyPdAjaLcdlxa3SVvvmENLE3OAJTf7yDvikdw45UnDO_ZxZuynJUSKDPvb-fuMRZJoGHPwLh-cfV6GUnyQ3C39K5YQNY5ZHQsRL7qSowaAHQu55FpTxkKQrWPV82ERX3V8-MQiE85LIoQjNeR3au_KTK_6E-StTI2GDVN_KiR0q_ZDXvDBUKUy1Wuazz-fpmDOBno_uODqLZXiXbndDoODhS8mRZSyj295GadyShPvkPTz1uflL30vrOvHdT9nrEFVDjbaP_e9MWNbZclEDcJQBmcuj7Lr2yVvVuAtCo02xpq8588lfmgBA + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJlYTE0MDM4MS00OGU5LTQwNWItOTdiMy03NDc3OTBjMjZmYmIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODMsImV4cCI6MTYxNjY5MTE4MywiaWF0IjoxNjE2Njg2NjgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.PM1Qs_8V8TCbrgz72AK0LVfJMTGMMozm6RMVjUvrKAmx7fP1mdjVjkcyBvKBajEdhWzMkjso8I-y1e5baj8Wr6VR8al4XBBNt-eBLYvhTIVFAgByK1Loyeq99GXyWQO7kDWThT4SFaVPijMayVo7rUnxfPmqUi2AXFa4_LljyVTM3ME_gjtPMXQt1zhe9udZ2UTiMXGlIwwsgss1wSAVv4ZsLE1yUrU1dQZzjsNv16wFSmucU2_84tUtsHO3adKMEl8Jqg-ruK0gcOpM97ZEadDGGK5F8lWxpGFRFoS47cYaQMJfG0o_laER7nS8DozbWaAEZEF9RH7qgxc7IglPfQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:03 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '599' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:03 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: '{"deleteEnabled": true, "writeEnabled": false, "listEnabled": true, "readEnabled": + true}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '88' + Content-Type: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: PATCH + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_write"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '215' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:03 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_write",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODEsIm5iZiI6MTYxNjY4NzI4MSwiZXhwIjoxNjE2NzczOTgxLCJhaW8iOiJFMlpnWURoNlNOS1lkL3MwRll0N3k3ZytzbnZPQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYlU0R2x5WmptVUMzRFJUN2lJSmZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NLtmKZXYAPW4sDYSanx9hO95le8c6IvZTNytaoWO3JKN0ztHI3-qkLCRBUKvZmA28feYbuLgp_yzusctE25OntuW10s3njXUovWoRpAvtCZXvqjZnVtKt4aBCAM0xbAYw-2OFm_RQcVnqVPo3oHR6z13B7nfuA7LH884Prr7QzmEPu4sYs7AqSm5pY2ESSZRUYdh_gt8X-S34KgJBFxDmBRfQfC_rRQx6KYHprL9PJCUFL2dH0WP70AmxxnT5vaLwr9zDhn8o_sCQOrv8G6puYNLK82NeT8SKOjLHrNTKagfO3c8gLrnDwOePHnCWnvGSXomGtb6Tqk7bbF6b5MfDQ + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjZWRkY2QxZi1mN2FhLTQ1NjUtYmM1MC1hYjY2OGUxNzA4MDQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODQsImV4cCI6MTYxNjY5ODM4NCwiaWF0IjoxNjE2Njg2Njg0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.k1ng9kfSydeB43wHTfwM5c3K6TPbr2U_xNfxME43QKoA7SuZh5083PlLgBHMLAyxpapJ2pxagyx3ho1yXa9bQFmzUfAlAiZbj1E0wWT7l08pf5cvvHVah0SZnALCZDLO0KDhOwjUxI0ZbI4mXsfgHNJjtc3hW4o52xWLe252nuLGHXksAhTQ95xezZMxymEzGJ5XoMqKbi2WlIswmkgGcuWbluo6bPVoWC85pdLnW97gwze_7KNEr7M5CXEzfw_umsdTDR3C9F9ovBtV2XHewPo3gJfZKAtwspAA-QxOUPjwyyIjOrU4u1T3W0UhUDWPKiJgHcEDN5-ehb0ZiOX8JQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:04 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_write&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjZWRkY2QxZi1mN2FhLTQ1NjUtYmM1MC1hYjY2OGUxNzA4MDQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODQsImV4cCI6MTYxNjY5ODM4NCwiaWF0IjoxNjE2Njg2Njg0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.k1ng9kfSydeB43wHTfwM5c3K6TPbr2U_xNfxME43QKoA7SuZh5083PlLgBHMLAyxpapJ2pxagyx3ho1yXa9bQFmzUfAlAiZbj1E0wWT7l08pf5cvvHVah0SZnALCZDLO0KDhOwjUxI0ZbI4mXsfgHNJjtc3hW4o52xWLe252nuLGHXksAhTQ95xezZMxymEzGJ5XoMqKbi2WlIswmkgGcuWbluo6bPVoWC85pdLnW97gwze_7KNEr7M5CXEzfw_umsdTDR3C9F9ovBtV2XHewPo3gJfZKAtwspAA-QxOUPjwyyIjOrU4u1T3W0UhUDWPKiJgHcEDN5-ehb0ZiOX8JQ + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1080' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2NjBiNWY5NS1lMjRjLTQ4NWUtYWUxZS1iYmIyNzZkZDk1ZDQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODQsImV4cCI6MTYxNjY5MTE4NCwiaWF0IjoxNjE2Njg2Njg0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfd3JpdGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.IsPLnCPrwL5oanK9s2XQLL-hpOHipVkc77wwBy4O1zgfZYwh9TVbtlSzwlTIWQ2r8FfnCZW0EK3veSJwJS20LqgArtW13fjlENsdj8flVcstMDD_hB6VmTcrVCrwEc1jiglNoD-81FxuaM5lFXoXJAR3nk0Xk7KKu0_cRtdvxvV4WoidZrHWNktvqWkznO7zqAP5ewhpvEYolp9Rn5WpxxQiBCyvStfMO8CjdkhdKv1LPjyFDRiBq4v3nBnpEOurcM07S9kt3DFx1QcFHiUiSnj-MRyGyzCunf0rt5Q0wHh5bFc1cT03pKBvHqXnCa9YHo2ziidwSCp6G78WL1KRmQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:04 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: '{"deleteEnabled": true, "writeEnabled": false, "listEnabled": true, "readEnabled": + true}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '88' + Content-Type: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: PATCH + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security + Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '912' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:04 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:04 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODEsIm5iZiI6MTYxNjY4NzI4MSwiZXhwIjoxNjE2NzczOTgxLCJhaW8iOiJFMlpnWURoNlNOS1lkL3MwRll0N3k3ZytzbnZPQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYlU0R2x5WmptVUMzRFJUN2lJSmZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NLtmKZXYAPW4sDYSanx9hO95le8c6IvZTNytaoWO3JKN0ztHI3-qkLCRBUKvZmA28feYbuLgp_yzusctE25OntuW10s3njXUovWoRpAvtCZXvqjZnVtKt4aBCAM0xbAYw-2OFm_RQcVnqVPo3oHR6z13B7nfuA7LH884Prr7QzmEPu4sYs7AqSm5pY2ESSZRUYdh_gt8X-S34KgJBFxDmBRfQfC_rRQx6KYHprL9PJCUFL2dH0WP70AmxxnT5vaLwr9zDhn8o_sCQOrv8G6puYNLK82NeT8SKOjLHrNTKagfO3c8gLrnDwOePHnCWnvGSXomGtb6Tqk7bbF6b5MfDQ + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OWI5YWZjNy0wYjBjLTQ5ZjgtOTZmYy0yMWMwODY5NTYxMGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODUsImV4cCI6MTYxNjY5ODM4NSwiaWF0IjoxNjE2Njg2Njg1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ojwbVDdsJMsZKQiu_PquX2pX4YM0kQj7W8xetyxSMEQcQD2p4wdgJRNmDg0s6PY5oBQ409z8yK1PK3NrZh8wjUNUjQzhDY1ua_j2BLkzLNRjX928kwc5n-YBco1x3ynb2KaUwvSlaKiZV2W6MNyawNnKYVMyvdIMb_jwgtweRamFF_-clbDPi6iKftr5RdSaXxKsV0RLzy2Rta1SrE4vAwmP_jWI1oPcn_tD_NEtreZQB-1rv7wAsAjaY6V5fH8r2Gaq3h_hy-u4EsHKDZ-WnKRxmZcjhu1IRoMEnULXNWybLJbmMbeJ-Fhus_Xkzjf3oXS7qVHAxcWWzrcsK61_qg"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:05 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OWI5YWZjNy0wYjBjLTQ5ZjgtOTZmYy0yMWMwODY5NTYxMGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODUsImV4cCI6MTYxNjY5ODM4NSwiaWF0IjoxNjE2Njg2Njg1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ojwbVDdsJMsZKQiu_PquX2pX4YM0kQj7W8xetyxSMEQcQD2p4wdgJRNmDg0s6PY5oBQ409z8yK1PK3NrZh8wjUNUjQzhDY1ua_j2BLkzLNRjX928kwc5n-YBco1x3ynb2KaUwvSlaKiZV2W6MNyawNnKYVMyvdIMb_jwgtweRamFF_-clbDPi6iKftr5RdSaXxKsV0RLzy2Rta1SrE4vAwmP_jWI1oPcn_tD_NEtreZQB-1rv7wAsAjaY6V5fH8r2Gaq3h_hy-u4EsHKDZ-WnKRxmZcjhu1IRoMEnULXNWybLJbmMbeJ-Fhus_Xkzjf3oXS7qVHAxcWWzrcsK61_qg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4ZDg3MWJmNy1kMDJiLTQ5ZmQtOWVmOS0xM2ViMmVmMGVkNWEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODUsImV4cCI6MTYxNjY5MTE4NSwiaWF0IjoxNjE2Njg2Njg1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.II556GGzvBav_weasT6AxJN3Xr5R8twidPi4RVx5M3CvzkYxm51-bsjxf-FrJXmjrFUVyZOHRb5FK0nwm0_xaIYlm4lyB0_sgfn9vq8fq61QYZ5kBY51AYWT3QfvYMweEwYCuh7CrKW3R3hLitMh9lHbGeaClDpORNtJsx_kyUvJ44R1zv6Fo-BRZlyWk1-JQYRAbSM8V37hcmF4YikR1eIGMycSJo7hwknlHIciLk0xGyWrrfxOGzc56ru2t23Rh2SzpIQSb5RZdNkl4grtyoJRpdZ80i6Ja3tXkDZQJiQ980xb8KVig-zMbaWDxuEPe1Y9y2JqJw2CVcF7cowSGA"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:05 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security + Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '912' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:05 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml new file mode 100644 index 000000000000..ae5b069c1adf --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml @@ -0,0 +1,503 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:07 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODYsIm5iZiI6MTYxNjY4NzI4NiwiZXhwIjoxNjE2NzczOTg2LCJhaW8iOiJFMlpnWUNqYWJjTlFhSzFTd2pqSG0vZlB1a3NHQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQTBjNFVZVUkwRS1nVjY1a1Rid1RBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JS98aJ1m8yRQE671Kfb0cb5YZAkWm1IVAH2QGYmODlx6fUC4Hw-70ztS2AOaq0PwvTXSGFjXf4PlRhYtURXXVnn0GC8InMokBklY5LJLa1GF_u5GJ6aIX2gYeHqIaKRMVjCZ0UnaprYkVjLY7ZSj0ulXHdj7elsrvlkcc50RIJ0peV5DoywrnDmfZN-uFmWKzQkvndRurqNOTpLxXBXLAOPjI9-8izCBiFd0irvHVqcP61w8bfH0mFcyN2tHPF8Z2TQ24rsyNm7ywo2m7p2OZv-_RI8fe-IAI2B1QJ6H28OIsTA17ppwd3tqgrBgZSnM7A4x6CAKy9D0fPufyOcyWw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhNTkwMzI5Zi0yODA3LTQ5MTUtYTRiZC01MTc2YmFjMDAxYTUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODgsImV4cCI6MTYxNjY5ODM4OCwiaWF0IjoxNjE2Njg2Njg4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.c8e2h_ed-dsRxNIlhdqYQ89f3O6bM9D5hCf6H_PsXDq1O-3EOxbhmOPqFvfGQSjW6atR5y5v-E2m68Lxlp17I8bMfN8VVJXlQoSBBmSTWanM8-6iVFn_VqUjq94WMOmwBo623OrfF8N9ZwJkZFs87MsBWXdYDxS4VbFYYpD5x__Y0a2tQV8-qL_fYrZGnbNIbNvED2djLaoBho3RE-O0wHALBHmrH_1jbKFjATZVqAt7JHF2qImiZU-vWJb7euyLdSNRvDIcJ2Q98j5D7YU61E6UwSB6suTYZqT_OeflneXm78a_2tMyFr1oc43_w4Od4RNg8ahVB7tW91EeS1AZmg"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:08 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhNTkwMzI5Zi0yODA3LTQ5MTUtYTRiZC01MTc2YmFjMDAxYTUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODgsImV4cCI6MTYxNjY5ODM4OCwiaWF0IjoxNjE2Njg2Njg4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.c8e2h_ed-dsRxNIlhdqYQ89f3O6bM9D5hCf6H_PsXDq1O-3EOxbhmOPqFvfGQSjW6atR5y5v-E2m68Lxlp17I8bMfN8VVJXlQoSBBmSTWanM8-6iVFn_VqUjq94WMOmwBo623OrfF8N9ZwJkZFs87MsBWXdYDxS4VbFYYpD5x__Y0a2tQV8-qL_fYrZGnbNIbNvED2djLaoBho3RE-O0wHALBHmrH_1jbKFjATZVqAt7JHF2qImiZU-vWJb7euyLdSNRvDIcJ2Q98j5D7YU61E6UwSB6suTYZqT_OeflneXm78a_2tMyFr1oc43_w4Od4RNg8ahVB7tW91EeS1AZmg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwZTJjODE0NS0wOWQ1LTQwZGQtYjRiMy1mYWZkMzBiOTg4N2UiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODgsImV4cCI6MTYxNjY5MTE4OCwiaWF0IjoxNjE2Njg2Njg4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.MQiOEmIs58hNQ8fqHFcU1BgwNA4vjql6Jq2Lt_DpGZpsYv8mTEgsU2xsD_-VuDKL1LuYCKJm4gjc7_NVW1zUsOeQoFuDSIj3dOdFRADfK18cKa4gjQlQgx6Kvqk4EGSeka6drixL7VWK61HZwr0chEtfdV65P3YUPJSgw-ULDnCXUGFjnN9cAybHC5YvMJYPpTgbA9Dg2UWOGu_j4tpasdyQ2uiyQ8KXyz_ugqAaDL2EIKXz9n6jwgbe9MWKdPKGZW-PXx5Y5szhS_XxaKSvV-b0RM_9PeyTzKrbcIUYh-omBuKxQq-waX67AqyjCYFv6BCzXza4ffQ4kgb1O-bulA"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:08 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '722' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:08 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: '{"deleteEnabled": true, "writeEnabled": false, "listEnabled": true, "readEnabled": + true}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '88' + Content-Type: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: PATCH + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_write"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '215' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:08 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_write",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODYsIm5iZiI6MTYxNjY4NzI4NiwiZXhwIjoxNjE2NzczOTg2LCJhaW8iOiJFMlpnWUNqYWJjTlFhSzFTd2pqSG0vZlB1a3NHQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQTBjNFVZVUkwRS1nVjY1a1Rid1RBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JS98aJ1m8yRQE671Kfb0cb5YZAkWm1IVAH2QGYmODlx6fUC4Hw-70ztS2AOaq0PwvTXSGFjXf4PlRhYtURXXVnn0GC8InMokBklY5LJLa1GF_u5GJ6aIX2gYeHqIaKRMVjCZ0UnaprYkVjLY7ZSj0ulXHdj7elsrvlkcc50RIJ0peV5DoywrnDmfZN-uFmWKzQkvndRurqNOTpLxXBXLAOPjI9-8izCBiFd0irvHVqcP61w8bfH0mFcyN2tHPF8Z2TQ24rsyNm7ywo2m7p2OZv-_RI8fe-IAI2B1QJ6H28OIsTA17ppwd3tqgrBgZSnM7A4x6CAKy9D0fPufyOcyWw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwODU1MzhmYS04MjMxLTQyMTMtOGM2Zi1hODMyZjAyNWNkNDgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODksImV4cCI6MTYxNjY5ODM4OSwiaWF0IjoxNjE2Njg2Njg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Bh1lG11oZaJ5RV6v7z3XQlLME6uYOiQ1A_FiNealZN2AUBBmHI9y6x3DOG6UpB9ls9dDkqHYbAxdL6kAZRCi1ICEy5ROn7bDMjW2icjcdM0yTQe9ZVN3vjODuV-Yy_rjSsoO_yavCbkEObnWxC5t1_rbSk3pC8O1zhk6I0_wGMxc8ZZmwx1oPmoampF-sJzzKvRofh01TZZ7Vq2omd0bL63GUAdGL_nRVZDqq5QiOwU8niL3sZ7WeJfgwLwGF2U85ZXuox2cwD7G2gKcuToiN4ZaanBcPhAU73S8Qj0g_TPNCA3v4QgF73Cvcll0Wgg8B5RgpbTUH0qeBDZ6WKoQ4w"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:09 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_write&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwODU1MzhmYS04MjMxLTQyMTMtOGM2Zi1hODMyZjAyNWNkNDgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODksImV4cCI6MTYxNjY5ODM4OSwiaWF0IjoxNjE2Njg2Njg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Bh1lG11oZaJ5RV6v7z3XQlLME6uYOiQ1A_FiNealZN2AUBBmHI9y6x3DOG6UpB9ls9dDkqHYbAxdL6kAZRCi1ICEy5ROn7bDMjW2icjcdM0yTQe9ZVN3vjODuV-Yy_rjSsoO_yavCbkEObnWxC5t1_rbSk3pC8O1zhk6I0_wGMxc8ZZmwx1oPmoampF-sJzzKvRofh01TZZ7Vq2omd0bL63GUAdGL_nRVZDqq5QiOwU8niL3sZ7WeJfgwLwGF2U85ZXuox2cwD7G2gKcuToiN4ZaanBcPhAU73S8Qj0g_TPNCA3v4QgF73Cvcll0Wgg8B5RgpbTUH0qeBDZ6WKoQ4w + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1080' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1OGYwYzY0Ny1iNjNmLTQ0N2QtOGU4OC1kM2Y3NGVhOGQ5OTIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODksImV4cCI6MTYxNjY5MTE4OSwiaWF0IjoxNjE2Njg2Njg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfd3JpdGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.LvrMN0nOnFuUzO_HejWEGKZq8nKUhIx4Xsvftt-ABSXr1o1TcZ8Wyn918tHrODKUrWG80QUKynjLcaozX2_APXy4aNvDPyCkNlTpRvCz57Z93xvrneUEBjtg3E9EfJcujuDxy91lfztPlO5JX7MCaYfnPdNuPjFMiH9K7mFooTNNNWrLd8cUpssufnEq4pfQCYQVwJZHbaJSzHJTNLArnioWmWzYFCwTsXGtNS8u7YRkZGGjlTTwAwHaDG3abi2Z0mR9yb3kgxKYTbkTD2tmDe-Jwx6oiZ2DpFvaMk4k_vBp29WppDFpPIi1Myb6vxUKIlb6sfydGoHHIc8qeYVaAQ"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:09 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: '{"deleteEnabled": true, "writeEnabled": false, "listEnabled": true, "readEnabled": + true}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '88' + Content-Type: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: PATCH + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security + Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '912' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:09 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/first + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:09 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODYsIm5iZiI6MTYxNjY4NzI4NiwiZXhwIjoxNjE2NzczOTg2LCJhaW8iOiJFMlpnWUNqYWJjTlFhSzFTd2pqSG0vZlB1a3NHQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQTBjNFVZVUkwRS1nVjY1a1Rid1RBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JS98aJ1m8yRQE671Kfb0cb5YZAkWm1IVAH2QGYmODlx6fUC4Hw-70ztS2AOaq0PwvTXSGFjXf4PlRhYtURXXVnn0GC8InMokBklY5LJLa1GF_u5GJ6aIX2gYeHqIaKRMVjCZ0UnaprYkVjLY7ZSj0ulXHdj7elsrvlkcc50RIJ0peV5DoywrnDmfZN-uFmWKzQkvndRurqNOTpLxXBXLAOPjI9-8izCBiFd0irvHVqcP61w8bfH0mFcyN2tHPF8Z2TQ24rsyNm7ywo2m7p2OZv-_RI8fe-IAI2B1QJ6H28OIsTA17ppwd3tqgrBgZSnM7A4x6CAKy9D0fPufyOcyWw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0ZjFiODRiOS1hOGM4LTRlMDAtYjEyYy1kMWJhMzkyOGZmNzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTAsImV4cCI6MTYxNjY5ODM5MCwiaWF0IjoxNjE2Njg2NjkwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Ty0kIc8Rzy1KVE50SCiJZS8GgPeRv1XoC5WMawSKLgYcXWAiTzhT3CtkOC1z2PbU6MH-h5r-w_T_N1vt6Eb2Ph71AXwguiivXKY0GJrfZgPMjcYYwoRfFAGJArymPTQxaeaPpKNx5OdwlmsH63S5XOTZFvdSCjjpBK_qUlyNrh1P-2cI4UTNcbLq6z2V1FQjkQi9QKBxWzjEjR6isFEo0dzy2LedkWpbBqfMHpok050kkCG66wC49BXAgXjrbkz2uUtXrXg9RrTrjTVZ8na9f6pk2i-dKBRskOmt4INDDMkQWeF6oq01OmRtj0baP-UUtTtLiDheKe1f_OPr0Yuvnw"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:10 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0ZjFiODRiOS1hOGM4LTRlMDAtYjEyYy1kMWJhMzkyOGZmNzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTAsImV4cCI6MTYxNjY5ODM5MCwiaWF0IjoxNjE2Njg2NjkwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Ty0kIc8Rzy1KVE50SCiJZS8GgPeRv1XoC5WMawSKLgYcXWAiTzhT3CtkOC1z2PbU6MH-h5r-w_T_N1vt6Eb2Ph71AXwguiivXKY0GJrfZgPMjcYYwoRfFAGJArymPTQxaeaPpKNx5OdwlmsH63S5XOTZFvdSCjjpBK_qUlyNrh1P-2cI4UTNcbLq6z2V1FQjkQi9QKBxWzjEjR6isFEo0dzy2LedkWpbBqfMHpok050kkCG66wC49BXAgXjrbkz2uUtXrXg9RrTrjTVZ8na9f6pk2i-dKBRskOmt4INDDMkQWeF6oq01OmRtj0baP-UUtTtLiDheKe1f_OPr0Yuvnw + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmNGVjOTgzNS0xZTk2LTRjZjAtODE5My04NmJmNTVmZTdlMzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTAsImV4cCI6MTYxNjY5MTE5MCwiaWF0IjoxNjE2Njg2NjkwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.JD52eHxP_xlRlJKpd0lVBYONjkG8xfob0_KC_GuPN-5mzs9wKfcKEpK2bgU12D-ErrGfw4AWJDO6hf0oAHyr1ak7LLL0xcu0ItGeiqXnsPQ2JtnYxhYpwjIImE3RqhhNWoRr2xbj7-qsdjxjSACMp7Abp9oOjYMHMBTV7Pg4tCh6-CaCehXQ08F4mcyrmd9xPBkNwCsKWw5xgqll5H6prbCfsr-qtFiO2PZGfAy2xX0JV1_23Eg0YlFoAcyreyoGfZEjtcYAI0ox6cxQJjITGvplCWjydHeB-JazYoAlBACeKjb4kXZ_h2mS1YyQquozBiiCGfGbs81I_3whJlrWug"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:10 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/first + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '406' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:10 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml new file mode 100644 index 000000000000..58bc0e5b89e6 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '196' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:12 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyOTEsIm5iZiI6MTYxNjY4NzI5MSwiZXhwIjoxNjE2NzczOTkxLCJhaW8iOiJFMlpnWUpqY0luTE5lVjA0KzY1STkvc01iWmUzQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQllRYzdWcjdZRUtYSExoRExMVVJBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.MZIdEfCYCN7zXIE9mddygnyqG_vtaCk4orba85U81eUQurX2stJK4jyvvWJIGnruU6i6CQL4QO7UY-f3-NlWgxE1Nvfw3AMNt3SR9zYk7ZxvKjYH9mn7i2XsFgp-5Uk-mv8uyF6YISTgSFHPfxptVk46BS3nFnbDAYqpfegxiIvBkRgGY2Ixn7cE2o8d9yWxra7kd_e0CFk19Uv9YwG7d22yczX_uH1vkYXcucm2VQWchjo0fErt1aZpoG7TfjgWuTv_B56zAt5ECvhKog23CnM3R8EFNssyor-0ntDLfa4liSq3l0JAVFSaIED6io-pFcOTqHsCQOYmxnkUhDCy_w + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1YWUwMTdhYy05MDFhLTQ0YjgtOGE0MC0yNzM1YzNiMzYwY2EiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTMsImV4cCI6MTYxNjY5ODM5MywiaWF0IjoxNjE2Njg2NjkzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.W1y1jY1cxgKMaqeWHWi_COohmK71Arujmtp7RGQcR9u-s5kSiuiJIPiQvQKLf94jJC3lDq0FUfVJc96aABTLG3zbPB6_uSzC7KLwJGYYi9mFRC6RVTIiIoa93tu-E5UMDb3pzwfWMteMbkEUjoKL4LrrMvZLmzplgDDoACdmFzFLBGAkC0_vMQZ8oiaO5soQtkLc9bNVrRLut7_fmL7VvNFfGGOqQSpTIk2jdxkD3E6e1ryLGZjC8QCkREWTe5I_0AKNgCGTo0Pv6iTslWVMot49_g5T9nxyvsQ1FzWh_3m3OsmxQdjkXYQz1st588foPEP_eZRiKMvpi7Y1d4B2yg"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:13 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry%3Acatalog%3A%2A&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1YWUwMTdhYy05MDFhLTQ0YjgtOGE0MC0yNzM1YzNiMzYwY2EiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTMsImV4cCI6MTYxNjY5ODM5MywiaWF0IjoxNjE2Njg2NjkzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.W1y1jY1cxgKMaqeWHWi_COohmK71Arujmtp7RGQcR9u-s5kSiuiJIPiQvQKLf94jJC3lDq0FUfVJc96aABTLG3zbPB6_uSzC7KLwJGYYi9mFRC6RVTIiIoa93tu-E5UMDb3pzwfWMteMbkEUjoKL4LrrMvZLmzplgDDoACdmFzFLBGAkC0_vMQZ8oiaO5soQtkLc9bNVrRLut7_fmL7VvNFfGGOqQSpTIk2jdxkD3E6e1ryLGZjC8QCkREWTe5I_0AKNgCGTo0Pv6iTslWVMot49_g5T9nxyvsQ1FzWh_3m3OsmxQdjkXYQz1st588foPEP_eZRiKMvpi7Y1d4B2yg + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1063' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkZTI5MTY4OC0wZTE0LTRlMzYtOWM2Yy03MWEzYmJlMTI3MzYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTMsImV4cCI6MTYxNjY5MTE5MywiaWF0IjoxNjE2Njg2NjkzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.aV8vCrkK7meZbNIvSeTnKdWtThsfqAU1VI0N-_Q2QliU7-PljVr_agP0DvpcjB6XB2wYiEwaWysr-CBI8JNSEhNZ4i8Z80EsSFMZth0EX3u5GUq4KFfx6zAtEwwQAergpqEpgM4LBn6z1UFWJI_6dCBlJtye5TWzLFKarhe_ocFiWpPrfk459VUr0UCEFr_PL0w-YwcnibP8z0dAROkwJHq8D64mFOBrFnWZR-_HJSu9l-eyYEOF-IySnUO34FqMh-LImdld-VX_xFiZYbOxraXiFK9BMcSzjzlVOD2vQ1JTiCaiiDp5X1eGzQPktpHVTiKMcXHN2sQu338wgEbr-g"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:13 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '125' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 15:53:13 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 78d1302cc247..38921df0155c 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -21,7 +21,7 @@ ) from azure.core.paging import ItemPaged -from testcase import ContainerRegistryTestClass +from testcase import ContainerRegistryTestClass, AcrBodyReplacer acr_preparer = functools.partial( PowerShellPreparer, @@ -31,10 +31,12 @@ class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): + def __init__(self, method_name): + super(TestContainerRepositoryClient, self).__init__(method_name) + self.vcr.match_on = ["path", "method", "query"] + self.recording_processors.append(AcrBodyReplacer()) + self.repository = "hello-world" - repository = "hello-world" - - @pytest.mark.live_test_only @acr_preparer() def test_get_attributes(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index 0732e8bd0955..9ea94489e206 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -4,7 +4,10 @@ # Licensed under the MIT License. # ------------------------------------ from datetime import datetime +import json import os +import re +import six from azure.containerregistry import ( ContainerRepositoryClient, @@ -16,19 +19,94 @@ from azure.identity import DefaultAzureCredential +from azure_devtools.scenario_tests import RecordingProcessor + +from azure.core.credentials import AccessToken + +REDACTED = "REDACTED" + +class AcrBodyReplacer(RecordingProcessor): + """Replace request body for oauth2 exchanges""" + def __init__(self, replacement="redacted"): + self._replacement = replacement + self._401_replacement = 'Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token"' + + def _scrub_body(self, body): + # type: (bytes) -> bytes + s = body.decode("utf-8") + s = s.split("&") + for idx, pair in enumerate(s): + [k, v] = pair.split("=") + if k == "access_token" or k == + + def process_request(self, request): + if request.body and isinstance(request.body, six.binary_type): + request.body = self._scrub_body(request.body) + else: + pass + + return request + + def process_response(self, response): + try: + headers = response['headers'] + auth_header = None + if "www-authenticate" in headers: + response['headers']["www-authenticate"] = self._401_replacement + + body = response['body'] + try: + refresh = json.loads(body['string']) + if "refresh_token" in refresh.keys(): + refresh['refresh_token'] = REDACTED + body['string'] = json.dumps(refresh) + if "access_token" in refresh.keys(): + refresh["access_token"] = REDACTED + body['string'] = json.dumps(refresh) + + except json.decoder.JSONDecodeError: + pass + + + return response + except (KeyError, ValueError): + return response + + +class FakeTokenCredential(object): + """Protocol for classes able to provide OAuth tokens. + :param str scopes: Lets you specify the type of access needed. + """ + def __init__(self): + self.token = AccessToken("YOU SHALL NOT PASS", 0) + + def get_token(self, *args): + return self.token + class ContainerRegistryTestClass(object): + + def __init__(self, method_name): + # self.vcr.match_on = ["path", "method", "query"] + self.recording_processors.append(AcrBodyReplacer()) + def create_registry_client(self, endpoint): + token = DefaultAzureCredential() + if not self.is_live: + token = FakeTokenCredential() return ContainerRegistryClient( endpoint=endpoint, - credential=DefaultAzureCredential(), + credential=token, ) def create_repository_client(self, endpoint, name): + token = DefaultAzureCredential() + if not self.is_live: + token = FakeTokenCredential() return ContainerRepositoryClient( endpoint=endpoint, repository=name, - credential=DefaultAzureCredential(), + credential=token, ) def assert_content_permission(self, content_perm, content_perm2): diff --git a/tools/azure-devtools/src/azure_devtools/scenario_tests/recording_processors.py b/tools/azure-devtools/src/azure_devtools/scenario_tests/recording_processors.py index 3e9c3cb29162..f1ac45485922 100644 --- a/tools/azure-devtools/src/azure_devtools/scenario_tests/recording_processors.py +++ b/tools/azure-devtools/src/azure_devtools/scenario_tests/recording_processors.py @@ -191,9 +191,12 @@ def process_request(self, request): request.uri = request.uri.replace(old, new) if is_text_payload(request) and request.body: - body = six.ensure_str(request.body) - if old in body: - request.body = body.replace(old, new) + if isinstance(request.body, dict): + pass + else: + body = six.ensure_str(request.body) + if old in body: + request.body = body.replace(old, new) if request.body and request.uri and is_batch_payload(request): import re From 6be366a6f98c8f9cb51f5012de96fe898ded5dc3 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 25 Mar 2021 16:34:35 -0400 Subject: [PATCH 66/86] working live and playback --- .../containerregistry/_exchange_client.py | 32 +--- .../azure-containerregistry/tests/__init__.py | 0 .../tests/async_tests/__init__.py | 1 - .../tests/async_tests/asynctestcase.py | 63 +++++++ ...test_delete_repository_does_not_exist.yaml | 18 +- .../test_container_registry.test_get.yaml | 113 ------------ ...ainer_registry.test_list_repositories.yaml | 18 +- .../async_tests/test_container_registry.py | 8 +- ...test_auth_flow.test_get_refresh_token.yaml | 74 -------- ...egistry_client.test_list_repositories.yaml | 19 +- ...repository_client.test_get_attributes.yaml | 164 +++++++++++++++++ ...repository_client.test_get_properties.yaml | 19 +- ...test_get_registry_artifact_properties.yaml | 46 +++-- ...tainer_repository_client.test_get_tag.yaml | 19 +- ...y_client.test_list_registry_artifacts.yaml | 23 ++- ...iner_repository_client.test_list_tags.yaml | 19 +- ...tory_client.test_list_tags_descending.yaml | 19 +- ...y_client.test_set_manifest_properties.yaml | 85 +++++---- ...sitory_client.test_set_tag_properties.yaml | 63 ++++--- ...nge_client.test_auth_policy_in_action.yaml | 165 ------------------ .../tests/test_auth_flow.py | 69 -------- .../tests/test_container_registry_client.py | 8 +- .../tests/test_container_repository_client.py | 18 +- .../tests/test_exchange_client.py | 22 +-- .../azure-containerregistry/tests/testcase.py | 38 ++-- 25 files changed, 443 insertions(+), 680 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/__init__.py create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/asynctestcase.py delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py index 9ce60045a920..f13d4232b5ec 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -6,6 +6,7 @@ import json import os import re +from typing import TYPE_CHECKING from azure.core.pipeline.policies import SansIOHTTPPolicy from azure.core.pipeline.transport import HttpRequest @@ -13,6 +14,8 @@ from ._generated import ContainerRegistry from ._user_agent import USER_AGENT +if TYPE_CHECKING + from azure.core.credentials import TokenCredential class ExchangeClientAuthenticationPolicy(SansIOHTTPPolicy): """Authentication policy for exchange client that does not modify the request""" @@ -44,6 +47,7 @@ class ACRExchangeClient(object): AUTHORIZATION = "Authorization" def __init__(self, endpoint, credential, **kwargs): + # type: (str, TokenCredential, Dict[str, Any]) -> None if not endpoint.startswith("https://"): endpoint = "https://" + endpoint self._endpoint = endpoint @@ -59,39 +63,19 @@ def __init__(self, endpoint, credential, **kwargs): self._credential = credential def get_acr_access_token(self, challenge): + # type: (str) -> str parsed_challenge = self._parse_challenge(challenge) refresh_token = self.exchange_aad_token_for_refresh_token(**parsed_challenge) - return self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) + return self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) def exchange_aad_token_for_refresh_token(self, service=None, scope=None, **kwargs): - - # body = """grant_type=access_token&service={}&access_token={}""".format(service, self._credential.get_token(self._credential_scopes).token) - - # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} - # request = HttpRequest("POST", self._endpoint + "/oauth2/exchange", headers=headers, data=body) - - # resp = self._client._client._pipeline.run(request) - # refresh_token = resp.http_response.internal_response.content - - # return json.loads(refresh_token)["refresh_token"] - + # type: (str, str, Dict[str, Any]) -> str refresh_token = self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( service, self._credential.get_token(self._credential_scopes).token) return refresh_token.refresh_token def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): - - # body = """grant_type=refresh_token&service={}&scope={}&refresh_token={}""".format( - # service, scope, refresh_token) - - # headers = {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded'} - # request = HttpRequest("POST", self._endpoint + "/oauth2/token", headers=headers, data=body) - - # resp = self._client._client._pipeline.run(request) - - # access_token = resp.http_response.internal_response.content - # return json.loads(access_token)["access_token"] - + # type: (str, str, str) -> str access_token = self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( service, scope, refresh_token) return access_token.access_token diff --git a/sdk/containerregistry/azure-containerregistry/tests/__init__.py b/sdk/containerregistry/azure-containerregistry/tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py index d55ccad1f573..e69de29bb2d1 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py @@ -1 +0,0 @@ -__path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/asynctestcase.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/asynctestcase.py new file mode 100644 index 000000000000..48c357b49353 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/asynctestcase.py @@ -0,0 +1,63 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +from datetime import datetime +import json +import os +import re +import six + +from azure.containerregistry.aio import ( + ContainerRepositoryClient, + ContainerRegistryClient, +) +from azure.containerregistry import ( + TagProperties, + ContentPermissions, + RegistryArtifactProperties, +) + +from azure.core.credentials import AccessToken +from azure.identity.aio import DefaultAzureCredential + +from azure_devtools.scenario_tests import RecordingProcessor +from devtools_testutils import AzureTestCase + +from ..testcase import ContainerRegistryTestClass + + +class AsyncFakeTokenCredential(object): + """Protocol for classes able to provide OAuth tokens. + :param str scopes: Lets you specify the type of access needed. + """ + def __init__(self): + self.token = AccessToken("YOU SHALL NOT PASS", 0) + + async def get_token(self, *args): + return self.token + + +class AsyncContainerRegistryTestClass(ContainerRegistryTestClass): + + def __init__(self, method_name): + super(AsyncContainerRegistryTestClass, self).__init__(method_name) + + def get_credential(self): + if self.is_live: + return DefaultAzureCredential() + return AsyncFakeTokenCredential() + + def create_registry_client(self, endpoint): + return ContainerRegistryClient( + endpoint=endpoint, + credential=self.get_credential(), + ) + + def create_repository_client(self, endpoint, name): + return ContainerRepositoryClient( + endpoint=endpoint, + repository=name, + credential=self.get_credential(), + ) \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml index 997b1bbc7a0f..3d228017f69a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml @@ -19,11 +19,11 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:46 GMT + date: Thu, 25 Mar 2021 20:03:40 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:not_real_repo:delete",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: nosniff status: code: 401 @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/not_real_repo - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODg1MjUsIm5iZiI6MTYxNjY4ODUyNSwiZXhwIjoxNjE2Nzc1MjI1LCJhaW8iOiJFMlpnWVBDNE5rdnF6em05OHRNVG1tTWVlT1dLQWdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoicE9ONTM4TU9Za0c2eEtZN2VFNWpBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.K4z8Y3OnXAXX9unFr66_FKvt0TRHxljiFTUVJg8l9nbsfp2x6G9NkjSDBzg2AlpsMjg2VcKPd_bNR7Eo-Sr1CxswX1azmaFDgPeFVqLmtK9cllRuwpngMNnlMNHPWRFvn3JnBiBvKn9SWM0d234RMMUmS_u96xNmri6ue-zxitJQg79qlDKrZungQTyoao3HJBdFkRry8hufIc-O6r2xNx1iHmchFZwoPM_RPdpZq0v07K7PzFdIYkNb5EEVB_U7LIMVmhksyhoAEzGq82T0EM8QotfeQTWBkd88_5gUCaJaJkiy081InwhQ1uSc5vX540d__LU-bvnW5u5aFitoCg + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3MDIzMTksIm5iZiI6MTYxNjcwMjMxOSwiZXhwIjoxNjE2Nzg5MDE5LCJhaW8iOiJFMlpnWURBMkxtMCtHYW5PVnp6YjhQM3BQUlBlQVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYzhkdjhUOG9KVS1YUGg0RDlXb3BBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.llZmQNVaGoLRLxhBgVpWwP_iAmWNPSMyOjA2f5xUudiWiB1v8SN7grk7DsS9P4TXnJLpQtGYvpek_QZZav7oflTlLuvhpUILKQaSqJj5ons5jmGneLe-T0Dx66SPRRCGL8MgPRcZFxDqL17rcXHcbQR26YLjrCA9JoraTPdhi17eo112N9UPgpZASOjceGIrtg5jgNDx-r02eacIz4rWNqrHIOT8cikZ7FwD3-N4I1yE6ry5VO5_97KxMy_LkQYMz_Huq2U7VRjEUIyjk1xw6_UjLOnfKDtRsWsYlRSCrph24IVvLhyOqqpkPhuVmvfuzr1vHl1ZetwfWZPC5AETvw grant_type: access_token service: seankane.azurecr.io headers: @@ -43,11 +43,11 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZTQ0OTc1Mi00YWY5LTRjMDQtODYzNC0wMDIyYTBjMDE4NmYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjcsImV4cCI6MTYxNjY5OTYyNywiaWF0IjoxNjE2Njg3OTI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZB_fKjLcFgD2p-KiR2uOgXHkNHuRQfA1rV3gvJ4PxulC9e2UcbxArM6HGy_cTBOjXRg0pGT5HRYaPGOs4HzBHOowKnYajgx20f04FprTgJprIYKGCcp0rT8U_9GB6ZwPmY3KyCA3ScbkqAe8_GdjjqD6k-LCyYG3w00Z4WP3XaPJ-RaKTTrRBr2NinOkntmgDAauab8Q8S8hOTdLDlA1i5TIqXGkEq_JRsbr_P9Zq4PrXYcFPhNFwuobo-Dc3TboGDobInehNfjyOq99x6cZp2y15B9ltMF6lWVI9-0LYk5uXoVHJsvpsR_aWPf8rA14hxZ1XIn0C1PQQ4YeFvmV0g"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:47 GMT + date: Thu, 25 Mar 2021 20:03:41 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZTQ0OTc1Mi00YWY5LTRjMDQtODYzNC0wMDIyYTBjMDE4NmYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjcsImV4cCI6MTYxNjY5OTYyNywiaWF0IjoxNjE2Njg3OTI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ZB_fKjLcFgD2p-KiR2uOgXHkNHuRQfA1rV3gvJ4PxulC9e2UcbxArM6HGy_cTBOjXRg0pGT5HRYaPGOs4HzBHOowKnYajgx20f04FprTgJprIYKGCcp0rT8U_9GB6ZwPmY3KyCA3ScbkqAe8_GdjjqD6k-LCyYG3w00Z4WP3XaPJ-RaKTTrRBr2NinOkntmgDAauab8Q8S8hOTdLDlA1i5TIqXGkEq_JRsbr_P9Zq4PrXYcFPhNFwuobo-Dc3TboGDobInehNfjyOq99x6cZp2y15B9ltMF6lWVI9-0LYk5uXoVHJsvpsR_aWPf8rA14hxZ1XIn0C1PQQ4YeFvmV0g + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiMTUyNDFlMy1mOGUyLTQ5ZDUtYWRiNy1lOGMyZTM3OTZlM2MiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3MDE3MjEsImV4cCI6MTYxNjcxMzQyMSwiaWF0IjoxNjE2NzAxNzIxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.IZ02pQqPFVvpI99e-fdyIl3wF_6PV0dKF1wIa1EqEWbwsa9RRUZ_7R5XKyfk5b30b4a096qXBCt9e8F1j7PnnsRSHtMjd19PxxvDxxpzwuFBfXH-BuyMXfb4p_bqR_Lpa1FK0vmYhrbWd8i2Fz_dxJe-yr6cSpBHN1dA7YINxIbfovfW-JXSc5i-uas2dWXcdBHoOhfs_Q88uSaFu32it-H8G9PgVQUf5R7op3kAvBDIizgydvIgBNNhBXpq5MP17hW74k725Ww7ebkF27Qq47ZdOnImb7dN77RD882w1-bsGWWsWulr-mvHsKaLWW8X38hshg_TccU7g-vp1N3r_Q scope: repository:not_real_repo:delete service: seankane.azurecr.io headers: @@ -70,11 +70,11 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkYWFlMjE1NS05MzUxLTQ5YzktYmJkNy02MDMyMjkwMTUwZTkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjcsImV4cCI6MTYxNjY5MjQyNywiaWF0IjoxNjE2Njg3OTI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJub3RfcmVhbF9yZXBvIiwiYWN0aW9ucyI6WyJkZWxldGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.FkpNJr_GHPVSYd7KE2rTyRDfxu5zQjmMJWBa9rcz9VkHzOLySANrGgqp25Tz1BHBcKms8j29kkNh-6Soabo_fg8iGBrudWMfQgghnsKSRUmKsG33YrasJyczec3TZw0zdZO7FxeWTJupak3qAq8VhQbnbKcSY5vMDelOzP88BwYJ3ImTedrDhAPr88cwt0JoZ-4WNhuyUSInSM5S1CwggYbDE2jS1kti3UAwHhmULZApe3qMoXdpm9gcgLP-z2hntmGMYKelYok2M8xmc2plF8CspS8wz-EayC1dxpzCpCrWnk52cOUtBKJT57NsJYpO2fG3csayksaAeHfT5ruLEQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:47 GMT + date: Thu, 25 Mar 2021 20:03:41 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -102,7 +102,7 @@ interactions: connection: keep-alive content-length: '121' content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:47 GMT + date: Thu, 25 Mar 2021 20:03:41 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml deleted file mode 100644 index ef3c859c905d..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_get.yaml +++ /dev/null @@ -1,113 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '214' - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 15:42:28 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" - x-content-type-options: nosniff - status: - code: 401 - message: Unauthorized - url: https://seankane.azurecr.io/acr/v1/hello-world -- request: - body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODY2NDYsIm5iZiI6MTYxNjY4NjY0NiwiZXhwIjoxNjE2NzczMzQ2LCJhaW8iOiJFMlpnWU5EYktYMlI5L0oyWm5WdGMzblBUTFYwQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRFNKWGFkX1E4VXFMTWpEM2oyUnVBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.Cqc9CKfdMvjmxBml3J-hv-V-w6vU0vwyy7hNU6UlHe1inPFlEflcqN_XRX-wNcIKFVsmLUsoh5Kfw9r87A1DJS57gyRIE8YzNFIWiw2CRDrveFAW6TfPukbXwdaHUwDd_owpdnDbsOvTDrMISmls_q8ZEhdRvdJb3GtyjZiC9Z7q_CWus_HBEwx0I5SWF7nKzMXGYwncObKYpGo5TI6k9C6VOt-8nlnRvfAueU_aqlMzAB7fu4NZtVIRmkE_gK3u4UNf_FYZWWOZk_2X8CgM-o327pJ5HFR-EhqiL7fuot52uPlADNCjCQP5qX6ENzURPiJsblQcWHVRqB2Fg3nmjQ - grant_type: access_token - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkN2M2NWM2ZC05OTM0LTQxYWYtOGJkYi02ZTU0Y2FkODI4ZjkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODYwNTAsImV4cCI6MTYxNjY5Nzc1MCwiaWF0IjoxNjE2Njg2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.hO0zLR6XtQB6hZZXMqgHPezRei8TDjQfJ1VFAW7qMQ2RiXQ0dT_nfWqHJlWbx6E0NS_P1k--N0d6gBhoDCAOG3FACc7hYtMyzHCJ76dGqVRdyYp44P6OwosYr19tdfDAVi8Wleo96IgPmeE-PBzaJIzOXvcXgDSWLbpvixZc_Jx2hDmHM2V7LlMB2thwerNUnj50m1SA6J7uVEiZNhHGQvNPIBVB5KIUE-i2AgcmLp22VazJ51o7wkWzodPVmXMkLEhhWqFjq6IUQC_GcYueZ6WEvTAhM2p23Wn8AqPU_VciO7CczTdvtpbiXeYknXIslyXLUWSsxyiKVfAI5GzJDw"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 15:42:30 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/exchange -- request: - body: - grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkN2M2NWM2ZC05OTM0LTQxYWYtOGJkYi02ZTU0Y2FkODI4ZjkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODYwNTAsImV4cCI6MTYxNjY5Nzc1MCwiaWF0IjoxNjE2Njg2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.hO0zLR6XtQB6hZZXMqgHPezRei8TDjQfJ1VFAW7qMQ2RiXQ0dT_nfWqHJlWbx6E0NS_P1k--N0d6gBhoDCAOG3FACc7hYtMyzHCJ76dGqVRdyYp44P6OwosYr19tdfDAVi8Wleo96IgPmeE-PBzaJIzOXvcXgDSWLbpvixZc_Jx2hDmHM2V7LlMB2thwerNUnj50m1SA6J7uVEiZNhHGQvNPIBVB5KIUE-i2AgcmLp22VazJ51o7wkWzodPVmXMkLEhhWqFjq6IUQC_GcYueZ6WEvTAhM2p23Wn8AqPU_VciO7CczTdvtpbiXeYknXIslyXLUWSsxyiKVfAI5GzJDw - scope: repository:hello-world:metadata_read - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1Y2NkNjM0MS0xMDhiLTQ3ZWItODczNC02NTU5NGIwYjkxMDEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODYwNTAsImV4cCI6MTYxNjY5MDU1MCwiaWF0IjoxNjE2Njg2MDUwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.e059O57qmQa3vMGk7LMr8HM2WzKTCzau4xOByi8MQjDe-p6mtYGuV6ownAqi1w-eybZqKAQX-ommpk15RXKbVkkrpFg5Tbz2-I5EcshkyR2ESFIo0DxvldlJXEWK9FyNuwTfWaWptU734xKY8GPdcsRzid5bl5JsQAD2oWFXxbJnDD9WP00U5r4wiqO0I0s6Q97Ce4AtNMEX87SXTWDQ4jMeMRCxsUV6L5a8P55Cd5NdpqEq2baHP9OZZEwysDhDlNhLIMPoQFfssHIz5b5IjOAwJ8gbPmzHz7HWLtwqYZyhOhpBYhTpawoZC0lVG6CTZ0lYyqk7AVYLv5gDAwTvzQ"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 15:42:30 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/token -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '289' - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 15:42:30 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/acr/v1/hello-world -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml index 9580ef074ca4..b59264c49b73 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml @@ -19,11 +19,11 @@ interactions: connection: keep-alive content-length: '196' content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:48 GMT + date: Thu, 25 Mar 2021 20:03:42 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: nosniff status: code: 401 @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/_catalog - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODg1MjcsIm5iZiI6MTYxNjY4ODUyNywiZXhwIjoxNjE2Nzc1MjI3LCJhaW8iOiJFMlpnWUFpUVNmb1hWUmJ1dWxkSU41TjN0NG96QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT0V4eF9MVU9JMG1FUHVMNEo5RjBBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.kSFkot0f5ek0fy-AqLPjRRFWpWOVVrXSnN67klzZgrLi6do9zYvfXptJUkGkxu3Oyj1i3ea-gNpD6-VEcWG25zsK3w8lIKO9gpV0jebmj3aRB8jk_K9Tgk84mHAzzFSAF4fTFXkrFSbsdt4ntwlGuy_LNprtsJqUnpyF-OsR5s8pqF0Vkew-2_PO1ZVDixaxIzELHyLoqPPb2zC4F5TB0TYEjotB7Ds97rTzjPC-kKTILnsYbzi9zwZ4uWKQlfh03ZXvFO4zmOgceujP8LT-fyuOJCc_MB5PLyn7dW6UOa_Dl2BfK80mE0Ot_yDboNQMTJke9fJFT5kQRK1higtj8w + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3MDIzMjIsIm5iZiI6MTYxNjcwMjMyMiwiZXhwIjoxNjE2Nzg5MDIyLCJhaW8iOiJFMlpnWURpbUxwSDBNK3lBOTk2ZzNtZlRReVg3QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibktzak1aYVBtRUdIMGJzT0Y0OFZBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.dBQ2ttHP5V0CmkwwzPvOOqowj9ZDj5gOjewhu1gUkxC9NOMoWuZ-trSkvwLV4yLHq-LIjCTSVp9Ac6viRzI-lU0TfV7Tst5_YxzJWs7X8Nk7jOD5B_1QOdEG-9oTI6myeGyA64UgiAEoFgAzz-0ZBQ7_GIPp03inoWWSvNqyn3DhLpqVSzcO72F4tMVMjvzQStpfcT3SEDM3PPhxteYhEsmbnsku8N_kIREnndeLbAiMlkX4Ht1em0vZ9WO_Ja6Mo6ChbJsDS_xzb9my8LWpnAtZwQFqvC6RaFSD5zdhzZ5JobXZ27DmDMMI1QuQYck1zMdQapeTH8meIgj_4YhWqw grant_type: access_token service: seankane.azurecr.io headers: @@ -43,11 +43,11 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMzE3MGMzNy04OGZhLTRhMTAtYTc3Ny0yYWNjZWQzZmQ0ZDAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjksImV4cCI6MTYxNjY5OTYyOSwiaWF0IjoxNjE2Njg3OTI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.afyBJmPJQA4hdbwvImWni_CSIw8rxtI6J6YBX82hDXmS9478jsO37ZfIpYgMfiewO3f0MY0p53rC3HhTVuH9yk5_qtM5UC0gMBkMovxxGvjsme77g9H356k2kdWl-hSsDm1Q3XAzYO5bAKrBET6Xo4pe6aROxN7sMMVBHSf7guDmXPbY4FMZxhKI8tWwH3RemAQQ4YTzPy2dc5sKAvriEju--a_mGvQUDMoHGecY1Qo6e2ZuzYqnANqopu0eSRjPFv8UwLR91YAEfrqWPOFMrXDdWqI7i_NCpc3MIauw3L-ytbUvifawCTBMr8g2nYTwWiNdR82y8Qyn28PJA9fnEg"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:49 GMT + date: Thu, 25 Mar 2021 20:03:43 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMzE3MGMzNy04OGZhLTRhMTAtYTc3Ny0yYWNjZWQzZmQ0ZDAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjksImV4cCI6MTYxNjY5OTYyOSwiaWF0IjoxNjE2Njg3OTI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.afyBJmPJQA4hdbwvImWni_CSIw8rxtI6J6YBX82hDXmS9478jsO37ZfIpYgMfiewO3f0MY0p53rC3HhTVuH9yk5_qtM5UC0gMBkMovxxGvjsme77g9H356k2kdWl-hSsDm1Q3XAzYO5bAKrBET6Xo4pe6aROxN7sMMVBHSf7guDmXPbY4FMZxhKI8tWwH3RemAQQ4YTzPy2dc5sKAvriEju--a_mGvQUDMoHGecY1Qo6e2ZuzYqnANqopu0eSRjPFv8UwLR91YAEfrqWPOFMrXDdWqI7i_NCpc3MIauw3L-ytbUvifawCTBMr8g2nYTwWiNdR82y8Qyn28PJA9fnEg + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzMGJhYTgzOC1lMjUyLTQwMDItOTYzMy0zNWI5YzM2MjEyNjEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3MDE3MjMsImV4cCI6MTYxNjcxMzQyMywiaWF0IjoxNjE2NzAxNzIzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.T0_ckQSEkxsL0mBlw1APIHDD5ZX6cuQrPuzgg0CzMBur1pO7eH7J1BV3wfqBnFLGVBudP3gIEg9FRbwlvae_vQKm5Jqu23shLlqOBT9gq4zS8ynkNq28O1eRMJtVx5gSUKqVKg52gvI56xObd8Jk3Y1e0Y36d8OwJsHrMXciwyQjODaolTn40MvMKzKJFEjN8yaWpw6ihtYast75rAIFe_nqdMyzL4WBXc_koxgB7iCxwXHFNpUFi4rI5mElYDtSPkXAp9yzQbBh2lykOorLb6wrq1Rv6vBVly5byjGOMPcH_0SErwqHn0wE3tH8_19eXy_Oq3m77dWc2_FuE2qpaA scope: registry:catalog:* service: seankane.azurecr.io headers: @@ -70,11 +70,11 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3Y2I1MjVjZi1jODA1LTRiOTItYTA2NC1jZWI2MzczNjY4YTUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODc5MjksImV4cCI6MTYxNjY5MjQyOSwiaWF0IjoxNjE2Njg3OTI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.kj7B-g32r8lVjxkhJwq9_ucje6zGHXNFlxQduMG_YKwUnockoiRbAUZ_1xoWg9JCUnlcR1dkLt4uhIt6Zh5w5FspeUuuZrjeTsdmnbxO_XV055OphwRy1OcHPejNUHdQpb8hbSWtPKvjsUAm-7jsqFQnDv4QVfsPGPv69Afs65LDuCKFOxi175079sxXhtCr2yi5j1DPrZVTasRL9ydFjPPS50YSMG3xi_OQjJXsxqb-xcmfLaz17h_zFiCmBA_PzAnx1gDRQKPkHgjAUHj1W0S6MXHJOp4cFJfqim6lMij401d1Z1U4HSEH1eWvlOemYXuC4oOJHGgvtblD-kw9DQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:49 GMT + date: Thu, 25 Mar 2021 20:03:43 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -101,7 +101,7 @@ interactions: connection: keep-alive content-length: '125' content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 16:13:49 GMT + date: Thu, 25 Mar 2021 20:03:43 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py index 93701f41f266..6ede04115062 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py @@ -19,7 +19,7 @@ from azure.core.paging import ItemPaged from azure.identity.aio import DefaultAzureCredential -# from testcase import ContainerRegistryTestClass +from .asynctestcase import AsyncContainerRegistryTestClass acr_preparer = functools.partial( @@ -29,11 +29,8 @@ ) -class TestContainerRegistryClient(AzureTestCase): - def create_registry_client(self, endpoint): - return ContainerRegistryClient(endpoint=endpoint, credential=DefaultAzureCredential()) +class TestContainerRegistryClient(AsyncContainerRegistryTestClass): - @pytest.mark.live_test_only @acr_preparer() async def test_list_repositories(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) @@ -61,7 +58,6 @@ def test_delete_repository(self, containerregistry_baseurl): assert len(deleted_result.deleted_registry_artifact_digests) == 1 assert len(deleted_result.deleted_tags) == 1 - @pytest.mark.live_test_only @acr_preparer() async def test_delete_repository_does_not_exist(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml deleted file mode 100644 index 71c0f25cba02..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_auth_flow.test_get_refresh_token.yaml +++ /dev/null @@ -1,74 +0,0 @@ -interactions: -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNTQsIm5iZiI6MTYxNjY4NzI1NCwiZXhwIjoxNjE2NzczOTU0LCJhaW8iOiJFMlpnWU9oUlR0TDllT3RtYjUwbTY1elp2eHNUQVE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibWlVOEZXQklNVXk2eHJLX2pDNFJBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JvWpWhQByofdCAQ-UHPu6vuMAWuNo7ce6ceVvDjnXVaXye_8X5BS1O9poEJ2TphzXZJQ0vRBEkkwZaap6zneR5zi55MGChSX92tAPeLEq5z1gh6YCDfrQHX2nN6aB7jMFJWlpj8DojkAcMh9wNYww8PoPitTKyc0pD3aoHTWUXeuYnAg9JRGhIMwjdTNHuTc6mwFsTcDmpZJ1KLxCC3CJbtp6zZj86OiK4y_v4EORfr4_wmE-mpJojwBcCxIF-L_UPLVAnx-OJIjttJ779dZ679N13tsKgVdjXBxKGF3KfJ_V3mdyOalp4I1wBhBNzm3QUT6wsk70bckzCLESLFBgA - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkNDAxMDY2Ny1mYjgyLTRhMDktYjZhZS1lOWMyODc2NzcwMzgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTYsImV4cCI6MTYxNjY5ODM1NiwiaWF0IjoxNjE2Njg2NjU2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.XgSJn0OtHEMBlxjqEaQ_h9a_T3fHIwgEsqBE1mfKq3DaK3HHMuWNoAhDbjsAcGrbRVqL7sw3q95hepDohgnw2WDelvHjACDP9xYwyRZQj9WT7xRwOcUrEsVd0o1OrUJKv0T__7p3aGGdf-Lml98n3uePzqWOlVbUv7sl1LHmWvq3iWi6UUhD_v3OlwE3LBlGX4uwhxVpKnQbDpSXn6GoSrlaxMz6cJES-I2Fd_iwd1hJqGPsQl2kLpuwo83vdGnGPl5FUOqC44fWNJcCGn8zMTPGKBKRr7bF_jAGCHZWgNhgbB9BqJL6Yf4XA_9HZO8lrfTVCIVKPV6x544VRvIM6w"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Thu, 25 Mar 2021 15:52:36 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkNDAxMDY2Ny1mYjgyLTRhMDktYjZhZS1lOWMyODc2NzcwMzgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTYsImV4cCI6MTYxNjY5ODM1NiwiaWF0IjoxNjE2Njg2NjU2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.XgSJn0OtHEMBlxjqEaQ_h9a_T3fHIwgEsqBE1mfKq3DaK3HHMuWNoAhDbjsAcGrbRVqL7sw3q95hepDohgnw2WDelvHjACDP9xYwyRZQj9WT7xRwOcUrEsVd0o1OrUJKv0T__7p3aGGdf-Lml98n3uePzqWOlVbUv7sl1LHmWvq3iWi6UUhD_v3OlwE3LBlGX4uwhxVpKnQbDpSXn6GoSrlaxMz6cJES-I2Fd_iwd1hJqGPsQl2kLpuwo83vdGnGPl5FUOqC44fWNJcCGn8zMTPGKBKRr7bF_jAGCHZWgNhgbB9BqJL6Yf4XA_9HZO8lrfTVCIVKPV6x544VRvIM6w - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1079' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2ZDU5OWNlYy05M2MzLTQ4Y2MtYWVhMy00YmI4ZWMxM2IwNjIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTcsImV4cCI6MTYxNjY5MTE1NywiaWF0IjoxNjE2Njg2NjU3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.R-OkJ83W76DYOwUDtAwEn2RP3FBO587ggFSNyLRaPaUUSW7Ns3IA5jhIwqaU0soEQHoCYurY_FossxciFQU0BZYiCZ0VzUeuASsR00XBhqKPsoSaKdzZftj2wqIe8GNA2SkQNT_rfe6sKYfBJUchIXqoQV1b7jFiP-QhI8KBxeKtmsSTWxF4IqeckihxLh42ubdJygjhocNlFGk0VRjCDELiL4OJmNAjbYHQ08zKno1jamyptF6tM4-3owiVLjirWylDD0sBVJ7XdFVa4WXBmEBVR8_--bP5ZQg-Hgb-C0OcxECtDvfg_m-ZAp4aJJRIAjurTibQhk_cmU5Sf8yl6Q"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Thu, 25 Mar 2021 15:52:37 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index 5861dde40863..8588647c622a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:38 GMT + - Thu, 25 Mar 2021 20:03:02 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNTcsIm5iZiI6MTYxNjY4NzI1NywiZXhwIjoxNjE2NzczOTU3LCJhaW8iOiJFMlpnWU5qTEZiVC9oTm4yaDZxU0J3NjFMbjV6RmdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZVJScVpHRk5URW1wQmNhQVJUV1BBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.M_sTJByBEUU9Zr0CPIuhiS3sVJJLyW3NVwyRMyFFBt-7SthCcbrVX9LZcfdr6nafLCexkYC4WtPdJ4xt9fTxJs9BTLBPEXp7mtZFs3EYzuASoEVHJLaMeYd1BwzRvRNcaAQJaTRLvazYGdJCD1UCPhsBmc5ocYfKXfSHL64B0tWJY6aivBzof_8c1Xan27wGg9WrssabDQu6OeXVl0m1jtXFb2HUpqTnqTNo8b-QhSlUy5ehyojZmZtyZLf55IHf_mrQWiVzzHRH83q15o70eMqRukjwHBQ7rMIO_HNqKvk97qDREdlvDGguINacnT57FbvoMO7rRke96cR9z9XKGg + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmNTY2ZTQxNy03NGJkLTRiMjAtYTgzZi0zMDQxMDFjNzQ1YzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTksImV4cCI6MTYxNjY5ODM1OSwiaWF0IjoxNjE2Njg2NjU5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.So0GO7Ge8zl-B6mZT-BTM4FwFNEKHUB1ScfeQT--TT6X-PQmr22jioIqhRHcIYebzxdTmzY61w1ecLTNnylKBrMTW1EBEqpt2lIcvfE9rz3k-z2GdYJjJOkdvnN5Fkf2sHXimk_EQahNLT1WfAr2tjr9AAMG8-IC0WVQbHsmVmynyQQPPcd5xvTQ1ftXjKoEzEjmTUOCCPJi_9o1Q0KMhQsRgSg9Vlr2PB_2NpS_xVPcoHCd69Z2bN5MUbzOAYRsCAit0Xfp9Yu4BdVmSYnotCEogGBSuQMv59tkLw4SIeLxYPla7UQdTOVduikKQ4-84ZaZfPHOUQk6EL-qQSLIRA"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:39 GMT + - Thu, 25 Mar 2021 20:03:04 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry%3Acatalog%3A%2A&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmNTY2ZTQxNy03NGJkLTRiMjAtYTgzZi0zMDQxMDFjNzQ1YzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTksImV4cCI6MTYxNjY5ODM1OSwiaWF0IjoxNjE2Njg2NjU5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.So0GO7Ge8zl-B6mZT-BTM4FwFNEKHUB1ScfeQT--TT6X-PQmr22jioIqhRHcIYebzxdTmzY61w1ecLTNnylKBrMTW1EBEqpt2lIcvfE9rz3k-z2GdYJjJOkdvnN5Fkf2sHXimk_EQahNLT1WfAr2tjr9AAMG8-IC0WVQbHsmVmynyQQPPcd5xvTQ1ftXjKoEzEjmTUOCCPJi_9o1Q0KMhQsRgSg9Vlr2PB_2NpS_xVPcoHCd69Z2bN5MUbzOAYRsCAit0Xfp9Yu4BdVmSYnotCEogGBSuQMv59tkLw4SIeLxYPla7UQdTOVduikKQ4-84ZaZfPHOUQk6EL-qQSLIRA + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry%3Acatalog%3A%2A&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2MGUxZjAzNS1jMjdjLTQ4ZDAtOTcwOS1kODdlOTQ4ODA3NjciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NTksImV4cCI6MTYxNjY5MTE1OSwiaWF0IjoxNjE2Njg2NjU5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.I9ArX-GXS8FfMSbDYAvoeebZtKRbTMWWALUPhc64J0B1CcCBrl3ehcwAn5wQ4S_XQIyYa7nG9bmSeBN3fCZiw4Pm2F1Ynyhdu6nHvVSw4u5YwVT2DENdE_FlIcNkTQs8XNobKOC4X7vV8Sx6s4fc4dK4g7MTSCAGWlIeknUdykPeg7q4o8evMsZqzhRiUPD4YSDL2OB1d8RGeWkIJExoz0werbfVfu2YeKWwK7jipAGS-GKPNtLYifT2U1VlRPh7I1ONkb7fnfXCG-DdllpsJB39K9LD0Rpyjh0XJkVxvrlpyITtC7-13o1hEYzMEjx_xxSDF0GdF1kloU-RX0D5dA"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:39 GMT + - Thu, 25 Mar 2021 20:03:04 GMT server: - openresty strict-transport-security: @@ -149,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:39 GMT + - Thu, 25 Mar 2021 20:03:05 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml new file mode 100644 index 000000000000..877d5cc2714d --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -0,0 +1,164 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 20:03:06 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 20:03:08 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 20:03:08 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '289' + content-type: + - application/json; charset=utf-8 + date: + - Thu, 25 Mar 2021 20:03:09 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml index c6e3a9024dff..c9438d51fd6f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:44 GMT + - Thu, 25 Mar 2021 20:03:10 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNjMsIm5iZiI6MTYxNjY4NzI2MywiZXhwIjoxNjE2NzczOTYzLCJhaW8iOiJFMlpnWUpqVFAzMkoydm9ENjBLdVNZc3ZycDQwRVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRVNPRTlTR2hVa091Q1h4Tm95Z1BBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.iErbO5UQhtcgGznf11mC1Pw3QrVJqZuUPRIgl53cmAVKL2O8M5uZh0065gZ79hXzyLIJ6HekAFSIaY9VSobLAL0tctdXAg2IL-spmUjOZn30EoWQrMAPQ5oSX7r1udzfovyIO9uIdGBKW312jnfA3maiZkkCQy8eqOax44_ceEroih4x_5kMSWS_Tmk100EimKta2T6-t2qy_xcuyUftvtTZBDlCZAtFJPTR1V38n_iTFvkJYMUraXMSzKO6Tiw5TsB7pkURbLuzszwleuTnB4-IJVREUUxXLXtFCi9CRO-1yMrPMwBx9zhe0o11AGZ_T2pVEjZ2C7_4-0_6gqQPpg + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMjk2NTI0OS0zNzAwLTQ5NWUtYmUxYy0wZTliMzAzZDE5MDkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjUsImV4cCI6MTYxNjY5ODM2NSwiaWF0IjoxNjE2Njg2NjY1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.TyriD1hq1OcG5uKwB3hq5SMaW5y56GQ6_msXw8zFJPTETnP70HcouFIHvJGzfFXFlF9xaNyfC1Er4WslQ2wlvx9ivgStmlFqS29fScZSDx2y5dzynvnnQY_w0947GkY26RI5zFVe_CQ3BUPhGsgFZXcV3l-mF4_crCuE5nCWqpZHlDWh-r3R7fw1R_xtMc--4znwDhyrg1Q5KdbgQGsT0ORAFRMtRHvjTtInjO4i0wLziDrhvYw55S9DLFnDwRTGcHOnF8HeGjvhv8ippsyNaLvR-v8eHGWFJV3TOrspecrE4dp4t_HJl2F4Y-rM-DxyPWMCykBR8OkumbmDFEFsmw"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:45 GMT + - Thu, 25 Mar 2021 20:03:11 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwMjk2NTI0OS0zNzAwLTQ5NWUtYmUxYy0wZTliMzAzZDE5MDkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjUsImV4cCI6MTYxNjY5ODM2NSwiaWF0IjoxNjE2Njg2NjY1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.TyriD1hq1OcG5uKwB3hq5SMaW5y56GQ6_msXw8zFJPTETnP70HcouFIHvJGzfFXFlF9xaNyfC1Er4WslQ2wlvx9ivgStmlFqS29fScZSDx2y5dzynvnnQY_w0947GkY26RI5zFVe_CQ3BUPhGsgFZXcV3l-mF4_crCuE5nCWqpZHlDWh-r3R7fw1R_xtMc--4znwDhyrg1Q5KdbgQGsT0ORAFRMtRHvjTtInjO4i0wLziDrhvYw55S9DLFnDwRTGcHOnF8HeGjvhv8ippsyNaLvR-v8eHGWFJV3TOrspecrE4dp4t_HJl2F4Y-rM-DxyPWMCykBR8OkumbmDFEFsmw + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0OWVmOTcwNS1lMTEwLTQ3N2UtYjhjMS1kZTA1MDUyYjMyMzQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjUsImV4cCI6MTYxNjY5MTE2NSwiaWF0IjoxNjE2Njg2NjY1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.EDfBShkfySbhHsVJHsXG4OLWycSA2ddp-Xp_m5k--gesNW23hRn_tHP7jggtdf33zDrhn7FMp4z6sA10Nl1c4aeFipOsDX3dAvim9mIU1s0jS9uenIhzzqm1nPDIL3sHS7YHnC6Z4xfKR4j1oqtmqIK_s_0nQq6qww2ae13HFDPgRhI2DqVXWP86eieBpNMG7jhK6wrO8U74BizzpkSlcqST5r8RYpdUr6UcHUFDwuVniwfttwYoMx3r4X2t4oTiszLR3Z9st5kxv6k5Vc6Z2bB3bTMyewuKEMiROcyJFavbHGjUdV516yseFlJmG02_k3jKKDwOR9X9-iGIk3fegQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:45 GMT + - Thu, 25 Mar 2021 20:03:11 GMT server: - openresty strict-transport-security: @@ -149,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:45 GMT + - Thu, 25 Mar 2021 20:03:11 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml index dfddec445293..d9aeffa98401 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:47 GMT + - Thu, 25 Mar 2021 20:03:13 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNjYsIm5iZiI6MTYxNjY4NzI2NiwiZXhwIjoxNjE2NzczOTY2LCJhaW8iOiJFMlpnWU5pOTZ5aHZaZzNIdDRjbnpyb2RGUEdlQ1FBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDVvaTZ0elZ3VXluWkEzNEdjZFZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.UrhZkKaCqLriAnO4wBlQfgnQSie3oUSeCteY1O3_HGG4ZnuOPsYxUDH_VvMBrpM8m9d1bQ9cygsp8apqBzYsP_tldBvKusiiOVSkU7A49lDirKx4DfijLPqvNYOYF19eOPwMhPMaRTAjM1vswICC87UfMe_OMUBNqd2XjfPeQ7YsD48opUxindvJHZ5p9GzEi9FrAj_6K2sk81tH7l3Cbs0yrJ3j9MfIk6zX18gFzCue26F25gEHf48GB6dpduAPRalMw7IgbX4FO3HeF33Y41HxmqmKfUkXlW5S1yTzgjrKtI4m39cr-jro98AYCOpFPL58COW6KDppPJemq64aSA + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMDgyNjVlYy0xYzkyLTQwYjItYWJmMS1jOTQ3ODk2ZjU4MzciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjcsImV4cCI6MTYxNjY5ODM2NywiaWF0IjoxNjE2Njg2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.MMFFfCYja2TZQ86y4vVHulWUVI98SGx1VQ5GPQUnCPBzU1DdXJjPP60-StCxmI1adibyz1UE_DtOtecm4mSPmIFO3awDdELbcngZEnYeR8A5gyzy8xFXhDtTCxOK2ZIJ4gXalpAQazRvx4hCdL7IvQDEgFowNfZG1QDsZti3GyNIS-CEWcTxMQKxM6Ic8NGmgAwl8-O3d6YMIyleDghsEHIWYa-c_GyiDLHCFwsihETXRPbBLotwxB9yqW7xJEoLSqmOG0I8H0crFZR99Z8dz9S9qltxlxMTI20TYwqzgBRzJgi_3vhvlKTv5LQk7vXKfBcpc1ewYVMmhazm5LcF_w"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:47 GMT + - Thu, 25 Mar 2021 20:03:15 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMDgyNjVlYy0xYzkyLTQwYjItYWJmMS1jOTQ3ODk2ZjU4MzciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjcsImV4cCI6MTYxNjY5ODM2NywiaWF0IjoxNjE2Njg2NjY3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.MMFFfCYja2TZQ86y4vVHulWUVI98SGx1VQ5GPQUnCPBzU1DdXJjPP60-StCxmI1adibyz1UE_DtOtecm4mSPmIFO3awDdELbcngZEnYeR8A5gyzy8xFXhDtTCxOK2ZIJ4gXalpAQazRvx4hCdL7IvQDEgFowNfZG1QDsZti3GyNIS-CEWcTxMQKxM6Ic8NGmgAwl8-O3d6YMIyleDghsEHIWYa-c_GyiDLHCFwsihETXRPbBLotwxB9yqW7xJEoLSqmOG0I8H0crFZR99Z8dz9S9qltxlxMTI20TYwqzgBRzJgi_3vhvlKTv5LQk7vXKfBcpc1ewYVMmhazm5LcF_w + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyYWYyNzI4MC00YTdlLTRiYTgtYTk2Zi1hM2IxOGUwNThkMDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjgsImV4cCI6MTYxNjY5MTE2OCwiaWF0IjoxNjE2Njg2NjY4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.ZsvarYmAXUucyCxdddmi240TvaiIX8DwdPhwEIaqyM_5o2_mg1wZK-ojF4F2T4fFOqiOKAwlg6i6x_DxFhMkBdizteapM07w-od2egsogoaosdR4O2cPI-qKNC71uZPMRps_3HBxDsgT10nbxjZgFazyOzccAuAjHi3vkuewvk5pItays5YAQ0PLribERK7yV-UebT2he80iHy8xCbEuxpHGD6RBsrckF5riBJ04dmmh3V6h8jC5P3LEC0Cyg075nygsfdGGGDBjxxgiHODvefzIG7DbXZ_76XK2yy33bBouiDzrfXo5gq5fMKLmN4cWqtKfd3cHgvDBF2I4hmUAmQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:48 GMT + - Thu, 25 Mar 2021 20:03:15 GMT server: - openresty strict-transport-security: @@ -149,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:48 GMT + - Thu, 25 Mar 2021 20:03:15 GMT docker-distribution-api-version: - registry/2.0 server: @@ -194,7 +193,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:48 GMT + - Thu, 25 Mar 2021 20:03:16 GMT docker-distribution-api-version: - registry/2.0 server: @@ -202,15 +201,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNjYsIm5iZiI6MTYxNjY4NzI2NiwiZXhwIjoxNjE2NzczOTY2LCJhaW8iOiJFMlpnWU5pOTZ5aHZaZzNIdDRjbnpyb2RGUEdlQ1FBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDVvaTZ0elZ3VXluWkEzNEdjZFZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.UrhZkKaCqLriAnO4wBlQfgnQSie3oUSeCteY1O3_HGG4ZnuOPsYxUDH_VvMBrpM8m9d1bQ9cygsp8apqBzYsP_tldBvKusiiOVSkU7A49lDirKx4DfijLPqvNYOYF19eOPwMhPMaRTAjM1vswICC87UfMe_OMUBNqd2XjfPeQ7YsD48opUxindvJHZ5p9GzEi9FrAj_6K2sk81tH7l3Cbs0yrJ3j9MfIk6zX18gFzCue26F25gEHf48GB6dpduAPRalMw7IgbX4FO3HeF33Y41HxmqmKfUkXlW5S1yTzgjrKtI4m39cr-jro98AYCOpFPL58COW6KDppPJemq64aSA + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -228,14 +226,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMWQxYzU0NS04MDBmLTQxYTItOGYyOS0zMDJlMWNlNzE5OWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjgsImV4cCI6MTYxNjY5ODM2OCwiaWF0IjoxNjE2Njg2NjY4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.NZFAQbMEBkSY25HOzDNlvaIGqvIg0xbl1R9HbWOCCvpGt0HBZA9UOnQZucVITQgBM2LD4JyRuB5sKqE_w1JKSyl5exPoHtPfTsMycZylwkDJnVttnmza3ufKHqyGGqUY14dxmOZFh1-quK-Fa-B4zOjjtkeuZHEfqsIOTrKZnPzFVVo2t-GiDjqHY5PVtPfzlcp8DSA_Vuuy6rsKcA434uVl7XflrBW1vWOxBmJPBUxORd4KVq3oVaJAOxRGRrVg0XbCdh8G1D3qVcH2AdXqYAn_Y5WWt3Z3JXDefAZKOFwonFtnWUieQiCQgjiAs8ugkqf0Dgge9q3-7tnEGFUZ5Q"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:48 GMT + - Thu, 25 Mar 2021 20:03:16 GMT server: - openresty strict-transport-security: @@ -246,7 +244,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMWQxYzU0NS04MDBmLTQxYTItOGYyOS0zMDJlMWNlNzE5OWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjgsImV4cCI6MTYxNjY5ODM2OCwiaWF0IjoxNjE2Njg2NjY4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.NZFAQbMEBkSY25HOzDNlvaIGqvIg0xbl1R9HbWOCCvpGt0HBZA9UOnQZucVITQgBM2LD4JyRuB5sKqE_w1JKSyl5exPoHtPfTsMycZylwkDJnVttnmza3ufKHqyGGqUY14dxmOZFh1-quK-Fa-B4zOjjtkeuZHEfqsIOTrKZnPzFVVo2t-GiDjqHY5PVtPfzlcp8DSA_Vuuy6rsKcA434uVl7XflrBW1vWOxBmJPBUxORd4KVq3oVaJAOxRGRrVg0XbCdh8G1D3qVcH2AdXqYAn_Y5WWt3Z3JXDefAZKOFwonFtnWUieQiCQgjiAs8ugkqf0Dgge9q3-7tnEGFUZ5Q + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -264,14 +262,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIxNjE5MDQ1OC1hNGM3LTQ4Y2YtYjYyOC05YTgzMTg0OGFkYWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NjksImV4cCI6MTYxNjY5MTE2OSwiaWF0IjoxNjE2Njg2NjY5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.IxHcEftOeiCig867HcRMyNslh4ts349FhFt8uAVEw5H0as_1n5vWA6abkg1-xXSWWL4LhZ4YfOh0K0Tb6POKzjjNmLePNkYJdSlXB4O8U9xEPvHwDu3tVI0hefriUbQnbqKpBTJRcXIvE1S6Fb-v3ieys8JVaZ8JYGdcPO7mif27PJ-AvNiTVDEoYN9AUd4s3AEIk-3EkCx45FHWQP4PE0EShgsCCxy7VsK8OS9i5rW1_Cng06T5mooRmKj_Tb-tGdDr5CteO6VyaVcE4jaPzPuZARyHgLZG1-uJbV9e5AuNi5QFXy5BNoDjcgRSb6MuokijVYidg11RmeqlU1CJ_A"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:49 GMT + - Thu, 25 Mar 2021 20:03:16 GMT server: - openresty strict-transport-security: @@ -296,9 +294,9 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security - Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys + Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} ' headers: @@ -310,11 +308,11 @@ interactions: connection: - keep-alive content-length: - - '913' + - '917' content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:49 GMT + - Thu, 25 Mar 2021 20:03:16 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml index 6487accafe60..cc9541008a6a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:51 GMT + - Thu, 25 Mar 2021 20:03:18 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzAsIm5iZiI6MTYxNjY4NzI3MCwiZXhwIjoxNjE2NzczOTcwLCJhaW8iOiJFMlpnWUdBTFdsSHptbG02OTl3TkEwWHJQWnY4QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiUjdTY1dnMlZVVTYwWmZnbjJCYVZBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.d9DiNZpvoxCKX271t_nMfFzEOBMhbCyXbhKnnbkFhfXO8WyMsZ77CGJefzWLAJQwL8Ia9C70SXTMU-yCPEuTsmPCISIHTEuWgXhrEbWWHHgsxMVCeFTPTirdIWb9kA92YzN2LNeiptPhGQyeH29rJRnKJHIf5K3bj9KPT9tFzOYXH1hHAKcrjLPoyukhDFL7GaehO1AXzsQ3DJZNGKmqe56P8LuJQsl1fEKq_RIfY5pOXB0VNAbIFnc61__6DMTkeoF9DEhZfWkqxwVp2qdNJbqi0lj1hWGj49pRd1fwXvqcaYIOD_bRVUNOQW5in1IDoXoJoGPUkstda7g3xQ7rBw + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiNmQxY2MyYi1mZWNkLTRjYjgtYmQyMi03ZGZiMDE4ZTZjNDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzEsImV4cCI6MTYxNjY5ODM3MSwiaWF0IjoxNjE2Njg2NjcxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Fo9gR9mk2nGQ-NA2QEha61OX_pMftZwPQqmRMBrs4YFmSfIdmiS5mn9i7nMsCwyYFsEWAyBWN-NUuRJHYC4RiMZUn0CMg6FKm_Ik2EgCCHuBN7wbt4IvxZS1s5xnuOelCqHOkZjXgdn7NxBCl0fE6LV2aYZ80L1xcEeVy1tUMGPVtA7PuyX6Z_9mU2IeZbwjANzhZtLZgH3TClAG1tBkGlpjjL0Fwzb2YVGEV0kGCll9c55ASMRDhsMKnLo_QPOEISabqp2jmn6wUbh6184C4RASRTGkEW02H_Mpu-TV62IkFHgVPHtSfqwXkrQ0c0NwkXL_Wf5_8KZinDtdL2jL_Q"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:51 GMT + - Thu, 25 Mar 2021 20:03:19 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiNmQxY2MyYi1mZWNkLTRjYjgtYmQyMi03ZGZiMDE4ZTZjNDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzEsImV4cCI6MTYxNjY5ODM3MSwiaWF0IjoxNjE2Njg2NjcxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Fo9gR9mk2nGQ-NA2QEha61OX_pMftZwPQqmRMBrs4YFmSfIdmiS5mn9i7nMsCwyYFsEWAyBWN-NUuRJHYC4RiMZUn0CMg6FKm_Ik2EgCCHuBN7wbt4IvxZS1s5xnuOelCqHOkZjXgdn7NxBCl0fE6LV2aYZ80L1xcEeVy1tUMGPVtA7PuyX6Z_9mU2IeZbwjANzhZtLZgH3TClAG1tBkGlpjjL0Fwzb2YVGEV0kGCll9c55ASMRDhsMKnLo_QPOEISabqp2jmn6wUbh6184C4RASRTGkEW02H_Mpu-TV62IkFHgVPHtSfqwXkrQ0c0NwkXL_Wf5_8KZinDtdL2jL_Q + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyY2M5MzZhYy02YTdiLTRjMGMtODQ3Mi01ODE4YjNmNDRhZTciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzIsImV4cCI6MTYxNjY5MTE3MiwiaWF0IjoxNjE2Njg2NjcyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.amZDrXRFPbqPNR3Su_5ktQFZxwqmmp_BRI0u8tQ7-GDHtyh7jQ7IQE3wKp-Q1-e8QJHpQ2b4bVXVveOsGZibmiSQHQgSEy1qs25wQHMetu_f36rx4uPWXb1NPaPPv7bMS0vO3pKd4rTWLDH_Z8lEEpfvp5bgGt3tjJCcwTCY5bBjEzVsIkVEj6ITzLS-z3-UW6hLgoXrLg_8GZiHVkFr3azN9Ddz176fJK6W36se1mX-XPAVo5MJ7Az1ZjqebHrxcsotjZkUaFJ8Jzk2CLVZo2vR0QJjY_1u9Gsr5pRdyaJju98OveHGSsHJhYohd8x8SdY9GVRYGyDSlyiJ23UZWw"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:52 GMT + - Thu, 25 Mar 2021 20:03:19 GMT server: - openresty strict-transport-security: @@ -149,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:52 GMT + - Thu, 25 Mar 2021 20:03:20 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml index f5e12c34bee7..346fafdf7cfa 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:53 GMT + - Thu, 25 Mar 2021 20:03:21 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzMsIm5iZiI6MTYxNjY4NzI3MywiZXhwIjoxNjE2NzczOTczLCJhaW8iOiJFMlpnWUZqVmwxRmt6WE0yeCsvd2ZBa0ZoK3cwQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoia1duME0ySTZORS1jU3EyV2JpTVpBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.nCh79PRrK1viGXpl9gQVTMYYMrCwZk1Vk-JlenkSb4gLj9OLahIoz4oAeM7PdJ76QoCO20jR0fs8ZkS-ZqqgcyJkiTQ1yX1TtvhnHhPxTIiaEc8YdqUusm2OO1-SzXslZHS_jfevJ3Iw9ireevFN_mSQyeKs33mhwlmFV6Tp9Cat5VGtnlMqObvXUTBLbfmxSZwFD6qQeIdpxEO_pJFz9438wh_ZXxZ68EIBEY3Isrk_QQX1rxUkSYdusccxwww7v5EV-ysSj-jz_jbztv4N1Lqs4-TL5PEaG6q4Zsg9H1Tho9PwnGkzEFEuaFoSOr6zf26pKIxiCg5u4WRPfU0S_w + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmMjNmZWFiOC02YThmLTQzZDAtYjJlMi1lMTFjZmFhMWQ1YTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzQsImV4cCI6MTYxNjY5ODM3NCwiaWF0IjoxNjE2Njg2Njc0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gvqjbRSrrSdB0Hgl5srbb9_Zo9JWdp5Wvon4zprFrTfUc1lwzKTVc7ADXtkP7ChMLHMI0_oU92XG2n2OyYzPKXopekp4V05hglM8fwxt7jskXzAOzBykgGZiYa4YXRhCH-frs2hLgG_b76cdWYXQeoyaY_vaL4hYxwa3xL6CfCQQwdZ11cZeqCNE6sF_16EvHmHZIjiEGhM3rmeKHVrvn2-pOK_1m5_gKvlVYslo3-Gq35Jg77XyLhr1cmrCqYeS5VlwyA1LVAGbj-YpiodjUe4i4X61VD8tM81Y4oC9i90YGTxtbx3DasGBBhAcHVwBG4MxkZbi08HMAEXou1SLjQ"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:54 GMT + - Thu, 25 Mar 2021 20:03:22 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmMjNmZWFiOC02YThmLTQzZDAtYjJlMi1lMTFjZmFhMWQ1YTMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzQsImV4cCI6MTYxNjY5ODM3NCwiaWF0IjoxNjE2Njg2Njc0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gvqjbRSrrSdB0Hgl5srbb9_Zo9JWdp5Wvon4zprFrTfUc1lwzKTVc7ADXtkP7ChMLHMI0_oU92XG2n2OyYzPKXopekp4V05hglM8fwxt7jskXzAOzBykgGZiYa4YXRhCH-frs2hLgG_b76cdWYXQeoyaY_vaL4hYxwa3xL6CfCQQwdZ11cZeqCNE6sF_16EvHmHZIjiEGhM3rmeKHVrvn2-pOK_1m5_gKvlVYslo3-Gq35Jg77XyLhr1cmrCqYeS5VlwyA1LVAGbj-YpiodjUe4i4X61VD8tM81Y4oC9i90YGTxtbx3DasGBBhAcHVwBG4MxkZbi08HMAEXou1SLjQ + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjMzg3ZjM1OS0zZjhhLTQxOTQtYjEyMC05NzUxM2NmODIzZTIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzQsImV4cCI6MTYxNjY5MTE3NCwiaWF0IjoxNjE2Njg2Njc0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.DDgHxpqtbRT485lm2oblRbAoDKOIzBh93HFR53f-lsVV21kIQ7LC-wymNoT5I8vsE_6Qd_TFo5kUFZBPY8w--NezAMs-ImmiuvqIJ-CWSMsJ72OSUL26bXULhGwRa-UhmOig9b6QkDJ-u4PZ-Tcx1FYkVzA0YvZqCm7rh43RsQk09GlddIaXCILTJraKUzgKjHz2qphxmhL6aX31z-7bsFLTXTMHLZ6BUWPbNEUL-4V_OXgIO25xmHCNjWYqC6EggA4y3VzUTskyQVzbLmzSXtcZ7U34YGU4VnJ2Ofjqr0_0qRoGv1H9YJ9WypWKxo3d7JtfRkAL03FUA4UoMPWmcg"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:54 GMT + - Thu, 25 Mar 2021 20:03:22 GMT server: - openresty strict-transport-security: @@ -133,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: @@ -145,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '599' + - '598' content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:54 GMT + - Thu, 25 Mar 2021 20:03:22 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index d1e9ee9c8c74..69000b6a35ec 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:56 GMT + - Thu, 25 Mar 2021 20:03:24 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzUsIm5iZiI6MTYxNjY4NzI3NSwiZXhwIjoxNjE2NzczOTc1LCJhaW8iOiJFMlpnWURCd0xWajdKakZyaDZ1UDRNcHB2cGFhQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQlBOX1RFeW16RWUzbjBkZzlQY1ZBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.VfCCMSfCfKp0rncwTfxcRvnL1k671J2wF1qGcMCWJbvY6etjAPPetdHA9QKe86McYDN-lVuHn_QcEAcJG7meUyQy21sFyCgx5GTJZKoSbE75D1S2wYZGdhercubifBCBny-uUsaEahpJpH3Uf_OSeSwf3ladYntOFepQR9iMbwqJjoqu5DD6fJvukp9-3fiE5G3z85UqJPa4Jk_a9bN1tIOagHFO4ATcQZh1YQnIjADhBxpklMlpUubGdvabVjPcDWQEgcRSvRwlnQLbK4G3PJW85cowRtFLHwJwNUWpWlJDHFdT5feh5f0htZEXLM5RSdEenkzJdU1lmtV8vnl4xA + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjOTZkZmRiNC05ZmY5LTRhYTEtODE0Mi0wMTIyNTIwMTE3MmMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzcsImV4cCI6MTYxNjY5ODM3NywiaWF0IjoxNjE2Njg2Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e0YNV0UAB8ufCo0baIF1AOEl1r0gEOSQEh4pz2n16oQuK5jUyFnfYUNCsgToAOiwu-ho_ZVpFJjIkkB3BpS6wLxg-26JPAbvIl7YOnDH9eCTra4UuKyfOXC52lFvkh2K5G-rOiajO-dI8-V8M0ziuUmHU5wFNZYJZMA2bsqjAiE57Pk2j-If4RYSDlRz_tM1VFIFck1LMXHjnTIREpS5RfaByo-nEMkAtzQFxNnvqTkbCvODkIceKx3UhQmFDmpEMhL26Bgef7fK5aY5hf5Y3ikh6CxEWOprfCaKh9LBfriP29UzRqxYa2Vxr9qzOKceqeLeBoaX9nPFTgo6hPPj1Q"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:57 GMT + - Thu, 25 Mar 2021 20:03:25 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjOTZkZmRiNC05ZmY5LTRhYTEtODE0Mi0wMTIyNTIwMTE3MmMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzcsImV4cCI6MTYxNjY5ODM3NywiaWF0IjoxNjE2Njg2Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.e0YNV0UAB8ufCo0baIF1AOEl1r0gEOSQEh4pz2n16oQuK5jUyFnfYUNCsgToAOiwu-ho_ZVpFJjIkkB3BpS6wLxg-26JPAbvIl7YOnDH9eCTra4UuKyfOXC52lFvkh2K5G-rOiajO-dI8-V8M0ziuUmHU5wFNZYJZMA2bsqjAiE57Pk2j-If4RYSDlRz_tM1VFIFck1LMXHjnTIREpS5RfaByo-nEMkAtzQFxNnvqTkbCvODkIceKx3UhQmFDmpEMhL26Bgef7fK5aY5hf5Y3ikh6CxEWOprfCaKh9LBfriP29UzRqxYa2Vxr9qzOKceqeLeBoaX9nPFTgo6hPPj1Q + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiMDMxMWJiNi1kMDYyLTQ1ZTgtODRhOC1lNGM0N2E3NDBlMjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2NzcsImV4cCI6MTYxNjY5MTE3NywiaWF0IjoxNjE2Njg2Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.JtI-gZZ7oL8wHuAsNLrkJX-RIAqZolwM4OXXc7OmAKDGI4Gokks7bvv4k4YkppzU1z2omrzVcRbVOoDq60IlBUbUF6cSYmpeo0eCVYQMfQ-Co5hBOix84554DXqr-rit_mB7kkXtOwmNIb2seJg81OUpgK497vGF1O7X7m2y1ACcu2f7enVqD-yoL75W50f5HTBHiStLSxeXLGBOa9EB1quBJWy2xGJcnhPXXy0FueGjT2f9DshBiL5-aghn2huJ9Gbd1FfwgFqlukBbTqRqoZnKx4115E1PmNn4Sqss3sMYYgQUboJ4yw1Qb4PRlXT6aUNukeItSEYTAtV_PmDDTQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:57 GMT + - Thu, 25 Mar 2021 20:03:25 GMT server: - openresty strict-transport-security: @@ -149,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:57 GMT + - Thu, 25 Mar 2021 20:03:25 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml index 674822015882..e76b458d06e8 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:52:59 GMT + - Thu, 25 Mar 2021 20:03:27 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyNzgsIm5iZiI6MTYxNjY4NzI3OCwiZXhwIjoxNjE2NzczOTc4LCJhaW8iOiJFMlpnWUdpcXRZMnBTODFaa2VheXh1K05aeWtQQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiekFzMkF1bXkzMGFCTnpxNDJsMlRBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.fxtnDcPLe6FLlBHg-a2Y-szSKkXA77Rz2jRBgTP49kLS61HWxt8Vg8XsTw4GPq22IrQfxoB4RhRUzEic5M-gt2_I9vatcMaHmZtR9zxbIiiAyMyUYQTU-jSzbhT-xujlwE_57hBvAdl9xvKaVsNWA3iCt7lxIr3E6JnKO_09p4YjuG7t4JkNLO8gvPinFz7YVvp37gWLhPWiKmV6FlKkhNrgVqmghjEECmsrZoczUAS-LUiHvzTt_ARp1hnVhoyxAqF6sniLJBkWYKtm63krXrnp_iWwORryFayJbGPSjWWa1dWEf7Aa6YayjlR1-8RF603QWSZehL4T4G2iAR1twg + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmZTU3MDE0NC0xYzYzLTRhYWQtYjRjYy1jNGRhY2FmZWU5MTYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODAsImV4cCI6MTYxNjY5ODM4MCwiaWF0IjoxNjE2Njg2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Gucl0Bvy-WzRnHFr8QXoSfyifY0IgvD5fnWsHwdfw47vY9PfqR0mz0Z3snzLA8zQEB3oCfTWdQYf3ZwwyJcmVxRCshaG-Qw5f6gQuEL9pk-mlwWJmWUdPPooqqtmjwnd7pyJ8y9iPTGGLBuFOtu_sE7YCl4omOjYpDk2avyTC9fl1KMTDP97TEa8gI1qDkOEshIxcgxN57b0N-83z3at6eZsNjAAKagBXIVUVuxFOPaA2Lg8OfruQq16Z3uiyLYpA8BpI-Y_TzO9ol8xjgKgP_qvUcFbziVWZsk7HzfSQocx21teXgz94v4glaT1_83tc6jd8gO1Kk2xJ0vlmIkVUw"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:00 GMT + - Thu, 25 Mar 2021 20:03:28 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmZTU3MDE0NC0xYzYzLTRhYWQtYjRjYy1jNGRhY2FmZWU5MTYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODAsImV4cCI6MTYxNjY5ODM4MCwiaWF0IjoxNjE2Njg2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Gucl0Bvy-WzRnHFr8QXoSfyifY0IgvD5fnWsHwdfw47vY9PfqR0mz0Z3snzLA8zQEB3oCfTWdQYf3ZwwyJcmVxRCshaG-Qw5f6gQuEL9pk-mlwWJmWUdPPooqqtmjwnd7pyJ8y9iPTGGLBuFOtu_sE7YCl4omOjYpDk2avyTC9fl1KMTDP97TEa8gI1qDkOEshIxcgxN57b0N-83z3at6eZsNjAAKagBXIVUVuxFOPaA2Lg8OfruQq16Z3uiyLYpA8BpI-Y_TzO9ol8xjgKgP_qvUcFbziVWZsk7HzfSQocx21teXgz94v4glaT1_83tc6jd8gO1Kk2xJ0vlmIkVUw + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3MTQ3ZmVmOS0wNjhlLTQ1YTgtOTJjYy0xMzllZmNjNTgwNzMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODAsImV4cCI6MTYxNjY5MTE4MCwiaWF0IjoxNjE2Njg2NjgwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.dZS5ftdS25i4awSxm-l09EKR3jOiNtW6bfxFJC7f5AIo_1zLHmC3_me9_VF75NmKOrMOwQrd1HjCqbroCF39i4aurRstw2ptAianSBiz0PBxCWiVV4OqYpxL0kvwzyHzXnR-IPdSuS2kkritErv4EPeLNYvpF4LkdBlC87wCQxDqExoTL33ttqiZMlVc59bv_hDa9_YdSRiad45jIfBdSPDyUEAVYJZ2fnBhKLZMrGqM-kBAeiyXS1g7FvawPgvoq_N5zjGCcFnUrekGDqto5BcqQ79kJUknkE33ADq32HtZZSGwFcq9l3lUlTT8_aWCRmpc8_jL-QT0bsA0oOJGLg"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:00 GMT + - Thu, 25 Mar 2021 20:03:28 GMT server: - openresty strict-transport-security: @@ -149,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:00 GMT + - Thu, 25 Mar 2021 20:03:29 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml index cd2b074239fb..a96e5c509912 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:02 GMT + - Thu, 25 Mar 2021 20:03:30 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODEsIm5iZiI6MTYxNjY4NzI4MSwiZXhwIjoxNjE2NzczOTgxLCJhaW8iOiJFMlpnWURoNlNOS1lkL3MwRll0N3k3ZytzbnZPQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYlU0R2x5WmptVUMzRFJUN2lJSmZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NLtmKZXYAPW4sDYSanx9hO95le8c6IvZTNytaoWO3JKN0ztHI3-qkLCRBUKvZmA28feYbuLgp_yzusctE25OntuW10s3njXUovWoRpAvtCZXvqjZnVtKt4aBCAM0xbAYw-2OFm_RQcVnqVPo3oHR6z13B7nfuA7LH884Prr7QzmEPu4sYs7AqSm5pY2ESSZRUYdh_gt8X-S34KgJBFxDmBRfQfC_rRQx6KYHprL9PJCUFL2dH0WP70AmxxnT5vaLwr9zDhn8o_sCQOrv8G6puYNLK82NeT8SKOjLHrNTKagfO3c8gLrnDwOePHnCWnvGSXomGtb6Tqk7bbF6b5MfDQ + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZjQzMWE0Ny05YzQwLTRkMWQtOTdhNy04NzViNzZiNDBiYzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODMsImV4cCI6MTYxNjY5ODM4MywiaWF0IjoxNjE2Njg2NjgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.V2lnkzCK17R4woVIYURzWFDjyzakX_CiyPdAjaLcdlxa3SVvvmENLE3OAJTf7yDvikdw45UnDO_ZxZuynJUSKDPvb-fuMRZJoGHPwLh-cfV6GUnyQ3C39K5YQNY5ZHQsRL7qSowaAHQu55FpTxkKQrWPV82ERX3V8-MQiE85LIoQjNeR3au_KTK_6E-StTI2GDVN_KiR0q_ZDXvDBUKUy1Wuazz-fpmDOBno_uODqLZXiXbndDoODhS8mRZSyj295GadyShPvkPTz1uflL30vrOvHdT9nrEFVDjbaP_e9MWNbZclEDcJQBmcuj7Lr2yVvVuAtCo02xpq8588lfmgBA"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:03 GMT + - Thu, 25 Mar 2021 20:03:31 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiZjQzMWE0Ny05YzQwLTRkMWQtOTdhNy04NzViNzZiNDBiYzkiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODMsImV4cCI6MTYxNjY5ODM4MywiaWF0IjoxNjE2Njg2NjgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.V2lnkzCK17R4woVIYURzWFDjyzakX_CiyPdAjaLcdlxa3SVvvmENLE3OAJTf7yDvikdw45UnDO_ZxZuynJUSKDPvb-fuMRZJoGHPwLh-cfV6GUnyQ3C39K5YQNY5ZHQsRL7qSowaAHQu55FpTxkKQrWPV82ERX3V8-MQiE85LIoQjNeR3au_KTK_6E-StTI2GDVN_KiR0q_ZDXvDBUKUy1Wuazz-fpmDOBno_uODqLZXiXbndDoODhS8mRZSyj295GadyShPvkPTz1uflL30vrOvHdT9nrEFVDjbaP_e9MWNbZclEDcJQBmcuj7Lr2yVvVuAtCo02xpq8588lfmgBA + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJlYTE0MDM4MS00OGU5LTQwNWItOTdiMy03NDc3OTBjMjZmYmIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODMsImV4cCI6MTYxNjY5MTE4MywiaWF0IjoxNjE2Njg2NjgzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.PM1Qs_8V8TCbrgz72AK0LVfJMTGMMozm6RMVjUvrKAmx7fP1mdjVjkcyBvKBajEdhWzMkjso8I-y1e5baj8Wr6VR8al4XBBNt-eBLYvhTIVFAgByK1Loyeq99GXyWQO7kDWThT4SFaVPijMayVo7rUnxfPmqUi2AXFa4_LljyVTM3ME_gjtPMXQt1zhe9udZ2UTiMXGlIwwsgss1wSAVv4ZsLE1yUrU1dQZzjsNv16wFSmucU2_84tUtsHO3adKMEl8Jqg-ruK0gcOpM97ZEadDGGK5F8lWxpGFRFoS47cYaQMJfG0o_laER7nS8DozbWaAEZEF9RH7qgxc7IglPfQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:03 GMT + - Thu, 25 Mar 2021 20:03:31 GMT server: - openresty strict-transport-security: @@ -133,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: @@ -145,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '599' + - '598' content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:03 GMT + - Thu, 25 Mar 2021 20:03:31 GMT docker-distribution-api-version: - registry/2.0 server: @@ -163,7 +162,7 @@ interactions: code: 200 message: OK - request: - body: '{"deleteEnabled": true, "writeEnabled": false, "listEnabled": true, "readEnabled": + body: '{"deleteEnabled": false, "writeEnabled": false, "listEnabled": true, "readEnabled": true}' headers: Accept: @@ -173,7 +172,7 @@ interactions: Connection: - keep-alive Content-Length: - - '88' + - '89' Content-Type: - application/json User-Agent: @@ -199,7 +198,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:03 GMT + - Thu, 25 Mar 2021 20:03:32 GMT docker-distribution-api-version: - registry/2.0 server: @@ -207,15 +206,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_write",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODEsIm5iZiI6MTYxNjY4NzI4MSwiZXhwIjoxNjE2NzczOTgxLCJhaW8iOiJFMlpnWURoNlNOS1lkL3MwRll0N3k3ZytzbnZPQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYlU0R2x5WmptVUMzRFJUN2lJSmZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NLtmKZXYAPW4sDYSanx9hO95le8c6IvZTNytaoWO3JKN0ztHI3-qkLCRBUKvZmA28feYbuLgp_yzusctE25OntuW10s3njXUovWoRpAvtCZXvqjZnVtKt4aBCAM0xbAYw-2OFm_RQcVnqVPo3oHR6z13B7nfuA7LH884Prr7QzmEPu4sYs7AqSm5pY2ESSZRUYdh_gt8X-S34KgJBFxDmBRfQfC_rRQx6KYHprL9PJCUFL2dH0WP70AmxxnT5vaLwr9zDhn8o_sCQOrv8G6puYNLK82NeT8SKOjLHrNTKagfO3c8gLrnDwOePHnCWnvGSXomGtb6Tqk7bbF6b5MfDQ + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -233,14 +231,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjZWRkY2QxZi1mN2FhLTQ1NjUtYmM1MC1hYjY2OGUxNzA4MDQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODQsImV4cCI6MTYxNjY5ODM4NCwiaWF0IjoxNjE2Njg2Njg0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.k1ng9kfSydeB43wHTfwM5c3K6TPbr2U_xNfxME43QKoA7SuZh5083PlLgBHMLAyxpapJ2pxagyx3ho1yXa9bQFmzUfAlAiZbj1E0wWT7l08pf5cvvHVah0SZnALCZDLO0KDhOwjUxI0ZbI4mXsfgHNJjtc3hW4o52xWLe252nuLGHXksAhTQ95xezZMxymEzGJ5XoMqKbi2WlIswmkgGcuWbluo6bPVoWC85pdLnW97gwze_7KNEr7M5CXEzfw_umsdTDR3C9F9ovBtV2XHewPo3gJfZKAtwspAA-QxOUPjwyyIjOrU4u1T3W0UhUDWPKiJgHcEDN5-ehb0ZiOX8JQ"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:04 GMT + - Thu, 25 Mar 2021 20:03:32 GMT server: - openresty strict-transport-security: @@ -251,7 +249,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_write&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjZWRkY2QxZi1mN2FhLTQ1NjUtYmM1MC1hYjY2OGUxNzA4MDQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODQsImV4cCI6MTYxNjY5ODM4NCwiaWF0IjoxNjE2Njg2Njg0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.k1ng9kfSydeB43wHTfwM5c3K6TPbr2U_xNfxME43QKoA7SuZh5083PlLgBHMLAyxpapJ2pxagyx3ho1yXa9bQFmzUfAlAiZbj1E0wWT7l08pf5cvvHVah0SZnALCZDLO0KDhOwjUxI0ZbI4mXsfgHNJjtc3hW4o52xWLe252nuLGHXksAhTQ95xezZMxymEzGJ5XoMqKbi2WlIswmkgGcuWbluo6bPVoWC85pdLnW97gwze_7KNEr7M5CXEzfw_umsdTDR3C9F9ovBtV2XHewPo3gJfZKAtwspAA-QxOUPjwyyIjOrU4u1T3W0UhUDWPKiJgHcEDN5-ehb0ZiOX8JQ + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_write&refresh_token=REDACTED headers: Accept: - application/json @@ -269,14 +267,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2NjBiNWY5NS1lMjRjLTQ4NWUtYWUxZS1iYmIyNzZkZDk1ZDQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODQsImV4cCI6MTYxNjY5MTE4NCwiaWF0IjoxNjE2Njg2Njg0LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfd3JpdGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.IsPLnCPrwL5oanK9s2XQLL-hpOHipVkc77wwBy4O1zgfZYwh9TVbtlSzwlTIWQ2r8FfnCZW0EK3veSJwJS20LqgArtW13fjlENsdj8flVcstMDD_hB6VmTcrVCrwEc1jiglNoD-81FxuaM5lFXoXJAR3nk0Xk7KKu0_cRtdvxvV4WoidZrHWNktvqWkznO7zqAP5ewhpvEYolp9Rn5WpxxQiBCyvStfMO8CjdkhdKv1LPjyFDRiBq4v3nBnpEOurcM07S9kt3DFx1QcFHiUiSnj-MRyGyzCunf0rt5Q0wHh5bFc1cT03pKBvHqXnCa9YHo2ziidwSCp6G78WL1KRmQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:04 GMT + - Thu, 25 Mar 2021 20:03:32 GMT server: - openresty strict-transport-security: @@ -287,7 +285,7 @@ interactions: code: 200 message: OK - request: - body: '{"deleteEnabled": true, "writeEnabled": false, "listEnabled": true, "readEnabled": + body: '{"deleteEnabled": false, "writeEnabled": false, "listEnabled": true, "readEnabled": true}' headers: Accept: @@ -297,7 +295,7 @@ interactions: Connection: - keep-alive Content-Length: - - '88' + - '89' Content-Type: - application/json User-Agent: @@ -306,9 +304,9 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security - Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys + Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} ' headers: @@ -320,11 +318,11 @@ interactions: connection: - keep-alive content-length: - - '912' + - '918' content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:04 GMT + - Thu, 25 Mar 2021 20:03:33 GMT docker-distribution-api-version: - registry/2.0 server: @@ -369,7 +367,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:04 GMT + - Thu, 25 Mar 2021 20:03:33 GMT docker-distribution-api-version: - registry/2.0 server: @@ -377,15 +375,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODEsIm5iZiI6MTYxNjY4NzI4MSwiZXhwIjoxNjE2NzczOTgxLCJhaW8iOiJFMlpnWURoNlNOS1lkL3MwRll0N3k3ZytzbnZPQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYlU0R2x5WmptVUMzRFJUN2lJSmZBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NLtmKZXYAPW4sDYSanx9hO95le8c6IvZTNytaoWO3JKN0ztHI3-qkLCRBUKvZmA28feYbuLgp_yzusctE25OntuW10s3njXUovWoRpAvtCZXvqjZnVtKt4aBCAM0xbAYw-2OFm_RQcVnqVPo3oHR6z13B7nfuA7LH884Prr7QzmEPu4sYs7AqSm5pY2ESSZRUYdh_gt8X-S34KgJBFxDmBRfQfC_rRQx6KYHprL9PJCUFL2dH0WP70AmxxnT5vaLwr9zDhn8o_sCQOrv8G6puYNLK82NeT8SKOjLHrNTKagfO3c8gLrnDwOePHnCWnvGSXomGtb6Tqk7bbF6b5MfDQ + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -403,14 +400,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OWI5YWZjNy0wYjBjLTQ5ZjgtOTZmYy0yMWMwODY5NTYxMGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODUsImV4cCI6MTYxNjY5ODM4NSwiaWF0IjoxNjE2Njg2Njg1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ojwbVDdsJMsZKQiu_PquX2pX4YM0kQj7W8xetyxSMEQcQD2p4wdgJRNmDg0s6PY5oBQ409z8yK1PK3NrZh8wjUNUjQzhDY1ua_j2BLkzLNRjX928kwc5n-YBco1x3ynb2KaUwvSlaKiZV2W6MNyawNnKYVMyvdIMb_jwgtweRamFF_-clbDPi6iKftr5RdSaXxKsV0RLzy2Rta1SrE4vAwmP_jWI1oPcn_tD_NEtreZQB-1rv7wAsAjaY6V5fH8r2Gaq3h_hy-u4EsHKDZ-WnKRxmZcjhu1IRoMEnULXNWybLJbmMbeJ-Fhus_Xkzjf3oXS7qVHAxcWWzrcsK61_qg"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:05 GMT + - Thu, 25 Mar 2021 20:03:33 GMT server: - openresty strict-transport-security: @@ -421,7 +418,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OWI5YWZjNy0wYjBjLTQ5ZjgtOTZmYy0yMWMwODY5NTYxMGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODUsImV4cCI6MTYxNjY5ODM4NSwiaWF0IjoxNjE2Njg2Njg1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ojwbVDdsJMsZKQiu_PquX2pX4YM0kQj7W8xetyxSMEQcQD2p4wdgJRNmDg0s6PY5oBQ409z8yK1PK3NrZh8wjUNUjQzhDY1ua_j2BLkzLNRjX928kwc5n-YBco1x3ynb2KaUwvSlaKiZV2W6MNyawNnKYVMyvdIMb_jwgtweRamFF_-clbDPi6iKftr5RdSaXxKsV0RLzy2Rta1SrE4vAwmP_jWI1oPcn_tD_NEtreZQB-1rv7wAsAjaY6V5fH8r2Gaq3h_hy-u4EsHKDZ-WnKRxmZcjhu1IRoMEnULXNWybLJbmMbeJ-Fhus_Xkzjf3oXS7qVHAxcWWzrcsK61_qg + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -439,14 +436,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4ZDg3MWJmNy1kMDJiLTQ5ZmQtOWVmOS0xM2ViMmVmMGVkNWEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODUsImV4cCI6MTYxNjY5MTE4NSwiaWF0IjoxNjE2Njg2Njg1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.II556GGzvBav_weasT6AxJN3Xr5R8twidPi4RVx5M3CvzkYxm51-bsjxf-FrJXmjrFUVyZOHRb5FK0nwm0_xaIYlm4lyB0_sgfn9vq8fq61QYZ5kBY51AYWT3QfvYMweEwYCuh7CrKW3R3hLitMh9lHbGeaClDpORNtJsx_kyUvJ44R1zv6Fo-BRZlyWk1-JQYRAbSM8V37hcmF4YikR1eIGMycSJo7hwknlHIciLk0xGyWrrfxOGzc56ru2t23Rh2SzpIQSb5RZdNkl4grtyoJRpdZ80i6Ja3tXkDZQJiQ980xb8KVig-zMbaWDxuEPe1Y9y2JqJw2CVcF7cowSGA"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:05 GMT + - Thu, 25 Mar 2021 20:03:33 GMT server: - openresty strict-transport-security: @@ -471,9 +468,9 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security - Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys + Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} ' headers: @@ -485,11 +482,11 @@ interactions: connection: - keep-alive content-length: - - '912' + - '918' content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:05 GMT + - Thu, 25 Mar 2021 20:03:34 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml index ae5b069c1adf..974cddbae28e 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:07 GMT + - Thu, 25 Mar 2021 20:03:35 GMT docker-distribution-api-version: - registry/2.0 server: @@ -39,15 +39,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODYsIm5iZiI6MTYxNjY4NzI4NiwiZXhwIjoxNjE2NzczOTg2LCJhaW8iOiJFMlpnWUNqYWJjTlFhSzFTd2pqSG0vZlB1a3NHQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQTBjNFVZVUkwRS1nVjY1a1Rid1RBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JS98aJ1m8yRQE671Kfb0cb5YZAkWm1IVAH2QGYmODlx6fUC4Hw-70ztS2AOaq0PwvTXSGFjXf4PlRhYtURXXVnn0GC8InMokBklY5LJLa1GF_u5GJ6aIX2gYeHqIaKRMVjCZ0UnaprYkVjLY7ZSj0ulXHdj7elsrvlkcc50RIJ0peV5DoywrnDmfZN-uFmWKzQkvndRurqNOTpLxXBXLAOPjI9-8izCBiFd0irvHVqcP61w8bfH0mFcyN2tHPF8Z2TQ24rsyNm7ywo2m7p2OZv-_RI8fe-IAI2B1QJ6H28OIsTA17ppwd3tqgrBgZSnM7A4x6CAKy9D0fPufyOcyWw + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -65,14 +64,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhNTkwMzI5Zi0yODA3LTQ5MTUtYTRiZC01MTc2YmFjMDAxYTUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODgsImV4cCI6MTYxNjY5ODM4OCwiaWF0IjoxNjE2Njg2Njg4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.c8e2h_ed-dsRxNIlhdqYQ89f3O6bM9D5hCf6H_PsXDq1O-3EOxbhmOPqFvfGQSjW6atR5y5v-E2m68Lxlp17I8bMfN8VVJXlQoSBBmSTWanM8-6iVFn_VqUjq94WMOmwBo623OrfF8N9ZwJkZFs87MsBWXdYDxS4VbFYYpD5x__Y0a2tQV8-qL_fYrZGnbNIbNvED2djLaoBho3RE-O0wHALBHmrH_1jbKFjATZVqAt7JHF2qImiZU-vWJb7euyLdSNRvDIcJ2Q98j5D7YU61E6UwSB6suTYZqT_OeflneXm78a_2tMyFr1oc43_w4Od4RNg8ahVB7tW91EeS1AZmg"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:08 GMT + - Thu, 25 Mar 2021 20:03:36 GMT server: - openresty strict-transport-security: @@ -83,7 +82,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhNTkwMzI5Zi0yODA3LTQ5MTUtYTRiZC01MTc2YmFjMDAxYTUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODgsImV4cCI6MTYxNjY5ODM4OCwiaWF0IjoxNjE2Njg2Njg4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.c8e2h_ed-dsRxNIlhdqYQ89f3O6bM9D5hCf6H_PsXDq1O-3EOxbhmOPqFvfGQSjW6atR5y5v-E2m68Lxlp17I8bMfN8VVJXlQoSBBmSTWanM8-6iVFn_VqUjq94WMOmwBo623OrfF8N9ZwJkZFs87MsBWXdYDxS4VbFYYpD5x__Y0a2tQV8-qL_fYrZGnbNIbNvED2djLaoBho3RE-O0wHALBHmrH_1jbKFjATZVqAt7JHF2qImiZU-vWJb7euyLdSNRvDIcJ2Q98j5D7YU61E6UwSB6suTYZqT_OeflneXm78a_2tMyFr1oc43_w4Od4RNg8ahVB7tW91EeS1AZmg + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -101,14 +100,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwZTJjODE0NS0wOWQ1LTQwZGQtYjRiMy1mYWZkMzBiOTg4N2UiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODgsImV4cCI6MTYxNjY5MTE4OCwiaWF0IjoxNjE2Njg2Njg4LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.MQiOEmIs58hNQ8fqHFcU1BgwNA4vjql6Jq2Lt_DpGZpsYv8mTEgsU2xsD_-VuDKL1LuYCKJm4gjc7_NVW1zUsOeQoFuDSIj3dOdFRADfK18cKa4gjQlQgx6Kvqk4EGSeka6drixL7VWK61HZwr0chEtfdV65P3YUPJSgw-ULDnCXUGFjnN9cAybHC5YvMJYPpTgbA9Dg2UWOGu_j4tpasdyQ2uiyQ8KXyz_ugqAaDL2EIKXz9n6jwgbe9MWKdPKGZW-PXx5Y5szhS_XxaKSvV-b0RM_9PeyTzKrbcIUYh-omBuKxQq-waX67AqyjCYFv6BCzXza4ffQ4kgb1O-bulA"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:08 GMT + - Thu, 25 Mar 2021 20:03:36 GMT server: - openresty strict-transport-security: @@ -149,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:08 GMT + - Thu, 25 Mar 2021 20:03:36 GMT docker-distribution-api-version: - registry/2.0 server: @@ -199,7 +198,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:08 GMT + - Thu, 25 Mar 2021 20:03:37 GMT docker-distribution-api-version: - registry/2.0 server: @@ -207,15 +206,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_write",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODYsIm5iZiI6MTYxNjY4NzI4NiwiZXhwIjoxNjE2NzczOTg2LCJhaW8iOiJFMlpnWUNqYWJjTlFhSzFTd2pqSG0vZlB1a3NHQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQTBjNFVZVUkwRS1nVjY1a1Rid1RBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JS98aJ1m8yRQE671Kfb0cb5YZAkWm1IVAH2QGYmODlx6fUC4Hw-70ztS2AOaq0PwvTXSGFjXf4PlRhYtURXXVnn0GC8InMokBklY5LJLa1GF_u5GJ6aIX2gYeHqIaKRMVjCZ0UnaprYkVjLY7ZSj0ulXHdj7elsrvlkcc50RIJ0peV5DoywrnDmfZN-uFmWKzQkvndRurqNOTpLxXBXLAOPjI9-8izCBiFd0irvHVqcP61w8bfH0mFcyN2tHPF8Z2TQ24rsyNm7ywo2m7p2OZv-_RI8fe-IAI2B1QJ6H28OIsTA17ppwd3tqgrBgZSnM7A4x6CAKy9D0fPufyOcyWw + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -233,14 +231,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwODU1MzhmYS04MjMxLTQyMTMtOGM2Zi1hODMyZjAyNWNkNDgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODksImV4cCI6MTYxNjY5ODM4OSwiaWF0IjoxNjE2Njg2Njg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Bh1lG11oZaJ5RV6v7z3XQlLME6uYOiQ1A_FiNealZN2AUBBmHI9y6x3DOG6UpB9ls9dDkqHYbAxdL6kAZRCi1ICEy5ROn7bDMjW2icjcdM0yTQe9ZVN3vjODuV-Yy_rjSsoO_yavCbkEObnWxC5t1_rbSk3pC8O1zhk6I0_wGMxc8ZZmwx1oPmoampF-sJzzKvRofh01TZZ7Vq2omd0bL63GUAdGL_nRVZDqq5QiOwU8niL3sZ7WeJfgwLwGF2U85ZXuox2cwD7G2gKcuToiN4ZaanBcPhAU73S8Qj0g_TPNCA3v4QgF73Cvcll0Wgg8B5RgpbTUH0qeBDZ6WKoQ4w"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:09 GMT + - Thu, 25 Mar 2021 20:03:37 GMT server: - openresty strict-transport-security: @@ -251,7 +249,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_write&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwODU1MzhmYS04MjMxLTQyMTMtOGM2Zi1hODMyZjAyNWNkNDgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODksImV4cCI6MTYxNjY5ODM4OSwiaWF0IjoxNjE2Njg2Njg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Bh1lG11oZaJ5RV6v7z3XQlLME6uYOiQ1A_FiNealZN2AUBBmHI9y6x3DOG6UpB9ls9dDkqHYbAxdL6kAZRCi1ICEy5ROn7bDMjW2icjcdM0yTQe9ZVN3vjODuV-Yy_rjSsoO_yavCbkEObnWxC5t1_rbSk3pC8O1zhk6I0_wGMxc8ZZmwx1oPmoampF-sJzzKvRofh01TZZ7Vq2omd0bL63GUAdGL_nRVZDqq5QiOwU8niL3sZ7WeJfgwLwGF2U85ZXuox2cwD7G2gKcuToiN4ZaanBcPhAU73S8Qj0g_TPNCA3v4QgF73Cvcll0Wgg8B5RgpbTUH0qeBDZ6WKoQ4w + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_write&refresh_token=REDACTED headers: Accept: - application/json @@ -269,14 +267,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1OGYwYzY0Ny1iNjNmLTQ0N2QtOGU4OC1kM2Y3NGVhOGQ5OTIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2ODksImV4cCI6MTYxNjY5MTE4OSwiaWF0IjoxNjE2Njg2Njg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfd3JpdGUiXX1dLCJyb2xlcyI6W10sImdyYW50X3R5cGUiOiJhY2Nlc3NfdG9rZW4ifQ.LvrMN0nOnFuUzO_HejWEGKZq8nKUhIx4Xsvftt-ABSXr1o1TcZ8Wyn918tHrODKUrWG80QUKynjLcaozX2_APXy4aNvDPyCkNlTpRvCz57Z93xvrneUEBjtg3E9EfJcujuDxy91lfztPlO5JX7MCaYfnPdNuPjFMiH9K7mFooTNNNWrLd8cUpssufnEq4pfQCYQVwJZHbaJSzHJTNLArnioWmWzYFCwTsXGtNS8u7YRkZGGjlTTwAwHaDG3abi2Z0mR9yb3kgxKYTbkTD2tmDe-Jwx6oiZ2DpFvaMk4k_vBp29WppDFpPIi1Myb6vxUKIlb6sfydGoHHIc8qeYVaAQ"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:09 GMT + - Thu, 25 Mar 2021 20:03:37 GMT server: - openresty strict-transport-security: @@ -307,8 +305,8 @@ interactions: response: body: string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security - Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/23/2021 4:51:56 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys + Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} ' headers: @@ -320,11 +318,11 @@ interactions: connection: - keep-alive content-length: - - '912' + - '917' content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:09 GMT + - Thu, 25 Mar 2021 20:03:38 GMT docker-distribution-api-version: - registry/2.0 server: @@ -369,7 +367,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:09 GMT + - Thu, 25 Mar 2021 20:03:38 GMT docker-distribution-api-version: - registry/2.0 server: @@ -377,15 +375,14 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="repository:hello-world:metadata_read",error="invalid_token" + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" x-content-type-options: - nosniff status: code: 401 message: Unauthorized - request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyODYsIm5iZiI6MTYxNjY4NzI4NiwiZXhwIjoxNjE2NzczOTg2LCJhaW8iOiJFMlpnWUNqYWJjTlFhSzFTd2pqSG0vZlB1a3NHQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQTBjNFVZVUkwRS1nVjY1a1Rid1RBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.JS98aJ1m8yRQE671Kfb0cb5YZAkWm1IVAH2QGYmODlx6fUC4Hw-70ztS2AOaq0PwvTXSGFjXf4PlRhYtURXXVnn0GC8InMokBklY5LJLa1GF_u5GJ6aIX2gYeHqIaKRMVjCZ0UnaprYkVjLY7ZSj0ulXHdj7elsrvlkcc50RIJ0peV5DoywrnDmfZN-uFmWKzQkvndRurqNOTpLxXBXLAOPjI9-8izCBiFd0irvHVqcP61w8bfH0mFcyN2tHPF8Z2TQ24rsyNm7ywo2m7p2OZv-_RI8fe-IAI2B1QJ6H28OIsTA17ppwd3tqgrBgZSnM7A4x6CAKy9D0fPufyOcyWw + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED headers: Accept: - application/json @@ -403,14 +400,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/exchange response: body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0ZjFiODRiOS1hOGM4LTRlMDAtYjEyYy1kMWJhMzkyOGZmNzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTAsImV4cCI6MTYxNjY5ODM5MCwiaWF0IjoxNjE2Njg2NjkwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Ty0kIc8Rzy1KVE50SCiJZS8GgPeRv1XoC5WMawSKLgYcXWAiTzhT3CtkOC1z2PbU6MH-h5r-w_T_N1vt6Eb2Ph71AXwguiivXKY0GJrfZgPMjcYYwoRfFAGJArymPTQxaeaPpKNx5OdwlmsH63S5XOTZFvdSCjjpBK_qUlyNrh1P-2cI4UTNcbLq6z2V1FQjkQi9QKBxWzjEjR6isFEo0dzy2LedkWpbBqfMHpok050kkCG66wC49BXAgXjrbkz2uUtXrXg9RrTrjTVZ8na9f6pk2i-dKBRskOmt4INDDMkQWeF6oq01OmRtj0baP-UUtTtLiDheKe1f_OPr0Yuvnw"}' + string: '{"refresh_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:10 GMT + - Thu, 25 Mar 2021 20:03:38 GMT server: - openresty strict-transport-security: @@ -421,7 +418,7 @@ interactions: code: 200 message: OK - request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0ZjFiODRiOS1hOGM4LTRlMDAtYjEyYy1kMWJhMzkyOGZmNzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTAsImV4cCI6MTYxNjY5ODM5MCwiaWF0IjoxNjE2Njg2NjkwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Ty0kIc8Rzy1KVE50SCiJZS8GgPeRv1XoC5WMawSKLgYcXWAiTzhT3CtkOC1z2PbU6MH-h5r-w_T_N1vt6Eb2Ph71AXwguiivXKY0GJrfZgPMjcYYwoRfFAGJArymPTQxaeaPpKNx5OdwlmsH63S5XOTZFvdSCjjpBK_qUlyNrh1P-2cI4UTNcbLq6z2V1FQjkQi9QKBxWzjEjR6isFEo0dzy2LedkWpbBqfMHpok050kkCG66wC49BXAgXjrbkz2uUtXrXg9RrTrjTVZ8na9f6pk2i-dKBRskOmt4INDDMkQWeF6oq01OmRtj0baP-UUtTtLiDheKe1f_OPr0Yuvnw + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED headers: Accept: - application/json @@ -439,14 +436,14 @@ interactions: uri: https://fake_url.azurecr.io/oauth2/token response: body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJmNGVjOTgzNS0xZTk2LTRjZjAtODE5My04NmJmNTVmZTdlMzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTAsImV4cCI6MTYxNjY5MTE5MCwiaWF0IjoxNjE2Njg2NjkwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjIuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVwb3NpdG9yeSIsIm5hbWUiOiJoZWxsby13b3JsZCIsImFjdGlvbnMiOlsibWV0YWRhdGFfcmVhZCJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.JD52eHxP_xlRlJKpd0lVBYONjkG8xfob0_KC_GuPN-5mzs9wKfcKEpK2bgU12D-ErrGfw4AWJDO6hf0oAHyr1ak7LLL0xcu0ItGeiqXnsPQ2JtnYxhYpwjIImE3RqhhNWoRr2xbj7-qsdjxjSACMp7Abp9oOjYMHMBTV7Pg4tCh6-CaCehXQ08F4mcyrmd9xPBkNwCsKWw5xgqll5H6prbCfsr-qtFiO2PZGfAy2xX0JV1_23Eg0YlFoAcyreyoGfZEjtcYAI0ox6cxQJjITGvplCWjydHeB-JazYoAlBACeKjb4kXZ_h2mS1YyQquozBiiCGfGbs81I_3whJlrWug"}' + string: '{"access_token": "REDACTED"}' headers: connection: - keep-alive content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:10 GMT + - Thu, 25 Mar 2021 20:03:38 GMT server: - openresty strict-transport-security: @@ -487,7 +484,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 15:53:10 GMT + - Thu, 25 Mar 2021 20:03:39 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml deleted file mode 100644 index 58bc0e5b89e6..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_exchange_client.test_auth_policy_in_action.yaml +++ /dev/null @@ -1,165 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '196' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 25 Mar 2021 15:53:12 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: - - Bearer realm="https://seankane.azurecr.io/oauth2/token",service="seankane.azurecr.io",scope="registry:catalog:*",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY2ODcyOTEsIm5iZiI6MTYxNjY4NzI5MSwiZXhwIjoxNjE2NzczOTkxLCJhaW8iOiJFMlpnWUpqY0luTE5lVjA0KzY1STkvc01iWmUzQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiQllRYzdWcjdZRUtYSExoRExMVVJBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.MZIdEfCYCN7zXIE9mddygnyqG_vtaCk4orba85U81eUQurX2stJK4jyvvWJIGnruU6i6CQL4QO7UY-f3-NlWgxE1Nvfw3AMNt3SR9zYk7ZxvKjYH9mn7i2XsFgp-5Uk-mv8uyF6YISTgSFHPfxptVk46BS3nFnbDAYqpfegxiIvBkRgGY2Ixn7cE2o8d9yWxra7kd_e0CFk19Uv9YwG7d22yczX_uH1vkYXcucm2VQWchjo0fErt1aZpoG7TfjgWuTv_B56zAt5ECvhKog23CnM3R8EFNssyor-0ntDLfa4liSq3l0JAVFSaIED6io-pFcOTqHsCQOYmxnkUhDCy_w - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1YWUwMTdhYy05MDFhLTQ0YjgtOGE0MC0yNzM1YzNiMzYwY2EiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTMsImV4cCI6MTYxNjY5ODM5MywiaWF0IjoxNjE2Njg2NjkzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.W1y1jY1cxgKMaqeWHWi_COohmK71Arujmtp7RGQcR9u-s5kSiuiJIPiQvQKLf94jJC3lDq0FUfVJc96aABTLG3zbPB6_uSzC7KLwJGYYi9mFRC6RVTIiIoa93tu-E5UMDb3pzwfWMteMbkEUjoKL4LrrMvZLmzplgDDoACdmFzFLBGAkC0_vMQZ8oiaO5soQtkLc9bNVrRLut7_fmL7VvNFfGGOqQSpTIk2jdxkD3E6e1ryLGZjC8QCkREWTe5I_0AKNgCGTo0Pv6iTslWVMot49_g5T9nxyvsQ1FzWh_3m3OsmxQdjkXYQz1st588foPEP_eZRiKMvpi7Y1d4B2yg"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Thu, 25 Mar 2021 15:53:13 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry%3Acatalog%3A%2A&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI1YWUwMTdhYy05MDFhLTQ0YjgtOGE0MC0yNzM1YzNiMzYwY2EiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTMsImV4cCI6MTYxNjY5ODM5MywiaWF0IjoxNjE2Njg2NjkzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.W1y1jY1cxgKMaqeWHWi_COohmK71Arujmtp7RGQcR9u-s5kSiuiJIPiQvQKLf94jJC3lDq0FUfVJc96aABTLG3zbPB6_uSzC7KLwJGYYi9mFRC6RVTIiIoa93tu-E5UMDb3pzwfWMteMbkEUjoKL4LrrMvZLmzplgDDoACdmFzFLBGAkC0_vMQZ8oiaO5soQtkLc9bNVrRLut7_fmL7VvNFfGGOqQSpTIk2jdxkD3E6e1ryLGZjC8QCkREWTe5I_0AKNgCGTo0Pv6iTslWVMot49_g5T9nxyvsQ1FzWh_3m3OsmxQdjkXYQz1st588foPEP_eZRiKMvpi7Y1d4B2yg - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1063' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkZTI5MTY4OC0wZTE0LTRlMzYtOWM2Yy03MWEzYmJlMTI3MzYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY2ODY2OTMsImV4cCI6MTYxNjY5MTE5MywiaWF0IjoxNjE2Njg2NjkzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiYWNjZXNzIjpbeyJ0eXBlIjoicmVnaXN0cnkiLCJuYW1lIjoiY2F0YWxvZyIsImFjdGlvbnMiOlsiKiJdfV0sInJvbGVzIjpbXSwiZ3JhbnRfdHlwZSI6ImFjY2Vzc190b2tlbiJ9.aV8vCrkK7meZbNIvSeTnKdWtThsfqAU1VI0N-_Q2QliU7-PljVr_agP0DvpcjB6XB2wYiEwaWysr-CBI8JNSEhNZ4i8Z80EsSFMZth0EX3u5GUq4KFfx6zAtEwwQAergpqEpgM4LBn6z1UFWJI_6dCBlJtye5TWzLFKarhe_ocFiWpPrfk459VUr0UCEFr_PL0w-YwcnibP8z0dAROkwJHq8D64mFOBrFnWZR-_HJSu9l-eyYEOF-IySnUO34FqMh-LImdld-VX_xFiZYbOxraXiFK9BMcSzjzlVOD2vQ1JTiCaiiDp5X1eGzQPktpHVTiKMcXHN2sQu338wgEbr-g"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Thu, 25 Mar 2021 15:53:13 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '125' - content-type: - - application/json; charset=utf-8 - date: - - Thu, 25 Mar 2021 15:53:13 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py b/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py deleted file mode 100644 index 42582412c27f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/test_auth_flow.py +++ /dev/null @@ -1,69 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -import functools -import os -import pytest - -from devtools_testutils import AzureTestCase, PowerShellPreparer - -from azure.containerregistry import ( - ContainerRepositoryClient, - ContainerRegistryClient, - RepositoryProperties, - ContentPermissions, - TagProperties, - TagOrderBy, -) -from azure.containerregistry._generated.models import Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema -from azure.core.paging import ItemPaged -from azure.identity import DefaultAzureCredential - -from testcase import ContainerRegistryTestClass - -acr_preparer = functools.partial( - PowerShellPreparer, - "containerregistry", - containerregistry_baseurl="fake_url.azurecr.io", -) - - -class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): - - repository = "hello-world" - - @pytest.mark.live_test_only - @acr_preparer() - def test_get_refresh_token(self, containerregistry_baseurl): - client = self.create_repository_client(containerregistry_baseurl, self.repository) - - service = "seankane.azurecr.io" - scope = "repository:hello-world:metadata_read" - - d = DefaultAzureCredential() - - token = d.get_token("https://management.core.windows.net/.default").token - print(token) - - m = Paths108HwamOauth2ExchangePostRequestbodyContentApplicationXWwwFormUrlencodedSchema( - service=service, - aad_accesstoken=token, - ) - - refresh = client._client.authentication.exchange_aad_access_token_for_acr_refresh_token( - service, token) - print(refresh.refresh_token) - - assert refresh is not None - assert refresh.refresh_token is not None - - access_token = client._client.authentication.exchange_acr_refresh_token_for_acr_access_token( - service, scope, refresh.refresh_token - ) - - assert access_token is not None - assert access_token.access_token is not None - - # assert m.access_token \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index cbbb373a738d..c876e56b02eb 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -18,7 +18,7 @@ from azure.core.paging import ItemPaged from azure.identity import DefaultAzureCredential -from testcase import ContainerRegistryTestClass +from .testcase import ContainerRegistryTestClass acr_preparer = functools.partial( @@ -28,8 +28,8 @@ ) -class TestContainerRegistryClient(AzureTestCase, ContainerRegistryTestClass): - @pytest.mark.live_test_only +class TestContainerRegistryClient(ContainerRegistryTestClass): + @acr_preparer() def test_list_repositories(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) @@ -59,7 +59,7 @@ def test_delete_repository(self, containerregistry_baseurl): assert len(deleted_result.deleted_tags) == 1 @pytest.mark.skip("Don't want to for now") - @pytest.mark.live_test_only + @acr_preparer() def test_delete_repository_does_not_exist(self, containerregistry_baseurl): client = self.create_registry_client(containerregistry_baseurl) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 38921df0155c..76bdb6586b6e 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -21,7 +21,7 @@ ) from azure.core.paging import ItemPaged -from testcase import ContainerRegistryTestClass, AcrBodyReplacer +from .testcase import ContainerRegistryTestClass, AcrBodyReplacer, FakeTokenCredential acr_preparer = functools.partial( PowerShellPreparer, @@ -30,7 +30,8 @@ ) -class TestContainerRepositoryClient(AzureTestCase, ContainerRegistryTestClass): +class TestContainerRepositoryClient(ContainerRegistryTestClass): + def __init__(self, method_name): super(TestContainerRepositoryClient, self).__init__(method_name) self.vcr.match_on = ["path", "method", "query"] @@ -46,7 +47,7 @@ def test_get_attributes(self, containerregistry_baseurl): assert repo_attribs is not None assert repo_attribs.content_permissions is not None - @pytest.mark.live_test_only + @acr_preparer() def test_get_properties(self, containerregistry_baseurl): repo_client = self.create_repository_client(containerregistry_baseurl, "hello-world") @@ -54,7 +55,7 @@ def test_get_properties(self, containerregistry_baseurl): properties = repo_client.get_properties() assert isinstance(properties.content_permissions, ContentPermissions) - @pytest.mark.live_test_only + @acr_preparer() def test_get_tag(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -64,7 +65,7 @@ def test_get_tag(self, containerregistry_baseurl): assert tag is not None assert isinstance(tag, TagProperties) - @pytest.mark.live_test_only + @acr_preparer() def test_list_registry_artifacts(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -79,7 +80,7 @@ def test_list_registry_artifacts(self, containerregistry_baseurl): assert artifact.tags is not None assert isinstance(artifact.tags, list) - @pytest.mark.live_test_only + @acr_preparer() def test_get_registry_artifact_properties(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -91,7 +92,7 @@ def test_get_registry_artifact_properties(self, containerregistry_baseurl): assert isinstance(properties.created_on, datetime) assert isinstance(properties.last_updated_on, datetime) - @pytest.mark.live_test_only + @acr_preparer() def test_list_tags(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -105,7 +106,7 @@ def test_list_tags(self, containerregistry_baseurl): assert count > 0 - @pytest.mark.live_test_only + @acr_preparer() def test_list_tags_descending(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -146,7 +147,6 @@ def test_set_manifest_properties(self, containerregistry_baseurl): break @pytest.mark.xfail - @pytest.mark.live_test_only @acr_preparer() def test_set_tag_properties(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py index 7d4628a3d5be..15b1668507da 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py @@ -20,7 +20,7 @@ from azure.core.paging import ItemPaged from azure.identity import DefaultAzureCredential -from testcase import ContainerRegistryTestClass +from .testcase import ContainerRegistryTestClass acr_preparer = functools.partial( @@ -30,12 +30,12 @@ ) -class TestExchangeClient(AzureTestCase, ContainerRegistryTestClass): +class TestExchangeClient(ContainerRegistryTestClass): def create_exchange_client(self, endpoint): return self.create_client_from_credential( ACRExchangeClient, - credential=self.get_credential(ACRExchangeClient), + credential=self.get_credential(), endpoint=endpoint, ) @@ -56,18 +56,4 @@ def test_exchange_client(self, containerregistry_baseurl): access_token = client.exchange_refresh_token_for_access_token(service, scope, refresh_token) assert access_token is not None assert len(access_token) > 100 - print(access_token) - - @pytest.mark.live_test_only - @acr_preparer() - def test_auth_policy_in_action(self, containerregistry_baseurl): - client = ContainerRegistryClient( - endpoint=containerregistry_baseurl, - credential=DefaultAzureCredential(), - ) - - prev = None - for repo in client.list_repositories(): - assert repo is not None - assert repo != prev - prev = repo \ No newline at end of file + print(access_token) \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index 9ea94489e206..86b05c05fdd4 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -17,11 +17,12 @@ RegistryArtifactProperties, ) +from azure.core.credentials import AccessToken from azure.identity import DefaultAzureCredential from azure_devtools.scenario_tests import RecordingProcessor +from devtools_testutils import AzureTestCase -from azure.core.credentials import AccessToken REDACTED = "REDACTED" @@ -33,17 +34,23 @@ def __init__(self, replacement="redacted"): def _scrub_body(self, body): # type: (bytes) -> bytes + if not isinstance(body, six.binary_type): + return body s = body.decode("utf-8") + if "access_token" not in s and "refresh_token" not in s: + return body s = s.split("&") for idx, pair in enumerate(s): [k, v] = pair.split("=") - if k == "access_token" or k == + if k == "access_token" or k == "refresh_token": + v = REDACTED + s[idx] = "=".join([k, v]) + s = "&".join(s) + return bytes(s, "utf-8") def process_request(self, request): - if request.body and isinstance(request.body, six.binary_type): + if request.body:# and isinstance(request.body, six.binary_type): request.body = self._scrub_body(request.body) - else: - pass return request @@ -67,7 +74,6 @@ def process_response(self, response): except json.decoder.JSONDecodeError: pass - return response except (KeyError, ValueError): return response @@ -84,29 +90,29 @@ def get_token(self, *args): return self.token -class ContainerRegistryTestClass(object): +class ContainerRegistryTestClass(AzureTestCase): def __init__(self, method_name): - # self.vcr.match_on = ["path", "method", "query"] + super(ContainerRegistryTestClass, self).__init__(method_name) + self.vcr.match_on = ["path", "method", "query"] self.recording_processors.append(AcrBodyReplacer()) + def get_credential(self): + if self.is_live: + return DefaultAzureCredential() + return FakeTokenCredential() + def create_registry_client(self, endpoint): - token = DefaultAzureCredential() - if not self.is_live: - token = FakeTokenCredential() return ContainerRegistryClient( endpoint=endpoint, - credential=token, + credential=self.get_credential(), ) def create_repository_client(self, endpoint, name): - token = DefaultAzureCredential() - if not self.is_live: - token = FakeTokenCredential() return ContainerRepositoryClient( endpoint=endpoint, repository=name, - credential=token, + credential=self.get_credential(), ) def assert_content_permission(self, content_perm, content_perm2): From d8e3a4dff9a709bbd1adfc10dd97933c43b0ec5d Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 25 Mar 2021 18:25:57 -0400 Subject: [PATCH 67/86] linting fixes, had to remove mypy because of issues in generated --- eng/tox/mypy_hard_failure_packages.py | 1 - .../azure/containerregistry/__init__.py | 2 +- .../_authentication_policy.py | 24 ++-- .../_container_registry_client.py | 4 +- .../_container_repository_client.py | 25 ++-- .../containerregistry/_exchange_client.py | 30 ++-- .../azure/containerregistry/_models.py | 4 +- .../aio/_async_authentication_policy.py | 21 ++- .../aio/_async_base_client.py | 4 +- .../aio/_async_container_registry_client.py | 8 +- .../aio/_async_container_repository_client.py | 54 +++++--- .../aio/_async_exchange_client.py | 36 +++-- .../authentication/_access_token_cache.py | 56 -------- .../authentication/_access_tokens_impl.py | 27 ---- .../authentication/_authentication_policy.py | 60 -------- .../_container_registry_credential_policy.py | 131 ------------------ .../_container_registry_token_credential.py | 33 ----- ...ontainer_registry_token_request_context.py | 14 -- .../_container_registry_token_service.py | 25 ---- .../authentication/_json_web_token.py | 5 - .../authentication/_refresh_token_impl.py | 5 - .../authentication/_token_service_impl.py | 36 ----- 22 files changed, 119 insertions(+), 486 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py delete mode 100644 sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py diff --git a/eng/tox/mypy_hard_failure_packages.py b/eng/tox/mypy_hard_failure_packages.py index cdcb1cc09f1f..8b5f6c93ac31 100644 --- a/eng/tox/mypy_hard_failure_packages.py +++ b/eng/tox/mypy_hard_failure_packages.py @@ -14,5 +14,4 @@ "azure-ai-formrecognizer", "azure-ai-metricsadvisor", "azure-eventgrid", - "azure-containerregistry", ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 82ab1b769a97..90683b53dba9 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -23,7 +23,7 @@ __version__ = VERSION __all__ = [ - "ACRExchangeClient" + "ACRExchangeClient", "ContainerRegistryClient", "ContainerRepositoryClient", "ContentPermissions", diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index f7be4a6de1c8..7cd038f9eaa2 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -4,22 +4,22 @@ # Licensed under the MIT License. # ------------------------------------ -from base64 import b64encode -import re from typing import TYPE_CHECKING -from azure.core.pipeline.policies import SansIOHTTPPolicy, HTTPPolicy +from azure.core.exceptions import ServiceRequestError +from azure.core.pipeline.policies import HTTPPolicy from ._exchange_client import ACRExchangeClient if TYPE_CHECKING: - from azure.core.pipeline import PipelineRequest + from azure.core.credentials import TokenCredential + from azure.core.pipeline import PipelineRequest, PipelineResponse + from typing import Optional def _enforce_https(request): # type: (PipelineRequest) -> None - """Raise ServiceRequestError if the request URL is non-HTTPS and the sender did not specify "enforce_https=False" - """ + """Raise ServiceRequestError if the request URL is non-HTTPS and the sender did not specify enforce_https=False""" # move 'enforce_https' from options to context so it persists # across retries but isn't passed to a transport implementation @@ -39,15 +39,15 @@ def _enforce_https(request): class ContainerRegistryChallengePolicy(HTTPPolicy): """Authentication policy for ACR which accepts a challenge""" - def __init__(self, credential, endpoint, *scopes, **kwargs): - # type: (TokenCredential, *str, **Any) -> None - super(HTTPPolicy, self).__init__() - self._scopes = ["https://management.core.windows.net/.default"] + def __init__(self, credential, endpoint): + # type: (TokenCredential, str) -> None + super(ContainerRegistryChallengePolicy, self).__init__() + self._scopes = "https://management.core.windows.net/.default" self._credential = credential self._token = None # type: Optional[AccessToken] self._exchange_client = ACRExchangeClient(endpoint, self._credential) - def _need_new_token(self): + def _need_new_token(self): # pylint: disable=no-self-use # type: () -> bool return True @@ -59,7 +59,7 @@ def on_request(self, request): """ if self._token is None or self._need_new_token(): - self._token = self._credential.get_token(*self._scopes) + self._token = self._credential.get_token(self._scopes) try: self._token = self._token.token except AttributeError: diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 59231507dead..a347eaae66be 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -43,7 +43,9 @@ def delete_repository(self, repository, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # NOTE: DELETE `/acr/v1/{name}` - return DeletedRepositoryResult._from_generated(self._client.container_registry.delete_repository(repository, **kwargs)) + return DeletedRepositoryResult._from_generated( # pylint: disable=protected-access + self._client.container_registry.delete_repository(repository, **kwargs) + ) def list_repositories(self, **kwargs): # type: (Dict[str, Any]) -> ItemPaged[str] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 446329494c20..9cf6e96aa7e6 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -81,7 +81,9 @@ def get_properties(self): :raises: None """ # GET '/acr/v1/{name}' - return RepositoryProperties._from_generated(self._client.container_registry_repository.get_properties(self.repository)) + return RepositoryProperties._from_generated( # pylint: disable=protected-access + self._client.container_registry_repository.get_properties(self.repository) + ) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): # type: (str, Dict[str, Any]) -> RegistryArtifactProperties @@ -96,7 +98,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): if self._is_tag(tag_or_digest): tag_or_digest = self.get_digest_from_tag(tag_or_digest) - return RegistryArtifactProperties._from_generated( + return RegistryArtifactProperties._from_generated( # pylint: disable=protected-access self._client.container_registry_repository.get_registry_artifact_properties( self.repository, tag_or_digest, **kwargs ) @@ -134,8 +136,13 @@ def list_registry_artifacts(self, **kwargs): n = kwargs.pop("top", None) orderby = kwargs.pop("order_by", None) return self._client.container_registry_repository.get_manifests( - self.repository, last=last, n=n, orderby=orderby, - cls=lambda objs: [RegistryArtifactProperties._from_generated(x) for x in objs] + self.repository, + last=last, + n=n, + orderby=orderby, + cls=lambda objs: [ + RegistryArtifactProperties._from_generated(x) for x in objs # pylint: disable=protected-access + ], ) def list_tags(self, **kwargs): @@ -155,7 +162,7 @@ def list_tags(self, **kwargs): n=kwargs.pop("top", None), orderby=kwargs.pop("order_by", None), digest=kwargs.pop("digest", None), - cls=lambda objs: [TagProperties._from_generated(o) for o in objs], + cls=lambda objs: [TagProperties._from_generated(o) for o in objs], # pylint: disable=protected-access **kwargs ) @@ -167,12 +174,12 @@ def set_manifest_properties(self, digest, permissions): :type digest: str :param permissions: The property's values to be set :type permissions: ContentPermissions - :returns: ~azure.core.paging.ItemPaged[TagProperties] + :returns: None :raises: None """ self._client.container_registry_repository.update_manifest_attributes( - self.repository, digest, permissions.to_generated() + self.repository, digest, value=permissions.to_generated() ) def set_tag_properties(self, tag_or_digest, permissions): @@ -183,12 +190,12 @@ def set_tag_properties(self, tag_or_digest, permissions): :type tag: str :param permissions: The property's values to be set :type permissions: ContentPermissions - :returns: ~azure.core.paging.ItemPaged[TagProperties] + :returns: None :raises: None """ if self._is_tag(tag_or_digest): tag_or_digest = self.get_digest_from_tag(tag_or_digest) self._client.container_registry_repository.update_manifest_attributes( - self.repository, tag_or_digest, permissions.to_generated() + self.repository, tag_or_digest, value=permissions.to_generated() ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py index f13d4232b5ec..5dc6188738f0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -3,19 +3,19 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -import json -import os import re from typing import TYPE_CHECKING from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.core.pipeline.transport import HttpRequest from ._generated import ContainerRegistry from ._user_agent import USER_AGENT -if TYPE_CHECKING +if TYPE_CHECKING: from azure.core.credentials import TokenCredential + from azure.core.pipeline import PipelineRequest, PipelineResponse + from typing import Dict, Any, List + class ExchangeClientAuthenticationPolicy(SansIOHTTPPolicy): """Authentication policy for exchange client that does not modify the request""" @@ -40,7 +40,7 @@ class ACRExchangeClient(object): """ BEARER = "Bearer" - AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile('(?:(\\w+)="([^""]*)")+') WWW_AUTHENTICATE = "WWW-Authenticate" SCOPE_PARAMETER = "scope" SERVICE_PARAMETER = "service" @@ -68,29 +68,31 @@ def get_acr_access_token(self, challenge): refresh_token = self.exchange_aad_token_for_refresh_token(**parsed_challenge) return self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) - def exchange_aad_token_for_refresh_token(self, service=None, scope=None, **kwargs): - # type: (str, str, Dict[str, Any]) -> str + def exchange_aad_token_for_refresh_token(self, service=None, **kwargs): + # type: (str, Dict[str, Any]) -> str refresh_token = self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( - service, self._credential.get_token(self._credential_scopes).token) + service=service, access_token=self._credential.get_token(self._credential_scopes).token, **kwargs + ) return refresh_token.refresh_token def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): # type: (str, str, str) -> str access_token = self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( - service, scope, refresh_token) + service=service, scope=scope, refresh_token=refresh_token, **kwargs + ) return access_token.access_token def _parse_challenge(self, header): # type: (str) -> Dict[str, Any] """Parse challenge header into service and scope""" if header.startswith(self.BEARER): - challenge_params = header[len(self.BEARER)+1:] + challenge_params = header[len(self.BEARER) + 1 :] matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) self._clean(matches) ret = {} for i in range(0, len(matches), 2): - ret[matches[i]] = matches[i+1] + ret[matches[i]] = matches[i + 1] return ret @@ -108,16 +110,16 @@ def close(self): """ self._client.close() - def _clean(self, matches): + def _clean(self, matches): # pylint: disable=no-self-use # type: (List[str]) -> None while True: try: - matches.remove('') + matches.remove("") except ValueError: break while True: try: - matches.remove(',') + matches.remove(",") except ValueError: return diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 0d8613d44efc..d752f18d8a88 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -13,6 +13,7 @@ from ._generated.models import RepositoryProperties as GeneratedRepositoryProperties from ._generated.models import TagProperties as GeneratedTagProperties + class ContentPermissions(object): def __init__(self, **kwargs): self.can_delete = kwargs.get("can_delete") @@ -39,6 +40,7 @@ def to_generated(self): can_write=self.can_write, ) + class DeletedRepositoryResult(object): def __init__(self, **kwargs): self.deleted_registry_artifact_digests = kwargs.get("deleted_registry_artifact_digests", None) @@ -124,7 +126,7 @@ def _from_generated(cls, generated): manifest_count=generated.registry_artifact_count, tag_count=generated.tag_count, content_permissions=generated.writeable_properties, - registry=generated.additional_properties.get("registry", None) + registry=generated.additional_properties.get("registry", None), ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py index 1c5b2f1b60b2..87e43169fd7e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py @@ -3,23 +3,22 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ - -from base64 import b64encode -import re from typing import TYPE_CHECKING +from azure.core.exceptions import ServiceRequestError from azure.core.pipeline.policies import AsyncHTTPPolicy from ._async_exchange_client import ACRExchangeClient if TYPE_CHECKING: - from azure.core.pipeline import PipelineRequest + from azure.core.credentials import TokenCredential + from azure.core.pipeline import PipelineRequest, PipelineResponse + from typing import Optional, Dict, Any, Union def _enforce_https(request): # type: (PipelineRequest) -> None - """Raise ServiceRequestError if the request URL is non-HTTPS and the sender did not specify "enforce_https=False" - """ + """Raise ServiceRequestError if the request URL is non-HTTPS and the sender did not specify enforce_https=False""" # move 'enforce_https' from options to context so it persists # across retries but isn't passed to a transport implementation @@ -39,15 +38,15 @@ def _enforce_https(request): class ContainerRegistryChallengePolicy(AsyncHTTPPolicy): """Authentication policy for ACR which accepts a challenge""" - def __init__(self, credential, endpoint, *scopes, **kwargs): - # type: (TokenCredential, str, *str, **Any) -> None - super(AsyncHTTPPolicy, self).__init__() + def __init__(self, credential, endpoint): + # type: (TokenCredential, str) -> None + super(ContainerRegistryChallengePolicy, self).__init__() self._scopes = "https://management.core.windows.net/.default" self._credential = credential - self._token = None # type: Optional[AccessToken] + self._token = None # type: Union[str, None] self._exchange_client = ACRExchangeClient(endpoint, self._credential) - def _need_new_token(self): + def _need_new_token(self): # pylint: disable=no-self-use # type: () -> bool return True diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py index d64a8efa93f0..fbdd04f23e66 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_base_client.py @@ -38,8 +38,8 @@ def __init__(self, endpoint, credential, **kwargs): # pylint:disable=client-met **kwargs ) - async def __enter__(self): - await self._client.__enter__() + async def __aenter__(self): + await self._client.__aenter__() return self async def __aexit__(self, *args): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index 4e7e6dd12291..b98236016b1b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -25,7 +25,6 @@ def __init__( self._credential = credential super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) - async def delete_repository(self, repository: str, **kwargs: Dict[str, Any]) -> DeletedRepositoryResult: """Delete a repository @@ -35,9 +34,7 @@ async def delete_repository(self, repository: str, **kwargs: Dict[str, Any]) -> :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ result = await self._client.container_registry.delete_repository(repository, **kwargs) - return DeletedRepositoryResult._from_generated(result) - - + return DeletedRepositoryResult._from_generated(result) # pylint: disable=protected-access def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: @@ -45,6 +42,5 @@ def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: last=kwargs.pop("last", None), n=kwargs.pop("max", None), **kwargs ) - def get_repository_client(self, name: str, **kwargs) -> SyncContainerRegistryClient: - pass \ No newline at end of file + pass diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 98716522b9eb..7933880bcfe8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -5,14 +5,18 @@ # ------------------------------------ from typing import TYPE_CHECKING -from azure.core.async_paging import AsyncItemPaged - from ._async_base_client import ContainerRegistryBaseClient -from .._container_registry_client import ContainerRegistryClient as SyncContainerRegistryClient -from .._models import RepositoryProperties +from .._models import ( + RegistryArtifactProperties, + RepositoryProperties, + TagProperties, +) if TYPE_CHECKING: + from .._models import ContentPermissions + from azure.core.async_paging import AsyncItemPaged from azure.core.credentials_async import AsyncTokenCredential + from typing import Dict, Any class ContainerRepositoryClient(ContainerRegistryBaseClient): @@ -26,7 +30,6 @@ def __init__( self.repository = repository super(ContainerRepositoryClient, self).__init__(endpoint=self._endpoint, credential=credential, **kwargs) - async def delete(self, **kwargs): # type: (...) -> None """Delete a repository @@ -60,7 +63,7 @@ def delete_tag(self, tag): def get_digest_from_tag(self, tag): # type: (str) -> str - for t in self.list_tags(): + async for t in self.list_tags(): if t.name == tag: return t.digest raise ValueError("Could not find a digest for tag {}".format(tag)) @@ -73,7 +76,7 @@ async def get_properties(self): :raises: None """ # GET '/acr/v1/{name}' - return RepositoryProperties._from_generated( + return RepositoryProperties._from_generated( # pylint: disable=protected-access await self._client.container_registry_repository.get_properties(self.repository) ) @@ -90,7 +93,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): if self._is_tag(tag_or_digest): tag_or_digest = self.get_digest_from_tag(tag_or_digest) - return RegistryArtifactProperties._from_generated( + return RegistryArtifactProperties._from_generated( # pylint: disable=protected-access self._client.container_registry_repository.get_registry_artifact_properties( self.repository, tag_or_digest, **kwargs ) @@ -111,7 +114,7 @@ def get_tag_properties(self, tag, **kwargs): ) def list_registry_artifacts(self, **kwargs): - # type: (...) -> ItemPaged[RegistryArtifactProperties] + # type: (...) -> AsyncItemPaged[RegistryArtifactProperties] """List the artifacts for a repository :keyword last: Query parameter for the last item in the previous query @@ -120,7 +123,7 @@ def list_registry_artifacts(self, **kwargs): :type n: int :keyword orderby: Order by query parameter :type orderby: :class:~azure.containerregistry.RegistryArtifactOrderBy - :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] + :returns: ~azure.core.paging.AsyncItemPaged[RegistryArtifactProperties] :raises: None """ # GET /acr/v1/{name}/_manifests @@ -128,19 +131,24 @@ def list_registry_artifacts(self, **kwargs): n = kwargs.pop("top", None) orderby = kwargs.pop("order_by", None) return self._client.container_registry_repository.get_manifests( - self.repository, last=last, n=n, orderby=orderby, - cls=lambda objs: [RegistryArtifactProperties._from_generated(x) for x in objs] + self.repository, + last=last, + n=n, + orderby=orderby, + cls=lambda objs: [ + RegistryArtifactProperties._from_generated(x) for x in objs # pylint: disable=protected-access + ], ) def list_tags(self, **kwargs): - # type: (...) -> ItemPaged[TagProperties] + # type: (...) -> AsyncItemPaged[TagProperties] """List the tags for a repository :param last: Query parameter for the last item in the previous call. Ensuing call will return values after last lexically :type last: str :param order_by: Query paramter for ordering by time ascending or descending - :returns: ~azure.core.paging.ItemPaged[TagProperties] + :returns: ~azure.core.paging.AsyncItemPaged[TagProperties] :raises: None """ return self._client.container_registry_repository.get_tags( @@ -149,11 +157,11 @@ def list_tags(self, **kwargs): n=kwargs.pop("top", None), orderby=kwargs.pop("order_by", None), digest=kwargs.pop("digest", None), - cls=lambda objs: [TagProperties._from_generated(o) for o in objs], + cls=lambda objs: [TagProperties._from_generated(o) for o in objs], # pylint: disable=protected-access **kwargs ) - def set_manifest_properties(self, digest, permissions): + async def set_manifest_properties(self, digest, permissions): # type: (str, ContentPermissions) -> None """Set the properties for a manifest @@ -161,15 +169,15 @@ def set_manifest_properties(self, digest, permissions): :type digest: str :param permissions: The property's values to be set :type permissions: ContentPermissions - :returns: ~azure.core.paging.ItemPaged[TagProperties] + :returns: None :raises: None """ - self._client.container_registry_repository.update_manifest_attributes( - self.repository, digest, permissions.to_generated() + await self._client.container_registry_repository.update_manifest_attributes( + self.repository, digest, value=permissions.to_generated() ) - def set_tag_properties(self, tag_or_digest, permissions): + async def set_tag_properties(self, tag_or_digest, permissions): # type: (str, ContentPermissions) -> None """Set the properties for a tag @@ -177,12 +185,12 @@ def set_tag_properties(self, tag_or_digest, permissions): :type tag: str :param permissions: The property's values to be set :type permissions: ContentPermissions - :returns: ~azure.core.paging.ItemPaged[TagProperties] + :returns: None :raises: None """ if self._is_tag(tag_or_digest): tag_or_digest = self.get_digest_from_tag(tag_or_digest) - self._client.container_registry_repository.update_manifest_attributes( - self.repository, tag_or_digest, permissions.to_generated() + await self._client.container_registry_repository.update_manifest_attributes( + self.repository, tag_or_digest, value=permissions.to_generated() ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py index 4fdf25ba4fae..f1ffb0e1d738 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py @@ -3,16 +3,19 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ -import json -import os import re +from typing import TYPE_CHECKING from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.core.pipeline.transport import HttpRequest from .._generated.aio import ContainerRegistry from .._user_agent import USER_AGENT +if TYPE_CHECKING: + from typing import Dict, List, Any + from azure.core.credentials import TokenCredential + from azure.core.pipeline import PipelineRequest, PipelineResponse + class ExchangeClientAuthenticationPolicy(SansIOHTTPPolicy): """Authentication policy for exchange client that does not modify the request""" @@ -31,19 +34,21 @@ class ACRExchangeClient(object): :param endpoint: Azure Container Registry endpoint :type endpoint: str + :param credential: Azure Token Credential to authenticate requests with + :type credential: :class:~azure.core.TokenCredential :param credential: AAD Token for authenticating requests with Azure :type credential: :class:`azure.identity.DefaultTokenCredential` - """ BEARER = "Bearer" - AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") + AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile('(?:(\\w+)="([^""]*)")+') WWW_AUTHENTICATE = "WWW-Authenticate" SCOPE_PARAMETER = "scope" SERVICE_PARAMETER = "service" AUTHORIZATION = "Authorization" def __init__(self, endpoint, credential, **kwargs): + # type: (str, TokenCredential, Dict[str, Any]) -> None if not endpoint.startswith("https://"): endpoint = "https://" + endpoint self._endpoint = endpoint @@ -59,32 +64,37 @@ def __init__(self, endpoint, credential, **kwargs): self._credential = credential async def get_acr_access_token(self, challenge): + # type: (str) -> str parsed_challenge = self._parse_challenge(challenge) refresh_token = await self.exchange_aad_token_for_refresh_token(**parsed_challenge) return await self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) - async def exchange_aad_token_for_refresh_token(self, service=None, scope=None, **kwargs): + async def exchange_aad_token_for_refresh_token(self, service=None, **kwargs): + # type: (str, Dict[str, Any]) -> str token = await self._credential.get_token(self._credential_scopes) refresh_token = await self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( - service, token.token) + service, token.token, **kwargs + ) return refresh_token.refresh_token async def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): + # type: (str, str, str, Dict[str, Any]) -> str access_token = await self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( - service, scope, refresh_token) + service, scope, refresh_token, **kwargs + ) return access_token.access_token def _parse_challenge(self, header): # type: (str) -> Dict[str, Any] """Parse challenge header into service and scope""" if header.startswith(self.BEARER): - challenge_params = header[len(self.BEARER)+1:] + challenge_params = header[len(self.BEARER) + 1 :] matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) self._clean(matches) ret = {} for i in range(0, len(matches), 2): - ret[matches[i]] = matches[i+1] + ret[matches[i]] = matches[i + 1] return ret @@ -102,16 +112,16 @@ def close(self): """ self._client.close() - def _clean(self, matches): + def _clean(self, matches): # pylint: disable=no-self-use # type: (List[str]) -> None while True: try: - matches.remove('') + matches.remove("") except ValueError: break while True: try: - matches.remove(',') + matches.remove(",") except ValueError: return diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py deleted file mode 100644 index f38c17e25040..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_token_cache.py +++ /dev/null @@ -1,56 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -from datetime import datetime -import logging -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from ._access_token import AccessToken - from ._container_registry_token_credential import ContainerRegistryTokenCredential - from ._container_registry_token_request_context import ContainerRegistryTokenRequestContext - -logger = logging.getLogger() - - -class AccessTokenCacheImpl(object): - """An access token cache that supports caching and refreshing a token""" - - # Delay after a refresh to attempt another refresh token - _refresh_delay = 30 - # Offset before token expiry to attempt proactive token refresh - _refresh_offset = 300 - - def __init__(self, token_credential): - # type: (ContainerRegistryTokenCredential) -> None - self._token_credential = token_credential - self.should_refresh = True - - def get_token(self, token_request_context): - # type: (ContainerRegistryTokenContext) -> AccessToken - self.retrieve_token(token_request_context) - - def retrieve_token(self, token_request_context): - # type: (ContainerRegistryTokenContext) -> AccessToken - # Caching implementation will go here - - token_refresh = self._token_credential.get_token(token_request_context) - - return token_refresh - - def _check_if_force_refresh(self, token_request_context): - # type: (ContainerRegistryTokenContext) -> bool - # TODO: Add caching in later previews - return True - - def _process_token_refresh(self, now, fallback): - # type: (datetime, AccessToken) -> AccessToken - return fallback - - def refresh_log(self, cache, now, log): - # type: (AccessToken, datetime, str) -> str - if not cache: - return "." - return "Retry may be attempted after {} seconds.".format(self._refresh_delay) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py deleted file mode 100644 index e22043bd6dba..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_access_tokens_impl.py +++ /dev/null @@ -1,27 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - - -class AccessTokensImpl(object): - """Provides access to all the operations defined in AcessTokensService""" - - def __init__(self, url, pipeline, client): - # type: (str, HttpPipeline, ContainerRegistry) -> None - self.url = url - self.service = pipeline - - def get_access_token_with_response(self, grant_type, service_name, scope, refresh_token): - # type: (str, str, str, str) -> AcrAccessToken - return self.service.get_access_token(self.url, grant_type, service_name, scope, refresh_token) - - def get_access_token(self, grant_type, service_name, scope, refresh_token): - # type: (str, str, str, str) -> AccessToken - return self.get_access_token_with_response(grant_type, service_name, scope, refresh_token) - - def get_access_token(self, url, grant_type, service, scope, refresh_token): - # type: (str, str, str, str, str) -> AcrAccessToken - _models_access_token = self._client.access_tokens.get(service, scope, refresh_token) - return AcrAccessToken._from_generated(_models_access_token) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py deleted file mode 100644 index a5f2546e1ebd..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_authentication_policy.py +++ /dev/null @@ -1,60 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - -from base64 import b64encode -import re - -from azure.core.pipeline.policies import SansIOHTTPPolicy - - -class ContainerRegistryUserCredential(object): - """Credential used to authenticate with Container Registry service""" - - def __init__(self, username, password): - self._user = username - self._password = password - - def get_token(self): - token_str = "{}:{}".format(self._user, self._password) - token_bytes = token_str.encode("ascii") - b64_bytes = b64encode(token_bytes) - return b64_bytes.decode("ascii") - - -class ContainerRegistryUserCredentialPolicy(SansIOHTTPPolicy): - """HTTP pipeline policy to authenticate using ContainerRegistryUserCredential""" - - def __init__(self, credential): - self._credential = credential - - @staticmethod - def _update_headers(headers, token): - headers["Authorization"] = "Basic {}".format(token) - - def on_request(self, request): - # type: (PipelineRequest) -> None - self._update_headers(request.http_request.headers, self._credential.get_token()) - - -class ContainerRegistryCredentialPolicy(SansIOHTTPPolicy): - """Challenge based authentication policy for ACR. This policy is used for getting - the AAD Token, refresh token, and access token before performing a call to service. - - :param credential: Azure Token Credential for authenticating with Azure - :type credential: TokenCredential - """ - - BEARER = "Bearer" - AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") - WWW_AUTHENTICATE = "WWW-Authenticate" - SCOPE_PARAMETER = "scope" - SERVICE_PARAMETER = "service" - AUTHORIZATION = "Authorization" - - def __init__(self, credential, url, pipeline): - self._credential = credential - self.url = url - self.pipeline = pipeline \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py deleted file mode 100644 index 0939dd3c58cb..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_credential_policy.py +++ /dev/null @@ -1,131 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -import re -from typing import TYPE_CHECKING - -from azure.core.pipeline.policies import ChallengeAuthenticationPolicy - -from ._container_registry_token_service import ContainerRegistryTokenService - -if TYPE_CHECKING: - from azure.core.credentials import TokenCredential - from typing import List - - -# Follows challenge based authorization scheme - -# For example: - -# 1. GET /api/vr/acr/repositories (no authorization included) -# Return Header: 401: www-authenticate header - Bearer realm="{url}",service="{service_name}",scope="{scope}",error="invalid_token". - -# 2. Parse service_name, scope from the service - -# 3. POST /api/oauth2/exchange (grant-type=refresh_token) -# Request Body: {service, scope, grant-type, aadToken w/ ARM scope} -# Response Body: {acr refresh token} - -# 4. POST /api/oauth2/token (grant-type=access_token) -# Request Body: {acr refresh token, scope, grant-type} -# Response Body: {acr access token} - -# 5. GET /api/v1/acr/repositories -# Request Header: {Bearer acr acces token} - - -class ContainerRegistryCredentialPolicy(ChallengeAuthenticationPolicy): - """Challenge based authentication policy for ACR. This policy is used for getting - the AAD Token, refresh token, and access token before performing a call to service. - - :param TokenCredential credential: Azure Token Credential for authenticating with Azure - :param str url: base URL for ACR account - """ - - BEARER = "Bearer" - AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile("(?:(\\w+)=\"([^\"\"]*)\")+") - WWW_AUTHENTICATE = "WWW-Authenticate" - SCOPE_PARAMETER = "scope" - SERVICE_PARAMETER = "service" - AUTHORIZATION = "Authorization" - - def __init__(self, credential, url, pipeline): - # type: (TokenCredential, str, HttpPipeline) -> None - self._credential = credential - self.url = url - self.pipeline = pipeline - self.container_registry_token_service = ContainerRegistryTokenService( - credential, url, pipeline - ) - - @classmethod - def from_token_service(cls, token_service): - # type: (ContainerRegistryTokenService) -> ContainerRegistryCredentialPolicy - return cls(token_service.credential, token_service.url, token_service.pipeline) - - def process(self, context, next): - # type: (HttpPipelineContext, HttpPipelinePolicy) -> HttpResponse - if not self.url.startswith("https"): - raise ValueError("Token Credentials require a URL using the HTTPS protocol scheme") - - http_response = next.process() - auth_header = http_response.headers[self.WWW_AUTHENTICATE] - if http_response.status_code == 401 and auth_header is not None: - return None - - def authorize_request(self, context, token_request_context): - # type: (HttpPipelineContext, ContainerRegistryTokenRequestContext) -> None - context.http_request.headers[self.AUTHORIZATION] = "{} {}".format( - self.BEARER, - self.token_service.get_token() - ) - - def on_request(self, request): - # type: (PipelineRequest) -> None - """Called before the policy sends a request""" - pass - - def send(self, request): - # type: (PipelineRequest) -> PipelineResponse - """Authorizes a request with a bearer token, possibly handling an authentication challenge""" - - pass - - def authorize_request(self, context, token_request_context): - # type: (HttpPipelineCallContext, ContainerRegistryTokenRequestContext) -> None - pass - - def on_challenge(self, context, response): - # type: (HttpPipelineCallContext, HttpResponse) -> bool - return False - - def parse_bearer_challenge(self, header): - # type: (str) -> dict[str, str] - if header.startswith(self.BEARER): - challenge_params = header[len(self.BEARER)+1:] - - matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) - self._clean(matches) - ret = {} - for i in range(len(matches), 2): - ret[matches[i]] = matches[i+1] - - return ret - - return {} - - def _clean(self, matches): - # type: (List[str]) -> None - while: - try: - matches.remove('') - except ValueError: - break - - while: - try: - matches.remove(',') - except ValueError: - return \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py deleted file mode 100644 index 34d16fdc784d..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_credential.py +++ /dev/null @@ -1,33 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - - -class ContainerRegistryTokenCredential(object): - """Token credential representing the container registry refresh token. - This token is unique per registry operation, - - :param token_service: TokenServiceImplementation - :type token_service: TokenServiceImpl - :param token_credential: AAD Token Credential - :type token_credential: :class:`~azure.core.credential.TokenCredential` - """ - - AAD_DEFAULT_SCOPE = "https://management.core.windows.net/.default" - - def __init__(self, token_service, aad_token_credential): - # type: (TokenServiceImpl, TokenCredential) -> None - self.token_service = token_service - self.token_credential = aad_token_credential - - def get_token(self, context): - # type: (ContainerRegistryTokenRequestContext) -> AccessToken - service_name = context.get_service_name() - - token = self.token_credential.get_token( - TokenRequestContext().add_scopes(self.AAD_DEFAULT_SCOPE) - ) - - return self.token_service.get_acr_refresh_token(token.get_token, service_name) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py deleted file mode 100644 index 73dbf28c6149..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_request_context.py +++ /dev/null @@ -1,14 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - - -class ContainerRegistryTokenRequestContext(object): - """A token request context associated with a given container registry token""" - - def __init__(self, service_name, scope): - # type: (str, str) -> None - self.service_name = service_name - self.scope = scope diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py deleted file mode 100644 index 68ed6a15fbcc..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_container_registry_token_service.py +++ /dev/null @@ -1,25 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from ._container_registry_token_request_context import ContainerRegistryTokenRequestContext - - -class ContainerRegistryTokenService(object): - """A token service for obtaining tokens to be used by the container registry service""" - - def __init__(self, token_credential, url, pipeline): - self.token_service = TokenService(url, pipeline) - self.refresh_cache = None # TODO: decide on cache - - def get_token(self, req_context): - # type: (ContainerRegistryTokenRequestContext) -> AccessToken - scope = req_context.scope - service_name = req_context.service_name - - refresh_token = self.refresh_cache.get_token(req_context) - return self.token_service.get_acr_access_token(refresh_token, scope, service_name) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py deleted file mode 100644 index 15227605df4f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_json_web_token.py +++ /dev/null @@ -1,5 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py deleted file mode 100644 index 15227605df4f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_refresh_token_impl.py +++ /dev/null @@ -1,5 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py deleted file mode 100644 index d5b9c7f5d3ed..000000000000 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/authentication/_token_service_impl.py +++ /dev/null @@ -1,36 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from ._container_registry_token_request_context import ContainerRegistryTokenRequestContext - - -class TokenServiceImpl(object): - """Token service implementation that wraps the authentication REST APIs for ACR""" - - def __init__(self, url, pipeline): - # type: (str, HttpPipeline) -> None - self._url = url - self.pipeline = pipeline - self.access_token_impl = AccessTokenImpl(url, pipeline) - self.refresh_token_impl = RefreshTokenImpl(url, pipeline) - - def get_acr_access_token(self, refresh_token, scope, service_name): - # type: (str, str, str) -> str - access_token = self.access_token_impl.get_acr_access_token("refresh_token", service_name, scope, refresh_token) - # Here is where caching would go if we implement it - return access_token - - def get_acr_refresh_token(self, aad_token, service_name): - # type: (str, str) -> str - # Here is where caching would go if we implement it - return self.refresh_token_impl( - "access_token", - aad_token, - None, - service_name - ) \ No newline at end of file From 5d97e0b703c1383ba9724c96aa459af36b552e29 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 11:24:31 -0400 Subject: [PATCH 68/86] adding conftest, fixing up async issue --- .../_container_repository_client.py | 16 ++++++------- .../containerregistry/_exchange_client.py | 14 ++++++----- .../aio/_async_container_repository_client.py | 16 ++++++------- .../aio/_async_exchange_client.py | 14 ++++++----- .../azure-containerregistry/tests/conftest.py | 13 ++++++++++ ...test_get_registry_artifact_properties.yaml | 24 +++++++++---------- 6 files changed, 55 insertions(+), 42 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/conftest.py diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 9cf6e96aa7e6..2a801d05c182 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -35,6 +35,11 @@ def __init__(self, endpoint, repository, credential, **kwargs): self.repository = repository super(ContainerRepositoryClient, self).__init__(endpoint=self._endpoint, credential=credential, **kwargs) + def _get_digest_from_tag(self, tag): + # type: (str) -> str + tag_props = self.get_tag_properties(tag) + return tag_props.digest + def delete(self, **kwargs): # type: (...) -> None """Delete a repository @@ -66,13 +71,6 @@ def delete_tag(self, tag): """ raise NotImplementedError("Has not been implemented") - def get_digest_from_tag(self, tag): - # type: (str) -> str - for t in self.list_tags(): - if t.name == tag: - return t.digest - raise ValueError("Could not find a digest for tag {}".format(tag)) - def get_properties(self): # type: (...) -> RepositoryProperties """Get the properties of a repository @@ -96,7 +94,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): """ # GET '/acr/v1/{name}/_manifests/{digest}' if self._is_tag(tag_or_digest): - tag_or_digest = self.get_digest_from_tag(tag_or_digest) + tag_or_digest = self._get_digest_from_tag(tag_or_digest) return RegistryArtifactProperties._from_generated( # pylint: disable=protected-access self._client.container_registry_repository.get_registry_artifact_properties( @@ -194,7 +192,7 @@ def set_tag_properties(self, tag_or_digest, permissions): :raises: None """ if self._is_tag(tag_or_digest): - tag_or_digest = self.get_digest_from_tag(tag_or_digest) + tag_or_digest = self._get_digest_from_tag(tag_or_digest) self._client.container_registry_repository.update_manifest_attributes( self.repository, tag_or_digest, value=permissions.to_generated() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py index 5dc6188738f0..26bcc626d1fb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -65,20 +65,22 @@ def __init__(self, endpoint, credential, **kwargs): def get_acr_access_token(self, challenge): # type: (str) -> str parsed_challenge = self._parse_challenge(challenge) - refresh_token = self.exchange_aad_token_for_refresh_token(**parsed_challenge) - return self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) + refresh_token = self.exchange_aad_token_for_refresh_token(service=parsed_challenge["service"]) + return self.exchange_refresh_token_for_access_token( + refresh_token, service=parsed_challenge["service"], scope=parsed_challenge["scope"] + ) - def exchange_aad_token_for_refresh_token(self, service=None, **kwargs): + def exchange_aad_token_for_refresh_token(self, service=None): # type: (str, Dict[str, Any]) -> str refresh_token = self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( - service=service, access_token=self._credential.get_token(self._credential_scopes).token, **kwargs + service=service, access_token=self._credential.get_token(self._credential_scopes).token ) return refresh_token.refresh_token - def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): + def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None): # type: (str, str, str) -> str access_token = self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( - service=service, scope=scope, refresh_token=refresh_token, **kwargs + service=service, scope=scope, refresh_token=refresh_token ) return access_token.access_token diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 7933880bcfe8..ac4584ded375 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -30,6 +30,11 @@ def __init__( self.repository = repository super(ContainerRepositoryClient, self).__init__(endpoint=self._endpoint, credential=credential, **kwargs) + async def _get_digest_from_tag(self, tag): + # type: (str) -> str + tag_props = await self.get_tag_properties(tag) + return tag_props.digest + async def delete(self, **kwargs): # type: (...) -> None """Delete a repository @@ -61,13 +66,6 @@ def delete_tag(self, tag): """ raise NotImplementedError("Has not been implemented") - def get_digest_from_tag(self, tag): - # type: (str) -> str - async for t in self.list_tags(): - if t.name == tag: - return t.digest - raise ValueError("Could not find a digest for tag {}".format(tag)) - async def get_properties(self): # type: (...) -> RepositoryProperties """Get the properties of a repository @@ -91,7 +89,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): """ # GET '/acr/v1/{name}/_manifests/{digest}' if self._is_tag(tag_or_digest): - tag_or_digest = self.get_digest_from_tag(tag_or_digest) + tag_or_digest = self._get_digest_from_tag(tag_or_digest) return RegistryArtifactProperties._from_generated( # pylint: disable=protected-access self._client.container_registry_repository.get_registry_artifact_properties( @@ -189,7 +187,7 @@ async def set_tag_properties(self, tag_or_digest, permissions): :raises: None """ if self._is_tag(tag_or_digest): - tag_or_digest = self.get_digest_from_tag(tag_or_digest) + tag_or_digest = self._get_digest_from_tag(tag_or_digest) await self._client.container_registry_repository.update_manifest_attributes( self.repository, tag_or_digest, value=permissions.to_generated() diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py index f1ffb0e1d738..1c9e8cb3aa68 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py @@ -66,21 +66,23 @@ def __init__(self, endpoint, credential, **kwargs): async def get_acr_access_token(self, challenge): # type: (str) -> str parsed_challenge = self._parse_challenge(challenge) - refresh_token = await self.exchange_aad_token_for_refresh_token(**parsed_challenge) - return await self.exchange_refresh_token_for_access_token(refresh_token, **parsed_challenge) + refresh_token = await self.exchange_aad_token_for_refresh_token(service=parsed_challenge["service"]) + return await self.exchange_refresh_token_for_access_token( + refresh_token, service=parsed_challenge["service"], scope=parsed_challenge["scope"] + ) - async def exchange_aad_token_for_refresh_token(self, service=None, **kwargs): + async def exchange_aad_token_for_refresh_token(self, service=None): # type: (str, Dict[str, Any]) -> str token = await self._credential.get_token(self._credential_scopes) refresh_token = await self._client.authentication.exchange_aad_access_token_for_acr_refresh_token( - service, token.token, **kwargs + service, token.token ) return refresh_token.refresh_token - async def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None, **kwargs): + async def exchange_refresh_token_for_access_token(self, refresh_token, service=None, scope=None): # type: (str, str, str, Dict[str, Any]) -> str access_token = await self._client.authentication.exchange_acr_refresh_token_for_acr_access_token( - service, scope, refresh_token, **kwargs + service, scope, refresh_token ) return access_token.access_token diff --git a/sdk/containerregistry/azure-containerregistry/tests/conftest.py b/sdk/containerregistry/azure-containerregistry/tests/conftest.py new file mode 100644 index 000000000000..fa149c11d410 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/conftest.py @@ -0,0 +1,13 @@ +# coding: utf-8 +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +import sys + +# Ignore async tests for Python < 3.5 +collect_ignore_glob = [] +if sys.version_info < (3, 5): + collect_ignore_glob.append("*_async.py") \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml index d9aeffa98401..cbf8e91bd9ae 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml @@ -11,7 +11,7 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest response: body: string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:13 GMT + - Fri, 26 Mar 2021 15:20:11 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:15 GMT + - Fri, 26 Mar 2021 15:20:12 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:15 GMT + - Fri, 26 Mar 2021 15:20:12 GMT server: - openresty strict-transport-security: @@ -129,10 +129,10 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '722' + - '380' content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:15 GMT + - Fri, 26 Mar 2021 15:20:13 GMT docker-distribution-api-version: - registry/2.0 server: @@ -193,7 +193,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:16 GMT + - Fri, 26 Mar 2021 15:20:13 GMT docker-distribution-api-version: - registry/2.0 server: @@ -233,7 +233,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:16 GMT + - Fri, 26 Mar 2021 15:20:13 GMT server: - openresty strict-transport-security: @@ -269,7 +269,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:16 GMT + - Fri, 26 Mar 2021 15:20:13 GMT server: - openresty strict-transport-security: @@ -312,7 +312,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:16 GMT + - Fri, 26 Mar 2021 15:20:14 GMT docker-distribution-api-version: - registry/2.0 server: From 451a186e8c08854b18d14c5b0cd6e71f0be8ddc9 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 11:43:38 -0400 Subject: [PATCH 69/86] renaming the async test file --- .../async_tests/test_container_registry.py | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py deleted file mode 100644 index 6ede04115062..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry.py +++ /dev/null @@ -1,66 +0,0 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -import functools -import os -import pytest -import six - -from devtools_testutils import AzureTestCase, PowerShellPreparer - -from azure.containerregistry import ( - DeletedRepositoryResult, - RepositoryProperties, -) -from azure.containerregistry.aio import ContainerRegistryClient, ContainerRepositoryClient -from azure.core.exceptions import ResourceNotFoundError -from azure.core.paging import ItemPaged -from azure.identity.aio import DefaultAzureCredential - -from .asynctestcase import AsyncContainerRegistryTestClass - - -acr_preparer = functools.partial( - PowerShellPreparer, - "containerregistry", - containerregistry_baseurl="fake_url.azurecr.io", -) - - -class TestContainerRegistryClient(AsyncContainerRegistryTestClass): - - @acr_preparer() - async def test_list_repositories(self, containerregistry_baseurl): - client = self.create_registry_client(containerregistry_baseurl) - - repositories = client.list_repositories() - - count = 0 - prev = None - async for repo in client.list_repositories(): - count += 1 - assert isinstance(repo, six.string_types) - assert prev != repo - prev = repo - - assert count > 0 - - @pytest.mark.skip("Don't want to delete for now") - @acr_preparer() - def test_delete_repository(self, containerregistry_baseurl): - client = self.create_registry_client(containerregistry_baseurl) - - deleted_result = client.delete_repository("debian") - - assert isinstance(deleted_result, DeletedRepositoryResult) - assert len(deleted_result.deleted_registry_artifact_digests) == 1 - assert len(deleted_result.deleted_tags) == 1 - - @acr_preparer() - async def test_delete_repository_does_not_exist(self, containerregistry_baseurl): - client = self.create_registry_client(containerregistry_baseurl) - - with pytest.raises(ResourceNotFoundError): - deleted_result = await client.delete_repository("not_real_repo") From 23caed4839afe8fc1f8a99983d9b8b3d28269f5c Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 11:50:12 -0400 Subject: [PATCH 70/86] fixing async tests --- .../azure/containerregistry/__init__.py | 1 - .../azure/containerregistry/aio/__init__.py | 8 ++ ...test_delete_repository_does_not_exist.yaml | 114 ------------------ ...ainer_registry.test_list_repositories.yaml | 113 ----------------- 4 files changed, 8 insertions(+), 228 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 90683b53dba9..6c90e04b040d 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -23,7 +23,6 @@ __version__ = VERSION __all__ = [ - "ACRExchangeClient", "ContainerRegistryClient", "ContainerRepositoryClient", "ContentPermissions", diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py index 75d8c6e33a3f..7ea2cd7e2883 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/__init__.py @@ -1,3 +1,11 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + from ._async_container_registry_client import ContainerRegistryClient from ._async_container_repository_client import ContainerRepositoryClient diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml deleted file mode 100644 index 3d228017f69a..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_delete_repository_does_not_exist.yaml +++ /dev/null @@ -1,114 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE - uri: https://fake_url.azurecr.io/acr/v1/not_real_repo - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '209' - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:40 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" - x-content-type-options: nosniff - status: - code: 401 - message: Unauthorized - url: https://seankane.azurecr.io/acr/v1/not_real_repo -- request: - body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3MDIzMTksIm5iZiI6MTYxNjcwMjMxOSwiZXhwIjoxNjE2Nzg5MDE5LCJhaW8iOiJFMlpnWURBMkxtMCtHYW5PVnp6YjhQM3BQUlBlQVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiYzhkdjhUOG9KVS1YUGg0RDlXb3BBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.llZmQNVaGoLRLxhBgVpWwP_iAmWNPSMyOjA2f5xUudiWiB1v8SN7grk7DsS9P4TXnJLpQtGYvpek_QZZav7oflTlLuvhpUILKQaSqJj5ons5jmGneLe-T0Dx66SPRRCGL8MgPRcZFxDqL17rcXHcbQR26YLjrCA9JoraTPdhi17eo112N9UPgpZASOjceGIrtg5jgNDx-r02eacIz4rWNqrHIOT8cikZ7FwD3-N4I1yE6ry5VO5_97KxMy_LkQYMz_Huq2U7VRjEUIyjk1xw6_UjLOnfKDtRsWsYlRSCrph24IVvLhyOqqpkPhuVmvfuzr1vHl1ZetwfWZPC5AETvw - grant_type: access_token - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:41 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/exchange -- request: - body: - grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJiMTUyNDFlMy1mOGUyLTQ5ZDUtYWRiNy1lOGMyZTM3OTZlM2MiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3MDE3MjEsImV4cCI6MTYxNjcxMzQyMSwiaWF0IjoxNjE2NzAxNzIxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.IZ02pQqPFVvpI99e-fdyIl3wF_6PV0dKF1wIa1EqEWbwsa9RRUZ_7R5XKyfk5b30b4a096qXBCt9e8F1j7PnnsRSHtMjd19PxxvDxxpzwuFBfXH-BuyMXfb4p_bqR_Lpa1FK0vmYhrbWd8i2Fz_dxJe-yr6cSpBHN1dA7YINxIbfovfW-JXSc5i-uas2dWXcdBHoOhfs_Q88uSaFu32it-H8G9PgVQUf5R7op3kAvBDIizgydvIgBNNhBXpq5MP17hW74k725Ww7ebkF27Qq47ZdOnImb7dN77RD882w1-bsGWWsWulr-mvHsKaLWW8X38hshg_TccU7g-vp1N3r_Q - scope: repository:not_real_repo:delete - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:41 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/token -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE - uri: https://fake_url.azurecr.io/acr/v1/not_real_repo - response: - body: - string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known - to registry","detail":{"name":"not_real_repo"}}]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '121' - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:41 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - status: - code: 404 - message: Not Found - url: https://seankane.azurecr.io/acr/v1/not_real_repo -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml deleted file mode 100644 index b59264c49b73..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry.test_list_repositories.yaml +++ /dev/null @@ -1,113 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '196' - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:42 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" - x-content-type-options: nosniff - status: - code: 401 - message: Unauthorized - url: https://seankane.azurecr.io/acr/v1/_catalog -- request: - body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3MDIzMjIsIm5iZiI6MTYxNjcwMjMyMiwiZXhwIjoxNjE2Nzg5MDIyLCJhaW8iOiJFMlpnWURpbUxwSDBNK3lBOTk2ZzNtZlRReVg3QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibktzak1aYVBtRUdIMGJzT0Y0OFZBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.dBQ2ttHP5V0CmkwwzPvOOqowj9ZDj5gOjewhu1gUkxC9NOMoWuZ-trSkvwLV4yLHq-LIjCTSVp9Ac6viRzI-lU0TfV7Tst5_YxzJWs7X8Nk7jOD5B_1QOdEG-9oTI6myeGyA64UgiAEoFgAzz-0ZBQ7_GIPp03inoWWSvNqyn3DhLpqVSzcO72F4tMVMjvzQStpfcT3SEDM3PPhxteYhEsmbnsku8N_kIREnndeLbAiMlkX4Ht1em0vZ9WO_Ja6Mo6ChbJsDS_xzb9my8LWpnAtZwQFqvC6RaFSD5zdhzZ5JobXZ27DmDMMI1QuQYck1zMdQapeTH8meIgj_4YhWqw - grant_type: access_token - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:43 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/exchange -- request: - body: - grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIzMGJhYTgzOC1lMjUyLTQwMDItOTYzMy0zNWI5YzM2MjEyNjEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3MDE3MjMsImV4cCI6MTYxNjcxMzQyMywiaWF0IjoxNjE2NzAxNzIzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.T0_ckQSEkxsL0mBlw1APIHDD5ZX6cuQrPuzgg0CzMBur1pO7eH7J1BV3wfqBnFLGVBudP3gIEg9FRbwlvae_vQKm5Jqu23shLlqOBT9gq4zS8ynkNq28O1eRMJtVx5gSUKqVKg52gvI56xObd8Jk3Y1e0Y36d8OwJsHrMXciwyQjODaolTn40MvMKzKJFEjN8yaWpw6ihtYast75rAIFe_nqdMyzL4WBXc_koxgB7iCxwXHFNpUFi4rI5mElYDtSPkXAp9yzQbBh2lykOorLb6wrq1Rv6vBVly5byjGOMPcH_0SErwqHn0wE3tH8_19eXy_Oq3m77dWc2_FuE2qpaA - scope: registry:catalog:* - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:43 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/token -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '125' - content-type: application/json; charset=utf-8 - date: Thu, 25 Mar 2021 20:03:43 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/acr/v1/_catalog -version: 1 From f4799e55a93a2a654bd89791694e5630d06edc02 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 12:16:51 -0400 Subject: [PATCH 71/86] more fixes --- .../azure-containerregistry/MANIFEST.in | 1 - ...test_delete_repository_does_not_exist.yaml | 114 ++++++++++++++++++ ...registry_async.test_list_repositories.yaml | 113 +++++++++++++++++ .../test_container_registry_async.py | 66 ++++++++++ 4 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_list_repositories.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry_async.py diff --git a/sdk/containerregistry/azure-containerregistry/MANIFEST.in b/sdk/containerregistry/azure-containerregistry/MANIFEST.in index 81d3dcd1770b..caca8d1ac56e 100644 --- a/sdk/containerregistry/azure-containerregistry/MANIFEST.in +++ b/sdk/containerregistry/azure-containerregistry/MANIFEST.in @@ -1,5 +1,4 @@ include *.md -include LICENSE.txt include azure/__init__.py recursive-include tests *.py recursive-include samples *.py *.md \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml new file mode 100644 index 000000000000..55da262fd8db --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml @@ -0,0 +1,114 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '209' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:30 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/not_real_repo +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzM0MDksIm5iZiI6MTYxNjc3MzQwOSwiZXhwIjoxNjE2ODYwMTA5LCJhaW8iOiJFMlpnWUpETzU5UHdZWHd3aTNucGpUelZLdWxzQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRWtPSmtQZmNnVS1mVkxXLTRWNFdBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.aUsJv4k_2mmllwISeomhPLr-aFm5Pg6x_jjFohvdNUPnMl92DDnEpxXGFK5oAABOEROiIZMzGNJwt075jJbn3oiW0hKq8X4Whu6V3i4C6LiMtfmUyUaPmxYUjbLoyVAnFemiYft-_FoBmtxEqri7GuiJYB4AjgljlG0UBIHzzPu851_w65IUDpu7gNkUH6KA-TjZZJk6twEpglB7z5na7gEE0jDRRTY1rHaLPGrgbAFD51w3489U_Wy4hoHgJhXDnWpV2Dqlb_QToF1R77ToJKl_VUNlAWDe2A-oQS8wo1UaMwI8ZsvJpG0N_O7gw7EdLExUZyapPpWvHM5ek_CYwQ + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:31 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwOGRjOTJhMi1jOWNhLTQ5YjMtODVkMS1kYjA5M2EwNzg0ZGYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3NzI4MTEsImV4cCI6MTYxNjc4NDUxMSwiaWF0IjoxNjE2NzcyODExLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.BMpSaeTUWY5MZmobUx8cjw4OV3_ZMfCMVm_c3RCHD5erzrWJKti1Gkc_QceCE4LGPkIFg8WQFzBGPvVZbtFgTb8g6fFOaBjiZ64TfWr77cDnaZwcsdhcGAzifKfueXKj-pLEf4U0fRYjXFYGak_SZrfAcFLImTEnO4WhbdL72Em6w1YJGUQhcNJD07WdIJmbd3FmiLIaKPwr8zKadTio_EcQc8W88KcOxTTbOW0efhXxhdatlJnUdMCW7u-CXlYFldMQSaSGD_zwggaXwW3b-jE3FuihSOGLsM_KkKf3gpF8gC0U-KGnvu9lUCkcLH5W_l4MuhJJIr47oHUwGx9fgQ + scope: repository:not_real_repo:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:31 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"not_real_repo"}}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '121' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:31 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 404 + message: Not Found + url: https://seankane.azurecr.io/acr/v1/not_real_repo +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_list_repositories.yaml new file mode 100644 index 000000000000..713c1eaefa0a --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_list_repositories.yaml @@ -0,0 +1,113 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '196' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:32 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/_catalog +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzM0MTIsIm5iZiI6MTYxNjc3MzQxMiwiZXhwIjoxNjE2ODYwMTEyLCJhaW8iOiJFMlpnWUtpL2tPUjBXU3Z5OE8waXNSQmo0L3hlQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiU1luMWJydnhZVUN2NEV6NnhzTmxBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.R-4xM3SmIMqJ0F7RhVc_hus2aAbQNXDARGq6SjGYx3hTNkfYszokd2f2zErLtFgTavwRVJW4IU4EC7SXhFdDr23HOIzrgiUxP7lVydgqIsrcMNlitrN4wO9SXX0VFaGq15-84bBRI45DWVbZYQzXROpK-Cu7wB18D4xYD8Oy-JHJWjdgGh-a3NM8cJ_i-E6oKVU9jJP81BBsuWT9ThQ-FQpjsTh_Ry8MknpN6sI3Cfi_Hej2Zg4wTMb9QcIX_dVNsL-xnctNaytTyW0U17nkOXVUXZn_mZYJ7L6YakY-xN7pr8B83Q2rMsVLv8Kjj31PB01RZAUc_zhjJbSoDFaGhQ + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:33 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMjNmNzFmMC02MDI5LTRkYWYtOTEwZS04NjU1OWQzYzFlZWMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3NzI4MTMsImV4cCI6MTYxNjc4NDUxMywiaWF0IjoxNjE2NzcyODEzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.V6y0HXtyD3WKNv5HB1bTIxc2F7UOwYiqebm3IOTvr66T-g53vDRjDG_xvHg-8YNM2FJ_oowg6FG1tm76HWHjP99DnYmGHqd41GJU4TumpWAc2P030HwKLlJE8cwt6wpqcvz57IEZl5bRiwq9y6EOASwc57coS6eGAVLlVSe5HoHO1tOVKRvWg0HWNPs6cStLB2i-JD5cxAusHpwJz_UfBpKJJABMEVYfpwdb07QbyFGrJPwlIeuuB5eMmVIE-Fiqq3XbOhMTNFT-d-3aJBEVjX2f4jtqcUL8w71oY0Ugu7akYrx8MT61I6bGW9SBOB827zw9F2l-9XMGT3ngjqznPA + scope: registry:catalog:* + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:33 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '125' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 15:48:33 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/_catalog +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry_async.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry_async.py new file mode 100644 index 000000000000..6ede04115062 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry_async.py @@ -0,0 +1,66 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools +import os +import pytest +import six + +from devtools_testutils import AzureTestCase, PowerShellPreparer + +from azure.containerregistry import ( + DeletedRepositoryResult, + RepositoryProperties, +) +from azure.containerregistry.aio import ContainerRegistryClient, ContainerRepositoryClient +from azure.core.exceptions import ResourceNotFoundError +from azure.core.paging import ItemPaged +from azure.identity.aio import DefaultAzureCredential + +from .asynctestcase import AsyncContainerRegistryTestClass + + +acr_preparer = functools.partial( + PowerShellPreparer, + "containerregistry", + containerregistry_baseurl="fake_url.azurecr.io", +) + + +class TestContainerRegistryClient(AsyncContainerRegistryTestClass): + + @acr_preparer() + async def test_list_repositories(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + repositories = client.list_repositories() + + count = 0 + prev = None + async for repo in client.list_repositories(): + count += 1 + assert isinstance(repo, six.string_types) + assert prev != repo + prev = repo + + assert count > 0 + + @pytest.mark.skip("Don't want to delete for now") + @acr_preparer() + def test_delete_repository(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + deleted_result = client.delete_repository("debian") + + assert isinstance(deleted_result, DeletedRepositoryResult) + assert len(deleted_result.deleted_registry_artifact_digests) == 1 + assert len(deleted_result.deleted_tags) == 1 + + @acr_preparer() + async def test_delete_repository_does_not_exist(self, containerregistry_baseurl): + client = self.create_registry_client(containerregistry_baseurl) + + with pytest.raises(ResourceNotFoundError): + deleted_result = await client.delete_repository("not_real_repo") From 35df07712308858f2749ef394561b3bfabe07042 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 13:28:19 -0400 Subject: [PATCH 72/86] removing async tests folder --- .../azure-containerregistry/tests/__init__.py | 0 .../tests/async_tests/__init__.py | 0 .../tests/{async_tests => }/asynctestcase.py | 2 +- ..._async.test_delete_repository_does_not_exist.yaml | 12 ++++++------ ...tainer_registry_async.test_list_repositories.yaml | 12 ++++++------ .../test_container_registry_async.py | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/__init__.py delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py rename sdk/containerregistry/azure-containerregistry/tests/{async_tests => }/asynctestcase.py (97%) rename sdk/containerregistry/azure-containerregistry/tests/{async_tests => }/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml (77%) rename sdk/containerregistry/azure-containerregistry/tests/{async_tests => }/recordings/test_container_registry_async.test_list_repositories.yaml (77%) rename sdk/containerregistry/azure-containerregistry/tests/{async_tests => }/test_container_registry_async.py (97%) diff --git a/sdk/containerregistry/azure-containerregistry/tests/__init__.py b/sdk/containerregistry/azure-containerregistry/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py b/sdk/containerregistry/azure-containerregistry/tests/async_tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/asynctestcase.py b/sdk/containerregistry/azure-containerregistry/tests/asynctestcase.py similarity index 97% rename from sdk/containerregistry/azure-containerregistry/tests/async_tests/asynctestcase.py rename to sdk/containerregistry/azure-containerregistry/tests/asynctestcase.py index 48c357b49353..fe7b14c2bdae 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/asynctestcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/asynctestcase.py @@ -25,7 +25,7 @@ from azure_devtools.scenario_tests import RecordingProcessor from devtools_testutils import AzureTestCase -from ..testcase import ContainerRegistryTestClass +from testcase import ContainerRegistryTestClass class AsyncFakeTokenCredential(object): diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml similarity index 77% rename from sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml rename to sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml index 55da262fd8db..aae751479a02 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:30 GMT + date: Fri, 26 Mar 2021 17:28:06 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/not_real_repo - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzM0MDksIm5iZiI6MTYxNjc3MzQwOSwiZXhwIjoxNjE2ODYwMTA5LCJhaW8iOiJFMlpnWUpETzU5UHdZWHd3aTNucGpUelZLdWxzQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiRWtPSmtQZmNnVS1mVkxXLTRWNFdBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.aUsJv4k_2mmllwISeomhPLr-aFm5Pg6x_jjFohvdNUPnMl92DDnEpxXGFK5oAABOEROiIZMzGNJwt075jJbn3oiW0hKq8X4Whu6V3i4C6LiMtfmUyUaPmxYUjbLoyVAnFemiYft-_FoBmtxEqri7GuiJYB4AjgljlG0UBIHzzPu851_w65IUDpu7gNkUH6KA-TjZZJk6twEpglB7z5na7gEE0jDRRTY1rHaLPGrgbAFD51w3489U_Wy4hoHgJhXDnWpV2Dqlb_QToF1R77ToJKl_VUNlAWDe2A-oQS8wo1UaMwI8ZsvJpG0N_O7gw7EdLExUZyapPpWvHM5ek_CYwQ + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzkzODUsIm5iZiI6MTYxNjc3OTM4NSwiZXhwIjoxNjE2ODY2MDg1LCJhaW8iOiJFMlpnWUdBTFdsSHptbG02OTl3TkEwWHJQWnY4QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSE5ZYzIyV0NSMFNWM2FHSkQ3WmtBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.Kwyr899j8sp9_O_zfiqcAwr5Kj9uoznVPusQ2aFQG55RkJfgyTE3Z9YU1EHSZmhg50X5NQOa8pw8IUJwtUzriFVOxfEsQ8vS9zWvFwae-RZOGbfHpH0OdRkuuu-nyAgk9tYXuebhwxNi_f6Z0GLi93hmpYif0IPaMPCDwdXQ3APLFiUQxbxJS5pGMPY4Uw2BmJkpe8zalff_bzFiUpe_rhb_ztaRQa1TGntHh-XSchNG9rXhAUqNrNod0LckOJBlV7MF_DE_uy3mYY14OsmyGoZS1H5Y1wenaeAP-1v5BdLYwXAN_Br21WxNqR7eYlvEh-LJcD35N54nHxhLNBQRBA grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:31 GMT + date: Fri, 26 Mar 2021 17:28:07 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIwOGRjOTJhMi1jOWNhLTQ5YjMtODVkMS1kYjA5M2EwNzg0ZGYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3NzI4MTEsImV4cCI6MTYxNjc4NDUxMSwiaWF0IjoxNjE2NzcyODExLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.BMpSaeTUWY5MZmobUx8cjw4OV3_ZMfCMVm_c3RCHD5erzrWJKti1Gkc_QceCE4LGPkIFg8WQFzBGPvVZbtFgTb8g6fFOaBjiZ64TfWr77cDnaZwcsdhcGAzifKfueXKj-pLEf4U0fRYjXFYGak_SZrfAcFLImTEnO4WhbdL72Em6w1YJGUQhcNJD07WdIJmbd3FmiLIaKPwr8zKadTio_EcQc8W88KcOxTTbOW0efhXxhdatlJnUdMCW7u-CXlYFldMQSaSGD_zwggaXwW3b-jE3FuihSOGLsM_KkKf3gpF8gC0U-KGnvu9lUCkcLH5W_l4MuhJJIr47oHUwGx9fgQ + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4NjE1ZWY5Mi0zMDc5LTQzODQtODIyOS05ZTlhNWNkZTJlYjAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3Nzg3ODcsImV4cCI6MTYxNjc5MDQ4NywiaWF0IjoxNjE2Nzc4Nzg3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gwqXUWOtzspvn5uJPhC-vTg7i7878tPgZ7cQAq5fj6d-6GpSt10WwF-gYBkaFY_fjsxgg6bE842Q06pDa7SmNjpIPNRONGxGpGZNBvBwYq_B1QzY9FAUOckaPwxN4MFSG8jiUEGCsXbQTLqNs9dk9TXS2KrtejYqYjCuNmnXemFdDXkf59SWjdUipY43RpVpvMd7Gh0hag9D6IfbbkcLGLd5-3_MaqKEMJ8l8kchS1HMj8l5SelgHFEzvLH199O5jD6mIVPAR2PCQjgUDz8loqHl-zpyeVuwxqE_U3u4PcwvUTXO-C-RLErktTTMDozV9bWajfmCCUTsKmeTH006dA scope: repository:not_real_repo:delete service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:31 GMT + date: Fri, 26 Mar 2021 17:28:07 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -102,7 +102,7 @@ interactions: connection: keep-alive content-length: '121' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:31 GMT + date: Fri, 26 Mar 2021 17:28:07 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml similarity index 77% rename from sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_list_repositories.yaml rename to sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml index 713c1eaefa0a..f4becfd3a810 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/recordings/test_container_registry_async.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '196' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:32 GMT + date: Fri, 26 Mar 2021 17:28:08 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/_catalog - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzM0MTIsIm5iZiI6MTYxNjc3MzQxMiwiZXhwIjoxNjE2ODYwMTEyLCJhaW8iOiJFMlpnWUtpL2tPUjBXU3Z5OE8waXNSQmo0L3hlQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiU1luMWJydnhZVUN2NEV6NnhzTmxBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.R-4xM3SmIMqJ0F7RhVc_hus2aAbQNXDARGq6SjGYx3hTNkfYszokd2f2zErLtFgTavwRVJW4IU4EC7SXhFdDr23HOIzrgiUxP7lVydgqIsrcMNlitrN4wO9SXX0VFaGq15-84bBRI45DWVbZYQzXROpK-Cu7wB18D4xYD8Oy-JHJWjdgGh-a3NM8cJ_i-E6oKVU9jJP81BBsuWT9ThQ-FQpjsTh_Ry8MknpN6sI3Cfi_Hej2Zg4wTMb9QcIX_dVNsL-xnctNaytTyW0U17nkOXVUXZn_mZYJ7L6YakY-xN7pr8B83Q2rMsVLv8Kjj31PB01RZAUc_zhjJbSoDFaGhQ + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzkzODcsIm5iZiI6MTYxNjc3OTM4NywiZXhwIjoxNjE2ODY2MDg3LCJhaW8iOiJFMlpnWUtoWG1lZ2NabTZtY0NYSExmL1ZwdU9CQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiMGFlQ0hDMTVqVU9fZXFHZVVBT1dBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.mb-AISCQA6alM9VQyNP24rpcZtoGLdouFrcq1rUI7LBMginjvRBcICDb5lRNm8sGIuqAUklL3G0fGY2Q9pp9Shmx-LRbAvlW9uBm7gul3HbN-H2M6n8aJov3K60hM2E_eDK2-E0ikSXyx2r2_Nhw7qwuDGqiDMTl8aL7x35bMjKFTtj0qf3dKpGnGRNMJ_iS6fr2wmi-aXjshpyGx3EpL4F5BkXPp9goWnb4NwlGeC4sgRsZ_MH3et7b7DrmkfuvJEoGOyak78XKf3OuPFA4JVOHclvpx1K_i-2rlyW8WmmfsotIHV9jpe-FYbeg8XLTwqipUPfPtEkS77Bo-xnE_Q grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:33 GMT + date: Fri, 26 Mar 2021 17:28:09 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMjNmNzFmMC02MDI5LTRkYWYtOTEwZS04NjU1OWQzYzFlZWMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3NzI4MTMsImV4cCI6MTYxNjc4NDUxMywiaWF0IjoxNjE2NzcyODEzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.V6y0HXtyD3WKNv5HB1bTIxc2F7UOwYiqebm3IOTvr66T-g53vDRjDG_xvHg-8YNM2FJ_oowg6FG1tm76HWHjP99DnYmGHqd41GJU4TumpWAc2P030HwKLlJE8cwt6wpqcvz57IEZl5bRiwq9y6EOASwc57coS6eGAVLlVSe5HoHO1tOVKRvWg0HWNPs6cStLB2i-JD5cxAusHpwJz_UfBpKJJABMEVYfpwdb07QbyFGrJPwlIeuuB5eMmVIE-Fiqq3XbOhMTNFT-d-3aJBEVjX2f4jtqcUL8w71oY0Ugu7akYrx8MT61I6bGW9SBOB827zw9F2l-9XMGT3ngjqznPA + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjMzE2YjQxNS04ZTVkLTQ2ZmQtYmIzNS0xMGYyYzE1NmYzMjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3Nzg3ODksImV4cCI6MTYxNjc5MDQ4OSwiaWF0IjoxNjE2Nzc4Nzg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.XpiPCB79B28LGRfh3khp1pUTJMsaJr2h8Cqr3pqkX9FWzjQrrmf6qxzOU3lZ-0s7oX4WFwXz8tDmS7HK1NfkuA3rc_TRYGMOprwuoWjJQ2HybutROc1DhO4cI_z7nxFcJACTtLo15wDKYizQMmMdAZlyHII2b3IzzpI6vOHufPbyldfJtFZjWIZnXqxjh1Uvbywb7vwVQ7GjFJ-w1iSU8aE547BpFiRyzKBi9dKf5Wr5CpPw-M7Jx6sJ57wXbybXa3W_mjoh3A2CBs4KwI9GIRdcQIgD2biwLp7pXfhsxOXyeBdOVzustaZWXyGGojcR6MkzV-wPRdN5mB9OKGOM-A scope: registry:catalog:* service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:33 GMT + date: Fri, 26 Mar 2021 17:28:09 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -101,7 +101,7 @@ interactions: connection: keep-alive content-length: '125' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 15:48:33 GMT + date: Fri, 26 Mar 2021 17:28:09 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_async.py similarity index 97% rename from sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry_async.py rename to sdk/containerregistry/azure-containerregistry/tests/test_container_registry_async.py index 6ede04115062..4a9a3872b237 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/async_tests/test_container_registry_async.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_async.py @@ -19,7 +19,7 @@ from azure.core.paging import ItemPaged from azure.identity.aio import DefaultAzureCredential -from .asynctestcase import AsyncContainerRegistryTestClass +from asynctestcase import AsyncContainerRegistryTestClass acr_preparer = functools.partial( From f95947d1d0fdc04a6b984fc284ad1f7aaaf24060 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 15:20:58 -0400 Subject: [PATCH 73/86] addressing charles and anna's comments, thank you both --- .../azure-containerregistry/MANIFEST.in | 1 + .../azure/containerregistry/__init__.py | 1 - .../_authentication_policy.py | 16 +-- .../azure/containerregistry/_base_client.py | 4 - .../_container_repository_client.py | 29 ++--- .../containerregistry/_exchange_client.py | 35 +----- .../azure/containerregistry/_helpers.py | 41 ++++++ .../azure/containerregistry/_models.py | 2 +- .../aio/_async_container_registry_client.py | 9 +- .../aio/_async_container_repository_client.py | 21 ++-- .../aio/_async_exchange_client.py | 35 +----- ...test_delete_repository_does_not_exist.yaml | 12 +- ...registry_async.test_list_repositories.yaml | 12 +- ...egistry_client.test_list_repositories.yaml | 8 +- ...repository_client.test_get_attributes.yaml | 8 +- ...repository_client.test_get_properties.yaml | 8 +- ...test_get_registry_artifact_properties.yaml | 16 +-- ...tainer_repository_client.test_get_tag.yaml | 8 +- ...y_client.test_list_registry_artifacts.yaml | 8 +- ...iner_repository_client.test_list_tags.yaml | 8 +- ...tory_client.test_list_tags_descending.yaml | 8 +- ...y_client.test_set_manifest_properties.yaml | 24 ++-- ...sitory_client.test_set_tag_properties.yaml | 24 ++-- .../tests/test_container_registry_client.py | 2 +- .../tests/test_container_repository_client.py | 2 +- .../tests/test_exchange_client.py | 118 +++++++++--------- 26 files changed, 218 insertions(+), 242 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/MANIFEST.in b/sdk/containerregistry/azure-containerregistry/MANIFEST.in index caca8d1ac56e..456471044cf1 100644 --- a/sdk/containerregistry/azure-containerregistry/MANIFEST.in +++ b/sdk/containerregistry/azure-containerregistry/MANIFEST.in @@ -1,4 +1,5 @@ include *.md include azure/__init__.py +include LICENSE.txt recursive-include tests *.py recursive-include samples *.py *.md \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py index 6c90e04b040d..580f112f26b8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/__init__.py @@ -8,7 +8,6 @@ from ._container_registry_client import ContainerRegistryClient from ._container_repository_client import ContainerRepositoryClient -from ._exchange_client import ACRExchangeClient from ._models import ( ContentPermissions, DeletedRepositoryResult, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index 7cd038f9eaa2..be79e6d09f37 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -44,27 +44,17 @@ def __init__(self, credential, endpoint): super(ContainerRegistryChallengePolicy, self).__init__() self._scopes = "https://management.core.windows.net/.default" self._credential = credential - self._token = None # type: Optional[AccessToken] + self._token = None # type: Optional[str] self._exchange_client = ACRExchangeClient(endpoint, self._credential) - def _need_new_token(self): # pylint: disable=no-self-use - # type: () -> bool - return True - def on_request(self, request): # type: (PipelineRequest) -> None """Called before the policy sends a request. The base implementation authorizes the request with a bearer token. :param ~azure.core.pipeline.PipelineRequest request: the request """ - - if self._token is None or self._need_new_token(): - self._token = self._credential.get_token(self._scopes) - try: - self._token = self._token.token - except AttributeError: - pass - request.http_request.headers["Authorization"] = "Bearer " + self._token + # Future caching implementation will be included here + pass # pylint: disable=unnecessary-pass def send(self, request): # type: (PipelineRequest) -> PipelineResponse diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py index 2396763946ab..624bd2cb1a7c 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_base_client.py @@ -51,7 +51,3 @@ def close(self): Calling this method is unnecessary when using the client as a context manager. """ self._client.close() - - def _is_tag(self, tag_or_digest): # pylint: disable=no-self-use - tag = tag_or_digest.split(":") - return not (len(tag) == 2 and tag[0].startswith(u"sha")) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 2a801d05c182..41a23ae1d7b0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING from ._base_client import ContainerRegistryBaseClient +from ._helpers import _is_tag from ._models import RepositoryProperties, TagProperties, RegistryArtifactProperties if TYPE_CHECKING: @@ -49,7 +50,7 @@ def delete(self, **kwargs): """ self._client.container_registry.delete_repository(self.repository, **kwargs) - def delete_registry_artifact(self, digest): + def delete_registry_artifact(self, digest, **kwargs): # type: (str) -> None """Delete a registry artifact @@ -60,7 +61,7 @@ def delete_registry_artifact(self, digest): """ raise NotImplementedError("Has not been implemented") - def delete_tag(self, tag): + def delete_tag(self, tag, **kwargs): # type: (str) -> None """Delete a tag @@ -71,7 +72,7 @@ def delete_tag(self, tag): """ raise NotImplementedError("Has not been implemented") - def get_properties(self): + def get_properties(self, **kwargs): # type: (...) -> RepositoryProperties """Get the properties of a repository @@ -80,7 +81,7 @@ def get_properties(self): """ # GET '/acr/v1/{name}' return RepositoryProperties._from_generated( # pylint: disable=protected-access - self._client.container_registry_repository.get_properties(self.repository) + self._client.container_registry_repository.get_properties(self.repository, **kwargs) ) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): @@ -93,7 +94,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # GET '/acr/v1/{name}/_manifests/{digest}' - if self._is_tag(tag_or_digest): + if _is_tag(tag_or_digest): tag_or_digest = self._get_digest_from_tag(tag_or_digest) return RegistryArtifactProperties._from_generated( # pylint: disable=protected-access @@ -122,8 +123,8 @@ def list_registry_artifacts(self, **kwargs): :keyword last: Query parameter for the last item in the previous query :type last: str - :keyword n: Max number of items to be returned - :type n: int + :keyword page_size: Max number of items to be returned + :type page_size: int :keyword orderby: Order by query parameter :type orderby: :class:~azure.containerregistry.RegistryArtifactOrderBy :returns: ~azure.core.paging.ItemPaged[RegistryArtifactProperties] @@ -131,7 +132,7 @@ def list_registry_artifacts(self, **kwargs): """ # GET /acr/v1/{name}/_manifests last = kwargs.pop("last", None) - n = kwargs.pop("top", None) + n = kwargs.pop("page_size", None) orderby = kwargs.pop("order_by", None) return self._client.container_registry_repository.get_manifests( self.repository, @@ -157,14 +158,14 @@ def list_tags(self, **kwargs): return self._client.container_registry_repository.get_tags( self.repository, last=kwargs.pop("last", None), - n=kwargs.pop("top", None), + n=kwargs.pop("page_size", None), orderby=kwargs.pop("order_by", None), digest=kwargs.pop("digest", None), cls=lambda objs: [TagProperties._from_generated(o) for o in objs], # pylint: disable=protected-access **kwargs ) - def set_manifest_properties(self, digest, permissions): + def set_manifest_properties(self, digest, permissions, **kwargs): # type: (str, ContentPermissions) -> None """Set the properties for a manifest @@ -177,10 +178,10 @@ def set_manifest_properties(self, digest, permissions): """ self._client.container_registry_repository.update_manifest_attributes( - self.repository, digest, value=permissions.to_generated() + self.repository, digest, value=permissions._to_generated(), **kwargs # pylint: disable=protected-access ) - def set_tag_properties(self, tag_or_digest, permissions): + def set_tag_properties(self, tag_or_digest, permissions, **kwargs): # type: (str, ContentPermissions) -> None """Set the properties for a tag @@ -191,9 +192,9 @@ def set_tag_properties(self, tag_or_digest, permissions): :returns: None :raises: None """ - if self._is_tag(tag_or_digest): + if _is_tag(tag_or_digest): tag_or_digest = self._get_digest_from_tag(tag_or_digest) self._client.container_registry_repository.update_manifest_attributes( - self.repository, tag_or_digest, value=permissions.to_generated() + self.repository, tag_or_digest, value=permissions._to_generated(), **kwargs # pylint: disable=protected-access ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py index 26bcc626d1fb..bc306f9496c3 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_exchange_client.py @@ -9,6 +9,7 @@ from azure.core.pipeline.policies import SansIOHTTPPolicy from ._generated import ContainerRegistry +from ._helpers import _parse_challenge from ._user_agent import USER_AGENT if TYPE_CHECKING: @@ -48,7 +49,7 @@ class ACRExchangeClient(object): def __init__(self, endpoint, credential, **kwargs): # type: (str, TokenCredential, Dict[str, Any]) -> None - if not endpoint.startswith("https://"): + if not endpoint.startswith("https://") and not endpoint.startswith("http://"): endpoint = "https://" + endpoint self._endpoint = endpoint self._credential_scopes = "https://management.core.windows.net/.default" @@ -56,7 +57,7 @@ def __init__(self, endpoint, credential, **kwargs): credential=credential, url=endpoint, sdk_moniker=USER_AGENT, - authentication_policy=ExchangeClientAuthenticationPolicy(), + authentication_policy=SansIOHTTPPolicy(), credential_scopes=kwargs.pop("credential_scopes", self._credential_scopes), **kwargs ) @@ -64,7 +65,7 @@ def __init__(self, endpoint, credential, **kwargs): def get_acr_access_token(self, challenge): # type: (str) -> str - parsed_challenge = self._parse_challenge(challenge) + parsed_challenge = _parse_challenge(challenge) refresh_token = self.exchange_aad_token_for_refresh_token(service=parsed_challenge["service"]) return self.exchange_refresh_token_for_access_token( refresh_token, service=parsed_challenge["service"], scope=parsed_challenge["scope"] @@ -84,20 +85,6 @@ def exchange_refresh_token_for_access_token(self, refresh_token, service=None, s ) return access_token.access_token - def _parse_challenge(self, header): - # type: (str) -> Dict[str, Any] - """Parse challenge header into service and scope""" - if header.startswith(self.BEARER): - challenge_params = header[len(self.BEARER) + 1 :] - - matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) - self._clean(matches) - ret = {} - for i in range(0, len(matches), 2): - ret[matches[i]] = matches[i + 1] - - return ret - def __enter__(self): self._client.__enter__() return self @@ -111,17 +98,3 @@ def close(self): Calling this method is unnecessary when using the client as a context manager. """ self._client.close() - - def _clean(self, matches): # pylint: disable=no-self-use - # type: (List[str]) -> None - while True: - try: - matches.remove("") - except ValueError: - break - - while True: - try: - matches.remove(",") - except ValueError: - return diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py index 15227605df4f..e9e8b26973da 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_helpers.py @@ -3,3 +3,44 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import re + +BEARER = "Bearer" +AUTHENTICATION_CHALLENGE_PARAMS_PATTERN = re.compile('(?:(\\w+)="([^""]*)")+') + + +def _is_tag(tag_or_digest): + # type: (str) -> bool + tag = tag_or_digest.split(":") + return not (len(tag) == 2 and tag[0].startswith(u"sha")) + + +def _clean(matches): + # type: (List[str]) -> None + """This method removes empty strings and commas from the regex matching of the Challenge header""" + while True: + try: + matches.remove("") + except ValueError: + break + + while True: + try: + matches.remove(",") + except ValueError: + return + + +def _parse_challenge(header): + # type: (str) -> Dict[str, str] + """Parse challenge header into service and scope""" + if header.startswith(BEARER): + challenge_params = header[len(BEARER) + 1 :] + + matches = re.split(AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) + _clean(matches) + ret = {} + for i in range(0, len(matches), 2): + ret[matches[i]] = matches[i + 1] + + return ret diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index d752f18d8a88..44f679dcd544 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -31,7 +31,7 @@ def _from_generated(cls, generated): can_write=generated.can_write, ) - def to_generated(self): + def _to_generated(self): # type: () -> ContentProperties return ContentProperties( can_delete=self.can_delete, diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index b98236016b1b..d6e74dd13ca7 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -8,7 +8,7 @@ from azure.core.async_paging import AsyncItemPaged from ._async_base_client import ContainerRegistryBaseClient -from .._container_registry_client import ContainerRegistryClient as SyncContainerRegistryClient +from ._async_container_repository_client import ContainerRepositoryClient from .._models import RepositoryProperties, DeletedRepositoryResult if TYPE_CHECKING: @@ -39,8 +39,9 @@ async def delete_repository(self, repository: str, **kwargs: Dict[str, Any]) -> def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: return self._client.container_registry.get_repositories( - last=kwargs.pop("last", None), n=kwargs.pop("max", None), **kwargs + last=kwargs.pop("last", None), n=kwargs.pop("page_size", None), **kwargs ) - def get_repository_client(self, name: str, **kwargs) -> SyncContainerRegistryClient: - pass + def get_repository_client(self, name: str, **kwargs) -> ContainerRepositoryClient: + + return ContainerRepositoryClient(self._endpoint, name, self._credential, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index ac4584ded375..934cdd7f8790 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING from ._async_base_client import ContainerRegistryBaseClient +from .._helpers import _is_tag from .._models import ( RegistryArtifactProperties, RepositoryProperties, @@ -44,7 +45,7 @@ async def delete(self, **kwargs): """ await self._client.container_registry.delete_repository(self.repository, **kwargs) - def delete_registry_artifact(self, digest): + def delete_registry_artifact(self, digest, **kwargs): # type: (str) -> None """Delete a registry artifact @@ -55,7 +56,7 @@ def delete_registry_artifact(self, digest): """ raise NotImplementedError("Has not been implemented") - def delete_tag(self, tag): + def delete_tag(self, tag, **kwargs): # type: (str) -> None """Delete a tag @@ -66,7 +67,7 @@ def delete_tag(self, tag): """ raise NotImplementedError("Has not been implemented") - async def get_properties(self): + async def get_properties(self, **kwargs): # type: (...) -> RepositoryProperties """Get the properties of a repository @@ -75,7 +76,7 @@ async def get_properties(self): """ # GET '/acr/v1/{name}' return RepositoryProperties._from_generated( # pylint: disable=protected-access - await self._client.container_registry_repository.get_properties(self.repository) + await self._client.container_registry_repository.get_properties(self.repository, **kwargs) ) def get_registry_artifact_properties(self, tag_or_digest, **kwargs): @@ -88,7 +89,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ # GET '/acr/v1/{name}/_manifests/{digest}' - if self._is_tag(tag_or_digest): + if _is_tag(tag_or_digest): tag_or_digest = self._get_digest_from_tag(tag_or_digest) return RegistryArtifactProperties._from_generated( # pylint: disable=protected-access @@ -159,7 +160,7 @@ def list_tags(self, **kwargs): **kwargs ) - async def set_manifest_properties(self, digest, permissions): + async def set_manifest_properties(self, digest, permissions, **kwargs): # type: (str, ContentPermissions) -> None """Set the properties for a manifest @@ -172,10 +173,10 @@ async def set_manifest_properties(self, digest, permissions): """ await self._client.container_registry_repository.update_manifest_attributes( - self.repository, digest, value=permissions.to_generated() + self.repository, digest, value=permissions._to_generated(), **kwargs # pylint: disable=protected-access ) - async def set_tag_properties(self, tag_or_digest, permissions): + async def set_tag_properties(self, tag_or_digest, permissions, **kwargs): # type: (str, ContentPermissions) -> None """Set the properties for a tag @@ -186,9 +187,9 @@ async def set_tag_properties(self, tag_or_digest, permissions): :returns: None :raises: None """ - if self._is_tag(tag_or_digest): + if _is_tag(tag_or_digest): tag_or_digest = self._get_digest_from_tag(tag_or_digest) await self._client.container_registry_repository.update_manifest_attributes( - self.repository, tag_or_digest, value=permissions.to_generated() + self.repository, tag_or_digest, value=permissions._to_generated(), **kwargs # pylint: disable=protected-access ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py index 1c9e8cb3aa68..62fa2b430339 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_exchange_client.py @@ -9,6 +9,7 @@ from azure.core.pipeline.policies import SansIOHTTPPolicy from .._generated.aio import ContainerRegistry +from .._helpers import _parse_challenge from .._user_agent import USER_AGENT if TYPE_CHECKING: @@ -65,7 +66,7 @@ def __init__(self, endpoint, credential, **kwargs): async def get_acr_access_token(self, challenge): # type: (str) -> str - parsed_challenge = self._parse_challenge(challenge) + parsed_challenge = _parse_challenge(challenge) refresh_token = await self.exchange_aad_token_for_refresh_token(service=parsed_challenge["service"]) return await self.exchange_refresh_token_for_access_token( refresh_token, service=parsed_challenge["service"], scope=parsed_challenge["scope"] @@ -86,20 +87,6 @@ async def exchange_refresh_token_for_access_token(self, refresh_token, service=N ) return access_token.access_token - def _parse_challenge(self, header): - # type: (str) -> Dict[str, Any] - """Parse challenge header into service and scope""" - if header.startswith(self.BEARER): - challenge_params = header[len(self.BEARER) + 1 :] - - matches = re.split(self.AUTHENTICATION_CHALLENGE_PARAMS_PATTERN, challenge_params) - self._clean(matches) - ret = {} - for i in range(0, len(matches), 2): - ret[matches[i]] = matches[i + 1] - - return ret - async def __aenter__(self): self._client.__aenter__() return self @@ -107,23 +94,9 @@ async def __aenter__(self): async def __aexit__(self, *args): self._client.__aexit__(*args) - def close(self): + async def close(self): # type: () -> None """Close sockets opened by the client. Calling this method is unnecessary when using the client as a context manager. """ - self._client.close() - - def _clean(self, matches): # pylint: disable=no-self-use - # type: (List[str]) -> None - while True: - try: - matches.remove("") - except ValueError: - break - - while True: - try: - matches.remove(",") - except ValueError: - return + await self._client.close() diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml index aae751479a02..91808faa7197 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:06 GMT + date: Fri, 26 Mar 2021 19:11:56 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/not_real_repo - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzkzODUsIm5iZiI6MTYxNjc3OTM4NSwiZXhwIjoxNjE2ODY2MDg1LCJhaW8iOiJFMlpnWUdBTFdsSHptbG02OTl3TkEwWHJQWnY4QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSE5ZYzIyV0NSMFNWM2FHSkQ3WmtBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.Kwyr899j8sp9_O_zfiqcAwr5Kj9uoznVPusQ2aFQG55RkJfgyTE3Z9YU1EHSZmhg50X5NQOa8pw8IUJwtUzriFVOxfEsQ8vS9zWvFwae-RZOGbfHpH0OdRkuuu-nyAgk9tYXuebhwxNi_f6Z0GLi93hmpYif0IPaMPCDwdXQ3APLFiUQxbxJS5pGMPY4Uw2BmJkpe8zalff_bzFiUpe_rhb_ztaRQa1TGntHh-XSchNG9rXhAUqNrNod0LckOJBlV7MF_DE_uy3mYY14OsmyGoZS1H5Y1wenaeAP-1v5BdLYwXAN_Br21WxNqR7eYlvEh-LJcD35N54nHxhLNBQRBA + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3ODU2MTUsIm5iZiI6MTYxNjc4NTYxNSwiZXhwIjoxNjE2ODcyMzE1LCJhaW8iOiJFMlpnWUppeStHcmhwRi8ydXVJTlJZWVdENTMyQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoicG9FSktZMDg4VTZNaVlsWVVFeWFBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.l45ebp_h34EBB6Dl-xcL3CBf3Qa7x-Fv1-yN-LHDRnPKvlywGiyEG-Lmz8yZd0a7jjMQGzYsXHp5xNB6NYlwjV1GkIKoA6MP78pOCauntLbY_LOe-PcvQxt8quED6Hewr2BcyGqwgbCtOOL15MxWS5uPEKkIVRvbMxEpSt_lUSxUmiEclYge4GzZA9ZwldBe8zBlUBgaUXOVlkqa_q7QZm2ZQMdxRYTvmLVoxQ2NV54h-1dnsd-dBtic1ShhgRSs7gv_gLxZB4SDixD-oIYH3bqTXAYPsYhE-KWEewS3U8hCiFyGtn4iZbaVvxXFmVINzrn3TbUTMjDMAh7euY6iTQ grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:07 GMT + date: Fri, 26 Mar 2021 19:11:57 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI4NjE1ZWY5Mi0zMDc5LTQzODQtODIyOS05ZTlhNWNkZTJlYjAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3Nzg3ODcsImV4cCI6MTYxNjc5MDQ4NywiaWF0IjoxNjE2Nzc4Nzg3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gwqXUWOtzspvn5uJPhC-vTg7i7878tPgZ7cQAq5fj6d-6GpSt10WwF-gYBkaFY_fjsxgg6bE842Q06pDa7SmNjpIPNRONGxGpGZNBvBwYq_B1QzY9FAUOckaPwxN4MFSG8jiUEGCsXbQTLqNs9dk9TXS2KrtejYqYjCuNmnXemFdDXkf59SWjdUipY43RpVpvMd7Gh0hag9D6IfbbkcLGLd5-3_MaqKEMJ8l8kchS1HMj8l5SelgHFEzvLH199O5jD6mIVPAR2PCQjgUDz8loqHl-zpyeVuwxqE_U3u4PcwvUTXO-C-RLErktTTMDozV9bWajfmCCUTsKmeTH006dA + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2NjAyNGFlMi1hYzgwLTQzZDMtODY2ZS03NjFkMmRlMWZmYzMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3ODUwMTcsImV4cCI6MTYxNjc5NjcxNywiaWF0IjoxNjE2Nzg1MDE3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.bvjGjDZ8skSThXd1morPV-fPWml9CIx_7HGh2yGgY62fZPVhFoXCGoH05DI3QtMgM4yuZhcCrdsBKqAcDaSbJOOYHleIubAPrftybCF7DwuZ15i5xYZ4WO7faMAOzdQQOO03I5drY2qEK620C_p4XzCuE91dcrhJg3VIplo_6ddXIjM7FABXZzGEgBDZmO2gWdjNMfCJgvwFvJ0TD2guA6LCTNGQKn-FSC1LHFv7wkzOpUPhEhoj9QO3pzAglvbbGqDeWf8q5G5XcX7rbarN_JfVrkxKW5MaNijkqVrH7KDbmdbfGWW_AtLcwsIe965VQGx3-JasBvFjJYHigCtHuA scope: repository:not_real_repo:delete service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:07 GMT + date: Fri, 26 Mar 2021 19:11:57 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -102,7 +102,7 @@ interactions: connection: keep-alive content-length: '121' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:07 GMT + date: Fri, 26 Mar 2021 19:11:58 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml index f4becfd3a810..5e6bff2088ed 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '196' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:08 GMT + date: Fri, 26 Mar 2021 19:11:59 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/_catalog - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3NzkzODcsIm5iZiI6MTYxNjc3OTM4NywiZXhwIjoxNjE2ODY2MDg3LCJhaW8iOiJFMlpnWUtoWG1lZ2NabTZtY0NYSExmL1ZwdU9CQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiMGFlQ0hDMTVqVU9fZXFHZVVBT1dBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.mb-AISCQA6alM9VQyNP24rpcZtoGLdouFrcq1rUI7LBMginjvRBcICDb5lRNm8sGIuqAUklL3G0fGY2Q9pp9Shmx-LRbAvlW9uBm7gul3HbN-H2M6n8aJov3K60hM2E_eDK2-E0ikSXyx2r2_Nhw7qwuDGqiDMTl8aL7x35bMjKFTtj0qf3dKpGnGRNMJ_iS6fr2wmi-aXjshpyGx3EpL4F5BkXPp9goWnb4NwlGeC4sgRsZ_MH3et7b7DrmkfuvJEoGOyak78XKf3OuPFA4JVOHclvpx1K_i-2rlyW8WmmfsotIHV9jpe-FYbeg8XLTwqipUPfPtEkS77Bo-xnE_Q + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3ODU2MTgsIm5iZiI6MTYxNjc4NTYxOCwiZXhwIjoxNjE2ODcyMzE4LCJhaW8iOiJFMlpnWUdqbnVGZ2xuWDdtdGpKendSNWxZYVd2QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiVktCMGlIbFFLVWVGYjdpc2RJR0lBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.RGuKi7DkUI1nKj9UhaW9VzXbk6c5pCfHmlv2WtG-TPJrxs-RKevTiRXic35bEUmbQZbXqg4QEDPnKqKc_N8-k1piOXC9U3emicNM4O6jLHx4IFLhFddt14sEvD1ZP3a0DC0taDiJ9uSbrafRgnSfr426iI4B8hXLxmumvIE1CjZ0NwMFZBvqv8Dn0KDCSWHQZXPcBadqCI0c99QN_Fddu1YDTLN43qOdTEdi_lCe7jUTgWaRCcJ-0awB7HKddPaUQpF6a77Kk84rHVyCETFXtZrocyKbxoAVkr41bKXVhEV2BJ_j93BxJ9X_1Q4pYuOQIQq8iejzsZNV8HQy2QmI9A grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:09 GMT + date: Fri, 26 Mar 2021 19:12:01 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjMzE2YjQxNS04ZTVkLTQ2ZmQtYmIzNS0xMGYyYzE1NmYzMjQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3Nzg3ODksImV4cCI6MTYxNjc5MDQ4OSwiaWF0IjoxNjE2Nzc4Nzg5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.XpiPCB79B28LGRfh3khp1pUTJMsaJr2h8Cqr3pqkX9FWzjQrrmf6qxzOU3lZ-0s7oX4WFwXz8tDmS7HK1NfkuA3rc_TRYGMOprwuoWjJQ2HybutROc1DhO4cI_z7nxFcJACTtLo15wDKYizQMmMdAZlyHII2b3IzzpI6vOHufPbyldfJtFZjWIZnXqxjh1Uvbywb7vwVQ7GjFJ-w1iSU8aE547BpFiRyzKBi9dKf5Wr5CpPw-M7Jx6sJ57wXbybXa3W_mjoh3A2CBs4KwI9GIRdcQIgD2biwLp7pXfhsxOXyeBdOVzustaZWXyGGojcR6MkzV-wPRdN5mB9OKGOM-A + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5YWNmMWFlYy0xZDBiLTRhOWItOWMyYy05MjBlZmY5OTdlOGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3ODUwMjEsImV4cCI6MTYxNjc5NjcyMSwiaWF0IjoxNjE2Nzg1MDIxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.dFO8g1vmv5HLuLdhyF-Tpe-EhN_hbssAKpoHpdZywdYuUjygQTgN49sso312wB54leXVx7ZPayNGjDNkvUmKr9Za9sqW3dvtmwaTeAfWBeL9TvwZ2hC7UOqX4OyecPtNa21g5_8ngp_B2tVsKfsBJlWnlwm8bxjZJaeCJqTna8I3AGxwPlrMZlit-g1rnaCoLlVhIbaFjqtwUjXMuA3C26S-ICSDN92U1nXLvRNtjFmtAuyCk_kOvE_b3e3ssYOUlBAWrR5j_TFxmx0JW3Apg3WQgooUM42hZ44_fumF1gIUks2mH2nZD6wEE2S_2JJanWJL696Fco4RZQntS5BZQA scope: registry:catalog:* service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:09 GMT + date: Fri, 26 Mar 2021 19:12:01 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -101,7 +101,7 @@ interactions: connection: keep-alive content-length: '125' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 17:28:09 GMT + date: Fri, 26 Mar 2021 19:12:02 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index 8588647c622a..174751c7ffc1 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:02 GMT + - Fri, 26 Mar 2021 19:12:04 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:04 GMT + - Fri, 26 Mar 2021 19:12:07 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:04 GMT + - Fri, 26 Mar 2021 19:12:07 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:05 GMT + - Fri, 26 Mar 2021 19:12:08 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml index 877d5cc2714d..0b40402db475 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:06 GMT + - Fri, 26 Mar 2021 19:12:09 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:08 GMT + - Fri, 26 Mar 2021 19:12:11 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:08 GMT + - Fri, 26 Mar 2021 19:12:11 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:09 GMT + - Fri, 26 Mar 2021 19:12:11 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml index c9438d51fd6f..b8a6cd9e07fa 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:10 GMT + - Fri, 26 Mar 2021 19:12:14 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:11 GMT + - Fri, 26 Mar 2021 19:12:17 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:11 GMT + - Fri, 26 Mar 2021 19:12:17 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:11 GMT + - Fri, 26 Mar 2021 19:12:17 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml index cbf8e91bd9ae..5f0c88feabdc 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:11 GMT + - Fri, 26 Mar 2021 19:12:18 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:12 GMT + - Fri, 26 Mar 2021 19:12:20 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:12 GMT + - Fri, 26 Mar 2021 19:12:21 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:13 GMT + - Fri, 26 Mar 2021 19:12:21 GMT docker-distribution-api-version: - registry/2.0 server: @@ -193,7 +193,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:13 GMT + - Fri, 26 Mar 2021 19:12:21 GMT docker-distribution-api-version: - registry/2.0 server: @@ -233,7 +233,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:13 GMT + - Fri, 26 Mar 2021 19:12:21 GMT server: - openresty strict-transport-security: @@ -269,7 +269,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:13 GMT + - Fri, 26 Mar 2021 19:12:22 GMT server: - openresty strict-transport-security: @@ -312,7 +312,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 15:20:14 GMT + - Fri, 26 Mar 2021 19:12:22 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml index cc9541008a6a..e3be0d71bd80 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:18 GMT + - Fri, 26 Mar 2021 19:12:23 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:19 GMT + - Fri, 26 Mar 2021 19:12:25 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:19 GMT + - Fri, 26 Mar 2021 19:12:25 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:20 GMT + - Fri, 26 Mar 2021 19:12:25 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml index 346fafdf7cfa..8b53bbc58c3f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:21 GMT + - Fri, 26 Mar 2021 19:12:26 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:22 GMT + - Fri, 26 Mar 2021 19:12:27 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:22 GMT + - Fri, 26 Mar 2021 19:12:28 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:22 GMT + - Fri, 26 Mar 2021 19:12:28 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index 69000b6a35ec..184201453ab8 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:24 GMT + - Fri, 26 Mar 2021 19:12:28 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:25 GMT + - Fri, 26 Mar 2021 19:12:30 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:25 GMT + - Fri, 26 Mar 2021 19:12:30 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:25 GMT + - Fri, 26 Mar 2021 19:12:30 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml index e76b458d06e8..01736685b291 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:27 GMT + - Fri, 26 Mar 2021 19:12:31 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:28 GMT + - Fri, 26 Mar 2021 19:12:32 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:28 GMT + - Fri, 26 Mar 2021 19:12:33 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:29 GMT + - Fri, 26 Mar 2021 19:12:33 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml index a96e5c509912..a0d49e957e0a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:30 GMT + - Fri, 26 Mar 2021 19:12:33 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:31 GMT + - Fri, 26 Mar 2021 19:12:35 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:31 GMT + - Fri, 26 Mar 2021 19:12:35 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:31 GMT + - Fri, 26 Mar 2021 19:12:35 GMT docker-distribution-api-version: - registry/2.0 server: @@ -198,7 +198,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:32 GMT + - Fri, 26 Mar 2021 19:12:35 GMT docker-distribution-api-version: - registry/2.0 server: @@ -238,7 +238,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:32 GMT + - Fri, 26 Mar 2021 19:12:36 GMT server: - openresty strict-transport-security: @@ -274,7 +274,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:32 GMT + - Fri, 26 Mar 2021 19:12:36 GMT server: - openresty strict-transport-security: @@ -322,7 +322,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:33 GMT + - Fri, 26 Mar 2021 19:12:37 GMT docker-distribution-api-version: - registry/2.0 server: @@ -367,7 +367,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:33 GMT + - Fri, 26 Mar 2021 19:12:37 GMT docker-distribution-api-version: - registry/2.0 server: @@ -407,7 +407,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:33 GMT + - Fri, 26 Mar 2021 19:12:37 GMT server: - openresty strict-transport-security: @@ -443,7 +443,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:33 GMT + - Fri, 26 Mar 2021 19:12:37 GMT server: - openresty strict-transport-security: @@ -486,7 +486,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:34 GMT + - Fri, 26 Mar 2021 19:12:38 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml index 974cddbae28e..2b8bb3b921b5 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:35 GMT + - Fri, 26 Mar 2021 19:12:38 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:36 GMT + - Fri, 26 Mar 2021 19:12:40 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:36 GMT + - Fri, 26 Mar 2021 19:12:40 GMT server: - openresty strict-transport-security: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:36 GMT + - Fri, 26 Mar 2021 19:12:40 GMT docker-distribution-api-version: - registry/2.0 server: @@ -198,7 +198,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:37 GMT + - Fri, 26 Mar 2021 19:12:40 GMT docker-distribution-api-version: - registry/2.0 server: @@ -238,7 +238,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:37 GMT + - Fri, 26 Mar 2021 19:12:40 GMT server: - openresty strict-transport-security: @@ -274,7 +274,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:37 GMT + - Fri, 26 Mar 2021 19:12:41 GMT server: - openresty strict-transport-security: @@ -322,7 +322,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:38 GMT + - Fri, 26 Mar 2021 19:12:41 GMT docker-distribution-api-version: - registry/2.0 server: @@ -367,7 +367,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:38 GMT + - Fri, 26 Mar 2021 19:12:41 GMT docker-distribution-api-version: - registry/2.0 server: @@ -407,7 +407,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:38 GMT + - Fri, 26 Mar 2021 19:12:41 GMT server: - openresty strict-transport-security: @@ -443,7 +443,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:38 GMT + - Fri, 26 Mar 2021 19:12:42 GMT server: - openresty strict-transport-security: @@ -484,7 +484,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Thu, 25 Mar 2021 20:03:39 GMT + - Fri, 26 Mar 2021 19:12:42 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index c876e56b02eb..eddad8a8df7d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -18,7 +18,7 @@ from azure.core.paging import ItemPaged from azure.identity import DefaultAzureCredential -from .testcase import ContainerRegistryTestClass +from testcase import ContainerRegistryTestClass acr_preparer = functools.partial( diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 76bdb6586b6e..d1a2d03bb30c 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -21,7 +21,7 @@ ) from azure.core.paging import ItemPaged -from .testcase import ContainerRegistryTestClass, AcrBodyReplacer, FakeTokenCredential +from testcase import ContainerRegistryTestClass, AcrBodyReplacer, FakeTokenCredential acr_preparer = functools.partial( PowerShellPreparer, diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py index 15b1668507da..6d972da3de98 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py @@ -1,59 +1,59 @@ -# coding=utf-8 -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -import functools -import os -import pytest -import six - -from devtools_testutils import AzureTestCase, PowerShellPreparer - -from azure.containerregistry import ( - ContainerRegistryClient, - ContainerRepositoryClient, - DeletedRepositoryResult, - ACRExchangeClient -) -from azure.core.exceptions import ResourceNotFoundError -from azure.core.paging import ItemPaged -from azure.identity import DefaultAzureCredential - -from .testcase import ContainerRegistryTestClass - - -acr_preparer = functools.partial( - PowerShellPreparer, - "containerregistry", - containerregistry_baseurl="fake_url.azurecr.io", -) - - -class TestExchangeClient(ContainerRegistryTestClass): - - def create_exchange_client(self, endpoint): - return self.create_client_from_credential( - ACRExchangeClient, - credential=self.get_credential(), - endpoint=endpoint, - ) - - @pytest.mark.skip("not needed") - @acr_preparer() - def test_exchange_client(self, containerregistry_baseurl): - client = self.create_exchange_client(containerregistry_baseurl) - - service = "seankane.azurecr.io" - scope = "repository:hello-world:metadata_read" - - refresh_token = client.exchange_aad_token_for_refresh_token(service, scope) - assert refresh_token is not None - assert len(refresh_token) > 100 - print(refresh_token) - - - access_token = client.exchange_refresh_token_for_access_token(service, scope, refresh_token) - assert access_token is not None - assert len(access_token) > 100 - print(access_token) \ No newline at end of file +# # coding=utf-8 +# # ------------------------------------ +# # Copyright (c) Microsoft Corporation. +# # Licensed under the MIT License. +# # ------------------------------------ +# import functools +# import os +# import pytest +# import six + +# from devtools_testutils import AzureTestCase, PowerShellPreparer + +# from azure.containerregistry import ( +# ContainerRegistryClient, +# ContainerRepositoryClient, +# DeletedRepositoryResult, +# ACRExchangeClient +# ) +# from azure.core.exceptions import ResourceNotFoundError +# from azure.core.paging import ItemPaged +# from azure.identity import DefaultAzureCredential + +# from testcase import ContainerRegistryTestClass + + +# acr_preparer = functools.partial( +# PowerShellPreparer, +# "containerregistry", +# containerregistry_baseurl="fake_url.azurecr.io", +# ) + + +# class TestExchangeClient(ContainerRegistryTestClass): + +# def create_exchange_client(self, endpoint): +# return self.create_client_from_credential( +# ACRExchangeClient, +# credential=self.get_credential(), +# endpoint=endpoint, +# ) + +# @pytest.mark.skip("not needed") +# @acr_preparer() +# def test_exchange_client(self, containerregistry_baseurl): +# client = self.create_exchange_client(containerregistry_baseurl) + +# service = "seankane.azurecr.io" +# scope = "repository:hello-world:metadata_read" + +# refresh_token = client.exchange_aad_token_for_refresh_token(service, scope) +# assert refresh_token is not None +# assert len(refresh_token) > 100 +# print(refresh_token) + + +# access_token = client.exchange_refresh_token_for_access_token(service, scope, refresh_token) +# assert access_token is not None +# assert len(access_token) > 100 +# print(access_token) \ No newline at end of file From 0941cec355932bacad141b8f74f61110287e8265 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 15:37:50 -0400 Subject: [PATCH 74/86] removing more from authpolicy --- .../containerregistry/_authentication_policy.py | 2 +- .../aio/_async_authentication_policy.py | 16 +++------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py index be79e6d09f37..993b2c13d5d1 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_authentication_policy.py @@ -44,7 +44,7 @@ def __init__(self, credential, endpoint): super(ContainerRegistryChallengePolicy, self).__init__() self._scopes = "https://management.core.windows.net/.default" self._credential = credential - self._token = None # type: Optional[str] + self._token = None # type: Optional[AccessToken] self._exchange_client = ACRExchangeClient(endpoint, self._credential) def on_request(self, request): diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py index 87e43169fd7e..709994d55c1e 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_authentication_policy.py @@ -43,27 +43,17 @@ def __init__(self, credential, endpoint): super(ContainerRegistryChallengePolicy, self).__init__() self._scopes = "https://management.core.windows.net/.default" self._credential = credential - self._token = None # type: Union[str, None] + self._token = None # type: Union[AccessToken] self._exchange_client = ACRExchangeClient(endpoint, self._credential) - def _need_new_token(self): # pylint: disable=no-self-use - # type: () -> bool - return True - async def on_request(self, request): # type: (PipelineRequest) -> None """Called before the policy sends a request. The base implementation authorizes the request with a bearer token. :param ~azure.core.pipeline.PipelineRequest request: the request """ - - if self._token is None or self._need_new_token(): - self._token = await self._credential.get_token(self._scopes) - try: - self._token = self._token.token - except AttributeError: - pass - request.http_request.headers["Authorization"] = "Bearer " + self._token + # Future caching implementation will be included here + pass # pylint: disable=unnecessary-pass async def send(self, request): # type: (PipelineRequest) -> PipelineResponse From 4714e61ae185866802251616d9a793489a5319e5 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 15:44:58 -0400 Subject: [PATCH 75/86] removing exchange client --- .../tests/test_exchange_client.py | 59 ------------------- 1 file changed, 59 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py deleted file mode 100644 index 6d972da3de98..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/test_exchange_client.py +++ /dev/null @@ -1,59 +0,0 @@ -# # coding=utf-8 -# # ------------------------------------ -# # Copyright (c) Microsoft Corporation. -# # Licensed under the MIT License. -# # ------------------------------------ -# import functools -# import os -# import pytest -# import six - -# from devtools_testutils import AzureTestCase, PowerShellPreparer - -# from azure.containerregistry import ( -# ContainerRegistryClient, -# ContainerRepositoryClient, -# DeletedRepositoryResult, -# ACRExchangeClient -# ) -# from azure.core.exceptions import ResourceNotFoundError -# from azure.core.paging import ItemPaged -# from azure.identity import DefaultAzureCredential - -# from testcase import ContainerRegistryTestClass - - -# acr_preparer = functools.partial( -# PowerShellPreparer, -# "containerregistry", -# containerregistry_baseurl="fake_url.azurecr.io", -# ) - - -# class TestExchangeClient(ContainerRegistryTestClass): - -# def create_exchange_client(self, endpoint): -# return self.create_client_from_credential( -# ACRExchangeClient, -# credential=self.get_credential(), -# endpoint=endpoint, -# ) - -# @pytest.mark.skip("not needed") -# @acr_preparer() -# def test_exchange_client(self, containerregistry_baseurl): -# client = self.create_exchange_client(containerregistry_baseurl) - -# service = "seankane.azurecr.io" -# scope = "repository:hello-world:metadata_read" - -# refresh_token = client.exchange_aad_token_for_refresh_token(service, scope) -# assert refresh_token is not None -# assert len(refresh_token) > 100 -# print(refresh_token) - - -# access_token = client.exchange_refresh_token_for_access_token(service, scope, refresh_token) -# assert access_token is not None -# assert len(access_token) > 100 -# print(access_token) \ No newline at end of file From 209ecaa8472d45c6962f33fd7c7f0b04b5f377f4 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 16:06:29 -0400 Subject: [PATCH 76/86] tests for delete tag --- .../_container_repository_client.py | 7 +- .../aio/_async_container_repository_client.py | 6 +- ...> test_container_registry_client_async.py} | 0 .../tests/test_container_repository_client.py | 8 ++- .../test_container_repository_client_async.py | 36 ++++++++++ sdk/containerregistry/test-resources.json | 70 +++++++++++++++++++ 6 files changed, 116 insertions(+), 11 deletions(-) rename sdk/containerregistry/azure-containerregistry/tests/{test_container_registry_async.py => test_container_registry_client_async.py} (100%) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py create mode 100644 sdk/containerregistry/test-resources.json diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 41a23ae1d7b0..33e1c06bb36a 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -63,14 +63,15 @@ def delete_registry_artifact(self, digest, **kwargs): def delete_tag(self, tag, **kwargs): # type: (str) -> None - """Delete a tag + """Delete a tag from a repository :param tag: The digest of the artifact to be deleted :type tag: str :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - raise NotImplementedError("Has not been implemented") + self._client.container_registry_repository.delete_tag( + self.repository, tag, **kwargs) def get_properties(self, **kwargs): # type: (...) -> RepositoryProperties @@ -93,7 +94,6 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :returns: :class:~azure.containerregistry.RegistryArtifactProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - # GET '/acr/v1/{name}/_manifests/{digest}' if _is_tag(tag_or_digest): tag_or_digest = self._get_digest_from_tag(tag_or_digest) @@ -112,7 +112,6 @@ def get_tag_properties(self, tag, **kwargs): :returns: :class:~azure.containerregistry.TagProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - # GET '/acr/v1/{name}/_tags/{reference}' return TagProperties._from_generated( # pylint: disable=protected-access self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 934cdd7f8790..07158eaceb33 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -65,7 +65,8 @@ def delete_tag(self, tag, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - raise NotImplementedError("Has not been implemented") + await self._client.container_registry_repository.delete_tag( + self.repository, tag, **kwargs) async def get_properties(self, **kwargs): # type: (...) -> RepositoryProperties @@ -74,7 +75,6 @@ async def get_properties(self, **kwargs): :returns: :class:~azure.containerregistry.RepositoryProperties :raises: None """ - # GET '/acr/v1/{name}' return RepositoryProperties._from_generated( # pylint: disable=protected-access await self._client.container_registry_repository.get_properties(self.repository, **kwargs) ) @@ -88,7 +88,6 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): :returns: :class:~azure.containerregistry.RegistryArtifactProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - # GET '/acr/v1/{name}/_manifests/{digest}' if _is_tag(tag_or_digest): tag_or_digest = self._get_digest_from_tag(tag_or_digest) @@ -107,7 +106,6 @@ def get_tag_properties(self, tag, **kwargs): :returns: :class:~azure.containerregistry.TagProperties :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - # GET '/acr/v1/{name}/_tags/{reference}' return TagProperties._from_generated( # pylint: disable=protected-access self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) ) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py similarity index 100% rename from sdk/containerregistry/azure-containerregistry/tests/test_container_registry_async.py rename to sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index d1a2d03bb30c..ee1617c55e3e 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -7,6 +7,7 @@ import functools import os import pytest +import subprocess from devtools_testutils import AzureTestCase, PowerShellPreparer @@ -38,6 +39,10 @@ def __init__(self, method_name): self.recording_processors.append(AcrBodyReplacer()) self.repository = "hello-world" + def _import_tag_to_be_deleted(self, repository="hello-world"): + command = ["powershell.exe", "Import-AzcontainerRegistryImage", "-ResourceGroupName"] + subprocess.run(command) + @acr_preparer() def test_get_attributes(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -47,7 +52,6 @@ def test_get_attributes(self, containerregistry_baseurl): assert repo_attribs is not None assert repo_attribs.content_permissions is not None - @acr_preparer() def test_get_properties(self, containerregistry_baseurl): repo_client = self.create_repository_client(containerregistry_baseurl, "hello-world") @@ -55,7 +59,6 @@ def test_get_properties(self, containerregistry_baseurl): properties = repo_client.get_properties() assert isinstance(properties.content_permissions, ContentPermissions) - @acr_preparer() def test_get_tag(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -65,7 +68,6 @@ def test_get_tag(self, containerregistry_baseurl): assert tag is not None assert isinstance(tag, TagProperties) - @acr_preparer() def test_list_registry_artifacts(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py new file mode 100644 index 000000000000..fc57dfbae6be --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py @@ -0,0 +1,36 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ +import functools +import os +import pytest +import six + +from devtools_testutils import AzureTestCase, PowerShellPreparer + +from azure.containerregistry import ( + DeletedRepositoryResult, + RepositoryProperties, +) +from azure.containerregistry.aio import ContainerRegistryClient, ContainerRepositoryClient +from azure.core.exceptions import ResourceNotFoundError +from azure.core.paging import ItemPaged +from azure.identity.aio import DefaultAzureCredential + +from asynctestcase import AsyncContainerRegistryTestClass + + +acr_preparer = functools.partial( + PowerShellPreparer, + "containerregistry", + containerregistry_baseurl="fake_url.azurecr.io", +) + + +class TestContainerRegistryClient(AsyncContainerRegistryTestClass): + + @acr_preparer() + async def test_delete_tag(self, containerregistry_baseurl): + pass \ No newline at end of file diff --git a/sdk/containerregistry/test-resources.json b/sdk/containerregistry/test-resources.json new file mode 100644 index 000000000000..5fe3abd98e38 --- /dev/null +++ b/sdk/containerregistry/test-resources.json @@ -0,0 +1,70 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "baseName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "The base resource name." + } + }, + "tenantId": { + "type": "string", + "metadata": { + "description": "The tenant ID to which the application and resources belong." + } + }, + "testApplicationOid": { + "type": "string", + "metadata": { + "description": "The client OID to grant access to test resources." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "The location of the resource. By default, this is the same as the resource group." + } + } + }, + "variables": { + "apiVersion": "2019-05-01", + "endpointValue": "[format('https://{0}.azurecr.io', parameters('baseName'))]" + }, + "resources": [ + { + "type": "Microsoft.ContainerRegistry/registries", + "apiVersion": "[variables('apiVersion')]", + "name": "[parameters('baseName')]", + "location": "[parameters('location')]", + "properties": { + "endpoint": "[variables('endpointValue')]", + "adminUserEnabled": true + }, + "sku": { + "name": "Basic", + "tier": "Basic" + } + } + ], + "outputs": { + "CONTAINERREGISTRY_REGISTRY_NAME": { + "type": "string", + "value": "[parameters('baseName')]" + }, + "CONTAINERREGISTRY_ENDPOINT": { + "type": "string", + "value": "[variables('endpointValue')]" + }, + "CONTAINERREGISTRY_USERNAME": { + "type": "string", + "value": "[listCredentials(parameters('baseName'), variables('apiVersion')).username]" + }, + "CONTAINERREGISTRY_PASSWORD": { + "type": "string", + "value": "[listCredentials(parameters('baseName'), variables('apiVersion')).passwords[0].value]" + } + } + } \ No newline at end of file From 9c62e8c55faeab2cec01eb3cebbd417274ea04d3 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 26 Mar 2021 17:49:40 -0400 Subject: [PATCH 77/86] importing tags for delete operations --- .../aio/_async_container_repository_client.py | 6 +- ...test_delete_repository_does_not_exist.yaml | 114 ++++ ...y_client_async.test_list_repositories.yaml | 113 ++++ ...ner_repository_client.test_delete_tag.yaml | 491 ++++++++++++++++++ ...pository_client_async.test_delete_tag.yaml | 334 ++++++++++++ .../tests/test_container_repository_client.py | 23 +- .../test_container_repository_client_async.py | 26 +- .../azure-containerregistry/tests/testcase.py | 24 + 8 files changed, 1119 insertions(+), 12 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 07158eaceb33..6782ac714241 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -56,7 +56,7 @@ def delete_registry_artifact(self, digest, **kwargs): """ raise NotImplementedError("Has not been implemented") - def delete_tag(self, tag, **kwargs): + async def delete_tag(self, tag, **kwargs): # type: (str) -> None """Delete a tag @@ -97,7 +97,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): ) ) - def get_tag_properties(self, tag, **kwargs): + async def get_tag_properties(self, tag, **kwargs): # type: (str, Dict[str, Any]) -> TagProperties """Get the properties for a tag @@ -107,7 +107,7 @@ def get_tag_properties(self, tag, **kwargs): :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ return TagProperties._from_generated( # pylint: disable=protected-access - self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) + await self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) ) def list_registry_artifacts(self, **kwargs): diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml new file mode 100644 index 000000000000..a19548ecb5f7 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml @@ -0,0 +1,114 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '209' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:09 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/not_real_repo +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ4NjksIm5iZiI6MTYxNjc5NDg2OSwiZXhwIjoxNjE2ODgxNTY5LCJhaW8iOiJFMlpnWUxDWXhEdnRUVXU1NUMxMWRrNTlrWVB4QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZkJzaldKcFhoRXk4YUhPMnlrdW1BQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.oTFW_t_8Kz6fkCijZxxELhAqBD7i1raHaf1c4Ywr4s-bbv4ByOefFH3T8-9ZFd54fJMYzDPXWwRl8ESYfpMVlunhV92b3uFa3lTsBN053FnDAyfd5g-oRJu-Qu_mSFAMZ7ZeG5DN_k9sshIpzkMwMMB_yXYK1ZhNj14zrfUNwSaBKOzXhYNovviip0rOlyyfyUzT3_lfvkKyAdVK9XNGE85BPOy33uaERcWIP2FoJKO3OYyyXRSytTDgG-ZrvLCKlKbzg_nFDI3J6GNmCMIwqDgsifC0SPqhSQKi3RtWhCbK5lBqS9tTvzviE03E4ZeLcm-wKx7UidT43buiYGHMkQ + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:10 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OWE4Y2U5OC00YzM1LTRiZTMtOThhNS0zOWNiM2ViODAxNjMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQyNzAsImV4cCI6MTYxNjgwNTk3MCwiaWF0IjoxNjE2Nzk0MjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.kIBjuxvVmfqekywxk-I8CdzQ7sYQByC47ZBEoOqfpNeM-hWjuCyxTMqQHRgEKCnVuZedXNkMVxiyoZIy5s191RF9cx_e63pFnqeTTmMONIZja1YSbmGyR8NDpwiPJQkVfY4Qsr_vUYh2o4zze9KWNShnyAMeUjJrxBxtvuOUNTOWmev1eStYEWZw5Y0aIb_DC8dtx0TGYy2Xn5Ws6NuwmXjXz8sCb1D_pA4tpsuoY3R775y0ap_IQcNZ6Ye6zb42XP9ctsRUgn5y1CvuAcNfSa64YG52xQ2yHKSPxFLd5Ip-WRzyO1ozTLIS6l5bn3oDeIhHSSGPHMQD9najBBxObA + scope: repository:not_real_repo:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:10 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"not_real_repo"}}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '121' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:10 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 404 + message: Not Found + url: https://seankane.azurecr.io/acr/v1/not_real_repo +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml new file mode 100644 index 000000000000..262baf25b1c8 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml @@ -0,0 +1,113 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '196' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:11 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/_catalog +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ4NzEsIm5iZiI6MTYxNjc5NDg3MSwiZXhwIjoxNjE2ODgxNTcxLCJhaW8iOiJFMlpnWUdBOFBmdDkvWnpkKzJlTFJIb3BIMTV3REFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZVh1TjlUZE9zMDZIMHZFMXZCT1pBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.A0KGuU0tjXdWdsE3m4K6_P1M9w46jUOduAPy4pRaPlYjiWmoDiwWCryGkyVEzoXNPsiLXMKKlQckDfoARiZSRvDubZThaQj4058kZeujsv8IRetWWeHN9ZMrSZnjvM9rFiIHtvsXwcBQO9kjA6S-J7VyX4NqA426a6XHpKpl2rD_37xllNtRgkSZZi2sf-yzL2WVYD-1pItATFRFXnkHFN_bx_PqJfv3d9X7ROpgWZJWK0h2naLo_8Tw2PjrBgTPRfeIZeTyunQdsygyyj7aNHindSQ1ll_LgwCjj7YKHpG9K9M3fFvIm9AzMV0qxDSB_f7secnCHXkmBnCtjAv5Iw + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:12 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjZmRlMDZlYS1mYTk3LTQzZGUtYmUxZi1kNjJkODI3ZGE4NzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQyNzIsImV4cCI6MTYxNjgwNTk3MiwiaWF0IjoxNjE2Nzk0MjcyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Lyhcfioww5o7H8IF1kOqNqt3slu8_8iz01HTDKHIkljKLiq17qs_9jhkkCwk-IZoVnOOVPDCpTsOb6YaS9T-AkYdID5UYLl8JGNEiVskZx-TMO0y4GCrqks8mVvJcjYryWzkKIrZJlDwWAjIMTJdBAIepKk1RgWSekHYttI8lqVnly817N3wJtBwJPM7FPAcxKEO1FVe__YCavfyW60-_ehF-xJny_JSAdUtYerLFI7OSsaaP1YCoGWjMPoxUXBYTjtDnSCx-Uz_-gR1KmgiX30FgoQqwwhRLAE0pxFsefYtPZ-jdkhEioGDnAYSE5SfTfZ56euZum_P7ctDAVPSgQ + scope: registry:catalog:* + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:12 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '103' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:46:13 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/_catalog +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml new file mode 100644 index 000000000000..b813dc498cdf --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml @@ -0,0 +1,491 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:22 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:24 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:24 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-26T21:41:14.1972221Z","lastUpdateTime":"2021-03-26T21:41:14.1972221Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '387' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:24 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '207' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:24 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:25 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Adelete&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1072' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:25 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '0' + date: + - Fri, 26 Mar 2021 21:41:25 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-int-docker-content-digest: + - sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24 + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:35 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:36 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:36 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"TAG_UNKNOWN","message":"the specified tag does + not exist"}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '81' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 26 Mar 2021 21:41:36 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 404 + message: Not Found +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml new file mode 100644 index 000000000000..b38db386ed50 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml @@ -0,0 +1,334 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '214' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:41:54 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ2MTQsIm5iZiI6MTYxNjc5NDYxNCwiZXhwIjoxNjE2ODgxMzE0LCJhaW8iOiJFMlpnWUpncjd5M0NLR295ZGVVbEUxL09mck5jQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2lHQ3FBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NVBIvW3PyYFC8QQG4x4_XkzWHYrJHvz_6LGIrV7r6K_nsoUDY2iwzY4wF44O0voATg8ta4fND8YdL9cqtLdmLrtfkNpj3RM81XY73Ui0zHJa5cO8UNJnkUHG_XlIM3sZ6sSw57mOmSUce4MBl9JOQr_p2HCRQwbQVNMafCacfmqtFhKGbmSZMztL33rNZDF7pAaPQc5GutIl4COjQNUTigBWKynAOMiiG2pfpkWIh20P3WZTGtD-AH0kkL5pyRAjLByaHOvk0tydhL0MTOKBT7CFXDVF_N9wDDHYy9J8RjreWLSuIHwwaea_D7mvmp2bAVL4lkuIFgjJmGDAxtfn5w + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:41:55 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjNjExMjA3OS1lMTA4LTQ1YzQtOGZlMC0yMWM3YjQ3ZjZiYzciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQwMTUsImV4cCI6MTYxNjgwNTcxNSwiaWF0IjoxNjE2Nzk0MDE1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.WcYJOqzx7Y8cKsUV5vNXFR1RwDbhH80Eeo2dKj4aTi4Dyh9JvyldhreUYgTssUDR99tXjPPDw4MxGN9S9M5mPy-b4e_HiEi8fMSFe7PJh4RH6KIydW9sxyBqzLoKaM7WHiBrH7KwhAyDliPD8uRXg_ICgABPnuBYlSdGzmi-9HyIWh6_9oC7nQgMwK0JlETYCkNxaPxbjmVAiXEK5h52-Sx1ADCpjF5Epx56AdZ11oJ1MYeSDQXPBa01k6E1aRwGttaasoJNJx7LnwWKeIPgHLb534kWS-6O9rYEod4YSU4GS-c374YcHH2NBxkH7JVA7Iio4xcR8Eue7esLB13_Vw + scope: repository:hello-world:metadata_read + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:41:55 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-26T21:41:44.7917402Z","lastUpdateTime":"2021-03-26T21:41:44.7917402Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '387' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:41:55 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '207' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:41:55 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ2MTQsIm5iZiI6MTYxNjc5NDYxNCwiZXhwIjoxNjE2ODgxMzE0LCJhaW8iOiJFMlpnWUpncjd5M0NLR295ZGVVbEUxL09mck5jQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2lHQ3FBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NVBIvW3PyYFC8QQG4x4_XkzWHYrJHvz_6LGIrV7r6K_nsoUDY2iwzY4wF44O0voATg8ta4fND8YdL9cqtLdmLrtfkNpj3RM81XY73Ui0zHJa5cO8UNJnkUHG_XlIM3sZ6sSw57mOmSUce4MBl9JOQr_p2HCRQwbQVNMafCacfmqtFhKGbmSZMztL33rNZDF7pAaPQc5GutIl4COjQNUTigBWKynAOMiiG2pfpkWIh20P3WZTGtD-AH0kkL5pyRAjLByaHOvk0tydhL0MTOKBT7CFXDVF_N9wDDHYy9J8RjreWLSuIHwwaea_D7mvmp2bAVL4lkuIFgjJmGDAxtfn5w + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:41:55 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhZTg0ZWE3My1hMTE4LTQ2ZDktYWI1MC03Mzg2YThlMzMzODUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQwMTUsImV4cCI6MTYxNjgwNTcxNSwiaWF0IjoxNjE2Nzk0MDE1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.pa6UocvH_9D6cJ-he7bc7nhiBEr2GumCc0MO0ap00o94OKf574PG8RhYTekCTf2yedgbzR0nSnZXvTai73qgZuSQaH_O_2aGcaWz9efJjvgc-REjePgWBRB2FSGK7u4EeYdIFLIeATjMzGhgna1udExE5SZhbVt7VkCP78GvmypPB5g5-CZ2FW37Mo7j5i3l8G6Jvbk_wI-yhGEAIZxa0jIrKugFLQ0B4UHko5FA6t9_c0BtJosGHPB5B71KiTKtECmG-Am1Loiw0ASadA7oFaaff5EhtcDrZlDLlSW9dyEN8IeFVVPdIqY1mHdNHw3qp2sjz32jLz_dSK3U1fj2KQ + scope: repository:hello-world:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:41:56 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '0' + date: Fri, 26 Mar 2021 21:41:56 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + x-ms-int-docker-content-digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24 + status: + code: 202 + message: Accepted + url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '214' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:42:06 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ2MTQsIm5iZiI6MTYxNjc5NDYxNCwiZXhwIjoxNjE2ODgxMzE0LCJhaW8iOiJFMlpnWUpncjd5M0NLR295ZGVVbEUxL09mck5jQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2lHQ3FBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NVBIvW3PyYFC8QQG4x4_XkzWHYrJHvz_6LGIrV7r6K_nsoUDY2iwzY4wF44O0voATg8ta4fND8YdL9cqtLdmLrtfkNpj3RM81XY73Ui0zHJa5cO8UNJnkUHG_XlIM3sZ6sSw57mOmSUce4MBl9JOQr_p2HCRQwbQVNMafCacfmqtFhKGbmSZMztL33rNZDF7pAaPQc5GutIl4COjQNUTigBWKynAOMiiG2pfpkWIh20P3WZTGtD-AH0kkL5pyRAjLByaHOvk0tydhL0MTOKBT7CFXDVF_N9wDDHYy9J8RjreWLSuIHwwaea_D7mvmp2bAVL4lkuIFgjJmGDAxtfn5w + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:42:06 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIxMTMyZTY5OS03MDMwLTRkNTktYjE3Ni01Nzc3NDJkZTQzNmIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQwMjYsImV4cCI6MTYxNjgwNTcyNiwiaWF0IjoxNjE2Nzk0MDI2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.YG3fFy8fTJt2YVRPQ1p5yXr8BO0NoUhD-wroVo-NBbEHBm8wP6zi-zqMP_epwOuPtYd3fjtehsX31ETFECTNwQs8reSyEI6_0_PppzgIH3chcapOKVOlfAnPIggyOgYtHw3If4etNytqBaALEMJvDuThepxVGxXB5Y4zitTA1yAbdUSLBytThnSjENHHPxl8BCSCKrP2clO5e9yU10TdoIk9rNf5SVs11-VwYMbUkEel96IbK685a5FIgcVtyn8Kk-qT2-YApMCT6j3EYQG6apDtyuQhorNU1X6oWYgNg746glL6Wwth5iuoed5nRrPSrVYndyFQ-ANsZHJmbe10yQ + scope: repository:hello-world:metadata_read + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:42:07 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted + response: + body: + string: '{"errors":[{"code":"TAG_UNKNOWN","message":"the specified tag does + not exist"}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '81' + content-type: application/json; charset=utf-8 + date: Fri, 26 Mar 2021 21:42:07 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 404 + message: Not Found + url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index ee1617c55e3e..781b5697f2cc 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -8,6 +8,7 @@ import os import pytest import subprocess +import time from devtools_testutils import AzureTestCase, PowerShellPreparer @@ -20,6 +21,7 @@ TagProperties, TagOrderBy, ) +from azure.core.exceptions import ResourceNotFoundError from azure.core.paging import ItemPaged from testcase import ContainerRegistryTestClass, AcrBodyReplacer, FakeTokenCredential @@ -28,6 +30,7 @@ PowerShellPreparer, "containerregistry", containerregistry_baseurl="fake_url.azurecr.io", + containerregistry_resource_group="fake_rg", ) @@ -39,9 +42,20 @@ def __init__(self, method_name): self.recording_processors.append(AcrBodyReplacer()) self.repository = "hello-world" - def _import_tag_to_be_deleted(self, repository="hello-world"): - command = ["powershell.exe", "Import-AzcontainerRegistryImage", "-ResourceGroupName"] - subprocess.run(command) + @acr_preparer() + def test_delete_tag(self, containerregistry_baseurl, containerregistry_resource_group): + self._import_tag_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + + client = self.create_repository_client(containerregistry_baseurl, "hello-world") + + tag = client.get_tag_properties("to_be_deleted") + assert tag is not None + + client.delete_tag("to_be_deleted") + self.sleep(10) + + with pytest.raises(ResourceNotFoundError): + client.get_tag_properties("to_be_deleted") @acr_preparer() def test_get_attributes(self, containerregistry_baseurl): @@ -82,7 +96,6 @@ def test_list_registry_artifacts(self, containerregistry_baseurl): assert artifact.tags is not None assert isinstance(artifact.tags, list) - @acr_preparer() def test_get_registry_artifact_properties(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -94,7 +107,6 @@ def test_get_registry_artifact_properties(self, containerregistry_baseurl): assert isinstance(properties.created_on, datetime) assert isinstance(properties.last_updated_on, datetime) - @acr_preparer() def test_list_tags(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) @@ -108,7 +120,6 @@ def test_list_tags(self, containerregistry_baseurl): assert count > 0 - @acr_preparer() def test_list_tags_descending(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py index fc57dfbae6be..00dd12f1f7b6 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py @@ -7,6 +7,8 @@ import os import pytest import six +import subprocess +import time from devtools_testutils import AzureTestCase, PowerShellPreparer @@ -17,20 +19,38 @@ from azure.containerregistry.aio import ContainerRegistryClient, ContainerRepositoryClient from azure.core.exceptions import ResourceNotFoundError from azure.core.paging import ItemPaged -from azure.identity.aio import DefaultAzureCredential from asynctestcase import AsyncContainerRegistryTestClass +from testcase import AcrBodyReplacer acr_preparer = functools.partial( PowerShellPreparer, "containerregistry", containerregistry_baseurl="fake_url.azurecr.io", + containerregistry_resource_group="fake_rg", ) class TestContainerRegistryClient(AsyncContainerRegistryTestClass): + def __init__(self, method_name): + super(TestContainerRegistryClient, self).__init__(method_name) + self.vcr.match_on = ["path", "method", "query"] + self.recording_processors.append(AcrBodyReplacer()) + self.repository = "hello-world" + @acr_preparer() - async def test_delete_tag(self, containerregistry_baseurl): - pass \ No newline at end of file + async def test_delete_tag(self, containerregistry_baseurl, containerregistry_resource_group): + self._import_tag_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + + client = self.create_repository_client(containerregistry_baseurl, "hello-world") + + tag = await client.get_tag_properties("to_be_deleted") + assert tag is not None + + await client.delete_tag("to_be_deleted") + self.sleep(10) + + with pytest.raises(ResourceNotFoundError): + await client.get_tag_properties("to_be_deleted") \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index 86b05c05fdd4..c63d8cd75905 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -8,6 +8,7 @@ import os import re import six +import time from azure.containerregistry import ( ContainerRepositoryClient, @@ -97,6 +98,29 @@ def __init__(self, method_name): self.vcr.match_on = ["path", "method", "query"] self.recording_processors.append(AcrBodyReplacer()) + def sleep(self, t): + if self.is_live: + time.sleep(t) + + def _fake_sleep(self, *args, **kwargs): + pass + + def _import_tag_to_be_deleted(self, endpoint, repository="hello-world", resource_group="fake_rg"): + if not self.is_live: + return + registry = endpoint.split(".")[0] + command = [ + "powershell.exe", "Import-AzcontainerRegistryImage", + "-ResourceGroupName", "'{}'".format(resource_group), + "-RegistryName", "'{}'".format(registry), + "-SourceImage", "'library/hello-world'", + "-SourceRegistryUri", "'registry.hub.docker.com'", + "-TargetTag", "'hello-world:to_be_deleted'" + "-Mode", "'Force'" + + ] + subprocess.check_call(command) + def get_credential(self): if self.is_live: return DefaultAzureCredential() From c26d4226abc750f8d7ff69b27d1c37aa9b62950a Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 29 Mar 2021 10:51:05 -0400 Subject: [PATCH 78/86] cleanup --- ...ner_repository_client.test_delete_tag.yaml | 26 +-- ...y_client.test_list_registry_artifacts.yaml | 164 ------------------ .../azure-containerregistry/tests/testcase.py | 47 +++-- 3 files changed, 42 insertions(+), 195 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml index b813dc498cdf..398f2c083075 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:22 GMT + - Mon, 29 Mar 2021 14:47:29 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:24 GMT + - Mon, 29 Mar 2021 14:47:31 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:24 GMT + - Mon, 29 Mar 2021 14:47:31 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-26T21:41:14.1972221Z","lastUpdateTime":"2021-03-26T21:41:14.1972221Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-29T14:47:20.2311587Z","lastUpdateTime":"2021-03-29T14:47:20.2311587Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} ' headers: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:24 GMT + - Mon, 29 Mar 2021 14:47:31 GMT docker-distribution-api-version: - registry/2.0 server: @@ -195,7 +195,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:24 GMT + - Mon, 29 Mar 2021 14:47:31 GMT docker-distribution-api-version: - registry/2.0 server: @@ -235,7 +235,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:25 GMT + - Mon, 29 Mar 2021 14:47:31 GMT server: - openresty strict-transport-security: @@ -271,7 +271,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:25 GMT + - Mon, 29 Mar 2021 14:47:31 GMT server: - openresty strict-transport-security: @@ -310,7 +310,7 @@ interactions: content-length: - '0' date: - - Fri, 26 Mar 2021 21:41:25 GMT + - Mon, 29 Mar 2021 14:47:32 GMT docker-distribution-api-version: - registry/2.0 server: @@ -357,7 +357,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:35 GMT + - Mon, 29 Mar 2021 14:47:42 GMT docker-distribution-api-version: - registry/2.0 server: @@ -397,7 +397,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:36 GMT + - Mon, 29 Mar 2021 14:47:42 GMT server: - openresty strict-transport-security: @@ -433,7 +433,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:36 GMT + - Mon, 29 Mar 2021 14:47:42 GMT server: - openresty strict-transport-security: @@ -475,7 +475,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 21:41:36 GMT + - Mon, 29 Mar 2021 14:47:43 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml deleted file mode 100644 index 8b53bbc58c3f..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml +++ /dev/null @@ -1,164 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '214' - content-type: - - application/json; charset=utf-8 - date: - - Fri, 26 Mar 2021 19:12:26 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" - x-content-type-options: - - nosniff - status: - code: 401 - message: Unauthorized -- request: - body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1343' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token": "REDACTED"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Fri, 26 Mar 2021 19:12:27 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - Content-Length: - - '1079' - Content-Type: - - application/x-www-form-urlencoded - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token": "REDACTED"}' - headers: - connection: - - keep-alive - content-type: - - application/json; charset=utf-8 - date: - - Fri, 26 Mar 2021 19:12:28 GMT - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - transfer-encoding: - - chunked - status: - code: 200 - message: OK -- request: - body: null - headers: - Accept: - - application/json - Accept-Encoding: - - gzip, deflate - Connection: - - keep-alive - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests - response: - body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} - - ' - headers: - access-control-expose-headers: - - Docker-Content-Digest - - WWW-Authenticate - - Link - - X-Ms-Correlation-Request-Id - connection: - - keep-alive - content-length: - - '598' - content-type: - - application/json; charset=utf-8 - date: - - Fri, 26 Mar 2021 19:12:28 GMT - docker-distribution-api-version: - - registry/2.0 - server: - - openresty - strict-transport-security: - - max-age=31536000; includeSubDomains - - max-age=31536000; includeSubDomains - x-content-type-options: - - nosniff - status: - code: 200 - message: OK -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index c63d8cd75905..c827745f0c6b 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -8,6 +8,7 @@ import os import re import six +import subprocess import time from azure.containerregistry import ( @@ -27,8 +28,10 @@ REDACTED = "REDACTED" + class AcrBodyReplacer(RecordingProcessor): """Replace request body for oauth2 exchanges""" + def __init__(self, replacement="redacted"): self._replacement = replacement self._401_replacement = 'Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token"' @@ -50,27 +53,27 @@ def _scrub_body(self, body): return bytes(s, "utf-8") def process_request(self, request): - if request.body:# and isinstance(request.body, six.binary_type): + if request.body: request.body = self._scrub_body(request.body) return request def process_response(self, response): try: - headers = response['headers'] + headers = response["headers"] auth_header = None if "www-authenticate" in headers: - response['headers']["www-authenticate"] = self._401_replacement + response["headers"]["www-authenticate"] = self._401_replacement - body = response['body'] + body = response["body"] try: - refresh = json.loads(body['string']) + refresh = json.loads(body["string"]) if "refresh_token" in refresh.keys(): - refresh['refresh_token'] = REDACTED - body['string'] = json.dumps(refresh) + refresh["refresh_token"] = REDACTED + body["string"] = json.dumps(refresh) if "access_token" in refresh.keys(): refresh["access_token"] = REDACTED - body['string'] = json.dumps(refresh) + body["string"] = json.dumps(refresh) except json.decoder.JSONDecodeError: pass @@ -84,6 +87,7 @@ class FakeTokenCredential(object): """Protocol for classes able to provide OAuth tokens. :param str scopes: Lets you specify the type of access needed. """ + def __init__(self): self.token = AccessToken("YOU SHALL NOT PASS", 0) @@ -92,7 +96,6 @@ def get_token(self, *args): class ContainerRegistryTestClass(AzureTestCase): - def __init__(self, method_name): super(ContainerRegistryTestClass, self).__init__(method_name) self.vcr.match_on = ["path", "method", "query"] @@ -105,19 +108,27 @@ def sleep(self, t): def _fake_sleep(self, *args, **kwargs): pass - def _import_tag_to_be_deleted(self, endpoint, repository="hello-world", resource_group="fake_rg"): + def _import_tag_to_be_deleted( + self, endpoint, repository="hello-world", resource_group="fake_rg" + ): if not self.is_live: return registry = endpoint.split(".")[0] command = [ - "powershell.exe", "Import-AzcontainerRegistryImage", - "-ResourceGroupName", "'{}'".format(resource_group), - "-RegistryName", "'{}'".format(registry), - "-SourceImage", "'library/hello-world'", - "-SourceRegistryUri", "'registry.hub.docker.com'", - "-TargetTag", "'hello-world:to_be_deleted'" - "-Mode", "'Force'" - + "powershell.exe", + "Import-AzcontainerRegistryImage", + "-ResourceGroupName", + "'{}'".format(resource_group), + "-RegistryName", + "'{}'".format(registry), + "-SourceImage", + "'library/hello-world'", + "-SourceRegistryUri", + "'registry.hub.docker.com'", + "-TargetTag", + "'hello-world:to_be_deleted'", + "-Mode", + "'Force'", ] subprocess.check_call(command) From 96d9095a549e0d24c08d498ca34aa1403ecf1d69 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 29 Mar 2021 11:46:40 -0400 Subject: [PATCH 79/86] forgot to include a recording --- ...y_client.test_list_registry_artifacts.yaml | 164 ++++++++++++++++++ .../tests/test_container_repository_client.py | 6 +- 2 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml new file mode 100644 index 000000000000..0aa6ea127541 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml @@ -0,0 +1,164 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"hello-world","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 15:46:14 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 15:46:15 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ahello-world%3Ametadata_read&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1079' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 15:46:16 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-26T20:37:52.5557355Z","lastUpdateTime":"2021-03-26T20:37:52.5557355Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-26T20:57:13.8079297Z","lastUpdateTime":"2021-03-26T20:57:13.8079297Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-26T20:37:53.7763318Z","lastUpdateTime":"2021-03-26T20:37:53.7763318Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-26T20:37:53.4342095Z","lastUpdateTime":"2021-03-26T20:37:53.4342095Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-26T20:37:52.921838Z","lastUpdateTime":"2021-03-26T20:37:52.921838Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-26T20:37:53.6634624Z","lastUpdateTime":"2021-03-26T20:37:53.6634624Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-26T20:37:53.1185252Z","lastUpdateTime":"2021-03-26T20:37:53.1185252Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-26T20:37:52.8422032Z","lastUpdateTime":"2021-03-26T20:37:52.8422032Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-26T20:37:53.3206421Z","lastUpdateTime":"2021-03-26T20:37:53.3206421Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-26T20:37:52.6987713Z","lastUpdateTime":"2021-03-26T20:37:52.6987713Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 15:46:16 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 781b5697f2cc..43a37b7ac0f7 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -86,6 +86,7 @@ def test_get_tag(self, containerregistry_baseurl): def test_list_registry_artifacts(self, containerregistry_baseurl): client = self.create_repository_client(containerregistry_baseurl, self.repository) + count = 0 for artifact in client.list_registry_artifacts(): assert artifact is not None assert isinstance(artifact, RegistryArtifactProperties) @@ -93,8 +94,9 @@ def test_list_registry_artifacts(self, containerregistry_baseurl): assert isinstance(artifact.created_on, datetime) assert artifact.last_updated_on is not None assert isinstance(artifact.last_updated_on, datetime) - assert artifact.tags is not None - assert isinstance(artifact.tags, list) + count += 1 + + assert count > 0 @acr_preparer() def test_get_registry_artifact_properties(self, containerregistry_baseurl): From a2a9967d6f02ffd31b426893f61059c1b5dd958d Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 29 Mar 2021 13:35:51 -0400 Subject: [PATCH 80/86] add delete repo tests: --- .../aio/_async_container_registry_client.py | 2 +- ...egistry_client.test_delete_repository.yaml | 168 ++++++ ...test_delete_repository_does_not_exist.yaml | 169 ++++++ ...y_client_async.test_delete_repository.yaml | 113 ++++ ...test_delete_repository_does_not_exist.yaml | 12 +- ...ository_client.test_delete_repository.yaml | 492 ++++++++++++++++++ ...t.test_delete_repository_doesnt_exist.yaml | 169 ++++++ ...y_client_async.test_delete_repository.yaml | 335 ++++++++++++ ...c.test_delete_repository_doesnt_exist.yaml | 114 ++++ .../tests/test_container_registry_client.py | 14 +- .../test_container_registry_client_async.py | 12 +- .../tests/test_container_repository_client.py | 29 +- .../test_container_repository_client_async.py | 31 +- .../azure-containerregistry/tests/testcase.py | 24 + 14 files changed, 1657 insertions(+), 27 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index d6e74dd13ca7..acdd38a4d19f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -30,7 +30,7 @@ async def delete_repository(self, repository: str, **kwargs: Dict[str, Any]) -> :param repository: The repository to delete :type repository: str - :returns: None + :returns: :class:~azure.containerregistry.DeletedRepositoryResult :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ result = await self._client.container_registry.delete_repository(repository, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml new file mode 100644 index 000000000000..79bb18872c80 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml @@ -0,0 +1,168 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '209' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:22:28 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:22:30 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ato_be_deleted%3Adelete&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1074' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:22:30 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"manifestsDeleted":["sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9"],"tagsDeleted":["to_be_deleted"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '795' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:22:32 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 202 + message: Accepted +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml new file mode 100644 index 000000000000..a6db4fec1a2b --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml @@ -0,0 +1,169 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '209' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:13 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:14 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Anot_real_repo%3Adelete&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1074' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:14 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/not_real_repo + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"not_real_repo"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '121' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:15 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 404 + message: Not Found +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml new file mode 100644 index 000000000000..150682b59e07 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml @@ -0,0 +1,113 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '209' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:22:56 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/to_be_deleted +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgyNzYsIm5iZiI6MTYxNzAzODI3NiwiZXhwIjoxNjE3MTI0OTc2LCJhaW8iOiJFMlpnWUpqQTF5OFhzZEw3b2FCTTMwYlBIbVlaQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZ1J4ckdCblNhRTJZeUUtSTZmdjlBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.iIBCRRapm6l8YAVeq7ubG153fwq0wvzHighCcHXxS8qjiVd0K_QMZyHNfd0j1JChlLkksgaGvCQulwVWE8vqXKmGEwe-Q5a26ii9CBCtTY44xIPOmB8yyRPqfKc7E7Gri4QhQaiITwClcFl0amwk8sRaNFflwTmB3Obugo93kWQJQDiPXRum5tDkdkRUcMkPM75KEG32sBYQeJFAGtsXtPoDFRX0d-SyrW4GijXFPeJ85zTOGXm0PBSvARWIQYmbknfK2jnysP1uo7dmUtRVy9gQ6plRutFvv7qr3UmTaAjRjtaLMc5VORZ-kNdYTByEOdzFHHThWMasdTXmtTwpsg + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:22:57 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjNWViNWI2NC1lY2JiLTRjMjktOWY4OS04MzJjMTZlYTExNmQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc2NzcsImV4cCI6MTYxNzA0OTM3NywiaWF0IjoxNjE3MDM3Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.P0wzSQ0HoadHSNusm4o1DqF7b6f8tNIGzXJxUF-EwSPAxp_UB_IcGsVulX0VoZtP36qhL1EURHPRXi8CtqzCcaxynWGiTAA2E0fPpZ1WkJCe2VZimAkSf129W_mXatWJf9NIZFp9typzSWBoit6iZNg_JgqTjqhbKEX4zojVTtOJta2Q9m8vtZAxkAft4IvVqHYctM8SZAATurvsXpXSDoH61fOW4DpQOg0085-r1FpBPMVoLlKkElfyzPFkn2BpVdBo28-076HyT269wP_PoGfA9F6iyildTkxo_hdZMNBJ5-5l66PPAcrN0nk85cmOi_cGPQz2tz0t0G0a1un6uw + scope: repository:to_be_deleted:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:22:57 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"manifestsDeleted":["sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9"],"tagsDeleted":["to_be_deleted"]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '795' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:22:58 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 202 + message: Accepted + url: https://seankane.azurecr.io/acr/v1/to_be_deleted +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml index a19548ecb5f7..2c9ae9be8716 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:09 GMT + date: Mon, 29 Mar 2021 17:35:15 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/not_real_repo - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ4NjksIm5iZiI6MTYxNjc5NDg2OSwiZXhwIjoxNjE2ODgxNTY5LCJhaW8iOiJFMlpnWUxDWXhEdnRUVXU1NUMxMWRrNTlrWVB4QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZkJzaldKcFhoRXk4YUhPMnlrdW1BQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.oTFW_t_8Kz6fkCijZxxELhAqBD7i1raHaf1c4Ywr4s-bbv4ByOefFH3T8-9ZFd54fJMYzDPXWwRl8ESYfpMVlunhV92b3uFa3lTsBN053FnDAyfd5g-oRJu-Qu_mSFAMZ7ZeG5DN_k9sshIpzkMwMMB_yXYK1ZhNj14zrfUNwSaBKOzXhYNovviip0rOlyyfyUzT3_lfvkKyAdVK9XNGE85BPOy33uaERcWIP2FoJKO3OYyyXRSytTDgG-ZrvLCKlKbzg_nFDI3J6GNmCMIwqDgsifC0SPqhSQKi3RtWhCbK5lBqS9tTvzviE03E4ZeLcm-wKx7UidT43buiYGHMkQ + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzkwMTYsIm5iZiI6MTYxNzAzOTAxNiwiZXhwIjoxNjE3MTI1NzE2LCJhaW8iOiJFMlpnWUxpdVo3OXhzOFdHdkIxYUhXeStmMituQVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiLWFzX0xGOTJlVWFjdFN6bVQ1c1BBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.lXULYlyPw0I-nvw5J9TTkS9HfRKGjCEEEZsbAv4OARVoWPZGGHEW_NYQz77m4zHfz7PuXD0qPyGKIEC2qMmferd_cktH_jvYv2TdFau5mggI3zkWlAu0x9HVy_I-deEdTGzm6m37EC--aJDd6y274QEb5yCVwcexMYk-vpXNFbtYsAWZ6X8jctKdmm3D8K2QNzn45gARvtOfPeN0L1b_6wiv9qA1a_Y1zGSWT6RB1Tfe0IRcIdVHYyF5S7oWe_0C-wHN5nHzDoT7lFQx-EkhnUyHHoslxODTntHQRXr5gPLG-o5Gbc-BNV5MoUhQu3ojdKa5m_0CXh34m42BUJX2Iw grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:10 GMT + date: Mon, 29 Mar 2021 17:35:17 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI3OWE4Y2U5OC00YzM1LTRiZTMtOThhNS0zOWNiM2ViODAxNjMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQyNzAsImV4cCI6MTYxNjgwNTk3MCwiaWF0IjoxNjE2Nzk0MjcwLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.kIBjuxvVmfqekywxk-I8CdzQ7sYQByC47ZBEoOqfpNeM-hWjuCyxTMqQHRgEKCnVuZedXNkMVxiyoZIy5s191RF9cx_e63pFnqeTTmMONIZja1YSbmGyR8NDpwiPJQkVfY4Qsr_vUYh2o4zze9KWNShnyAMeUjJrxBxtvuOUNTOWmev1eStYEWZw5Y0aIb_DC8dtx0TGYy2Xn5Ws6NuwmXjXz8sCb1D_pA4tpsuoY3R775y0ap_IQcNZ6Ye6zb42XP9ctsRUgn5y1CvuAcNfSa64YG52xQ2yHKSPxFLd5Ip-WRzyO1ozTLIS6l5bn3oDeIhHSSGPHMQD9najBBxObA + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMTI3YjkzOS1iNTkwLTQxOTItYTUxNy01ZjdmYzNlOWQzNmMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzg0MTcsImV4cCI6MTYxNzA1MDExNywiaWF0IjoxNjE3MDM4NDE3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.p6RQLCCApPH_N2XXNcB7e-6N51qONOkOanipndPJmnF0SxXjMNZ1JpoDClZJFW-f4jUnPlhMOw7-V_9KkJO9q5jBKMX4iRfZJhlFqCn_RHgHOfc-xFw8S6MwFszit9iN1M6bVpl7qHHSp-GiB0iUe_9KDGCiojll5zESrjSMEKgjaHbRcF9sUiwjTED45dPjsVeLpgKmEkGs9pxJgPGn9E3YEGZUyvdQSA4wNsa_akHr2L3pUKposoZEMwzjQVNxh6Um-cdZfN_939bn_uLt5D9mkaY7eXBPkI283FjCOoBJ4R4cG79Q5cvUS2ajiHCewddSW1KXx2PGqMZHAz5QIg scope: repository:not_real_repo:delete service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:10 GMT + date: Mon, 29 Mar 2021 17:35:17 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -102,7 +102,7 @@ interactions: connection: keep-alive content-length: '121' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:10 GMT + date: Mon, 29 Mar 2021 17:35:17 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml new file mode 100644 index 000000000000..9b65d913e4ed --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml @@ -0,0 +1,492 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '196' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:17 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:18 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry%3Acatalog%3A%2A&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1063' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:19 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","to_be_deleted","ubuntu"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '119' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:19 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '209' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:20 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:21 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ato_be_deleted%3Adelete&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1074' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:21 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"manifestsDeleted":["sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9"],"tagsDeleted":["to_be_deleted"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '795' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:24 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '196' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:29 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:30 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=registry%3Acatalog%3A%2A&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1063' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:30 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '103' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:23:30 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml new file mode 100644 index 000000000000..b78e09025e8b --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml @@ -0,0 +1,169 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/does_not_exist + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"does_not_exist","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '210' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:18 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:19 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Adoes_not_exist%3Adelete&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1075' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:20 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/does_not_exist + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"does_not_exist"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '122' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 17:35:20 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 404 + message: Not Found +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml new file mode 100644 index 000000000000..fc6435bcc3aa --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml @@ -0,0 +1,335 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '196' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:45 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/_catalog +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgzMjYsIm5iZiI6MTYxNzAzODMyNiwiZXhwIjoxNjE3MTI1MDI2LCJhaW8iOiJFMlpnWUdBOFBmdDkvWnpkKzJlTFJIb3BIMTV3REFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDdGQzVodElRVVNVSDdUX3BDRVlBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.ZM7EvHmcgfCdXw-hPwJwRm_VLuIjPWP0yN9epulLmPQ9pMeJds_aiWmF5P6qDHYELGLVIxKojeOZxtkRf7FSHbqs3raFQI4QLsfWUdC-NvZUtcdWD-dWrUiKqgK8AIaEnOcn0DZNTwUnBtDWMi0aSX4Nl3L9KZpaXQXcgohkZQ0vkaTcnu81481nPf3FWEbxLjXltacuTrIdUhzvIl010vPZH4tPaOGUQcsxD1_YcOAcwVBNIqbuW4rmA-z1rmOFkeCxvCVIyep2MVJUmTUWxItf_Pt0f7g-U0q08nQsUbLNPupsKc-8hKLQICLvwrzcvKogagmZvsZJegvEPrAnGg + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:47 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5YWE2M2JlOC1hNTIxLTRhMmMtODcxYi05MThhYWQxYjI2ZWEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc3MjcsImV4cCI6MTYxNzA0OTQyNywiaWF0IjoxNjE3MDM3NzI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.AEweEuzrXzV66SX7QT8lEEsXqb6o9z0kEUG6o3d6SSSCiBYyHyfjda9K__1ofB36XlKLvVc5rKXin80xEFlSIwu3N9Fw-FB6DUzXWpGgicdQINJiSgNHXnhQtxeMg10MIZALQPYYypmmeLz5eCVOL8LcdUC09PTLTuYvGXv0XpSwfo9VYICzivFzRL4ky6PPoigVGIyirsEoWtt7MVmhtm6VY5OR57BjdW2dNo0Qylzg7Ns3SI2Jl8j4fSA0j2CQh_9KcOY9kpQfpmRg0wDjsbG8XzRQtiKGI_4GMGf1mCaJlw7Z9UnztHe1lIJUCet1K1MIM3HDxYotmdX69d40dg + scope: registry:catalog:* + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:47 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","to_be_deleted","ubuntu"]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '119' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:47 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/_catalog +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '209' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:47 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/to_be_deleted +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgzMjgsIm5iZiI6MTYxNzAzODMyOCwiZXhwIjoxNjE3MTI1MDI4LCJhaW8iOiJFMlpnWUdpcXRZMnBTODFaa2VheXh1K05aeWtQQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiaW9fZlFLMHFBVVdsTDNEcTZWUFlBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.UlKKG26ImkHfjGbtB8NaceIB83W-iwAXJ7RcCdFVF7zKIQg4SmxXSfFD2fjn2tB0u9IZXULUgf7a2xWqRQURQR-0K8CWd0TZRl65C6DrcPhL3U3nP6FvJ3SyfYO4sGW6P3ZcjHPfwWUnP-DAULzBnViDIOmSrC9RIBB4HzB936kAfw8WLKDiyrbEOksOEWQM0AKUZ9z8Oik82WzOqM-wRwSVwQggbsEAAs4Uw7djnR-9NsM6ULTgZU88aVbNlxENMa3Sic_bRJJt2iOj0sF5Dd64q2L4CEyO3R8Mzu3UoJDb0-6wcNFSeP0ZHD3RbaCQ3I2aFoTCWT-dwtNF5eqkiA + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:49 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkZTY4MDI1Zi1iMGUzLTQ1NmQtYTJiYy1lNmYyODE1Y2UwNWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc3MjksImV4cCI6MTYxNzA0OTQyOSwiaWF0IjoxNjE3MDM3NzI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.efL7AXLXW5eYRrnHem3sP3y6Jgt-5UxDH_6UZQOKko4sTwbjF5hSdujqKJcCVV7tcT6qPzpkNZoYChvPzzdViP3Y52_PRwzfK1Ww_z0DDh7KzYlUGv8uAV7Cy6ydwDyyVHSQa1e_Bu9f0myk2xRq1cvp0GBu3orApKnmnajiBtGMjXoUdO0-AxpLWMbZk8MCSVqG98GaOzkMdirZEaf_BpD1O04tg-e3AZtsTgjRboS_DVjk7vRxtTDXEZS7ItVtTi_vMQYTCwYeEaJ0vJx06F4A9gVE9gpGsC_o2Cr-HNumJLEDcWtH44JBC5_FFAw2C42tKstUGx1C7uU0f2dbgQ + scope: repository:to_be_deleted:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:49 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted + response: + body: + string: '{"manifestsDeleted":["sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9"],"tagsDeleted":["to_be_deleted"]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '795' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:51 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 202 + message: Accepted + url: https://seankane.azurecr.io/acr/v1/to_be_deleted +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '196' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:57 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/_catalog +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgzMjYsIm5iZiI6MTYxNzAzODMyNiwiZXhwIjoxNjE3MTI1MDI2LCJhaW8iOiJFMlpnWUdBOFBmdDkvWnpkKzJlTFJIb3BIMTV3REFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDdGQzVodElRVVNVSDdUX3BDRVlBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.ZM7EvHmcgfCdXw-hPwJwRm_VLuIjPWP0yN9epulLmPQ9pMeJds_aiWmF5P6qDHYELGLVIxKojeOZxtkRf7FSHbqs3raFQI4QLsfWUdC-NvZUtcdWD-dWrUiKqgK8AIaEnOcn0DZNTwUnBtDWMi0aSX4Nl3L9KZpaXQXcgohkZQ0vkaTcnu81481nPf3FWEbxLjXltacuTrIdUhzvIl010vPZH4tPaOGUQcsxD1_YcOAcwVBNIqbuW4rmA-z1rmOFkeCxvCVIyep2MVJUmTUWxItf_Pt0f7g-U0q08nQsUbLNPupsKc-8hKLQICLvwrzcvKogagmZvsZJegvEPrAnGg + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:57 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyMzg0NDlmOC0yOGNhLTRiMzUtYjZiMC02MWU3NzE5YTZiMzMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc3MzcsImV4cCI6MTYxNzA0OTQzNywiaWF0IjoxNjE3MDM3NzM3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.iS1gKkbBuumPlqpbYfWFhlCux6wzJJ7zyhsM2rB45GClsVTHHywp4gSJdMPsQwtZpRV6zIXiDRwT6LIMllJztVEAgyYtpJErQzCgRtl4pnekH77oAm4SUgPtW4n-rdd_lBAY2DK_pnKzwXlkoK7Yf5jkOPQw4fC6e2kbRIO-eTMZFr648Ab6XMn4OPtxk2ynlV2LaEEbQ0DjW15tcGzEWqEVmVEwNdk_xSbpcChMxXHph-nCz9tMn9RLqGuTXI8VIc6AhjdlMPLlGNabS4g9ITYgx2hGKQQuQ7fRB-YjD1XxU_rnxplGaqW1voSpasoAIurhVw2eb8hDFDen1-OntA + scope: registry:catalog:* + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:57 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/_catalog + response: + body: + string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","ubuntu"]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '103' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:23:57 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/_catalog +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml new file mode 100644 index 000000000000..7fbd5abd9e22 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml @@ -0,0 +1,114 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/does_not_exist + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"does_not_exist","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '210' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:35:20 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/does_not_exist +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzkwMjEsIm5iZiI6MTYxNzAzOTAyMSwiZXhwIjoxNjE3MTI1NzIxLCJhaW8iOiJFMlpnWVBpd3cyUEwzSTR3eFo3dW1XNnNYcDVhQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiTndYRDQzQWZNVUNSLVRfMzk4eElBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.aseuguWMUT-unLBgLaXuAm-8Z3fl8E3kkrkw2tMPRi4y11QWVQaKPpzuvyqFeyj913dNKkJ6hwNTmbPSlSbQXfkSG11Nh85cAE4I30gqXEo4zepm2skU6D5yVJruusH0mJ_HpuavI7k77truIm16w6f_vQweSYx6SnlT8gGOHDzT7ebO6nXg8D-DINqJM1rdkgDLeJuT17S2QYWno0c9pve4gnhIK5cZCO2r86adZX2FFeudnWCfWtFqe4tTEG-xFnS-qpC4Y_Ki7TB19ItxH6-bLWWc-k2jVcsTcNgY9EeB_gGlRbzAUgEQmMLxdyZu2M2Y2SPnd0PW09YeVqD_4Q + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:35:22 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0MmE3YjQyMy02Njc0LTRmZmItOGQzNi1mMGY1M2ZlNWMyZDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzg0MjIsImV4cCI6MTYxNzA1MDEyMiwiaWF0IjoxNjE3MDM4NDIyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ajVjufqmwhT1zxtUFmOgkdn02mfWpwLc2Gku2mSeNRMMseDhCE-7zI_VHjvgDGyJVaUtghN-nF7NyT5FqHff667ZqHcdBPkjRu_ByiJxHQgSl6sbdOh_DV22fsaSxgwwNJgWBheGkFqCpIv-QqBTuZ4jpgtUKUY2PtxHRUER351RugYYPZUhcntFbFbcZsRUm6aolb1QSjoP5rDTxiQXooH6uCV7Kr-iochmxLLZLW7FZcPPunTEVKDKQabVIbR9Ebce72AsI3u8c-BQmghLTgYt3F7EIQiVWt3tfB7pMhnOb1NZy1U0XTSspIPoivaYAYgMyfK4q_ypg-lMcokOUA + scope: repository:does_not_exist:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:35:22 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/acr/v1/does_not_exist + response: + body: + string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known + to registry","detail":{"name":"does_not_exist"}}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '122' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 17:35:22 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 404 + message: Not Found + url: https://seankane.azurecr.io/acr/v1/does_not_exist +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index eddad8a8df7d..ec90ccea803b 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -25,6 +25,7 @@ PowerShellPreparer, "containerregistry", containerregistry_baseurl="fake_url.azurecr.io", + containerregistry_resource_group="fake_rg", ) @@ -47,18 +48,19 @@ def test_list_repositories(self, containerregistry_baseurl): assert count > 0 - @pytest.mark.skip("Don't want to delete for now") @acr_preparer() - def test_delete_repository(self, containerregistry_baseurl): + def test_delete_repository(self, containerregistry_baseurl, containerregistry_resource_group): + self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + self.sleep(5) + client = self.create_registry_client(containerregistry_baseurl) - deleted_result = client.delete_repository("debian") + deleted_result = client.delete_repository("to_be_deleted") assert isinstance(deleted_result, DeletedRepositoryResult) - assert len(deleted_result.deleted_registry_artifact_digests) == 1 + assert len(deleted_result.deleted_registry_artifact_digests) == 10 assert len(deleted_result.deleted_tags) == 1 - - @pytest.mark.skip("Don't want to for now") + assert deleted_result.deleted_tags[0] == "to_be_deleted" @acr_preparer() def test_delete_repository_does_not_exist(self, containerregistry_baseurl): diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py index 4a9a3872b237..052a070bc3fb 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py @@ -26,6 +26,7 @@ PowerShellPreparer, "containerregistry", containerregistry_baseurl="fake_url.azurecr.io", + containerregistry_resource_group="fake_rg", ) @@ -47,16 +48,19 @@ async def test_list_repositories(self, containerregistry_baseurl): assert count > 0 - @pytest.mark.skip("Don't want to delete for now") @acr_preparer() - def test_delete_repository(self, containerregistry_baseurl): + async def test_delete_repository(self, containerregistry_baseurl, containerregistry_resource_group): + self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + self.sleep(5) + client = self.create_registry_client(containerregistry_baseurl) - deleted_result = client.delete_repository("debian") + deleted_result = await client.delete_repository("to_be_deleted") assert isinstance(deleted_result, DeletedRepositoryResult) - assert len(deleted_result.deleted_registry_artifact_digests) == 1 + assert len(deleted_result.deleted_registry_artifact_digests) == 10 assert len(deleted_result.deleted_tags) == 1 + assert deleted_result.deleted_tags[0] == "to_be_deleted" @acr_preparer() async def test_delete_repository_does_not_exist(self, containerregistry_baseurl): diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 43a37b7ac0f7..3d02f4b847ab 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -184,16 +184,27 @@ def test_set_tag_properties(self, containerregistry_baseurl): tags = client.set_manifest_properties() - @pytest.mark.skip("Don't want to delete right now") @acr_preparer() - def test_delete_repository(self, containerregistry_baseurl): - client = self.create_repository_client(containerregistry_baseurl, self.repository) - client.delete() + def test_delete_repository(self, containerregistry_baseurl, containerregistry_resource_group): + TO_BE_DELETED = "to_be_deleted" + + self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + + reg_client = self.create_registry_client(containerregistry_baseurl) + existing_repos = list(reg_client.list_repositories()) + assert TO_BE_DELETED in existing_repos - repo_client = self.create_registry_client(containerregistry_baseurl) + repo_client = self.create_repository_client(containerregistry_baseurl, TO_BE_DELETED) + repo_client.delete() + self.sleep(5) - repo_count = 0 - for repo in repo_client.list_repositories(): - repo_count += 1 + existing_repos = list(reg_client.list_repositories()) + assert TO_BE_DELETED not in existing_repos - assert repo_count == 0 + @acr_preparer() + def test_delete_repository_doesnt_exist(self, containerregistry_baseurl): + DOES_NOT_EXIST = "does_not_exist" + + repo_client = self.create_repository_client(containerregistry_baseurl, DOES_NOT_EXIST) + with pytest.raises(ResourceNotFoundError): + repo_client.delete() \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py index 00dd12f1f7b6..9088366751c0 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py @@ -53,4 +53,33 @@ async def test_delete_tag(self, containerregistry_baseurl, containerregistry_res self.sleep(10) with pytest.raises(ResourceNotFoundError): - await client.get_tag_properties("to_be_deleted") \ No newline at end of file + await client.get_tag_properties("to_be_deleted") + + @acr_preparer() + async def test_delete_repository(self, containerregistry_baseurl, containerregistry_resource_group): + TO_BE_DELETED = "to_be_deleted" + + self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + + reg_client = self.create_registry_client(containerregistry_baseurl) + existing_repos = [] + async for repo in reg_client.list_repositories(): + existing_repos.append(repo) + assert TO_BE_DELETED in existing_repos + + repo_client = self.create_repository_client(containerregistry_baseurl, TO_BE_DELETED) + await repo_client.delete() + self.sleep(5) + + existing_repos = [] + async for repo in reg_client.list_repositories(): + existing_repos.append(repo) + assert TO_BE_DELETED not in existing_repos + + @acr_preparer() + async def test_delete_repository_doesnt_exist(self, containerregistry_baseurl): + DOES_NOT_EXIST = "does_not_exist" + + repo_client = self.create_repository_client(containerregistry_baseurl, DOES_NOT_EXIST) + with pytest.raises(ResourceNotFoundError): + await repo_client.delete() diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index c827745f0c6b..4bff37072655 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -108,6 +108,30 @@ def sleep(self, t): def _fake_sleep(self, *args, **kwargs): pass + def import_repo_to_be_deleted( + self, endpoint, repository="to_be_deleted", resource_group="fake_rg" + ): + if not self.is_live: + return + registry = endpoint.split(".")[0] + command = [ + "powershell.exe", + "Import-AzcontainerRegistryImage", + "-ResourceGroupName", + "'{}'".format(resource_group), + "-RegistryName", + "'{}'".format(registry), + "-SourceImage", + "'library/hello-world'", + "-SourceRegistryUri", + "'registry.hub.docker.com'", + "-TargetTag", + "'{}:to_be_deleted'".format(repository), + "-Mode", + "'Force'", + ] + subprocess.check_call(command) + def _import_tag_to_be_deleted( self, endpoint, repository="hello-world", resource_group="fake_rg" ): From 510a046228d336ba31b959c515bddd3b4a7bd8eb Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Mon, 29 Mar 2021 14:51:35 -0400 Subject: [PATCH 81/86] regenerated from autorest, added delete artifact method to sync and async --- .../_container_repository_client.py | 4 +- ...ontainer_registry_repository_operations.py | 2 +- .../_generated/models/__init__.py | 7 + .../models/_container_registry_enums.py | 24 +- .../_generated/models/_models.py | 80 ++- .../_generated/models/_models_py3.py | 90 ++-- ...ontainer_registry_repository_operations.py | 2 +- .../azure/containerregistry/_models.py | 8 +- .../aio/_async_container_repository_client.py | 4 +- .../tests/constants.py | 7 + ..._client.test_delete_registry_artifact.yaml | 488 ++++++++++++++++++ ...t_async.test_delete_registry_artifact.yaml | 332 ++++++++++++ .../tests/test_container_registry_client.py | 5 +- .../test_container_registry_client_async.py | 5 +- .../tests/test_container_repository_client.py | 32 +- .../test_container_repository_client_async.py | 29 +- 16 files changed, 991 insertions(+), 128 deletions(-) create mode 100644 sdk/containerregistry/azure-containerregistry/tests/constants.py create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml create mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 33e1c06bb36a..da69b3bbc9e0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -52,14 +52,14 @@ def delete(self, **kwargs): def delete_registry_artifact(self, digest, **kwargs): # type: (str) -> None - """Delete a registry artifact + """Delete a registry artifact. A registry artifact can only be deleted from the digest :param digest: The digest of the artifact to be deleted :type digest: str :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - raise NotImplementedError("Has not been implemented") + self._client.container_registry_repository.delete_manifest(self.repository, digest) def delete_tag(self, tag, **kwargs): # type: (str) -> None diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index a5e395308f25..c014049daa73 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -413,7 +413,7 @@ def prepare_request(next_link=None): async def extract_data(pipeline_response): deserialized = self._deserialize('TagList', pipeline_response) - list_of_elem = deserialized.tags + list_of_elem = deserialized.tag_attribute_bases if cls: list_of_elem = cls(list_of_elem) return deserialized.link or None, AsyncList(list_of_elem) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py index fb30b2eeac5e..c3bf522b9e15 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/__init__.py @@ -81,6 +81,11 @@ from ._models import V1Manifest # type: ignore from ._models import V2Manifest # type: ignore +from ._container_registry_enums import ( + RegistryArtifactOrderBy, + TagOrderBy, +) + __all__ = [ 'AcrAccessToken', 'AcrErrorInfo', @@ -119,4 +124,6 @@ 'TagProperties', 'V1Manifest', 'V2Manifest', + 'RegistryArtifactOrderBy', + 'TagOrderBy', ] diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py index 4f9b6bfb490f..57139852c30f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py @@ -1,8 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) AutoRest Code Generator. +# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- @@ -26,10 +24,20 @@ def __getattr__(cls, name): raise AttributeError(name) -class PostContentSchemaGrantType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): - """Can take a value of access_token_refresh_token, or access_token, or refresh_token +class RegistryArtifactOrderBy(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + """Sort options for ordering registry artifacts in a collection. """ - ACCESS_TOKEN_REFRESH_TOKEN = "access_token_refresh_token" - ACCESS_TOKEN = "access_token" - REFRESH_TOKEN = "refresh_token" + #: Order registry artifacts by LastUpdatedOn field, from most recently updated to least recently + #: updated. + LAST_UPDATED_ON_DESCENDING = "timedesc" + #: Order registry artifacts by LastUpdatedOn field, from least recently updated to most recently + #: updated. + LAST_UPDATED_ON_ASCENDING = "timeasc" + +class TagOrderBy(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + + #: Order tags by LastUpdatedOn field, from most recently updated to least recently updated. + LAST_UPDATED_ON_DESCENDING = "timedesc" + #: Order tags by LastUpdatedOn field, from least recently updated to most recently updated. + LAST_UPDATED_ON_ASCENDING = "timeasc" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 81934d82941b..83e99e730925 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -191,7 +191,7 @@ def __init__( class ContentProperties(msrest.serialization.Model): - """ContentProperties. + """Changeable attributes. :param can_delete: Delete enabled. :type can_delete: bool @@ -438,18 +438,16 @@ class ManifestAttributesBase(msrest.serialization.Model): :type cpu_architecture: str :param operating_system: Operating system. :type operating_system: str - :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] - :param tags: Required. A set of tags. List of tags. + :param references: List of manifest attributes details. + :type references: list[~container_registry.models.ManifestAttributesManifestReferences] + :param tags: A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~container_registry.models.ContentProperties + :param writeable_properties: Writeable properties of the resource. + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { 'digest': {'required': True}, - 'tags': {'required': True}, - 'manifest_properties': {'required': True}, } _attribute_map = { @@ -459,9 +457,9 @@ class ManifestAttributesBase(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, 'operating_system': {'key': 'os', 'type': 'str'}, - 'registry_artifacts': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, + 'references': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -475,9 +473,9 @@ def __init__( self.last_updated_on = kwargs.get('last_updated_on', None) self.cpu_architecture = kwargs.get('cpu_architecture', None) self.operating_system = kwargs.get('operating_system', None) - self.registry_artifacts = kwargs.get('registry_artifacts', None) - self.tags = kwargs['tags'] - self.manifest_properties = kwargs['manifest_properties'] + self.references = kwargs.get('references', None) + self.tags = kwargs.get('tags', None) + self.writeable_properties = kwargs.get('writeable_properties', None) class ManifestAttributesManifest(msrest.serialization.Model): @@ -887,11 +885,9 @@ def __init__( class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. - All required parameters must be populated in order to send to Azure. - - :param repository: Required. Image name. + :param repository: Image name. :type repository: str - :param digest: Required. Manifest. + :param digest: Manifest. :type digest: str :param size: Image size. :type size: long @@ -903,21 +899,14 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type cpu_architecture: str :param operating_system: Operating system. :type operating_system: str - :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] - :param tags: Required. A set of tags. List of tags. + :param references: List of manifest attributes details. + :type references: list[~container_registry.models.ManifestAttributesManifestReferences] + :param tags: A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~container_registry.models.ContentProperties + :param writeable_properties: Writeable properties of the resource. + :type writeable_properties: ~container_registry.models.ContentProperties """ - _validation = { - 'repository': {'required': True}, - 'digest': {'required': True}, - 'tags': {'required': True}, - 'manifest_properties': {'required': True}, - } - _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'digest': {'key': 'manifest.digest', 'type': 'str'}, @@ -926,9 +915,9 @@ class RegistryArtifactProperties(msrest.serialization.Model): 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'registry_artifacts': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, + 'references': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'manifest.tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -936,16 +925,16 @@ def __init__( **kwargs ): super(RegistryArtifactProperties, self).__init__(**kwargs) - self.repository = kwargs['repository'] - self.digest = kwargs['digest'] + self.repository = kwargs.get('repository', None) + self.digest = kwargs.get('digest', None) self.size = kwargs.get('size', None) self.created_on = kwargs.get('created_on', None) self.last_updated_on = kwargs.get('last_updated_on', None) self.cpu_architecture = kwargs.get('cpu_architecture', None) self.operating_system = kwargs.get('operating_system', None) - self.registry_artifacts = kwargs.get('registry_artifacts', None) - self.tags = kwargs['tags'] - self.manifest_properties = kwargs['manifest_properties'] + self.references = kwargs.get('references', None) + self.tags = kwargs.get('tags', None) + self.writeable_properties = kwargs.get('writeable_properties', None) class Repositories(msrest.serialization.Model): @@ -980,19 +969,20 @@ class RepositoryProperties(msrest.serialization.Model): :type name: str :param created_on: Required. Image created time. :type created_on: ~datetime.datetime - :param last_updated_on: Image last update time. + :param last_updated_on: Required. Image last update time. :type last_updated_on: ~datetime.datetime :param registry_artifact_count: Required. Number of the manifests. :type registry_artifact_count: int :param tag_count: Required. Number of the tags. :type tag_count: int - :param writeable_properties: Required. Changeable attributes. + :param writeable_properties: Required. Writeable properties of the resource. :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { 'name': {'required': True}, 'created_on': {'required': True}, + 'last_updated_on': {'required': True}, 'registry_artifact_count': {'required': True}, 'tag_count': {'required': True}, 'writeable_properties': {'required': True}, @@ -1014,7 +1004,7 @@ def __init__( super(RepositoryProperties, self).__init__(**kwargs) self.name = kwargs['name'] self.created_on = kwargs['created_on'] - self.last_updated_on = kwargs.get('last_updated_on', None) + self.last_updated_on = kwargs['last_updated_on'] self.registry_artifact_count = kwargs['registry_artifact_count'] self.tag_count = kwargs['tag_count'] self.writeable_properties = kwargs['writeable_properties'] @@ -1056,7 +1046,7 @@ class TagAttributesBase(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime - :param writeable_properties: Changeable attributes. + :param writeable_properties: Writeable properties of the resource. :type writeable_properties: ~container_registry.models.ContentProperties """ @@ -1111,8 +1101,8 @@ class TagList(msrest.serialization.Model): :param repository: Required. Image name. :type repository: str - :param tags: A set of tags. List of tag attribute details. - :type tags: list[~container_registry.models.TagAttributesBase] + :param tag_attribute_bases: List of tag attribute details. + :type tag_attribute_bases: list[~container_registry.models.TagAttributesBase] :param link: :type link: str """ @@ -1123,7 +1113,7 @@ class TagList(msrest.serialization.Model): _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, - 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, + 'tag_attribute_bases': {'key': 'tags', 'type': '[TagAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -1133,7 +1123,7 @@ def __init__( ): super(TagList, self).__init__(**kwargs) self.repository = kwargs['repository'] - self.tags = kwargs.get('tags', None) + self.tag_attribute_bases = kwargs.get('tag_attribute_bases', None) self.link = kwargs.get('link', None) @@ -1152,7 +1142,7 @@ class TagProperties(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime - :param writeable_properties: Changeable attributes. + :param writeable_properties: Writeable properties of the resource. :type writeable_properties: ~container_registry.models.ContentProperties """ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index 8fe23c8756ef..78b68a6a44ec 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -222,7 +222,7 @@ def __init__( class ContentProperties(msrest.serialization.Model): - """ContentProperties. + """Changeable attributes. :param can_delete: Delete enabled. :type can_delete: bool @@ -502,18 +502,16 @@ class ManifestAttributesBase(msrest.serialization.Model): :type cpu_architecture: str :param operating_system: Operating system. :type operating_system: str - :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] - :param tags: Required. A set of tags. List of tags. + :param references: List of manifest attributes details. + :type references: list[~container_registry.models.ManifestAttributesManifestReferences] + :param tags: A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~container_registry.models.ContentProperties + :param writeable_properties: Writeable properties of the resource. + :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { 'digest': {'required': True}, - 'tags': {'required': True}, - 'manifest_properties': {'required': True}, } _attribute_map = { @@ -523,23 +521,23 @@ class ManifestAttributesBase(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, 'operating_system': {'key': 'os', 'type': 'str'}, - 'registry_artifacts': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, + 'references': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( self, *, digest: str, - tags: List[str], - manifest_properties: "ContentProperties", size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, cpu_architecture: Optional[str] = None, operating_system: Optional[str] = None, - registry_artifacts: Optional[List["ManifestAttributesManifestReferences"]] = None, + references: Optional[List["ManifestAttributesManifestReferences"]] = None, + tags: Optional[List[str]] = None, + writeable_properties: Optional["ContentProperties"] = None, **kwargs ): super(ManifestAttributesBase, self).__init__(**kwargs) @@ -549,9 +547,9 @@ def __init__( self.last_updated_on = last_updated_on self.cpu_architecture = cpu_architecture self.operating_system = operating_system - self.registry_artifacts = registry_artifacts + self.references = references self.tags = tags - self.manifest_properties = manifest_properties + self.writeable_properties = writeable_properties class ManifestAttributesManifest(msrest.serialization.Model): @@ -1020,11 +1018,9 @@ def __init__( class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. - All required parameters must be populated in order to send to Azure. - - :param repository: Required. Image name. + :param repository: Image name. :type repository: str - :param digest: Required. Manifest. + :param digest: Manifest. :type digest: str :param size: Image size. :type size: long @@ -1036,21 +1032,14 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type cpu_architecture: str :param operating_system: Operating system. :type operating_system: str - :param registry_artifacts: List of manifest attributes details. - :type registry_artifacts: list[~container_registry.models.ManifestAttributesManifestReferences] - :param tags: Required. A set of tags. List of tags. + :param references: List of manifest attributes details. + :type references: list[~container_registry.models.ManifestAttributesManifestReferences] + :param tags: A set of tags. List of tags. :type tags: list[str] - :param manifest_properties: Required. Changeable attributes. - :type manifest_properties: ~container_registry.models.ContentProperties + :param writeable_properties: Writeable properties of the resource. + :type writeable_properties: ~container_registry.models.ContentProperties """ - _validation = { - 'repository': {'required': True}, - 'digest': {'required': True}, - 'tags': {'required': True}, - 'manifest_properties': {'required': True}, - } - _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'digest': {'key': 'manifest.digest', 'type': 'str'}, @@ -1059,24 +1048,24 @@ class RegistryArtifactProperties(msrest.serialization.Model): 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'registry_artifacts': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, + 'references': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'manifest.tags', 'type': '[str]'}, - 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, + 'writeable_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, } def __init__( self, *, - repository: str, - digest: str, - tags: List[str], - manifest_properties: "ContentProperties", + repository: Optional[str] = None, + digest: Optional[str] = None, size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, cpu_architecture: Optional[str] = None, operating_system: Optional[str] = None, - registry_artifacts: Optional[List["ManifestAttributesManifestReferences"]] = None, + references: Optional[List["ManifestAttributesManifestReferences"]] = None, + tags: Optional[List[str]] = None, + writeable_properties: Optional["ContentProperties"] = None, **kwargs ): super(RegistryArtifactProperties, self).__init__(**kwargs) @@ -1087,9 +1076,9 @@ def __init__( self.last_updated_on = last_updated_on self.cpu_architecture = cpu_architecture self.operating_system = operating_system - self.registry_artifacts = registry_artifacts + self.references = references self.tags = tags - self.manifest_properties = manifest_properties + self.writeable_properties = writeable_properties class Repositories(msrest.serialization.Model): @@ -1127,19 +1116,20 @@ class RepositoryProperties(msrest.serialization.Model): :type name: str :param created_on: Required. Image created time. :type created_on: ~datetime.datetime - :param last_updated_on: Image last update time. + :param last_updated_on: Required. Image last update time. :type last_updated_on: ~datetime.datetime :param registry_artifact_count: Required. Number of the manifests. :type registry_artifact_count: int :param tag_count: Required. Number of the tags. :type tag_count: int - :param writeable_properties: Required. Changeable attributes. + :param writeable_properties: Required. Writeable properties of the resource. :type writeable_properties: ~container_registry.models.ContentProperties """ _validation = { 'name': {'required': True}, 'created_on': {'required': True}, + 'last_updated_on': {'required': True}, 'registry_artifact_count': {'required': True}, 'tag_count': {'required': True}, 'writeable_properties': {'required': True}, @@ -1159,10 +1149,10 @@ def __init__( *, name: str, created_on: datetime.datetime, + last_updated_on: datetime.datetime, registry_artifact_count: int, tag_count: int, writeable_properties: "ContentProperties", - last_updated_on: Optional[datetime.datetime] = None, **kwargs ): super(RepositoryProperties, self).__init__(**kwargs) @@ -1213,7 +1203,7 @@ class TagAttributesBase(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime - :param writeable_properties: Changeable attributes. + :param writeable_properties: Writeable properties of the resource. :type writeable_properties: ~container_registry.models.ContentProperties """ @@ -1276,8 +1266,8 @@ class TagList(msrest.serialization.Model): :param repository: Required. Image name. :type repository: str - :param tags: A set of tags. List of tag attribute details. - :type tags: list[~container_registry.models.TagAttributesBase] + :param tag_attribute_bases: List of tag attribute details. + :type tag_attribute_bases: list[~container_registry.models.TagAttributesBase] :param link: :type link: str """ @@ -1288,7 +1278,7 @@ class TagList(msrest.serialization.Model): _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, - 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, + 'tag_attribute_bases': {'key': 'tags', 'type': '[TagAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -1296,13 +1286,13 @@ def __init__( self, *, repository: str, - tags: Optional[List["TagAttributesBase"]] = None, + tag_attribute_bases: Optional[List["TagAttributesBase"]] = None, link: Optional[str] = None, **kwargs ): super(TagList, self).__init__(**kwargs) self.repository = repository - self.tags = tags + self.tag_attribute_bases = tag_attribute_bases self.link = link @@ -1321,7 +1311,7 @@ class TagProperties(msrest.serialization.Model): :type created_on: ~datetime.datetime :param last_updated_on: Required. Tag last update time. :type last_updated_on: ~datetime.datetime - :param writeable_properties: Changeable attributes. + :param writeable_properties: Writeable properties of the resource. :type writeable_properties: ~container_registry.models.ContentProperties """ diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index 36968b545726..afc76777c046 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -423,7 +423,7 @@ def prepare_request(next_link=None): def extract_data(pipeline_response): deserialized = self._deserialize('TagList', pipeline_response) - list_of_elem = deserialized.tags + list_of_elem = deserialized.tag_attribute_bases if cls: list_of_elem = cls(list_of_elem) return deserialized.link or None, iter(list_of_elem) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py index 44f679dcd544..622925bb3f70 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_models.py @@ -61,10 +61,10 @@ def __init__(self, **kwargs): self.digest = kwargs.get("digest", None) self.last_updated_on = kwargs.get("last_updated_on", None) self.operating_system = kwargs.get("operating_system", None) - self.registry_artifacts = kwargs.get("registry_artifacts", None) + self.references = kwargs.get("references", None) self.size = kwargs.get("size", None) self.tags = kwargs.get("tags", None) - self.content_permissions = kwargs.get("manifest_properties", None) + self.content_permissions = kwargs.get("content_permissions", None) if self.content_permissions: self.content_permissions = ContentPermissions._from_generated(self.content_permissions) @@ -76,11 +76,11 @@ def _from_generated(cls, generated): created_on=generated.created_on, digest=generated.digest, last_updated_on=generated.last_updated_on, - manifest_properties=generated.manifest_properties, operating_system=generated.operating_system, - registry_artifacts=generated.registry_artifacts, + references=generated.references, size=generated.size, tags=generated.tags, + content_permissions=generated.writeable_properties, ) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 6782ac714241..014c0c6f37d9 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -45,7 +45,7 @@ async def delete(self, **kwargs): """ await self._client.container_registry.delete_repository(self.repository, **kwargs) - def delete_registry_artifact(self, digest, **kwargs): + async def delete_registry_artifact(self, digest, **kwargs): # type: (str) -> None """Delete a registry artifact @@ -54,7 +54,7 @@ def delete_registry_artifact(self, digest, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - raise NotImplementedError("Has not been implemented") + await self._client.container_registry_repository.delete_manifest(self.repository, digest) async def delete_tag(self, tag, **kwargs): # type: (str) -> None diff --git a/sdk/containerregistry/azure-containerregistry/tests/constants.py b/sdk/containerregistry/azure-containerregistry/tests/constants.py new file mode 100644 index 000000000000..2412921b1631 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/constants.py @@ -0,0 +1,7 @@ +# coding=utf-8 +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +TO_BE_DELETED = "to_be_deleted" \ No newline at end of file diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml new file mode 100644 index 000000000000..ce5ef3aa66d0 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml @@ -0,0 +1,488 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '216' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:38 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:40 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ato_be_deleted%3Ametadata_read&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1081' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:40 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-29T18:46:36.2585193Z","lastUpdateTime":"2021-03-29T18:46:36.2585193Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:41 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/v2/to_be_deleted/manifests/sha256%3A1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '209' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:41 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:41 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ato_be_deleted%3Adelete&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1074' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:41 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/v2/to_be_deleted/manifests/sha256%3A1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 + response: + body: + string: '' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '0' + date: + - Mon, 29 Mar 2021 18:49:42 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-length: + - '216' + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:42 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: + - nosniff + status: + code: 401 + message: Unauthorized +- request: + body: grant_type=access_token&service=seankane.azurecr.io&access_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1343' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:42 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: grant_type=refresh_token&service=seankane.azurecr.io&scope=repository%3Ato_be_deleted%3Ametadata_read&refresh_token=REDACTED + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '1081' + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:43 GMT + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: + - Docker-Content-Digest + - WWW-Authenticate + - Link + - X-Ms-Correlation-Request-Id + connection: + - keep-alive + content-type: + - application/json; charset=utf-8 + date: + - Mon, 29 Mar 2021 18:49:43 GMT + docker-distribution-api-version: + - registry/2.0 + server: + - openresty + strict-transport-security: + - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml new file mode 100644 index 000000000000..5aad39fddfb4 --- /dev/null +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml @@ -0,0 +1,332 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '216' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:00 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/to_be_deleted/_manifests +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwNDM1MDAsIm5iZiI6MTYxNzA0MzUwMCwiZXhwIjoxNjE3MTMwMjAwLCJhaW8iOiJFMlpnWURpbzlzdFQ5NXFRUVVkK3hWSHRULy8xQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT3EydzMyVi14VXVqc0FrNm94Y0VBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.hWjWRe_6O2wql1pkNnQKG1oW1a3Z3SckZ6OZMIMM_LuporkwdltV7mK4FIdB5635Zyk8z2OjAuVGYFnReAcJUhOR0JoT6Xtf90cfH8TWSKvkw5iqUtBQfI_ZtKzfSHMQwoRDsdsFmgVeka_QlZmUhSffcUCEcBOiBbCEHeKy2SX8jTX4iNmDYW2DnLw_TTA5LJhTItY_U9imPZzuYoAe2d8ctOgYpBPWRDOgwAnjJBzALPi1o3BTjhoVSlcpioXoP8A0h-hVmNz77zehcQ8A2R0tSCfWZ3sNDevkj5cC5c7fCqHX7K26w4LdRCpollDZkm-4IoIMnuQOtTPXUhQ3aQ + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:01 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyZTcxMTViZS1mMDZkLTQ2MmQtOGRkOS03MmExZmFkNTBkYzQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwNDI5MDEsImV4cCI6MTYxNzA1NDYwMSwiaWF0IjoxNjE3MDQyOTAxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Zbqym1oarG3-7UyAP9oq7He6Fyw_e5ZhtlYlOwRKiXS0tJO8KTCqshja6ahY729Di-fk4RNnXIMXtS9lG4ZZuCs-3zTJvA1s0KnZoxaj34qjXdW8I1MYp1VM34DxTgjGX208zwcEuTK6uMB5b6v-4fd5bYUzYMk3T4_DwXH5pLUkSSqPxp0B1C9FVQ1EY59MZu4W2-8E73DSF4yBnTuZeI8KqNo9UCrP392L1avAQvywHfRCrPySYSKnbx23MIn23F1zEkZRHsP-NVivhppUFgUNXoLpW76mwVBYf2lHRg2jMbMDjMP1HjnyUowxpO0nzVnuMq6Ew6uWAA2PVzTIHw + scope: repository:to_be_deleted:metadata_read + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:01 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-29T18:49:54.088615Z","lastUpdateTime":"2021-03-29T18:49:54.088615Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:01 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/to_be_deleted/_manifests +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/v2/to_be_deleted/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"delete"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '209' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:02 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/v2/to_be_deleted/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwNDM1MDAsIm5iZiI6MTYxNzA0MzUwMCwiZXhwIjoxNjE3MTMwMjAwLCJhaW8iOiJFMlpnWURpbzlzdFQ5NXFRUVVkK3hWSHRULy8xQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT3EydzMyVi14VXVqc0FrNm94Y0VBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.hWjWRe_6O2wql1pkNnQKG1oW1a3Z3SckZ6OZMIMM_LuporkwdltV7mK4FIdB5635Zyk8z2OjAuVGYFnReAcJUhOR0JoT6Xtf90cfH8TWSKvkw5iqUtBQfI_ZtKzfSHMQwoRDsdsFmgVeka_QlZmUhSffcUCEcBOiBbCEHeKy2SX8jTX4iNmDYW2DnLw_TTA5LJhTItY_U9imPZzuYoAe2d8ctOgYpBPWRDOgwAnjJBzALPi1o3BTjhoVSlcpioXoP8A0h-hVmNz77zehcQ8A2R0tSCfWZ3sNDevkj5cC5c7fCqHX7K26w4LdRCpollDZkm-4IoIMnuQOtTPXUhQ3aQ + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:02 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0OWU5MDAxYS1hNWNkLTRiNmItOWU4NC1mMmM1YjNkODdlYzgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwNDI5MDIsImV4cCI6MTYxNzA1NDYwMiwiaWF0IjoxNjE3MDQyOTAyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gQ0SKisCvhSWqJMEifR6kY1iMO0Xp36JcD2fRjuIp72c5EsBbXRNv7LSe04KBAjVINHAwnlWvqoGPqzaZIWkd5X3J_rA145cJe3TZYW5XJqD_jqDeOLRC2HHaMGFW0aghSJvRVMn8k4nkwTwOTFJk24VkVk2Pio4I1awucQnB7DgQEj48JNyQsdudp5qP9V4RBuCEFGtAEeZJZ5R3_G1oJl_B4L8n4bShT5Rswk5g3OWndVjWWCKlDm69BrWEZD2MX_n593wt7pqbgbfhAcWAyuYnool41OT7jLjeHQp52wNp9yKFPUm3p-6Yi1WjesZdocUNGM5RKJ-PMlh89VAXg + scope: repository:to_be_deleted:delete + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:02 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: DELETE + uri: https://fake_url.azurecr.io/v2/to_be_deleted/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 + response: + body: + string: '' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '0' + date: Mon, 29 Mar 2021 18:50:02 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + status: + code: 202 + message: Accepted + url: https://seankane.azurecr.io/v2/to_be_deleted/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, + visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"to_be_deleted","Action":"metadata_read"}]}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-length: '216' + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:02 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" + x-content-type-options: nosniff + status: + code: 401 + message: Unauthorized + url: https://seankane.azurecr.io/acr/v1/to_be_deleted/_manifests +- request: + body: + access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwNDM1MDAsIm5iZiI6MTYxNzA0MzUwMCwiZXhwIjoxNjE3MTMwMjAwLCJhaW8iOiJFMlpnWURpbzlzdFQ5NXFRUVVkK3hWSHRULy8xQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT3EydzMyVi14VXVqc0FrNm94Y0VBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.hWjWRe_6O2wql1pkNnQKG1oW1a3Z3SckZ6OZMIMM_LuporkwdltV7mK4FIdB5635Zyk8z2OjAuVGYFnReAcJUhOR0JoT6Xtf90cfH8TWSKvkw5iqUtBQfI_ZtKzfSHMQwoRDsdsFmgVeka_QlZmUhSffcUCEcBOiBbCEHeKy2SX8jTX4iNmDYW2DnLw_TTA5LJhTItY_U9imPZzuYoAe2d8ctOgYpBPWRDOgwAnjJBzALPi1o3BTjhoVSlcpioXoP8A0h-hVmNz77zehcQ8A2R0tSCfWZ3sNDevkj5cC5c7fCqHX7K26w4LdRCpollDZkm-4IoIMnuQOtTPXUhQ3aQ + grant_type: access_token + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/exchange + response: + body: + string: '{"refresh_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:03 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/exchange +- request: + body: + grant_type: refresh_token + refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMmIyMGYxYi01NTU2LTRkYmUtYTFhOS04ZjBlYzQ2YWU0NGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwNDI5MDMsImV4cCI6MTYxNzA1NDYwMywiaWF0IjoxNjE3MDQyOTAzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.l0Q4Za29p7rbLlVmQTPCUVNogglznakiRH2r9UzNSeMIR8lCCxvLdlwcSufk8Yl9Z1Qm77tonTQDAiCQUq0zGlB3WR7RJtMpeIaQFoyQM0k-b4-i0HNSrYvYDS30WoJg7456gE5yPx27ZsJnQbl8HdZWPxPvu7QeMtRrLoTxtVJ4ivbt-LuoCtKuRpV2PV0lwUk2CiZUPTv0Pj8ClliwqZfCm1N-tE5wGeGqaI3xigoP6kCEe-m0UwGBa8UgTR2AXFgHCX94O2t8G6SsXdoLR2BfBV3yOou_bHAMclKxGpQutRjqnn4QN6-sDmO1wdecbZD-tn1a8H3Dvm3dZuasKg + scope: repository:to_be_deleted:metadata_read + service: seankane.azurecr.io + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://fake_url.azurecr.io/oauth2/token + response: + body: + string: '{"access_token": "REDACTED"}' + headers: + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:03 GMT + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/oauth2/token +- request: + body: null + headers: + Accept: + - application/json + User-Agent: + - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) + method: GET + uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests + response: + body: + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + + ' + headers: + access-control-expose-headers: X-Ms-Correlation-Request-Id + connection: keep-alive + content-type: application/json; charset=utf-8 + date: Mon, 29 Mar 2021 18:50:03 GMT + docker-distribution-api-version: registry/2.0 + server: openresty + strict-transport-security: max-age=31536000; includeSubDomains + transfer-encoding: chunked + x-content-type-options: nosniff + status: + code: 200 + message: OK + url: https://seankane.azurecr.io/acr/v1/to_be_deleted/_manifests +version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py index ec90ccea803b..a2834fcaf0c7 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client.py @@ -19,6 +19,7 @@ from azure.identity import DefaultAzureCredential from testcase import ContainerRegistryTestClass +from constants import TO_BE_DELETED acr_preparer = functools.partial( @@ -55,12 +56,12 @@ def test_delete_repository(self, containerregistry_baseurl, containerregistry_re client = self.create_registry_client(containerregistry_baseurl) - deleted_result = client.delete_repository("to_be_deleted") + deleted_result = client.delete_repository(TO_BE_DELETED) assert isinstance(deleted_result, DeletedRepositoryResult) assert len(deleted_result.deleted_registry_artifact_digests) == 10 assert len(deleted_result.deleted_tags) == 1 - assert deleted_result.deleted_tags[0] == "to_be_deleted" + assert deleted_result.deleted_tags[0] == TO_BE_DELETED @acr_preparer() def test_delete_repository_does_not_exist(self, containerregistry_baseurl): diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py index 052a070bc3fb..0bf8e9613d08 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_registry_client_async.py @@ -20,6 +20,7 @@ from azure.identity.aio import DefaultAzureCredential from asynctestcase import AsyncContainerRegistryTestClass +from constants import TO_BE_DELETED acr_preparer = functools.partial( @@ -55,12 +56,12 @@ async def test_delete_repository(self, containerregistry_baseurl, containerregis client = self.create_registry_client(containerregistry_baseurl) - deleted_result = await client.delete_repository("to_be_deleted") + deleted_result = await client.delete_repository(TO_BE_DELETED) assert isinstance(deleted_result, DeletedRepositoryResult) assert len(deleted_result.deleted_registry_artifact_digests) == 10 assert len(deleted_result.deleted_tags) == 1 - assert deleted_result.deleted_tags[0] == "to_be_deleted" + assert deleted_result.deleted_tags[0] == TO_BE_DELETED @acr_preparer() async def test_delete_repository_does_not_exist(self, containerregistry_baseurl): diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py index 3d02f4b847ab..0637076d576d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client.py @@ -25,6 +25,8 @@ from azure.core.paging import ItemPaged from testcase import ContainerRegistryTestClass, AcrBodyReplacer, FakeTokenCredential +from constants import TO_BE_DELETED + acr_preparer = functools.partial( PowerShellPreparer, @@ -48,14 +50,14 @@ def test_delete_tag(self, containerregistry_baseurl, containerregistry_resource_ client = self.create_repository_client(containerregistry_baseurl, "hello-world") - tag = client.get_tag_properties("to_be_deleted") + tag = client.get_tag_properties(TO_BE_DELETED) assert tag is not None - client.delete_tag("to_be_deleted") + client.delete_tag(TO_BE_DELETED) self.sleep(10) with pytest.raises(ResourceNotFoundError): - client.get_tag_properties("to_be_deleted") + client.get_tag_properties(TO_BE_DELETED) @acr_preparer() def test_get_attributes(self, containerregistry_baseurl): @@ -186,8 +188,6 @@ def test_set_tag_properties(self, containerregistry_baseurl): @acr_preparer() def test_delete_repository(self, containerregistry_baseurl, containerregistry_resource_group): - TO_BE_DELETED = "to_be_deleted" - self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) reg_client = self.create_registry_client(containerregistry_baseurl) @@ -207,4 +207,24 @@ def test_delete_repository_doesnt_exist(self, containerregistry_baseurl): repo_client = self.create_repository_client(containerregistry_baseurl, DOES_NOT_EXIST) with pytest.raises(ResourceNotFoundError): - repo_client.delete() \ No newline at end of file + repo_client.delete() + + @acr_preparer() + def test_delete_registry_artifact(self, containerregistry_baseurl, containerregistry_resource_group): + self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + + repo_client = self.create_repository_client(containerregistry_baseurl, TO_BE_DELETED) + + count = 0 + for artifact in repo_client.list_registry_artifacts(): + if count == 0: + repo_client.delete_registry_artifact(artifact.digest) + count += 1 + assert count > 0 + + artifacts = [] + for a in repo_client.list_registry_artifacts(): + artifacts.append(a) + + assert len(artifacts) > 0 + assert len(artifacts) == count - 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py index 9088366751c0..ae98c24cdcf1 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py @@ -22,6 +22,7 @@ from asynctestcase import AsyncContainerRegistryTestClass from testcase import AcrBodyReplacer +from constants import TO_BE_DELETED acr_preparer = functools.partial( @@ -46,19 +47,17 @@ async def test_delete_tag(self, containerregistry_baseurl, containerregistry_res client = self.create_repository_client(containerregistry_baseurl, "hello-world") - tag = await client.get_tag_properties("to_be_deleted") + tag = await client.get_tag_properties(TO_BE_DELETED) assert tag is not None - await client.delete_tag("to_be_deleted") + await client.delete_tag(TO_BE_DELETED) self.sleep(10) with pytest.raises(ResourceNotFoundError): - await client.get_tag_properties("to_be_deleted") + await client.get_tag_properties(TO_BE_DELETED) @acr_preparer() async def test_delete_repository(self, containerregistry_baseurl, containerregistry_resource_group): - TO_BE_DELETED = "to_be_deleted" - self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) reg_client = self.create_registry_client(containerregistry_baseurl) @@ -83,3 +82,23 @@ async def test_delete_repository_doesnt_exist(self, containerregistry_baseurl): repo_client = self.create_repository_client(containerregistry_baseurl, DOES_NOT_EXIST) with pytest.raises(ResourceNotFoundError): await repo_client.delete() + + @acr_preparer() + async def test_delete_registry_artifact(self, containerregistry_baseurl, containerregistry_resource_group): + self.import_repo_to_be_deleted(containerregistry_baseurl, resource_group=containerregistry_resource_group) + + repo_client = self.create_repository_client(containerregistry_baseurl, TO_BE_DELETED) + + count = 0 + async for artifact in repo_client.list_registry_artifacts(): + if count == 0: + await repo_client.delete_registry_artifact(artifact.digest) + count += 1 + assert count > 0 + + artifacts = [] + async for a in repo_client.list_registry_artifacts(): + artifacts.append(a) + + assert len(artifacts) > 0 + assert len(artifacts) == count - 1 \ No newline at end of file From 7ed4a0207c4b7edfff963d2eec736ba7069d8eb3 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 30 Mar 2021 08:36:12 -0400 Subject: [PATCH 82/86] fixing up recording files --- .../aio/_async_container_repository_client.py | 2 +- ...test_delete_repository_does_not_exist.yaml | 114 ------------------ ...registry_async.test_list_repositories.yaml | 113 ----------------- ...egistry_client.test_delete_repository.yaml | 8 +- ...test_delete_repository_does_not_exist.yaml | 8 +- ...egistry_client.test_list_repositories.yaml | 12 +- ...y_client_async.test_delete_repository.yaml | 12 +- ...test_delete_repository_does_not_exist.yaml | 12 +- ...y_client_async.test_list_repositories.yaml | 16 +-- ..._client.test_delete_registry_artifact.yaml | 28 ++--- ...ository_client.test_delete_repository.yaml | 32 ++--- ...t.test_delete_repository_doesnt_exist.yaml | 8 +- ...ner_repository_client.test_delete_tag.yaml | 26 ++-- ...repository_client.test_get_attributes.yaml | 12 +- ...repository_client.test_get_properties.yaml | 12 +- ...test_get_registry_artifact_properties.yaml | 28 ++--- ...tainer_repository_client.test_get_tag.yaml | 10 +- ...y_client.test_list_registry_artifacts.yaml | 10 +- ...iner_repository_client.test_list_tags.yaml | 12 +- ...tory_client.test_list_tags_descending.yaml | 12 +- ...y_client.test_set_manifest_properties.yaml | 62 +++++----- ...sitory_client.test_set_tag_properties.yaml | 46 ++++--- ...t_async.test_delete_registry_artifact.yaml | 40 +++--- ...y_client_async.test_delete_repository.yaml | 44 +++---- ...c.test_delete_repository_doesnt_exist.yaml | 12 +- ...pository_client_async.test_delete_tag.yaml | 40 +++--- .../azure-containerregistry/tests/testcase.py | 26 ++-- 27 files changed, 267 insertions(+), 490 deletions(-) delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml delete mode 100644 sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 014c0c6f37d9..f66478694fc0 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -54,7 +54,7 @@ async def delete_registry_artifact(self, digest, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - await self._client.container_registry_repository.delete_manifest(self.repository, digest) + await self._client.container_registry_repository.delete_manifest(self.repository, digest, **kwargs) async def delete_tag(self, tag, **kwargs): # type: (str) -> None diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml deleted file mode 100644 index 91808faa7197..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_delete_repository_does_not_exist.yaml +++ /dev/null @@ -1,114 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE - uri: https://fake_url.azurecr.io/acr/v1/not_real_repo - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"repository","Name":"not_real_repo","Action":"delete"}]}]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '209' - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:11:56 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" - x-content-type-options: nosniff - status: - code: 401 - message: Unauthorized - url: https://seankane.azurecr.io/acr/v1/not_real_repo -- request: - body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3ODU2MTUsIm5iZiI6MTYxNjc4NTYxNSwiZXhwIjoxNjE2ODcyMzE1LCJhaW8iOiJFMlpnWUppeStHcmhwRi8ydXVJTlJZWVdENTMyQXdBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoicG9FSktZMDg4VTZNaVlsWVVFeWFBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.l45ebp_h34EBB6Dl-xcL3CBf3Qa7x-Fv1-yN-LHDRnPKvlywGiyEG-Lmz8yZd0a7jjMQGzYsXHp5xNB6NYlwjV1GkIKoA6MP78pOCauntLbY_LOe-PcvQxt8quED6Hewr2BcyGqwgbCtOOL15MxWS5uPEKkIVRvbMxEpSt_lUSxUmiEclYge4GzZA9ZwldBe8zBlUBgaUXOVlkqa_q7QZm2ZQMdxRYTvmLVoxQ2NV54h-1dnsd-dBtic1ShhgRSs7gv_gLxZB4SDixD-oIYH3bqTXAYPsYhE-KWEewS3U8hCiFyGtn4iZbaVvxXFmVINzrn3TbUTMjDMAh7euY6iTQ - grant_type: access_token - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:11:57 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/exchange -- request: - body: - grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI2NjAyNGFlMi1hYzgwLTQzZDMtODY2ZS03NjFkMmRlMWZmYzMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3ODUwMTcsImV4cCI6MTYxNjc5NjcxNywiaWF0IjoxNjE2Nzg1MDE3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.bvjGjDZ8skSThXd1morPV-fPWml9CIx_7HGh2yGgY62fZPVhFoXCGoH05DI3QtMgM4yuZhcCrdsBKqAcDaSbJOOYHleIubAPrftybCF7DwuZ15i5xYZ4WO7faMAOzdQQOO03I5drY2qEK620C_p4XzCuE91dcrhJg3VIplo_6ddXIjM7FABXZzGEgBDZmO2gWdjNMfCJgvwFvJ0TD2guA6LCTNGQKn-FSC1LHFv7wkzOpUPhEhoj9QO3pzAglvbbGqDeWf8q5G5XcX7rbarN_JfVrkxKW5MaNijkqVrH7KDbmdbfGWW_AtLcwsIe965VQGx3-JasBvFjJYHigCtHuA - scope: repository:not_real_repo:delete - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:11:57 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/token -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: DELETE - uri: https://fake_url.azurecr.io/acr/v1/not_real_repo - response: - body: - string: '{"errors":[{"code":"NAME_UNKNOWN","message":"repository name not known - to registry","detail":{"name":"not_real_repo"}}]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '121' - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:11:58 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - status: - code: 404 - message: Not Found - url: https://seankane.azurecr.io/acr/v1/not_real_repo -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml deleted file mode 100644 index 5e6bff2088ed..000000000000 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_async.test_list_repositories.yaml +++ /dev/null @@ -1,113 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, - visit https://aka.ms/acr/authorization for more information.","detail":[{"Type":"registry","Name":"catalog","Action":"*"}]}]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '196' - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:11:59 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - www-authenticate: Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token" - x-content-type-options: nosniff - status: - code: 401 - message: Unauthorized - url: https://seankane.azurecr.io/acr/v1/_catalog -- request: - body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3ODU2MTgsIm5iZiI6MTYxNjc4NTYxOCwiZXhwIjoxNjE2ODcyMzE4LCJhaW8iOiJFMlpnWUdqbnVGZ2xuWDdtdGpKendSNWxZYVd2QUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiVktCMGlIbFFLVWVGYjdpc2RJR0lBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.RGuKi7DkUI1nKj9UhaW9VzXbk6c5pCfHmlv2WtG-TPJrxs-RKevTiRXic35bEUmbQZbXqg4QEDPnKqKc_N8-k1piOXC9U3emicNM4O6jLHx4IFLhFddt14sEvD1ZP3a0DC0taDiJ9uSbrafRgnSfr426iI4B8hXLxmumvIE1CjZ0NwMFZBvqv8Dn0KDCSWHQZXPcBadqCI0c99QN_Fddu1YDTLN43qOdTEdi_lCe7jUTgWaRCcJ-0awB7HKddPaUQpF6a77Kk84rHVyCETFXtZrocyKbxoAVkr41bKXVhEV2BJ_j93BxJ9X_1Q4pYuOQIQq8iejzsZNV8HQy2QmI9A - grant_type: access_token - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/exchange - response: - body: - string: '{"refresh_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:12:01 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/exchange -- request: - body: - grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5YWNmMWFlYy0xZDBiLTRhOWItOWMyYy05MjBlZmY5OTdlOGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3ODUwMjEsImV4cCI6MTYxNjc5NjcyMSwiaWF0IjoxNjE2Nzg1MDIxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.dFO8g1vmv5HLuLdhyF-Tpe-EhN_hbssAKpoHpdZywdYuUjygQTgN49sso312wB54leXVx7ZPayNGjDNkvUmKr9Za9sqW3dvtmwaTeAfWBeL9TvwZ2hC7UOqX4OyecPtNa21g5_8ngp_B2tVsKfsBJlWnlwm8bxjZJaeCJqTna8I3AGxwPlrMZlit-g1rnaCoLlVhIbaFjqtwUjXMuA3C26S-ICSDN92U1nXLvRNtjFmtAuyCk_kOvE_b3e3ssYOUlBAWrR5j_TFxmx0JW3Apg3WQgooUM42hZ44_fumF1gIUks2mH2nZD6wEE2S_2JJanWJL696Fco4RZQntS5BZQA - scope: registry:catalog:* - service: seankane.azurecr.io - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: POST - uri: https://fake_url.azurecr.io/oauth2/token - response: - body: - string: '{"access_token": "REDACTED"}' - headers: - connection: keep-alive - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:12:01 GMT - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - transfer-encoding: chunked - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/oauth2/token -- request: - body: null - headers: - Accept: - - application/json - User-Agent: - - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) - method: GET - uri: https://fake_url.azurecr.io/acr/v1/_catalog - response: - body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} - - ' - headers: - access-control-expose-headers: X-Ms-Correlation-Request-Id - connection: keep-alive - content-length: '125' - content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 19:12:02 GMT - docker-distribution-api-version: registry/2.0 - server: openresty - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - status: - code: 200 - message: OK - url: https://seankane.azurecr.io/acr/v1/_catalog -version: 1 diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml index 79bb18872c80..2541c73bd696 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository.yaml @@ -33,7 +33,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:22:28 GMT + - Tue, 30 Mar 2021 12:28:42 GMT docker-distribution-api-version: - registry/2.0 server: @@ -73,7 +73,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:22:30 GMT + - Tue, 30 Mar 2021 12:28:44 GMT server: - openresty strict-transport-security: @@ -109,7 +109,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:22:30 GMT + - Tue, 30 Mar 2021 12:28:44 GMT server: - openresty strict-transport-security: @@ -152,7 +152,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:22:32 GMT + - Tue, 30 Mar 2021 12:28:47 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml index a6db4fec1a2b..f85f5868de6c 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_delete_repository_does_not_exist.yaml @@ -33,7 +33,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:13 GMT + - Tue, 30 Mar 2021 12:28:47 GMT docker-distribution-api-version: - registry/2.0 server: @@ -73,7 +73,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:14 GMT + - Tue, 30 Mar 2021 12:28:49 GMT server: - openresty strict-transport-security: @@ -109,7 +109,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:14 GMT + - Tue, 30 Mar 2021 12:28:49 GMT server: - openresty strict-transport-security: @@ -153,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:15 GMT + - Tue, 30 Mar 2021 12:28:49 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml index 174751c7ffc1..444a8717c0a3 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client.test_list_repositories.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:04 GMT + - Tue, 30 Mar 2021 12:28:50 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:07 GMT + - Tue, 30 Mar 2021 12:28:52 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:07 GMT + - Tue, 30 Mar 2021 12:28:52 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","library/hello-world","ubuntu"]} + string: '{"repositories":["alpine/git","debian","hello-world","library/hello-world","ubuntu"]} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '125' + - '86' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:08 GMT + - Tue, 30 Mar 2021 12:28:53 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml index 150682b59e07..587d2709d078 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:22:56 GMT + date: Tue, 30 Mar 2021 12:29:16 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/to_be_deleted - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgyNzYsIm5iZiI6MTYxNzAzODI3NiwiZXhwIjoxNjE3MTI0OTc2LCJhaW8iOiJFMlpnWUpqQTF5OFhzZEw3b2FCTTMwYlBIbVlaQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZ1J4ckdCblNhRTJZeUUtSTZmdjlBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.iIBCRRapm6l8YAVeq7ubG153fwq0wvzHighCcHXxS8qjiVd0K_QMZyHNfd0j1JChlLkksgaGvCQulwVWE8vqXKmGEwe-Q5a26ii9CBCtTY44xIPOmB8yyRPqfKc7E7Gri4QhQaiITwClcFl0amwk8sRaNFflwTmB3Obugo93kWQJQDiPXRum5tDkdkRUcMkPM75KEG32sBYQeJFAGtsXtPoDFRX0d-SyrW4GijXFPeJ85zTOGXm0PBSvARWIQYmbknfK2jnysP1uo7dmUtRVy9gQ6plRutFvv7qr3UmTaAjRjtaLMc5VORZ-kNdYTByEOdzFHHThWMasdTXmtTwpsg + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:22:57 GMT + date: Tue, 30 Mar 2021 12:29:18 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjNWViNWI2NC1lY2JiLTRjMjktOWY4OS04MzJjMTZlYTExNmQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc2NzcsImV4cCI6MTYxNzA0OTM3NywiaWF0IjoxNjE3MDM3Njc3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.P0wzSQ0HoadHSNusm4o1DqF7b6f8tNIGzXJxUF-EwSPAxp_UB_IcGsVulX0VoZtP36qhL1EURHPRXi8CtqzCcaxynWGiTAA2E0fPpZ1WkJCe2VZimAkSf129W_mXatWJf9NIZFp9typzSWBoit6iZNg_JgqTjqhbKEX4zojVTtOJta2Q9m8vtZAxkAft4IvVqHYctM8SZAATurvsXpXSDoH61fOW4DpQOg0085-r1FpBPMVoLlKkElfyzPFkn2BpVdBo28-076HyT269wP_PoGfA9F6iyildTkxo_hdZMNBJ5-5l66PPAcrN0nk85cmOi_cGPQz2tz0t0G0a1un6uw + refresh_token: REDACTED scope: repository:to_be_deleted:delete service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:22:57 GMT + date: Tue, 30 Mar 2021 12:29:18 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -101,7 +101,7 @@ interactions: connection: keep-alive content-length: '795' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:22:58 GMT + date: Tue, 30 Mar 2021 12:29:21 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml index 2c9ae9be8716..665d9492952a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_delete_repository_does_not_exist.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:15 GMT + date: Tue, 30 Mar 2021 12:29:22 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/not_real_repo - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzkwMTYsIm5iZiI6MTYxNzAzOTAxNiwiZXhwIjoxNjE3MTI1NzE2LCJhaW8iOiJFMlpnWUxpdVo3OXhzOFdHdkIxYUhXeStmMituQVFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiLWFzX0xGOTJlVWFjdFN6bVQ1c1BBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.lXULYlyPw0I-nvw5J9TTkS9HfRKGjCEEEZsbAv4OARVoWPZGGHEW_NYQz77m4zHfz7PuXD0qPyGKIEC2qMmferd_cktH_jvYv2TdFau5mggI3zkWlAu0x9HVy_I-deEdTGzm6m37EC--aJDd6y274QEb5yCVwcexMYk-vpXNFbtYsAWZ6X8jctKdmm3D8K2QNzn45gARvtOfPeN0L1b_6wiv9qA1a_Y1zGSWT6RB1Tfe0IRcIdVHYyF5S7oWe_0C-wHN5nHzDoT7lFQx-EkhnUyHHoslxODTntHQRXr5gPLG-o5Gbc-BNV5MoUhQu3ojdKa5m_0CXh34m42BUJX2Iw + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:17 GMT + date: Tue, 30 Mar 2021 12:29:25 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMTI3YjkzOS1iNTkwLTQxOTItYTUxNy01ZjdmYzNlOWQzNmMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzg0MTcsImV4cCI6MTYxNzA1MDExNywiaWF0IjoxNjE3MDM4NDE3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.p6RQLCCApPH_N2XXNcB7e-6N51qONOkOanipndPJmnF0SxXjMNZ1JpoDClZJFW-f4jUnPlhMOw7-V_9KkJO9q5jBKMX4iRfZJhlFqCn_RHgHOfc-xFw8S6MwFszit9iN1M6bVpl7qHHSp-GiB0iUe_9KDGCiojll5zESrjSMEKgjaHbRcF9sUiwjTED45dPjsVeLpgKmEkGs9pxJgPGn9E3YEGZUyvdQSA4wNsa_akHr2L3pUKposoZEMwzjQVNxh6Um-cdZfN_939bn_uLt5D9mkaY7eXBPkI283FjCOoBJ4R4cG79Q5cvUS2ajiHCewddSW1KXx2PGqMZHAz5QIg + refresh_token: REDACTED scope: repository:not_real_repo:delete service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:17 GMT + date: Tue, 30 Mar 2021 12:29:25 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -102,7 +102,7 @@ interactions: connection: keep-alive content-length: '121' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:17 GMT + date: Tue, 30 Mar 2021 12:29:25 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml index 262baf25b1c8..e6fa6d39401f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_registry_client_async.test_list_repositories.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '196' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:11 GMT + date: Tue, 30 Mar 2021 12:29:26 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/_catalog - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ4NzEsIm5iZiI6MTYxNjc5NDg3MSwiZXhwIjoxNjE2ODgxNTcxLCJhaW8iOiJFMlpnWUdBOFBmdDkvWnpkKzJlTFJIb3BIMTV3REFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZVh1TjlUZE9zMDZIMHZFMXZCT1pBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.A0KGuU0tjXdWdsE3m4K6_P1M9w46jUOduAPy4pRaPlYjiWmoDiwWCryGkyVEzoXNPsiLXMKKlQckDfoARiZSRvDubZThaQj4058kZeujsv8IRetWWeHN9ZMrSZnjvM9rFiIHtvsXwcBQO9kjA6S-J7VyX4NqA426a6XHpKpl2rD_37xllNtRgkSZZi2sf-yzL2WVYD-1pItATFRFXnkHFN_bx_PqJfv3d9X7ROpgWZJWK0h2naLo_8Tw2PjrBgTPRfeIZeTyunQdsygyyj7aNHindSQ1ll_LgwCjj7YKHpG9K9M3fFvIm9AzMV0qxDSB_f7secnCHXkmBnCtjAv5Iw + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:12 GMT + date: Tue, 30 Mar 2021 12:29:27 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjZmRlMDZlYS1mYTk3LTQzZGUtYmUxZi1kNjJkODI3ZGE4NzAiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQyNzIsImV4cCI6MTYxNjgwNTk3MiwiaWF0IjoxNjE2Nzk0MjcyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Lyhcfioww5o7H8IF1kOqNqt3slu8_8iz01HTDKHIkljKLiq17qs_9jhkkCwk-IZoVnOOVPDCpTsOb6YaS9T-AkYdID5UYLl8JGNEiVskZx-TMO0y4GCrqks8mVvJcjYryWzkKIrZJlDwWAjIMTJdBAIepKk1RgWSekHYttI8lqVnly817N3wJtBwJPM7FPAcxKEO1FVe__YCavfyW60-_ehF-xJny_JSAdUtYerLFI7OSsaaP1YCoGWjMPoxUXBYTjtDnSCx-Uz_-gR1KmgiX30FgoQqwwhRLAE0pxFsefYtPZ-jdkhEioGDnAYSE5SfTfZ56euZum_P7ctDAVPSgQ + refresh_token: REDACTED scope: registry:catalog:* service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:12 GMT + date: Tue, 30 Mar 2021 12:29:27 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -93,15 +93,15 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","ubuntu"]} + string: '{"repositories":["alpine/git","debian","hello-world","library/hello-world","ubuntu"]} ' headers: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive - content-length: '103' + content-length: '86' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:46:13 GMT + date: Tue, 30 Mar 2021 12:29:27 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml index ce5ef3aa66d0..1447f770c2e8 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_registry_artifact.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:38 GMT + - Tue, 30 Mar 2021 12:29:44 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:40 GMT + - Tue, 30 Mar 2021 12:29:46 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:40 GMT + - Tue, 30 Mar 2021 12:29:46 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-29T18:46:36.2585193Z","lastUpdateTime":"2021-03-29T18:46:36.2585193Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-30T12:29:35.3709465Z","lastUpdateTime":"2021-03-30T12:29:35.3709465Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:29:35.1808975Z","lastUpdateTime":"2021-03-30T12:29:35.1808975Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-30T12:29:36.4998333Z","lastUpdateTime":"2021-03-30T12:29:36.4998333Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-30T12:29:35.9252437Z","lastUpdateTime":"2021-03-30T12:29:35.9252437Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-30T12:29:35.6437547Z","lastUpdateTime":"2021-03-30T12:29:35.6437547Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-30T12:29:35.8340458Z","lastUpdateTime":"2021-03-30T12:29:35.8340458Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-30T12:29:35.732856Z","lastUpdateTime":"2021-03-30T12:29:35.732856Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-30T12:29:35.5687191Z","lastUpdateTime":"2021-03-30T12:29:35.5687191Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-30T12:29:36.0408056Z","lastUpdateTime":"2021-03-30T12:29:36.0408056Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-30T12:29:35.491259Z","lastUpdateTime":"2021-03-30T12:29:35.491259Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: @@ -146,7 +146,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:41 GMT + - Tue, 30 Mar 2021 12:29:47 GMT docker-distribution-api-version: - registry/2.0 server: @@ -195,7 +195,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:41 GMT + - Tue, 30 Mar 2021 12:29:47 GMT docker-distribution-api-version: - registry/2.0 server: @@ -235,7 +235,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:41 GMT + - Tue, 30 Mar 2021 12:29:47 GMT server: - openresty strict-transport-security: @@ -271,7 +271,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:41 GMT + - Tue, 30 Mar 2021 12:29:47 GMT server: - openresty strict-transport-security: @@ -310,7 +310,7 @@ interactions: content-length: - '0' date: - - Mon, 29 Mar 2021 18:49:42 GMT + - Tue, 30 Mar 2021 12:29:48 GMT docker-distribution-api-version: - registry/2.0 server: @@ -355,7 +355,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:42 GMT + - Tue, 30 Mar 2021 12:29:48 GMT docker-distribution-api-version: - registry/2.0 server: @@ -395,7 +395,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:42 GMT + - Tue, 30 Mar 2021 12:29:48 GMT server: - openresty strict-transport-security: @@ -431,7 +431,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:43 GMT + - Tue, 30 Mar 2021 12:29:48 GMT server: - openresty strict-transport-security: @@ -456,7 +456,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:29:35.1808975Z","lastUpdateTime":"2021-03-30T12:29:35.1808975Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-30T12:29:36.4998333Z","lastUpdateTime":"2021-03-30T12:29:36.4998333Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-30T12:29:35.9252437Z","lastUpdateTime":"2021-03-30T12:29:35.9252437Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-30T12:29:35.6437547Z","lastUpdateTime":"2021-03-30T12:29:35.6437547Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-30T12:29:35.8340458Z","lastUpdateTime":"2021-03-30T12:29:35.8340458Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-30T12:29:35.732856Z","lastUpdateTime":"2021-03-30T12:29:35.732856Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-30T12:29:35.5687191Z","lastUpdateTime":"2021-03-30T12:29:35.5687191Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-30T12:29:36.0408056Z","lastUpdateTime":"2021-03-30T12:29:36.0408056Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-30T12:29:35.491259Z","lastUpdateTime":"2021-03-30T12:29:35.491259Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: @@ -470,7 +470,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 18:49:43 GMT + - Tue, 30 Mar 2021 12:29:49 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml index 9b65d913e4ed..3ea16f0f70c7 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:17 GMT + - Tue, 30 Mar 2021 12:30:04 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:18 GMT + - Tue, 30 Mar 2021 12:30:06 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:19 GMT + - Tue, 30 Mar 2021 12:30:06 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","to_be_deleted","ubuntu"]} + string: '{"repositories":["alpine/git","debian","hello-world","library/hello-world","to_be_deleted","ubuntu"]} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '119' + - '102' content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:19 GMT + - Tue, 30 Mar 2021 12:30:06 GMT docker-distribution-api-version: - registry/2.0 server: @@ -195,7 +195,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:20 GMT + - Tue, 30 Mar 2021 12:30:07 GMT docker-distribution-api-version: - registry/2.0 server: @@ -235,7 +235,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:21 GMT + - Tue, 30 Mar 2021 12:30:09 GMT server: - openresty strict-transport-security: @@ -271,7 +271,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:21 GMT + - Tue, 30 Mar 2021 12:30:09 GMT server: - openresty strict-transport-security: @@ -314,7 +314,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:24 GMT + - Tue, 30 Mar 2021 12:30:11 GMT docker-distribution-api-version: - registry/2.0 server: @@ -359,7 +359,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:29 GMT + - Tue, 30 Mar 2021 12:30:16 GMT docker-distribution-api-version: - registry/2.0 server: @@ -399,7 +399,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:30 GMT + - Tue, 30 Mar 2021 12:30:16 GMT server: - openresty strict-transport-security: @@ -435,7 +435,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:30 GMT + - Tue, 30 Mar 2021 12:30:16 GMT server: - openresty strict-transport-security: @@ -460,7 +460,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","ubuntu"]} + string: '{"repositories":["alpine/git","debian","hello-world","library/hello-world","ubuntu"]} ' headers: @@ -472,11 +472,11 @@ interactions: connection: - keep-alive content-length: - - '103' + - '86' content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:23:30 GMT + - Tue, 30 Mar 2021 12:30:17 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml index b78e09025e8b..52706d73fa87 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_repository_doesnt_exist.yaml @@ -33,7 +33,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:18 GMT + - Tue, 30 Mar 2021 12:30:17 GMT docker-distribution-api-version: - registry/2.0 server: @@ -73,7 +73,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:19 GMT + - Tue, 30 Mar 2021 12:30:19 GMT server: - openresty strict-transport-security: @@ -109,7 +109,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:20 GMT + - Tue, 30 Mar 2021 12:30:19 GMT server: - openresty strict-transport-security: @@ -153,7 +153,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 17:35:20 GMT + - Tue, 30 Mar 2021 12:30:19 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml index 398f2c083075..109f9645a389 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_delete_tag.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:29 GMT + - Tue, 30 Mar 2021 12:30:41 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:31 GMT + - Tue, 30 Mar 2021 12:30:44 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:31 GMT + - Tue, 30 Mar 2021 12:30:44 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-29T14:47:20.2311587Z","lastUpdateTime":"2021-03-29T14:47:20.2311587Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:30:30.6324224Z","lastUpdateTime":"2021-03-30T12:30:30.6324224Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} ' headers: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:31 GMT + - Tue, 30 Mar 2021 12:30:45 GMT docker-distribution-api-version: - registry/2.0 server: @@ -195,7 +195,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:31 GMT + - Tue, 30 Mar 2021 12:30:45 GMT docker-distribution-api-version: - registry/2.0 server: @@ -235,7 +235,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:31 GMT + - Tue, 30 Mar 2021 12:30:48 GMT server: - openresty strict-transport-security: @@ -271,7 +271,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:31 GMT + - Tue, 30 Mar 2021 12:30:49 GMT server: - openresty strict-transport-security: @@ -310,7 +310,7 @@ interactions: content-length: - '0' date: - - Mon, 29 Mar 2021 14:47:32 GMT + - Tue, 30 Mar 2021 12:30:49 GMT docker-distribution-api-version: - registry/2.0 server: @@ -357,7 +357,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:42 GMT + - Tue, 30 Mar 2021 12:30:59 GMT docker-distribution-api-version: - registry/2.0 server: @@ -397,7 +397,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:42 GMT + - Tue, 30 Mar 2021 12:31:00 GMT server: - openresty strict-transport-security: @@ -433,7 +433,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:42 GMT + - Tue, 30 Mar 2021 12:31:01 GMT server: - openresty strict-transport-security: @@ -475,7 +475,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 14:47:43 GMT + - Tue, 30 Mar 2021 12:31:01 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml index 0b40402db475..8e0903122ed8 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_attributes.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:09 GMT + - Tue, 30 Mar 2021 12:31:03 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:11 GMT + - Tue, 30 Mar 2021 12:31:05 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:11 GMT + - Tue, 30 Mar 2021 12:31:05 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-30T12:18:47.4147491Z","lastUpdateTime":"2021-03-30T12:30:49.5838939Z","manifestCount":10,"tagCount":1,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '289' + - '290' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:11 GMT + - Tue, 30 Mar 2021 12:31:05 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml index b8a6cd9e07fa..c27c95192b9c 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:14 GMT + - Tue, 30 Mar 2021 12:31:06 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:17 GMT + - Tue, 30 Mar 2021 12:31:07 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:17 GMT + - Tue, 30 Mar 2021 12:31:08 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-16T15:14:35.1042371Z","lastUpdateTime":"2021-03-16T15:16:49.2531522Z","manifestCount":1,"tagCount":2,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","createdTime":"2021-03-30T12:18:47.4147491Z","lastUpdateTime":"2021-03-30T12:30:49.5838939Z","manifestCount":10,"tagCount":1,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '289' + - '290' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:17 GMT + - Tue, 30 Mar 2021 12:31:08 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml index 5f0c88feabdc..d2c0c047c938 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_registry_artifact_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:18 GMT + - Tue, 30 Mar 2021 12:31:10 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:20 GMT + - Tue, 30 Mar 2021 12:31:15 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:21 GMT + - Tue, 30 Mar 2021 12:31:16 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:18:52.8272444Z","lastUpdateTime":"2021-03-30T12:18:52.8272444Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} ' headers: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:21 GMT + - Tue, 30 Mar 2021 12:31:16 GMT docker-distribution-api-version: - registry/2.0 server: @@ -173,7 +173,7 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24 response: body: string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, @@ -193,7 +193,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:21 GMT + - Tue, 30 Mar 2021 12:31:17 GMT docker-distribution-api-version: - registry/2.0 server: @@ -233,7 +233,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:21 GMT + - Tue, 30 Mar 2021 12:31:18 GMT server: - openresty strict-transport-security: @@ -269,7 +269,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:22 GMT + - Tue, 30 Mar 2021 12:31:18 GMT server: - openresty strict-transport-security: @@ -291,12 +291,10 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys - Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:18:47.4863064Z","lastUpdateTime":"2021-03-30T12:18:47.4863064Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true},"references":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","architecture":"amd64","os":"linux"},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","architecture":"arm","os":"linux"},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","architecture":"arm","os":"linux"},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","architecture":"arm64","os":"linux"},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","architecture":"386","os":"linux"},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","architecture":"mips64le","os":"linux"},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","architecture":"ppc64le","os":"linux"},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","architecture":"s390x","os":"linux"},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","architecture":"amd64","os":"windows"}]}} ' headers: @@ -308,11 +306,11 @@ interactions: connection: - keep-alive content-length: - - '917' + - '1564' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:22 GMT + - Tue, 30 Mar 2021 12:31:19 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml index e3be0d71bd80..22af0927484d 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_get_tag.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:23 GMT + - Tue, 30 Mar 2021 12:31:20 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:25 GMT + - Tue, 30 Mar 2021 12:31:24 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:25 GMT + - Tue, 30 Mar 2021 12:31:24 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:18:52.8272444Z","lastUpdateTime":"2021-03-30T12:18:52.8272444Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} ' headers: @@ -148,7 +148,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:25 GMT + - Tue, 30 Mar 2021 12:31:25 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml index 0aa6ea127541..2df851c7cf4f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_registry_artifacts.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 15:46:14 GMT + - Tue, 30 Mar 2021 12:31:26 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 15:46:15 GMT + - Tue, 30 Mar 2021 12:31:30 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 15:46:16 GMT + - Tue, 30 Mar 2021 12:31:30 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-26T20:37:52.5557355Z","lastUpdateTime":"2021-03-26T20:37:52.5557355Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-26T20:57:13.8079297Z","lastUpdateTime":"2021-03-26T20:57:13.8079297Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-26T20:37:53.7763318Z","lastUpdateTime":"2021-03-26T20:37:53.7763318Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-26T20:37:53.4342095Z","lastUpdateTime":"2021-03-26T20:37:53.4342095Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-26T20:37:52.921838Z","lastUpdateTime":"2021-03-26T20:37:52.921838Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-26T20:37:53.6634624Z","lastUpdateTime":"2021-03-26T20:37:53.6634624Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-26T20:37:53.1185252Z","lastUpdateTime":"2021-03-26T20:37:53.1185252Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-26T20:37:52.8422032Z","lastUpdateTime":"2021-03-26T20:37:52.8422032Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-26T20:37:53.3206421Z","lastUpdateTime":"2021-03-26T20:37:53.3206421Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-26T20:37:52.6987713Z","lastUpdateTime":"2021-03-26T20:37:52.6987713Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-30T12:18:47.6437335Z","lastUpdateTime":"2021-03-30T12:18:47.6437335Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":false,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:18:47.4863064Z","lastUpdateTime":"2021-03-30T12:18:47.4863064Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-30T12:18:48.9950981Z","lastUpdateTime":"2021-03-30T12:18:48.9950981Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-30T12:18:48.0921265Z","lastUpdateTime":"2021-03-30T12:18:48.0921265Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-30T12:18:47.9641681Z","lastUpdateTime":"2021-03-30T12:18:47.9641681Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-30T12:18:48.6908523Z","lastUpdateTime":"2021-03-30T12:18:48.6908523Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-30T12:18:48.2834053Z","lastUpdateTime":"2021-03-30T12:18:48.2834053Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-30T12:18:48.1605587Z","lastUpdateTime":"2021-03-30T12:18:48.1605587Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-30T12:18:48.5864242Z","lastUpdateTime":"2021-03-30T12:18:48.5864242Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-30T12:18:48.4392605Z","lastUpdateTime":"2021-03-30T12:18:48.4392605Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: @@ -146,7 +146,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Mon, 29 Mar 2021 15:46:16 GMT + - Tue, 30 Mar 2021 12:31:31 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml index 184201453ab8..6032407cf380 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:28 GMT + - Tue, 30 Mar 2021 12:31:32 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:30 GMT + - Tue, 30 Mar 2021 12:31:37 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:30 GMT + - Tue, 30 Mar 2021 12:31:37 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"latest","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:18:52.8272444Z","lastUpdateTime":"2021-03-30T12:18:52.8272444Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '722' + - '383' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:30 GMT + - Tue, 30 Mar 2021 12:31:38 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml index 01736685b291..a1942ffef7e2 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_list_tags_descending.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:31 GMT + - Tue, 30 Mar 2021 12:31:40 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:32 GMT + - Tue, 30 Mar 2021 12:31:44 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:33 GMT + - Tue, 30 Mar 2021 12:31:45 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags?orderby=0 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"latest","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:18:52.8272444Z","lastUpdateTime":"2021-03-30T12:18:52.8272444Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '722' + - '383' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:33 GMT + - Tue, 30 Mar 2021 12:31:45 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml index a0d49e957e0a..fe9ceef618f5 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_manifest_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:33 GMT + - Tue, 30 Mar 2021 12:31:48 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:35 GMT + - Tue, 30 Mar 2021 12:31:54 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:35 GMT + - Tue, 30 Mar 2021 12:31:54 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-30T12:18:47.6437335Z","lastUpdateTime":"2021-03-30T12:18:47.6437335Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":false,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:18:47.4863064Z","lastUpdateTime":"2021-03-30T12:18:47.4863064Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-30T12:18:48.9950981Z","lastUpdateTime":"2021-03-30T12:18:48.9950981Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-30T12:18:48.0921265Z","lastUpdateTime":"2021-03-30T12:18:48.0921265Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-30T12:18:47.9641681Z","lastUpdateTime":"2021-03-30T12:18:47.9641681Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-30T12:18:48.6908523Z","lastUpdateTime":"2021-03-30T12:18:48.6908523Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-30T12:18:48.2834053Z","lastUpdateTime":"2021-03-30T12:18:48.2834053Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-30T12:18:48.1605587Z","lastUpdateTime":"2021-03-30T12:18:48.1605587Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-30T12:18:48.5864242Z","lastUpdateTime":"2021-03-30T12:18:48.5864242Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-30T12:18:48.4392605Z","lastUpdateTime":"2021-03-30T12:18:48.4392605Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: @@ -143,12 +143,10 @@ interactions: - X-Ms-Correlation-Request-Id connection: - keep-alive - content-length: - - '598' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:35 GMT + - Tue, 30 Mar 2021 12:31:55 GMT docker-distribution-api-version: - registry/2.0 server: @@ -156,13 +154,15 @@ interactions: strict-transport-security: - max-age=31536000; includeSubDomains - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked x-content-type-options: - nosniff status: code: 200 message: OK - request: - body: '{"deleteEnabled": false, "writeEnabled": false, "listEnabled": true, "readEnabled": + body: '{"deleteEnabled": true, "writeEnabled": true, "listEnabled": true, "readEnabled": true}' headers: Accept: @@ -172,13 +172,13 @@ interactions: Connection: - keep-alive Content-Length: - - '89' + - '87' Content-Type: - application/json User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: PATCH - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 response: body: string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, @@ -198,7 +198,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:35 GMT + - Tue, 30 Mar 2021 12:31:56 GMT docker-distribution-api-version: - registry/2.0 server: @@ -238,7 +238,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:36 GMT + - Tue, 30 Mar 2021 12:31:57 GMT server: - openresty strict-transport-security: @@ -274,7 +274,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:36 GMT + - Tue, 30 Mar 2021 12:31:57 GMT server: - openresty strict-transport-security: @@ -285,7 +285,7 @@ interactions: code: 200 message: OK - request: - body: '{"deleteEnabled": false, "writeEnabled": false, "listEnabled": true, "readEnabled": + body: '{"deleteEnabled": true, "writeEnabled": true, "listEnabled": true, "readEnabled": true}' headers: Accept: @@ -295,18 +295,18 @@ interactions: Connection: - keep-alive Content-Length: - - '89' + - '87' Content-Type: - application/json User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: PATCH - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys - Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-30T12:18:47.6437335Z","lastUpdateTime":"2021-03-30T12:18:47.6437335Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security + Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/30/2021 12:18:49 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} ' headers: @@ -318,11 +318,11 @@ interactions: connection: - keep-alive content-length: - - '918' + - '816' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:37 GMT + - Tue, 30 Mar 2021 12:31:58 GMT docker-distribution-api-version: - registry/2.0 server: @@ -347,7 +347,7 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 response: body: string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, @@ -367,7 +367,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:37 GMT + - Tue, 30 Mar 2021 12:31:58 GMT docker-distribution-api-version: - registry/2.0 server: @@ -407,7 +407,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:37 GMT + - Tue, 30 Mar 2021 12:31:59 GMT server: - openresty strict-transport-security: @@ -443,7 +443,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:37 GMT + - Tue, 30 Mar 2021 12:31:59 GMT server: - openresty strict-transport-security: @@ -465,12 +465,12 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":false,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys - Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-30T12:18:47.6437335Z","lastUpdateTime":"2021-03-30T12:18:47.6437335Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan + InProgress\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security + Monitoring-Qualys Scanner\",\"result\":{\"version\":\"3/30/2021 12:18:49 PM\",\"summary\":[{\"severity\":\"High\",\"count\":0},{\"severity\":\"Medium\",\"count\":0},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} ' headers: @@ -482,11 +482,11 @@ interactions: connection: - keep-alive content-length: - - '918' + - '816' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:38 GMT + - Tue, 30 Mar 2021 12:32:00 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml index 2b8bb3b921b5..b56a7fe528a5 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client.test_set_tag_properties.yaml @@ -31,7 +31,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:38 GMT + - Tue, 30 Mar 2021 12:32:01 GMT docker-distribution-api-version: - registry/2.0 server: @@ -71,7 +71,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:40 GMT + - Tue, 30 Mar 2021 12:32:02 GMT server: - openresty strict-transport-security: @@ -107,7 +107,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:40 GMT + - Tue, 30 Mar 2021 12:32:02 GMT server: - openresty strict-transport-security: @@ -132,7 +132,7 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"name":"latest","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:16:49.3869143Z","lastUpdateTime":"2021-03-16T15:16:49.3869143Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tags":[{"name":"latest","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:18:52.8272444Z","lastUpdateTime":"2021-03-30T12:18:52.8272444Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}]} ' headers: @@ -144,11 +144,11 @@ interactions: connection: - keep-alive content-length: - - '722' + - '383' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:40 GMT + - Tue, 30 Mar 2021 12:32:02 GMT docker-distribution-api-version: - registry/2.0 server: @@ -178,7 +178,7 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: PATCH - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24 response: body: string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, @@ -198,7 +198,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:40 GMT + - Tue, 30 Mar 2021 12:32:03 GMT docker-distribution-api-version: - registry/2.0 server: @@ -238,7 +238,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:40 GMT + - Tue, 30 Mar 2021 12:32:03 GMT server: - openresty strict-transport-security: @@ -274,7 +274,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:41 GMT + - Tue, 30 Mar 2021 12:32:03 GMT server: - openresty strict-transport-security: @@ -301,12 +301,10 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: PATCH - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042 + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_manifests/sha256%3A308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24 response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","imageSize":2529,"createdTime":"2021-03-16T15:14:35.1695172Z","lastUpdateTime":"2021-03-16T15:14:35.1695172Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","configMediaType":"application/vnd.docker.container.image.v1+json","tags":["first","latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true,"quarantineDetails":"{\"state\":\"Scan - Passed\",\"link\":\"https://aka.ms/test\",\"scanner\":\"Azure Security Monitoring-Qualys - Scanner\",\"result\":{\"version\":\"2021-03-23T23:56:01.9480757Z\",\"summary\":[{\"severity\":\"High\",\"count\":6},{\"severity\":\"Medium\",\"count\":34},{\"severity\":\"Low\",\"count\":0}]}}","quarantineState":"Passed"}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","manifest":{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:18:47.4863064Z","lastUpdateTime":"2021-03-30T12:18:47.4863064Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["latest"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":false,"readEnabled":true,"listEnabled":true},"references":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","architecture":"amd64","os":"linux"},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","architecture":"arm","os":"linux"},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","architecture":"arm","os":"linux"},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","architecture":"arm64","os":"linux"},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","architecture":"386","os":"linux"},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","architecture":"mips64le","os":"linux"},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","architecture":"ppc64le","os":"linux"},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","architecture":"s390x","os":"linux"},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","architecture":"amd64","os":"windows"}]}} ' headers: @@ -318,11 +316,11 @@ interactions: connection: - keep-alive content-length: - - '917' + - '1564' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:41 GMT + - Tue, 30 Mar 2021 12:32:03 GMT docker-distribution-api-version: - registry/2.0 server: @@ -347,7 +345,7 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/first + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest response: body: string: '{"errors":[{"code":"UNAUTHORIZED","message":"authentication required, @@ -367,7 +365,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:41 GMT + - Tue, 30 Mar 2021 12:32:03 GMT docker-distribution-api-version: - registry/2.0 server: @@ -407,7 +405,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:41 GMT + - Tue, 30 Mar 2021 12:32:04 GMT server: - openresty strict-transport-security: @@ -443,7 +441,7 @@ interactions: content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:42 GMT + - Tue, 30 Mar 2021 12:32:04 GMT server: - openresty strict-transport-security: @@ -465,10 +463,10 @@ interactions: User-Agent: - azsdk-python-azure-containerregistry/0.0.1 Python/3.9.0rc1 (Windows-10-10.0.19041-SP0) method: GET - uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/first + uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/latest response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"first","digest":"sha256:90659bf80b44ce6be8234e6ff90a1ac34acbeb826903b02cfa0da11c82cbc042","createdTime":"2021-03-16T15:14:35.3014161Z","lastUpdateTime":"2021-03-16T15:14:35.3014161Z","signed":false,"quarantineState":"Passed","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"latest","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:18:52.8272444Z","lastUpdateTime":"2021-03-30T12:18:52.8272444Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} ' headers: @@ -480,11 +478,11 @@ interactions: connection: - keep-alive content-length: - - '406' + - '380' content-type: - application/json; charset=utf-8 date: - - Fri, 26 Mar 2021 19:12:42 GMT + - Tue, 30 Mar 2021 12:32:04 GMT docker-distribution-api-version: - registry/2.0 server: diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml index 5aad39fddfb4..551948084f6f 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_registry_artifact.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '216' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:00 GMT + date: Tue, 30 Mar 2021 12:32:21 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/to_be_deleted/_manifests - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwNDM1MDAsIm5iZiI6MTYxNzA0MzUwMCwiZXhwIjoxNjE3MTMwMjAwLCJhaW8iOiJFMlpnWURpbzlzdFQ5NXFRUVVkK3hWSHRULy8xQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT3EydzMyVi14VXVqc0FrNm94Y0VBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.hWjWRe_6O2wql1pkNnQKG1oW1a3Z3SckZ6OZMIMM_LuporkwdltV7mK4FIdB5635Zyk8z2OjAuVGYFnReAcJUhOR0JoT6Xtf90cfH8TWSKvkw5iqUtBQfI_ZtKzfSHMQwoRDsdsFmgVeka_QlZmUhSffcUCEcBOiBbCEHeKy2SX8jTX4iNmDYW2DnLw_TTA5LJhTItY_U9imPZzuYoAe2d8ctOgYpBPWRDOgwAnjJBzALPi1o3BTjhoVSlcpioXoP8A0h-hVmNz77zehcQ8A2R0tSCfWZ3sNDevkj5cC5c7fCqHX7K26w4LdRCpollDZkm-4IoIMnuQOtTPXUhQ3aQ + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:01 GMT + date: Tue, 30 Mar 2021 12:32:28 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyZTcxMTViZS1mMDZkLTQ2MmQtOGRkOS03MmExZmFkNTBkYzQiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwNDI5MDEsImV4cCI6MTYxNzA1NDYwMSwiaWF0IjoxNjE3MDQyOTAxLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.Zbqym1oarG3-7UyAP9oq7He6Fyw_e5ZhtlYlOwRKiXS0tJO8KTCqshja6ahY729Di-fk4RNnXIMXtS9lG4ZZuCs-3zTJvA1s0KnZoxaj34qjXdW8I1MYp1VM34DxTgjGX208zwcEuTK6uMB5b6v-4fd5bYUzYMk3T4_DwXH5pLUkSSqPxp0B1C9FVQ1EY59MZu4W2-8E73DSF4yBnTuZeI8KqNo9UCrP392L1avAQvywHfRCrPySYSKnbx23MIn23F1zEkZRHsP-NVivhppUFgUNXoLpW76mwVBYf2lHRg2jMbMDjMP1HjnyUowxpO0nzVnuMq6Ew6uWAA2PVzTIHw + refresh_token: REDACTED scope: repository:to_be_deleted:metadata_read service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:01 GMT + date: Tue, 30 Mar 2021 12:32:28 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -93,14 +93,14 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-29T18:49:54.088615Z","lastUpdateTime":"2021-03-29T18:49:54.088615Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792","imageSize":0,"createdTime":"2021-03-30T12:32:11.9400318Z","lastUpdateTime":"2021-03-30T12:32:11.9400318Z","architecture":"amd64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:32:11.5970249Z","lastUpdateTime":"2021-03-30T12:32:11.5970249Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-30T12:32:12.087437Z","lastUpdateTime":"2021-03-30T12:32:12.087437Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-30T12:32:12.9678728Z","lastUpdateTime":"2021-03-30T12:32:12.9678728Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-30T12:32:12.3723557Z","lastUpdateTime":"2021-03-30T12:32:12.3723557Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-30T12:32:13.0558039Z","lastUpdateTime":"2021-03-30T12:32:13.0558039Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-30T12:32:13.5214505Z","lastUpdateTime":"2021-03-30T12:32:13.5214505Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-30T12:32:12.4776624Z","lastUpdateTime":"2021-03-30T12:32:12.4776624Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-30T12:32:12.8779434Z","lastUpdateTime":"2021-03-30T12:32:12.8779434Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-30T12:32:12.2814609Z","lastUpdateTime":"2021-03-30T12:32:12.2814609Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:01 GMT + date: Tue, 30 Mar 2021 12:32:29 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -130,7 +130,7 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:02 GMT + date: Tue, 30 Mar 2021 12:32:29 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -142,7 +142,7 @@ interactions: url: https://seankane.azurecr.io/v2/to_be_deleted/manifests/sha256:1b26826f602946860c279fce658f31050cff2c596583af237d971f4629b57792 - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwNDM1MDAsIm5iZiI6MTYxNzA0MzUwMCwiZXhwIjoxNjE3MTMwMjAwLCJhaW8iOiJFMlpnWURpbzlzdFQ5NXFRUVVkK3hWSHRULy8xQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT3EydzMyVi14VXVqc0FrNm94Y0VBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.hWjWRe_6O2wql1pkNnQKG1oW1a3Z3SckZ6OZMIMM_LuporkwdltV7mK4FIdB5635Zyk8z2OjAuVGYFnReAcJUhOR0JoT6Xtf90cfH8TWSKvkw5iqUtBQfI_ZtKzfSHMQwoRDsdsFmgVeka_QlZmUhSffcUCEcBOiBbCEHeKy2SX8jTX4iNmDYW2DnLw_TTA5LJhTItY_U9imPZzuYoAe2d8ctOgYpBPWRDOgwAnjJBzALPi1o3BTjhoVSlcpioXoP8A0h-hVmNz77zehcQ8A2R0tSCfWZ3sNDevkj5cC5c7fCqHX7K26w4LdRCpollDZkm-4IoIMnuQOtTPXUhQ3aQ + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -158,7 +158,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:02 GMT + date: Tue, 30 Mar 2021 12:32:30 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -169,7 +169,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0OWU5MDAxYS1hNWNkLTRiNmItOWU4NC1mMmM1YjNkODdlYzgiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwNDI5MDIsImV4cCI6MTYxNzA1NDYwMiwiaWF0IjoxNjE3MDQyOTAyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.gQ0SKisCvhSWqJMEifR6kY1iMO0Xp36JcD2fRjuIp72c5EsBbXRNv7LSe04KBAjVINHAwnlWvqoGPqzaZIWkd5X3J_rA145cJe3TZYW5XJqD_jqDeOLRC2HHaMGFW0aghSJvRVMn8k4nkwTwOTFJk24VkVk2Pio4I1awucQnB7DgQEj48JNyQsdudp5qP9V4RBuCEFGtAEeZJZ5R3_G1oJl_B4L8n4bShT5Rswk5g3OWndVjWWCKlDm69BrWEZD2MX_n593wt7pqbgbfhAcWAyuYnool41OT7jLjeHQp52wNp9yKFPUm3p-6Yi1WjesZdocUNGM5RKJ-PMlh89VAXg + refresh_token: REDACTED scope: repository:to_be_deleted:delete service: seankane.azurecr.io headers: @@ -185,7 +185,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:02 GMT + date: Tue, 30 Mar 2021 12:32:30 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -209,7 +209,7 @@ interactions: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive content-length: '0' - date: Mon, 29 Mar 2021 18:50:02 GMT + date: Tue, 30 Mar 2021 12:32:30 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -238,7 +238,7 @@ interactions: connection: keep-alive content-length: '216' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:02 GMT + date: Tue, 30 Mar 2021 12:32:31 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -250,7 +250,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/to_be_deleted/_manifests - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwNDM1MDAsIm5iZiI6MTYxNzA0MzUwMCwiZXhwIjoxNjE3MTMwMjAwLCJhaW8iOiJFMlpnWURpbzlzdFQ5NXFRUVVkK3hWSHRULy8xQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiT3EydzMyVi14VXVqc0FrNm94Y0VBZyIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.hWjWRe_6O2wql1pkNnQKG1oW1a3Z3SckZ6OZMIMM_LuporkwdltV7mK4FIdB5635Zyk8z2OjAuVGYFnReAcJUhOR0JoT6Xtf90cfH8TWSKvkw5iqUtBQfI_ZtKzfSHMQwoRDsdsFmgVeka_QlZmUhSffcUCEcBOiBbCEHeKy2SX8jTX4iNmDYW2DnLw_TTA5LJhTItY_U9imPZzuYoAe2d8ctOgYpBPWRDOgwAnjJBzALPi1o3BTjhoVSlcpioXoP8A0h-hVmNz77zehcQ8A2R0tSCfWZ3sNDevkj5cC5c7fCqHX7K26w4LdRCpollDZkm-4IoIMnuQOtTPXUhQ3aQ + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -266,7 +266,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:03 GMT + date: Tue, 30 Mar 2021 12:32:31 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -277,7 +277,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhMmIyMGYxYi01NTU2LTRkYmUtYTFhOS04ZjBlYzQ2YWU0NGEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwNDI5MDMsImV4cCI6MTYxNzA1NDYwMywiaWF0IjoxNjE3MDQyOTAzLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.l0Q4Za29p7rbLlVmQTPCUVNogglznakiRH2r9UzNSeMIR8lCCxvLdlwcSufk8Yl9Z1Qm77tonTQDAiCQUq0zGlB3WR7RJtMpeIaQFoyQM0k-b4-i0HNSrYvYDS30WoJg7456gE5yPx27ZsJnQbl8HdZWPxPvu7QeMtRrLoTxtVJ4ivbt-LuoCtKuRpV2PV0lwUk2CiZUPTv0Pj8ClliwqZfCm1N-tE5wGeGqaI3xigoP6kCEe-m0UwGBa8UgTR2AXFgHCX94O2t8G6SsXdoLR2BfBV3yOou_bHAMclKxGpQutRjqnn4QN6-sDmO1wdecbZD-tn1a8H3Dvm3dZuasKg + refresh_token: REDACTED scope: repository:to_be_deleted:metadata_read service: seankane.azurecr.io headers: @@ -293,7 +293,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:03 GMT + date: Tue, 30 Mar 2021 12:32:31 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -312,14 +312,14 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/to_be_deleted/_manifests response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-29T18:33:26.4188433Z","lastUpdateTime":"2021-03-29T18:33:26.4188433Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-29T18:33:26.9893324Z","lastUpdateTime":"2021-03-29T18:33:26.9893324Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-29T18:33:26.812248Z","lastUpdateTime":"2021-03-29T18:33:26.812248Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-29T18:33:26.7610154Z","lastUpdateTime":"2021-03-29T18:33:26.7610154Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-29T18:33:26.8748922Z","lastUpdateTime":"2021-03-29T18:33:26.8748922Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-29T18:33:27.5628238Z","lastUpdateTime":"2021-03-29T18:33:27.5628238Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-29T18:33:29.7231407Z","lastUpdateTime":"2021-03-29T18:33:29.7231407Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-29T18:33:27.1797223Z","lastUpdateTime":"2021-03-29T18:33:27.1797223Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-29T18:33:26.9111873Z","lastUpdateTime":"2021-03-29T18:33:26.9111873Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} + string: '{"registry":"fake_url.azurecr.io","imageName":"to_be_deleted","manifests":[{"digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","imageSize":0,"createdTime":"2021-03-30T12:32:11.5970249Z","lastUpdateTime":"2021-03-30T12:32:11.5970249Z","mediaType":"application/vnd.docker.distribution.manifest.list.v2+json","tags":["to_be_deleted"],"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}},{"digest":"sha256:50b8560ad574c779908da71f7ce370c0a2471c098d44d1c8f6b513c5a55eeeb1","imageSize":0,"createdTime":"2021-03-30T12:32:12.087437Z","lastUpdateTime":"2021-03-30T12:32:12.087437Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:88b2e00179bd6c4064612403c8d42a13de7ca809d61fee966ce9e129860a8a90","imageSize":0,"createdTime":"2021-03-30T12:32:12.9678728Z","lastUpdateTime":"2021-03-30T12:32:12.9678728Z","architecture":"mips64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:963612c5503f3f1674f315c67089dee577d8cc6afc18565e0b4183ae355fb343","imageSize":0,"createdTime":"2021-03-30T12:32:12.3723557Z","lastUpdateTime":"2021-03-30T12:32:12.3723557Z","architecture":"arm64","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:b0408a0f1d74eced127a2658429f336ed8fa48e36d59878f155b19865e5dbd70","imageSize":0,"createdTime":"2021-03-30T12:32:13.0558039Z","lastUpdateTime":"2021-03-30T12:32:13.0558039Z","architecture":"amd64","os":"windows","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:bb7ab0fa94fdd78aca84b27a1bd46c4b811051f9b69905d81f5f267fc6546a9d","imageSize":0,"createdTime":"2021-03-30T12:32:13.5214505Z","lastUpdateTime":"2021-03-30T12:32:13.5214505Z","architecture":"ppc64le","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:cb55d8f7347376e1ba38ca740904b43c9a52f66c7d2ae1ef1a0de1bc9f40df98","imageSize":0,"createdTime":"2021-03-30T12:32:12.4776624Z","lastUpdateTime":"2021-03-30T12:32:12.4776624Z","architecture":"386","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e49abad529e5d9bd6787f3abeab94e09ba274fe34731349556a850b9aebbf7bf","imageSize":0,"createdTime":"2021-03-30T12:32:12.8779434Z","lastUpdateTime":"2021-03-30T12:32:12.8779434Z","architecture":"s390x","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}},{"digest":"sha256:e5785cb0c62cebbed4965129bae371f0589cadd6d84798fb58c2c5f9e237efd9","imageSize":0,"createdTime":"2021-03-30T12:32:12.2814609Z","lastUpdateTime":"2021-03-30T12:32:12.2814609Z","architecture":"arm","os":"linux","mediaType":"application/vnd.docker.distribution.manifest.v2+json","changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true,"quarantineState":"Passed"}}]} ' headers: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 18:50:03 GMT + date: Tue, 30 Mar 2021 12:32:31 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml index fc6435bcc3aa..ae380bb2adb1 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '196' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:45 GMT + date: Tue, 30 Mar 2021 12:32:47 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/_catalog - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgzMjYsIm5iZiI6MTYxNzAzODMyNiwiZXhwIjoxNjE3MTI1MDI2LCJhaW8iOiJFMlpnWUdBOFBmdDkvWnpkKzJlTFJIb3BIMTV3REFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDdGQzVodElRVVNVSDdUX3BDRVlBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.ZM7EvHmcgfCdXw-hPwJwRm_VLuIjPWP0yN9epulLmPQ9pMeJds_aiWmF5P6qDHYELGLVIxKojeOZxtkRf7FSHbqs3raFQI4QLsfWUdC-NvZUtcdWD-dWrUiKqgK8AIaEnOcn0DZNTwUnBtDWMi0aSX4Nl3L9KZpaXQXcgohkZQ0vkaTcnu81481nPf3FWEbxLjXltacuTrIdUhzvIl010vPZH4tPaOGUQcsxD1_YcOAcwVBNIqbuW4rmA-z1rmOFkeCxvCVIyep2MVJUmTUWxItf_Pt0f7g-U0q08nQsUbLNPupsKc-8hKLQICLvwrzcvKogagmZvsZJegvEPrAnGg + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:47 GMT + date: Tue, 30 Mar 2021 12:32:48 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI5YWE2M2JlOC1hNTIxLTRhMmMtODcxYi05MThhYWQxYjI2ZWEiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc3MjcsImV4cCI6MTYxNzA0OTQyNywiaWF0IjoxNjE3MDM3NzI3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.AEweEuzrXzV66SX7QT8lEEsXqb6o9z0kEUG6o3d6SSSCiBYyHyfjda9K__1ofB36XlKLvVc5rKXin80xEFlSIwu3N9Fw-FB6DUzXWpGgicdQINJiSgNHXnhQtxeMg10MIZALQPYYypmmeLz5eCVOL8LcdUC09PTLTuYvGXv0XpSwfo9VYICzivFzRL4ky6PPoigVGIyirsEoWtt7MVmhtm6VY5OR57BjdW2dNo0Qylzg7Ns3SI2Jl8j4fSA0j2CQh_9KcOY9kpQfpmRg0wDjsbG8XzRQtiKGI_4GMGf1mCaJlw7Z9UnztHe1lIJUCet1K1MIM3HDxYotmdX69d40dg + refresh_token: REDACTED scope: registry:catalog:* service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:47 GMT + date: Tue, 30 Mar 2021 12:32:49 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -93,15 +93,15 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","to_be_deleted","ubuntu"]} + string: '{"repositories":["alpine/git","debian","hello-world","library/hello-world","to_be_deleted","ubuntu"]} ' headers: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive - content-length: '119' + content-length: '102' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:47 GMT + date: Tue, 30 Mar 2021 12:32:49 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -130,7 +130,7 @@ interactions: connection: keep-alive content-length: '209' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:47 GMT + date: Tue, 30 Mar 2021 12:32:49 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -142,7 +142,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/to_be_deleted - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgzMjgsIm5iZiI6MTYxNzAzODMyOCwiZXhwIjoxNjE3MTI1MDI4LCJhaW8iOiJFMlpnWUdpcXRZMnBTODFaa2VheXh1K05aeWtQQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiaW9fZlFLMHFBVVdsTDNEcTZWUFlBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.UlKKG26ImkHfjGbtB8NaceIB83W-iwAXJ7RcCdFVF7zKIQg4SmxXSfFD2fjn2tB0u9IZXULUgf7a2xWqRQURQR-0K8CWd0TZRl65C6DrcPhL3U3nP6FvJ3SyfYO4sGW6P3ZcjHPfwWUnP-DAULzBnViDIOmSrC9RIBB4HzB936kAfw8WLKDiyrbEOksOEWQM0AKUZ9z8Oik82WzOqM-wRwSVwQggbsEAAs4Uw7djnR-9NsM6ULTgZU88aVbNlxENMa3Sic_bRJJt2iOj0sF5Dd64q2L4CEyO3R8Mzu3UoJDb0-6wcNFSeP0ZHD3RbaCQ3I2aFoTCWT-dwtNF5eqkiA + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -158,7 +158,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:49 GMT + date: Tue, 30 Mar 2021 12:32:50 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -169,7 +169,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJkZTY4MDI1Zi1iMGUzLTQ1NmQtYTJiYy1lNmYyODE1Y2UwNWUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc3MjksImV4cCI6MTYxNzA0OTQyOSwiaWF0IjoxNjE3MDM3NzI5LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.efL7AXLXW5eYRrnHem3sP3y6Jgt-5UxDH_6UZQOKko4sTwbjF5hSdujqKJcCVV7tcT6qPzpkNZoYChvPzzdViP3Y52_PRwzfK1Ww_z0DDh7KzYlUGv8uAV7Cy6ydwDyyVHSQa1e_Bu9f0myk2xRq1cvp0GBu3orApKnmnajiBtGMjXoUdO0-AxpLWMbZk8MCSVqG98GaOzkMdirZEaf_BpD1O04tg-e3AZtsTgjRboS_DVjk7vRxtTDXEZS7ItVtTi_vMQYTCwYeEaJ0vJx06F4A9gVE9gpGsC_o2Cr-HNumJLEDcWtH44JBC5_FFAw2C42tKstUGx1C7uU0f2dbgQ + refresh_token: REDACTED scope: repository:to_be_deleted:delete service: seankane.azurecr.io headers: @@ -185,7 +185,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:49 GMT + date: Tue, 30 Mar 2021 12:32:50 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -212,7 +212,7 @@ interactions: connection: keep-alive content-length: '795' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:51 GMT + date: Tue, 30 Mar 2021 12:32:52 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -241,7 +241,7 @@ interactions: connection: keep-alive content-length: '196' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:57 GMT + date: Tue, 30 Mar 2021 12:32:57 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -253,7 +253,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/_catalog - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzgzMjYsIm5iZiI6MTYxNzAzODMyNiwiZXhwIjoxNjE3MTI1MDI2LCJhaW8iOiJFMlpnWUdBOFBmdDkvWnpkKzJlTFJIb3BIMTV3REFBPSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiSDdGQzVodElRVVNVSDdUX3BDRVlBUSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.ZM7EvHmcgfCdXw-hPwJwRm_VLuIjPWP0yN9epulLmPQ9pMeJds_aiWmF5P6qDHYELGLVIxKojeOZxtkRf7FSHbqs3raFQI4QLsfWUdC-NvZUtcdWD-dWrUiKqgK8AIaEnOcn0DZNTwUnBtDWMi0aSX4Nl3L9KZpaXQXcgohkZQ0vkaTcnu81481nPf3FWEbxLjXltacuTrIdUhzvIl010vPZH4tPaOGUQcsxD1_YcOAcwVBNIqbuW4rmA-z1rmOFkeCxvCVIyep2MVJUmTUWxItf_Pt0f7g-U0q08nQsUbLNPupsKc-8hKLQICLvwrzcvKogagmZvsZJegvEPrAnGg + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -269,7 +269,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:57 GMT + date: Tue, 30 Mar 2021 12:32:58 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -280,7 +280,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIyMzg0NDlmOC0yOGNhLTRiMzUtYjZiMC02MWU3NzE5YTZiMzMiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzc3MzcsImV4cCI6MTYxNzA0OTQzNywiaWF0IjoxNjE3MDM3NzM3LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.iS1gKkbBuumPlqpbYfWFhlCux6wzJJ7zyhsM2rB45GClsVTHHywp4gSJdMPsQwtZpRV6zIXiDRwT6LIMllJztVEAgyYtpJErQzCgRtl4pnekH77oAm4SUgPtW4n-rdd_lBAY2DK_pnKzwXlkoK7Yf5jkOPQw4fC6e2kbRIO-eTMZFr648Ab6XMn4OPtxk2ynlV2LaEEbQ0DjW15tcGzEWqEVmVEwNdk_xSbpcChMxXHph-nCz9tMn9RLqGuTXI8VIc6AhjdlMPLlGNabS4g9ITYgx2hGKQQuQ7fRB-YjD1XxU_rnxplGaqW1voSpasoAIurhVw2eb8hDFDen1-OntA + refresh_token: REDACTED scope: registry:catalog:* service: seankane.azurecr.io headers: @@ -296,7 +296,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:57 GMT + date: Tue, 30 Mar 2021 12:32:58 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -315,15 +315,15 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/_catalog response: body: - string: '{"repositories":["alpine","alpine/git","busybox","debian","docker101tutorial","hello-world","ubuntu"]} + string: '{"repositories":["alpine/git","debian","hello-world","library/hello-world","ubuntu"]} ' headers: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive - content-length: '103' + content-length: '86' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:23:57 GMT + date: Tue, 30 Mar 2021 12:32:58 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml index 7fbd5abd9e22..33a755095523 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_repository_doesnt_exist.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '210' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:20 GMT + date: Tue, 30 Mar 2021 12:32:59 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/does_not_exist - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTcwMzkwMjEsIm5iZiI6MTYxNzAzOTAyMSwiZXhwIjoxNjE3MTI1NzIxLCJhaW8iOiJFMlpnWVBpd3cyUEwzSTR3eFo3dW1XNnNYcDVhQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiTndYRDQzQWZNVUNSLVRfMzk4eElBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.aseuguWMUT-unLBgLaXuAm-8Z3fl8E3kkrkw2tMPRi4y11QWVQaKPpzuvyqFeyj913dNKkJ6hwNTmbPSlSbQXfkSG11Nh85cAE4I30gqXEo4zepm2skU6D5yVJruusH0mJ_HpuavI7k77truIm16w6f_vQweSYx6SnlT8gGOHDzT7ebO6nXg8D-DINqJM1rdkgDLeJuT17S2QYWno0c9pve4gnhIK5cZCO2r86adZX2FFeudnWCfWtFqe4tTEG-xFnS-qpC4Y_Ki7TB19ItxH6-bLWWc-k2jVcsTcNgY9EeB_gGlRbzAUgEQmMLxdyZu2M2Y2SPnd0PW09YeVqD_4Q + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:22 GMT + date: Tue, 30 Mar 2021 12:33:00 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiI0MmE3YjQyMy02Njc0LTRmZmItOGQzNi1mMGY1M2ZlNWMyZDYiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTcwMzg0MjIsImV4cCI6MTYxNzA1MDEyMiwiaWF0IjoxNjE3MDM4NDIyLCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.ajVjufqmwhT1zxtUFmOgkdn02mfWpwLc2Gku2mSeNRMMseDhCE-7zI_VHjvgDGyJVaUtghN-nF7NyT5FqHff667ZqHcdBPkjRu_ByiJxHQgSl6sbdOh_DV22fsaSxgwwNJgWBheGkFqCpIv-QqBTuZ4jpgtUKUY2PtxHRUER351RugYYPZUhcntFbFbcZsRUm6aolb1QSjoP5rDTxiQXooH6uCV7Kr-iochmxLLZLW7FZcPPunTEVKDKQabVIbR9Ebce72AsI3u8c-BQmghLTgYt3F7EIQiVWt3tfB7pMhnOb1NZy1U0XTSspIPoivaYAYgMyfK4q_ypg-lMcokOUA + refresh_token: REDACTED scope: repository:does_not_exist:delete service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:22 GMT + date: Tue, 30 Mar 2021 12:33:00 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -102,7 +102,7 @@ interactions: connection: keep-alive content-length: '122' content-type: application/json; charset=utf-8 - date: Mon, 29 Mar 2021 17:35:22 GMT + date: Tue, 30 Mar 2021 12:33:00 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml index b38db386ed50..126f559ad43a 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml +++ b/sdk/containerregistry/azure-containerregistry/tests/recordings/test_container_repository_client_async.test_delete_tag.yaml @@ -19,7 +19,7 @@ interactions: connection: keep-alive content-length: '214' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:41:54 GMT + date: Tue, 30 Mar 2021 12:33:23 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -31,7 +31,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ2MTQsIm5iZiI6MTYxNjc5NDYxNCwiZXhwIjoxNjE2ODgxMzE0LCJhaW8iOiJFMlpnWUpncjd5M0NLR295ZGVVbEUxL09mck5jQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2lHQ3FBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NVBIvW3PyYFC8QQG4x4_XkzWHYrJHvz_6LGIrV7r6K_nsoUDY2iwzY4wF44O0voATg8ta4fND8YdL9cqtLdmLrtfkNpj3RM81XY73Ui0zHJa5cO8UNJnkUHG_XlIM3sZ6sSw57mOmSUce4MBl9JOQr_p2HCRQwbQVNMafCacfmqtFhKGbmSZMztL33rNZDF7pAaPQc5GutIl4COjQNUTigBWKynAOMiiG2pfpkWIh20P3WZTGtD-AH0kkL5pyRAjLByaHOvk0tydhL0MTOKBT7CFXDVF_N9wDDHYy9J8RjreWLSuIHwwaea_D7mvmp2bAVL4lkuIFgjJmGDAxtfn5w + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -47,7 +47,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:41:55 GMT + date: Tue, 30 Mar 2021 12:33:27 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -58,7 +58,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJjNjExMjA3OS1lMTA4LTQ1YzQtOGZlMC0yMWM3YjQ3ZjZiYzciLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQwMTUsImV4cCI6MTYxNjgwNTcxNSwiaWF0IjoxNjE2Nzk0MDE1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.WcYJOqzx7Y8cKsUV5vNXFR1RwDbhH80Eeo2dKj4aTi4Dyh9JvyldhreUYgTssUDR99tXjPPDw4MxGN9S9M5mPy-b4e_HiEi8fMSFe7PJh4RH6KIydW9sxyBqzLoKaM7WHiBrH7KwhAyDliPD8uRXg_ICgABPnuBYlSdGzmi-9HyIWh6_9oC7nQgMwK0JlETYCkNxaPxbjmVAiXEK5h52-Sx1ADCpjF5Epx56AdZ11oJ1MYeSDQXPBa01k6E1aRwGttaasoJNJx7LnwWKeIPgHLb534kWS-6O9rYEod4YSU4GS-c374YcHH2NBxkH7JVA7Iio4xcR8Eue7esLB13_Vw + refresh_token: REDACTED scope: repository:hello-world:metadata_read service: seankane.azurecr.io headers: @@ -74,7 +74,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:41:55 GMT + date: Tue, 30 Mar 2021 12:33:27 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -93,15 +93,15 @@ interactions: uri: https://fake_url.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted response: body: - string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-26T21:41:44.7917402Z","lastUpdateTime":"2021-03-26T21:41:44.7917402Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} + string: '{"registry":"fake_url.azurecr.io","imageName":"hello-world","tag":{"name":"to_be_deleted","digest":"sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24","createdTime":"2021-03-30T12:33:10.186609Z","lastUpdateTime":"2021-03-30T12:33:10.186609Z","signed":false,"changeableAttributes":{"deleteEnabled":true,"writeEnabled":true,"readEnabled":true,"listEnabled":true}}} ' headers: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive - content-length: '387' + content-length: '385' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:41:55 GMT + date: Tue, 30 Mar 2021 12:33:27 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -130,7 +130,7 @@ interactions: connection: keep-alive content-length: '207' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:41:55 GMT + date: Tue, 30 Mar 2021 12:33:28 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -142,7 +142,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ2MTQsIm5iZiI6MTYxNjc5NDYxNCwiZXhwIjoxNjE2ODgxMzE0LCJhaW8iOiJFMlpnWUpncjd5M0NLR295ZGVVbEUxL09mck5jQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2lHQ3FBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NVBIvW3PyYFC8QQG4x4_XkzWHYrJHvz_6LGIrV7r6K_nsoUDY2iwzY4wF44O0voATg8ta4fND8YdL9cqtLdmLrtfkNpj3RM81XY73Ui0zHJa5cO8UNJnkUHG_XlIM3sZ6sSw57mOmSUce4MBl9JOQr_p2HCRQwbQVNMafCacfmqtFhKGbmSZMztL33rNZDF7pAaPQc5GutIl4COjQNUTigBWKynAOMiiG2pfpkWIh20P3WZTGtD-AH0kkL5pyRAjLByaHOvk0tydhL0MTOKBT7CFXDVF_N9wDDHYy9J8RjreWLSuIHwwaea_D7mvmp2bAVL4lkuIFgjJmGDAxtfn5w + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -158,7 +158,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:41:55 GMT + date: Tue, 30 Mar 2021 12:33:28 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -169,7 +169,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiJhZTg0ZWE3My1hMTE4LTQ2ZDktYWI1MC03Mzg2YThlMzMzODUiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQwMTUsImV4cCI6MTYxNjgwNTcxNSwiaWF0IjoxNjE2Nzk0MDE1LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.pa6UocvH_9D6cJ-he7bc7nhiBEr2GumCc0MO0ap00o94OKf574PG8RhYTekCTf2yedgbzR0nSnZXvTai73qgZuSQaH_O_2aGcaWz9efJjvgc-REjePgWBRB2FSGK7u4EeYdIFLIeATjMzGhgna1udExE5SZhbVt7VkCP78GvmypPB5g5-CZ2FW37Mo7j5i3l8G6Jvbk_wI-yhGEAIZxa0jIrKugFLQ0B4UHko5FA6t9_c0BtJosGHPB5B71KiTKtECmG-Am1Loiw0ASadA7oFaaff5EhtcDrZlDLlSW9dyEN8IeFVVPdIqY1mHdNHw3qp2sjz32jLz_dSK3U1fj2KQ + refresh_token: REDACTED scope: repository:hello-world:delete service: seankane.azurecr.io headers: @@ -185,7 +185,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:41:56 GMT + date: Tue, 30 Mar 2021 12:33:28 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -209,7 +209,7 @@ interactions: access-control-expose-headers: X-Ms-Correlation-Request-Id connection: keep-alive content-length: '0' - date: Fri, 26 Mar 2021 21:41:56 GMT + date: Tue, 30 Mar 2021 12:33:29 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -239,7 +239,7 @@ interactions: connection: keep-alive content-length: '214' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:42:06 GMT + date: Tue, 30 Mar 2021 12:33:39 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains @@ -251,7 +251,7 @@ interactions: url: https://seankane.azurecr.io/acr/v1/hello-world/_tags/to_be_deleted - request: body: - access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0Ny8iLCJpYXQiOjE2MTY3OTQ2MTQsIm5iZiI6MTYxNjc5NDYxNCwiZXhwIjoxNjE2ODgxMzE0LCJhaW8iOiJFMlpnWUpncjd5M0NLR295ZGVVbEUxL09mck5jQUE9PSIsImFwcGlkIjoiZjg1MDY1MGMtMWZjZi00NDg5LWI0NmYtNzFhZjJlMzBkMzYwIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3LyIsIm9pZCI6IjMwNTExYzlkLWJhMWEtNGM3Yi1iNDIyLTViNTQzZGExMWIzZiIsInJoIjoiMC5BUm9BdjRqNWN2R0dyMEdScXkxODBCSGJSd3hsVVBqUEg0bEV0Rzl4cnk0dzAyQWFBQUEuIiwic3ViIjoiMzA1MTFjOWQtYmExYS00YzdiLWI0MjItNWI1NDNkYTExYjNmIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoibVg0SmFGTUU2VU9aQmtEd2lHQ3FBQSIsInZlciI6IjEuMCIsInhtc190Y2R0IjoxMjg5MjQxNTQ3fQ.NVBIvW3PyYFC8QQG4x4_XkzWHYrJHvz_6LGIrV7r6K_nsoUDY2iwzY4wF44O0voATg8ta4fND8YdL9cqtLdmLrtfkNpj3RM81XY73Ui0zHJa5cO8UNJnkUHG_XlIM3sZ6sSw57mOmSUce4MBl9JOQr_p2HCRQwbQVNMafCacfmqtFhKGbmSZMztL33rNZDF7pAaPQc5GutIl4COjQNUTigBWKynAOMiiG2pfpkWIh20P3WZTGtD-AH0kkL5pyRAjLByaHOvk0tydhL0MTOKBT7CFXDVF_N9wDDHYy9J8RjreWLSuIHwwaea_D7mvmp2bAVL4lkuIFgjJmGDAxtfn5w + access_token: REDACTED grant_type: access_token service: seankane.azurecr.io headers: @@ -267,7 +267,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:42:06 GMT + date: Tue, 30 Mar 2021 12:33:40 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -278,7 +278,7 @@ interactions: - request: body: grant_type: refresh_token - refresh_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ikk2NVk6VEVDUzpLTEhMOjZCVlE6SUJaRjpGRVhCOlk0VUg6SlRJUzo2VFBYOkNWWEE6SkxUSzpRS0RRIn0.eyJqdGkiOiIxMTMyZTY5OS03MDMwLTRkNTktYjE3Ni01Nzc3NDJkZTQzNmIiLCJzdWIiOiIzMDUxMWM5ZC1iYTFhLTRjN2ItYjQyMi01YjU0M2RhMTFiM2YiLCJuYmYiOjE2MTY3OTQwMjYsImV4cCI6MTYxNjgwNTcyNiwiaWF0IjoxNjE2Nzk0MDI2LCJpc3MiOiJBenVyZSBDb250YWluZXIgUmVnaXN0cnkiLCJhdWQiOiJzZWFua2FuZS5henVyZWNyLmlvIiwidmVyc2lvbiI6IjEuMCIsInJpZCI6ImExZTAxZmYzMzk2YzRmMTVhMmRjNjM2NzNkN2ZjYTMzIiwiZ3JhbnRfdHlwZSI6InJlZnJlc2hfdG9rZW4iLCJwZXJtaXNzaW9ucyI6eyJhY3Rpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdLCJub3RBY3Rpb25zIjpudWxsfSwicm9sZXMiOltdfQ.YG3fFy8fTJt2YVRPQ1p5yXr8BO0NoUhD-wroVo-NBbEHBm8wP6zi-zqMP_epwOuPtYd3fjtehsX31ETFECTNwQs8reSyEI6_0_PppzgIH3chcapOKVOlfAnPIggyOgYtHw3If4etNytqBaALEMJvDuThepxVGxXB5Y4zitTA1yAbdUSLBytThnSjENHHPxl8BCSCKrP2clO5e9yU10TdoIk9rNf5SVs11-VwYMbUkEel96IbK685a5FIgcVtyn8Kk-qT2-YApMCT6j3EYQG6apDtyuQhorNU1X6oWYgNg746glL6Wwth5iuoed5nRrPSrVYndyFQ-ANsZHJmbe10yQ + refresh_token: REDACTED scope: repository:hello-world:metadata_read service: seankane.azurecr.io headers: @@ -294,7 +294,7 @@ interactions: headers: connection: keep-alive content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:42:07 GMT + date: Tue, 30 Mar 2021 12:33:40 GMT server: openresty strict-transport-security: max-age=31536000; includeSubDomains transfer-encoding: chunked @@ -322,7 +322,7 @@ interactions: connection: keep-alive content-length: '81' content-type: application/json; charset=utf-8 - date: Fri, 26 Mar 2021 21:42:07 GMT + date: Tue, 30 Mar 2021 12:33:41 GMT docker-distribution-api-version: registry/2.0 server: openresty strict-transport-security: max-age=31536000; includeSubDomains diff --git a/sdk/containerregistry/azure-containerregistry/tests/testcase.py b/sdk/containerregistry/azure-containerregistry/tests/testcase.py index 4bff37072655..3e176e674716 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/testcase.py +++ b/sdk/containerregistry/azure-containerregistry/tests/testcase.py @@ -3,6 +3,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # ------------------------------------ +import copy from datetime import datetime import json import os @@ -31,13 +32,14 @@ class AcrBodyReplacer(RecordingProcessor): """Replace request body for oauth2 exchanges""" - def __init__(self, replacement="redacted"): self._replacement = replacement self._401_replacement = 'Bearer realm="https://fake_url.azurecr.io/oauth2/token",service="fake_url.azurecr.io",scope="fake_scope",error="invalid_token"' def _scrub_body(self, body): # type: (bytes) -> bytes + if isinstance(body, dict): + return self._scrub_body_dict(body) if not isinstance(body, six.binary_type): return body s = body.decode("utf-8") @@ -52,6 +54,13 @@ def _scrub_body(self, body): s = "&".join(s) return bytes(s, "utf-8") + def _scrub_body_dict(self, body): + new_body = copy.deepcopy(body) + for k in ["access_token", "refresh_token"]: + if k in new_body.keys(): + new_body[k] = REDACTED + return new_body + def process_request(self, request): if request.body: request.body = self._scrub_body(request.body) @@ -60,20 +69,20 @@ def process_request(self, request): def process_response(self, response): try: - headers = response["headers"] + headers = response['headers'] auth_header = None if "www-authenticate" in headers: - response["headers"]["www-authenticate"] = self._401_replacement + response['headers']["www-authenticate"] = self._401_replacement - body = response["body"] + body = response['body'] try: - refresh = json.loads(body["string"]) + refresh = json.loads(body['string']) if "refresh_token" in refresh.keys(): - refresh["refresh_token"] = REDACTED - body["string"] = json.dumps(refresh) + refresh['refresh_token'] = REDACTED + body['string'] = json.dumps(refresh) if "access_token" in refresh.keys(): refresh["access_token"] = REDACTED - body["string"] = json.dumps(refresh) + body['string'] = json.dumps(refresh) except json.decoder.JSONDecodeError: pass @@ -82,7 +91,6 @@ def process_response(self, response): except (KeyError, ValueError): return response - class FakeTokenCredential(object): """Protocol for classes able to provide OAuth tokens. :param str scopes: Lets you specify the type of access needed. From 850d69975f354464feac514316a52b236653ba0c Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Tue, 30 Mar 2021 08:56:41 -0400 Subject: [PATCH 83/86] linting issue --- .../azure/containerregistry/_container_repository_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index da69b3bbc9e0..fbe26dd34559 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -59,7 +59,7 @@ def delete_registry_artifact(self, digest, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - self._client.container_registry_repository.delete_manifest(self.repository, digest) + self._client.container_registry_repository.delete_manifest(self.repository, digest, **kwargs) def delete_tag(self, tag, **kwargs): # type: (str) -> None From 8ad77021487ef6133a26923917f7befed26daeca Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 1 Apr 2021 14:45:40 -0400 Subject: [PATCH 84/86] run black --- .../azure/containerregistry/_container_repository_client.py | 3 +-- .../aio/_async_container_repository_client.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index f22323ee1115..4a36decc7aa8 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -70,8 +70,7 @@ def delete_tag(self, tag, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - self._client.container_registry_repository.delete_tag( - self.repository, tag, **kwargs) + self._client.container_registry_repository.delete_tag(self.repository, tag, **kwargs) def get_properties(self, **kwargs): # type: (...) -> RepositoryProperties diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 45bc1fdf1be7..a5fa928f68bb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -71,8 +71,7 @@ async def delete_tag(self, tag: str, **kwargs) -> None: :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - await self._client.container_registry_repository.delete_tag( - self.repository, tag, **kwargs) + await self._client.container_registry_repository.delete_tag(self.repository, tag, **kwargs) async def get_properties(self, **kwargs) -> RepositoryProperties: """Get the properties of a repository From e228e3b4bb7290cf79e677f4557efdb2a29f71c2 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Thu, 1 Apr 2021 14:47:42 -0400 Subject: [PATCH 85/86] undoing all changes to generated code --- ...ontainer_registry_repository_operations.py | 2 +- .../models/_container_registry_enums.py | 24 +++----- .../_generated/models/_models.py | 50 +++++++++------- .../_generated/models/_models_py3.py | 59 +++++++++++-------- ...ontainer_registry_repository_operations.py | 2 +- 5 files changed, 74 insertions(+), 63 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py index c014049daa73..a5e395308f25 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/aio/operations/_container_registry_repository_operations.py @@ -413,7 +413,7 @@ def prepare_request(next_link=None): async def extract_data(pipeline_response): deserialized = self._deserialize('TagList', pipeline_response) - list_of_elem = deserialized.tag_attribute_bases + list_of_elem = deserialized.tags if cls: list_of_elem = cls(list_of_elem) return deserialized.link or None, AsyncList(list_of_elem) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py index 57139852c30f..4f9b6bfb490f 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_container_registry_enums.py @@ -1,6 +1,8 @@ # coding=utf-8 # -------------------------------------------------------------------------- -# Code generated by Microsoft (R) AutoRest Code Generator (autorest: 3.2.1, generator: {generator}) +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) AutoRest Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- @@ -24,20 +26,10 @@ def __getattr__(cls, name): raise AttributeError(name) -class RegistryArtifactOrderBy(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): - """Sort options for ordering registry artifacts in a collection. +class PostContentSchemaGrantType(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): + """Can take a value of access_token_refresh_token, or access_token, or refresh_token """ - #: Order registry artifacts by LastUpdatedOn field, from most recently updated to least recently - #: updated. - LAST_UPDATED_ON_DESCENDING = "timedesc" - #: Order registry artifacts by LastUpdatedOn field, from least recently updated to most recently - #: updated. - LAST_UPDATED_ON_ASCENDING = "timeasc" - -class TagOrderBy(with_metaclass(_CaseInsensitiveEnumMeta, str, Enum)): - - #: Order tags by LastUpdatedOn field, from most recently updated to least recently updated. - LAST_UPDATED_ON_DESCENDING = "timedesc" - #: Order tags by LastUpdatedOn field, from least recently updated to most recently updated. - LAST_UPDATED_ON_ASCENDING = "timeasc" + ACCESS_TOKEN_REFRESH_TOKEN = "access_token_refresh_token" + ACCESS_TOKEN = "access_token" + REFRESH_TOKEN = "refresh_token" diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py index 5798b6c92906..81934d82941b 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models.py @@ -191,7 +191,7 @@ def __init__( class ContentProperties(msrest.serialization.Model): - """Changeable attributes. + """ContentProperties. :param can_delete: Delete enabled. :type can_delete: bool @@ -448,6 +448,8 @@ class ManifestAttributesBase(msrest.serialization.Model): _validation = { 'digest': {'required': True}, + 'tags': {'required': True}, + 'manifest_properties': {'required': True}, } _attribute_map = { @@ -457,9 +459,9 @@ class ManifestAttributesBase(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, 'operating_system': {'key': 'os', 'type': 'str'}, - 'references': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, + 'registry_artifacts': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, + 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -473,9 +475,9 @@ def __init__( self.last_updated_on = kwargs.get('last_updated_on', None) self.cpu_architecture = kwargs.get('cpu_architecture', None) self.operating_system = kwargs.get('operating_system', None) - self.references = kwargs.get('references', None) - self.tags = kwargs.get('tags', None) - self.writeable_properties = kwargs.get('writeable_properties', None) + self.registry_artifacts = kwargs.get('registry_artifacts', None) + self.tags = kwargs['tags'] + self.manifest_properties = kwargs['manifest_properties'] class ManifestAttributesManifest(msrest.serialization.Model): @@ -885,9 +887,11 @@ def __init__( class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str - :param digest: Manifest. + :param digest: Required. Manifest. :type digest: str :param size: Image size. :type size: long @@ -907,6 +911,13 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type manifest_properties: ~container_registry.models.ContentProperties """ + _validation = { + 'repository': {'required': True}, + 'digest': {'required': True}, + 'tags': {'required': True}, + 'manifest_properties': {'required': True}, + } + _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'digest': {'key': 'manifest.digest', 'type': 'str'}, @@ -915,9 +926,9 @@ class RegistryArtifactProperties(msrest.serialization.Model): 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'references': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, + 'registry_artifacts': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'manifest.tags', 'type': '[str]'}, - 'writeable_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, + 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, } def __init__( @@ -925,16 +936,16 @@ def __init__( **kwargs ): super(RegistryArtifactProperties, self).__init__(**kwargs) - self.repository = kwargs.get('repository', None) - self.digest = kwargs.get('digest', None) + self.repository = kwargs['repository'] + self.digest = kwargs['digest'] self.size = kwargs.get('size', None) self.created_on = kwargs.get('created_on', None) self.last_updated_on = kwargs.get('last_updated_on', None) self.cpu_architecture = kwargs.get('cpu_architecture', None) self.operating_system = kwargs.get('operating_system', None) - self.references = kwargs.get('references', None) - self.tags = kwargs.get('tags', None) - self.writeable_properties = kwargs.get('writeable_properties', None) + self.registry_artifacts = kwargs.get('registry_artifacts', None) + self.tags = kwargs['tags'] + self.manifest_properties = kwargs['manifest_properties'] class Repositories(msrest.serialization.Model): @@ -969,7 +980,7 @@ class RepositoryProperties(msrest.serialization.Model): :type name: str :param created_on: Required. Image created time. :type created_on: ~datetime.datetime - :param last_updated_on: Required. Image last update time. + :param last_updated_on: Image last update time. :type last_updated_on: ~datetime.datetime :param registry_artifact_count: Required. Number of the manifests. :type registry_artifact_count: int @@ -982,7 +993,6 @@ class RepositoryProperties(msrest.serialization.Model): _validation = { 'name': {'required': True}, 'created_on': {'required': True}, - 'last_updated_on': {'required': True}, 'registry_artifact_count': {'required': True}, 'tag_count': {'required': True}, 'writeable_properties': {'required': True}, @@ -1004,7 +1014,7 @@ def __init__( super(RepositoryProperties, self).__init__(**kwargs) self.name = kwargs['name'] self.created_on = kwargs['created_on'] - self.last_updated_on = kwargs['last_updated_on'] + self.last_updated_on = kwargs.get('last_updated_on', None) self.registry_artifact_count = kwargs['registry_artifact_count'] self.tag_count = kwargs['tag_count'] self.writeable_properties = kwargs['writeable_properties'] @@ -1113,7 +1123,7 @@ class TagList(msrest.serialization.Model): _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, - 'tag_attribute_bases': {'key': 'tags', 'type': '[TagAttributesBase]'}, + 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -1123,7 +1133,7 @@ def __init__( ): super(TagList, self).__init__(**kwargs) self.repository = kwargs['repository'] - self.tag_attribute_bases = kwargs.get('tag_attribute_bases', None) + self.tags = kwargs.get('tags', None) self.link = kwargs.get('link', None) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py index daf971e105de..8fe23c8756ef 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/models/_models_py3.py @@ -222,7 +222,7 @@ def __init__( class ContentProperties(msrest.serialization.Model): - """Changeable attributes. + """ContentProperties. :param can_delete: Delete enabled. :type can_delete: bool @@ -512,6 +512,8 @@ class ManifestAttributesBase(msrest.serialization.Model): _validation = { 'digest': {'required': True}, + 'tags': {'required': True}, + 'manifest_properties': {'required': True}, } _attribute_map = { @@ -521,23 +523,23 @@ class ManifestAttributesBase(msrest.serialization.Model): 'last_updated_on': {'key': 'lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'architecture', 'type': 'str'}, 'operating_system': {'key': 'os', 'type': 'str'}, - 'references': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, + 'registry_artifacts': {'key': 'references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'tags', 'type': '[str]'}, - 'writeable_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, + 'manifest_properties': {'key': 'changeableAttributes', 'type': 'ContentProperties'}, } def __init__( self, *, digest: str, + tags: List[str], + manifest_properties: "ContentProperties", size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, cpu_architecture: Optional[str] = None, operating_system: Optional[str] = None, - references: Optional[List["ManifestAttributesManifestReferences"]] = None, - tags: Optional[List[str]] = None, - writeable_properties: Optional["ContentProperties"] = None, + registry_artifacts: Optional[List["ManifestAttributesManifestReferences"]] = None, **kwargs ): super(ManifestAttributesBase, self).__init__(**kwargs) @@ -547,9 +549,9 @@ def __init__( self.last_updated_on = last_updated_on self.cpu_architecture = cpu_architecture self.operating_system = operating_system - self.references = references + self.registry_artifacts = registry_artifacts self.tags = tags - self.writeable_properties = writeable_properties + self.manifest_properties = manifest_properties class ManifestAttributesManifest(msrest.serialization.Model): @@ -1018,9 +1020,11 @@ def __init__( class RegistryArtifactProperties(msrest.serialization.Model): """Manifest attributes details. - :param repository: Image name. + All required parameters must be populated in order to send to Azure. + + :param repository: Required. Image name. :type repository: str - :param digest: Manifest. + :param digest: Required. Manifest. :type digest: str :param size: Image size. :type size: long @@ -1040,6 +1044,13 @@ class RegistryArtifactProperties(msrest.serialization.Model): :type manifest_properties: ~container_registry.models.ContentProperties """ + _validation = { + 'repository': {'required': True}, + 'digest': {'required': True}, + 'tags': {'required': True}, + 'manifest_properties': {'required': True}, + } + _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, 'digest': {'key': 'manifest.digest', 'type': 'str'}, @@ -1048,24 +1059,24 @@ class RegistryArtifactProperties(msrest.serialization.Model): 'last_updated_on': {'key': 'manifest.lastUpdateTime', 'type': 'iso-8601'}, 'cpu_architecture': {'key': 'manifest.architecture', 'type': 'str'}, 'operating_system': {'key': 'manifest.os', 'type': 'str'}, - 'references': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, + 'registry_artifacts': {'key': 'manifest.references', 'type': '[ManifestAttributesManifestReferences]'}, 'tags': {'key': 'manifest.tags', 'type': '[str]'}, - 'writeable_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, + 'manifest_properties': {'key': 'manifest.changeableAttributes', 'type': 'ContentProperties'}, } def __init__( self, *, - repository: Optional[str] = None, - digest: Optional[str] = None, + repository: str, + digest: str, + tags: List[str], + manifest_properties: "ContentProperties", size: Optional[int] = None, created_on: Optional[datetime.datetime] = None, last_updated_on: Optional[datetime.datetime] = None, cpu_architecture: Optional[str] = None, operating_system: Optional[str] = None, - references: Optional[List["ManifestAttributesManifestReferences"]] = None, - tags: Optional[List[str]] = None, - writeable_properties: Optional["ContentProperties"] = None, + registry_artifacts: Optional[List["ManifestAttributesManifestReferences"]] = None, **kwargs ): super(RegistryArtifactProperties, self).__init__(**kwargs) @@ -1076,9 +1087,9 @@ def __init__( self.last_updated_on = last_updated_on self.cpu_architecture = cpu_architecture self.operating_system = operating_system - self.references = references + self.registry_artifacts = registry_artifacts self.tags = tags - self.writeable_properties = writeable_properties + self.manifest_properties = manifest_properties class Repositories(msrest.serialization.Model): @@ -1116,7 +1127,7 @@ class RepositoryProperties(msrest.serialization.Model): :type name: str :param created_on: Required. Image created time. :type created_on: ~datetime.datetime - :param last_updated_on: Required. Image last update time. + :param last_updated_on: Image last update time. :type last_updated_on: ~datetime.datetime :param registry_artifact_count: Required. Number of the manifests. :type registry_artifact_count: int @@ -1129,7 +1140,6 @@ class RepositoryProperties(msrest.serialization.Model): _validation = { 'name': {'required': True}, 'created_on': {'required': True}, - 'last_updated_on': {'required': True}, 'registry_artifact_count': {'required': True}, 'tag_count': {'required': True}, 'writeable_properties': {'required': True}, @@ -1149,7 +1159,6 @@ def __init__( *, name: str, created_on: datetime.datetime, - last_updated_on: datetime.datetime, registry_artifact_count: int, tag_count: int, writeable_properties: "ContentProperties", @@ -1279,7 +1288,7 @@ class TagList(msrest.serialization.Model): _attribute_map = { 'repository': {'key': 'imageName', 'type': 'str'}, - 'tag_attribute_bases': {'key': 'tags', 'type': '[TagAttributesBase]'}, + 'tags': {'key': 'tags', 'type': '[TagAttributesBase]'}, 'link': {'key': 'link', 'type': 'str'}, } @@ -1287,13 +1296,13 @@ def __init__( self, *, repository: str, - tag_attribute_bases: Optional[List["TagAttributesBase"]] = None, + tags: Optional[List["TagAttributesBase"]] = None, link: Optional[str] = None, **kwargs ): super(TagList, self).__init__(**kwargs) self.repository = repository - self.tag_attribute_bases = tag_attribute_bases + self.tags = tags self.link = link diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py index afc76777c046..36968b545726 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_generated/operations/_container_registry_repository_operations.py @@ -423,7 +423,7 @@ def prepare_request(next_link=None): def extract_data(pipeline_response): deserialized = self._deserialize('TagList', pipeline_response) - list_of_elem = deserialized.tag_attribute_bases + list_of_elem = deserialized.tags if cls: list_of_elem = cls(list_of_elem) return deserialized.link or None, iter(list_of_elem) From 738eb9e5a4c3ac398bfc2048334a89c2684e23c0 Mon Sep 17 00:00:00 2001 From: seankane-msft Date: Fri, 2 Apr 2021 13:10:44 -0400 Subject: [PATCH 86/86] adding distributed trace decorators --- .../_container_registry_client.py | 7 ++++++- .../_container_repository_client.py | 12 ++++++++++++ .../aio/_async_container_registry_client.py | 5 +++++ .../aio/_async_container_repository_client.py | 18 +++++++++++++++--- .../test_container_repository_client_async.py | 4 ++-- 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py index 8d437b7f507a..69679c0bb9fb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_registry_client.py @@ -4,7 +4,9 @@ # Licensed under the MIT License. # ------------------------------------ from typing import TYPE_CHECKING + from azure.core.paging import ItemPaged +from azure.core.tracing.decorator import distributed_trace from ._base_client import ContainerRegistryBaseClient from ._container_repository_client import ContainerRepositoryClient @@ -33,6 +35,7 @@ def __init__(self, endpoint, credential, **kwargs): self._credential = credential super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) + @distributed_trace def delete_repository(self, repository, **kwargs): # type: (str, Dict[str, Any]) -> DeletedRepositoryResult """Delete a repository @@ -42,11 +45,11 @@ def delete_repository(self, repository, **kwargs): :returns: None :raises: :class:~azure.core.exceptions.ResourceNotFoundError """ - # NOTE: DELETE `/acr/v1/{name}` return DeletedRepositoryResult._from_generated( # pylint: disable=protected-access self._client.container_registry.delete_repository(repository, **kwargs) ) + @distributed_trace def list_repositories(self, **kwargs): # type: (Dict[str, Any]) -> ItemPaged[str] """List all repositories @@ -62,6 +65,7 @@ def list_repositories(self, **kwargs): last=kwargs.pop("last", None), n=kwargs.pop("max", None), **kwargs ) + @distributed_trace def get_repository_client(self, repository, **kwargs): # type: (str, Dict[str, Any]) -> ContainerRepositoryClient """Get a repository client @@ -69,5 +73,6 @@ def get_repository_client(self, repository, **kwargs): :param repository: The repository to create a client for :type repository: str :returns: :class:~azure.containerregistry.ContainerRepositoryClient + :raises: None """ return ContainerRepositoryClient(self._endpoint, repository, credential=self._credential, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py index 4a36decc7aa8..1bea7c443f36 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/_container_repository_client.py @@ -5,6 +5,8 @@ # ------------------------------------ from typing import TYPE_CHECKING +from azure.core.tracing.decorator import distributed_trace + from ._base_client import ContainerRegistryBaseClient from ._helpers import _is_tag from ._models import RepositoryProperties, TagProperties, RegistryArtifactProperties @@ -41,6 +43,7 @@ def _get_digest_from_tag(self, tag): tag_props = self.get_tag_properties(tag) return tag_props.digest + @distributed_trace def delete(self, **kwargs): # type: (...) -> None """Delete a repository @@ -50,6 +53,7 @@ def delete(self, **kwargs): """ self._client.container_registry.delete_repository(self.repository, **kwargs) + @distributed_trace def delete_registry_artifact(self, digest, **kwargs): # type: (str) -> None """Delete a registry artifact. A registry artifact can only be deleted from the digest @@ -61,6 +65,7 @@ def delete_registry_artifact(self, digest, **kwargs): """ self._client.container_registry_repository.delete_manifest(self.repository, digest, **kwargs) + @distributed_trace def delete_tag(self, tag, **kwargs): # type: (str) -> None """Delete a tag from a repository @@ -72,6 +77,7 @@ def delete_tag(self, tag, **kwargs): """ self._client.container_registry_repository.delete_tag(self.repository, tag, **kwargs) + @distributed_trace def get_properties(self, **kwargs): # type: (...) -> RepositoryProperties """Get the properties of a repository @@ -84,6 +90,7 @@ def get_properties(self, **kwargs): self._client.container_registry_repository.get_properties(self.repository, **kwargs) ) + @distributed_trace def get_registry_artifact_properties(self, tag_or_digest, **kwargs): # type: (str, Dict[str, Any]) -> RegistryArtifactProperties """Get the properties of a registry artifact @@ -102,6 +109,7 @@ def get_registry_artifact_properties(self, tag_or_digest, **kwargs): ) ) + @distributed_trace def get_tag_properties(self, tag, **kwargs): # type: (str, Dict[str, Any]) -> TagProperties """Get the properties for a tag @@ -115,6 +123,7 @@ def get_tag_properties(self, tag, **kwargs): self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) ) + @distributed_trace def list_registry_artifacts(self, **kwargs): # type: (...) -> ItemPaged[RegistryArtifactProperties] """List the artifacts for a repository @@ -142,6 +151,7 @@ def list_registry_artifacts(self, **kwargs): ], ) + @distributed_trace def list_tags(self, **kwargs): # type: (...) -> ItemPaged[TagProperties] """List the tags for a repository @@ -163,6 +173,7 @@ def list_tags(self, **kwargs): **kwargs ) + @distributed_trace def set_manifest_properties(self, digest, permissions, **kwargs): # type: (str, ContentPermissions) -> None """Set the properties for a manifest @@ -179,6 +190,7 @@ def set_manifest_properties(self, digest, permissions, **kwargs): self.repository, digest, value=permissions._to_generated(), **kwargs # pylint: disable=protected-access ) + @distributed_trace def set_tag_properties(self, tag_or_digest, permissions, **kwargs): # type: (str, ContentPermissions) -> None """Set the properties for a tag diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py index 5757d03ec512..3984e63cae85 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_registry_client.py @@ -6,6 +6,8 @@ from typing import Any, Dict, TYPE_CHECKING from azure.core.async_paging import AsyncItemPaged +from azure.core.tracing.decorator import distributed_trace +from azure.core.tracing.decorator_async import distributed_trace_async from ._async_base_client import ContainerRegistryBaseClient from ._async_container_repository_client import ContainerRepositoryClient @@ -32,6 +34,7 @@ def __init__(self, endpoint: str, credential: "AsyncTokenCredential", **kwargs: self._credential = credential super(ContainerRegistryClient, self).__init__(endpoint=endpoint, credential=credential, **kwargs) + @distributed_trace_async async def delete_repository(self, repository: str, **kwargs: Dict[str, Any]) -> DeletedRepositoryResult: """Delete a repository @@ -43,12 +46,14 @@ async def delete_repository(self, repository: str, **kwargs: Dict[str, Any]) -> result = await self._client.container_registry.delete_repository(repository, **kwargs) return DeletedRepositoryResult._from_generated(result) # pylint: disable=protected-access + @distributed_trace def list_repositories(self, **kwargs) -> AsyncItemPaged[str]: return self._client.container_registry.get_repositories( last=kwargs.pop("last", None), n=kwargs.pop("page_size", None), **kwargs ) + @distributed_trace_async def get_repository_client(self, name: str, **kwargs) -> ContainerRepositoryClient: return ContainerRepositoryClient(self._endpoint, name, self._credential, **kwargs) diff --git a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py index 5b88162b1663..2c154897a4cb 100644 --- a/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py +++ b/sdk/containerregistry/azure-containerregistry/azure/containerregistry/aio/_async_container_repository_client.py @@ -6,6 +6,8 @@ from typing import TYPE_CHECKING, Dict, Any from azure.core.async_paging import AsyncItemPaged +from azure.core.tracing.decorator import distributed_trace +from azure.core.tracing.decorator_async import distributed_trace_async from ._async_base_client import ContainerRegistryBaseClient from .._helpers import _is_tag @@ -44,6 +46,7 @@ async def _get_digest_from_tag(self, tag: str) -> None: tag_props = await self.get_tag_properties(tag) return tag_props.digest + @distributed_trace_async async def delete(self, **kwargs: Dict[str, Any]) -> None: """Delete a repository @@ -52,6 +55,7 @@ async def delete(self, **kwargs: Dict[str, Any]) -> None: """ await self._client.container_registry.delete_repository(self.repository, **kwargs) + @distributed_trace_async async def delete_registry_artifact(self, digest: str, **kwargs) -> None: """Delete a registry artifact @@ -62,6 +66,7 @@ async def delete_registry_artifact(self, digest: str, **kwargs) -> None: """ await self._client.container_registry_repository.delete_manifest(self.repository, digest, **kwargs) + @distributed_trace_async async def delete_tag(self, tag: str, **kwargs) -> None: """Delete a tag from a repository @@ -72,6 +77,7 @@ async def delete_tag(self, tag: str, **kwargs) -> None: """ await self._client.container_registry_repository.delete_tag(self.repository, tag, **kwargs) + @distributed_trace_async async def get_properties(self, **kwargs) -> RepositoryProperties: """Get the properties of a repository @@ -82,6 +88,7 @@ async def get_properties(self, **kwargs) -> RepositoryProperties: await self._client.container_registry_repository.get_properties(self.repository, **kwargs) ) + @distributed_trace_async async def get_registry_artifact_properties(self, tag_or_digest: str, **kwargs) -> RegistryArtifactProperties: """Get the properties of a registry artifact @@ -99,6 +106,7 @@ async def get_registry_artifact_properties(self, tag_or_digest: str, **kwargs) - ) ) + @distributed_trace_async async def get_tag_properties(self, tag: str, **kwargs) -> TagProperties: """Get the properties for a tag @@ -111,7 +119,8 @@ async def get_tag_properties(self, tag: str, **kwargs) -> TagProperties: await self._client.container_registry_repository.get_tag_properties(self.repository, tag, **kwargs) ) - async def list_registry_artifacts(self, **kwargs) -> AsyncItemPaged[RegistryArtifactProperties]: + @distributed_trace + def list_registry_artifacts(self, **kwargs) -> AsyncItemPaged[RegistryArtifactProperties]: """List the artifacts for a repository :keyword last: Query parameter for the last item in the previous query @@ -137,7 +146,8 @@ async def list_registry_artifacts(self, **kwargs) -> AsyncItemPaged[RegistryArti **kwargs ) - async def list_tags(self, **kwargs) -> AsyncItemPaged[TagProperties]: + @distributed_trace + def list_tags(self, **kwargs) -> AsyncItemPaged[TagProperties]: """List the tags for a repository :param last: Query parameter for the last item in the previous call. Ensuing @@ -147,7 +157,7 @@ async def list_tags(self, **kwargs) -> AsyncItemPaged[TagProperties]: :returns: ~azure.core.paging.AsyncItemPaged[TagProperties] :raises: None """ - return await self._client.container_registry_repository.get_tags( + return self._client.container_registry_repository.get_tags( self.repository, last=kwargs.pop("last", None), n=kwargs.pop("top", None), @@ -157,6 +167,7 @@ async def list_tags(self, **kwargs) -> AsyncItemPaged[TagProperties]: **kwargs ) + @distributed_trace_async async def set_manifest_properties(self, digest: str, permissions: ContentPermissions, **kwargs) -> None: """Set the properties for a manifest @@ -172,6 +183,7 @@ async def set_manifest_properties(self, digest: str, permissions: ContentPermiss self.repository, digest, value=permissions._to_generated(), **kwargs # pylint: disable=protected-access ) + @distributed_trace_async async def set_tag_properties(self, tag_or_digest: str, permissions: ContentPermissions, **kwargs) -> None: """Set the properties for a tag diff --git a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py index 1ff29a983c2a..5e10da7c82fb 100644 --- a/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py +++ b/sdk/containerregistry/azure-containerregistry/tests/test_container_repository_client_async.py @@ -71,14 +71,14 @@ async def test_delete_registry_artifact(self, containerregistry_baseurl, contain repo_client = self.create_repository_client(containerregistry_baseurl, TO_BE_DELETED) count = 0 - async for artifact in await repo_client.list_registry_artifacts(): + async for artifact in repo_client.list_registry_artifacts(): if count == 0: await repo_client.delete_registry_artifact(artifact.digest) count += 1 assert count > 0 artifacts = [] - async for a in await repo_client.list_registry_artifacts(): + async for a in repo_client.list_registry_artifacts(): artifacts.append(a) assert len(artifacts) > 0