-
Notifications
You must be signed in to change notification settings - Fork 3.2k
[Container Registry] Update API for Beta 2 #18392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d7bcfe6
7a0b598
15bbaaf
b91302c
6f7c55c
22ecb18
d5986dd
1287136
145949b
09f3636
6e38bf1
d9659c0
941473a
44ceace
4e5dbc8
f7caebd
6ced986
5417f1d
83c0d90
c0ed9ff
ed3f937
ccec23b
afa0c1b
0e2e335
a05639a
91f150f
4af08b9
992df39
35eb6e5
fd701a4
cb3341e
c25fec2
91e9839
ba7d4da
8ef7421
2ae91f1
9c20c59
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,229 @@ | ||
| # coding=utf-8 | ||
| # ------------------------------------ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| # ------------------------------------ | ||
| from typing import TYPE_CHECKING | ||
|
|
||
| from azure.core.exceptions import ( | ||
| ClientAuthenticationError, | ||
| ResourceNotFoundError, | ||
| ResourceExistsError, | ||
| HttpResponseError, | ||
| map_error, | ||
| ) | ||
| from azure.core.paging import ItemPaged | ||
| from azure.core.pipeline import Pipeline | ||
| from azure.core.tracing.decorator import distributed_trace | ||
|
|
||
| from ._base_client import ContainerRegistryBaseClient, TransportWrapper | ||
| from ._generated.models import AcrErrors | ||
| from ._helpers import _parse_next_link | ||
| from ._models import ( | ||
| DeleteRepositoryResult, | ||
| ArtifactManifestProperties, | ||
| RepositoryProperties, | ||
| ) | ||
| from ._registry_artifact import RegistryArtifact | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing import Any, Dict | ||
| from azure.core.credentials import TokenCredential | ||
| from ._models import ContentProperties | ||
|
|
||
|
|
||
| class ContainerRepository(ContainerRegistryBaseClient): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this no longer a client? Is it because a user cannot instantiate it themselves?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A user could instantiate it themselves but it would look a little awkward. We received feedback from the service team that the two clients made it confusing on where a user should start. Krystof and Anne Thompson came up with a design where both |
||
| def __init__(self, endpoint, name, credential, **kwargs): | ||
| # type: (str, str, TokenCredential, Dict[str, Any]) -> None | ||
| """Create a ContainerRepository from an endpoint, repository name, and credential | ||
|
|
||
| :param str endpoint: An ACR endpoint | ||
| :param str name: The name of a repository | ||
| :param credential: The credential with which to authenticate | ||
| :type credential: :class:`~azure.core.credentials.TokenCredential` | ||
| :returns: None | ||
| :raises: None | ||
| """ | ||
| if not endpoint.startswith("https://") and not endpoint.startswith("http://"): | ||
| endpoint = "https://" + endpoint | ||
| self._endpoint = endpoint | ||
| self.name = name | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this also have something like the property on self.fully_qualified_name = self._endpoint + self.repository
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes adding it now. |
||
| self._credential = credential | ||
| self.fully_qualified_name = self._endpoint + self.name | ||
| super(ContainerRepository, self).__init__(endpoint=self._endpoint, credential=credential, **kwargs) | ||
|
|
||
| @distributed_trace | ||
| def delete(self, **kwargs): | ||
| # type: (Dict[str, Any]) -> DeleteRepositoryResult | ||
| """Delete a repository | ||
|
|
||
| :returns: Object containing information about the deleted repository | ||
| :rtype: :class:`~azure.containerregistry.DeleteRepositoryResult` | ||
| :raises: :class:`~azure.core.exceptions.ResourceNotFoundError` | ||
| """ | ||
| return DeleteRepositoryResult._from_generated( # pylint: disable=protected-access | ||
| self._client.container_registry.delete_repository(self.name, **kwargs) | ||
| ) | ||
|
|
||
| @distributed_trace | ||
| def get_properties(self, **kwargs): | ||
| # type: (Dict[str, Any]) -> RepositoryProperties | ||
| """Get the properties of a repository | ||
|
|
||
| :returns: :class:`~azure.containerregistry.RepositoryProperties` | ||
| :raises: :class:`~azure.core.exceptions.ResourceNotFoundError` | ||
| """ | ||
| return RepositoryProperties._from_generated( # pylint: disable=protected-access | ||
| self._client.container_registry.get_properties(self.name, **kwargs) | ||
| ) | ||
|
|
||
| @distributed_trace | ||
| def list_manifests(self, **kwargs): | ||
| # type: (Dict[str, Any]) -> ItemPaged[ArtifactManifestProperties] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are the listed items here the same data that I would get from a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes they are, both calls return the same data. |
||
| """List the artifacts for a repository | ||
|
|
||
| :keyword last: Query parameter for the last item in the previous call. Ensuing | ||
| call will return values after last lexically | ||
| :paramtype last: str | ||
| :keyword order_by: Query parameter for ordering by time ascending or descending | ||
| :paramtype order_by: :class:`~azure.containerregistry.ManifestOrder` | ||
| :keyword results_per_page: Number of repositories to return per page | ||
| :paramtype results_per_page: int | ||
| :return: ItemPaged[:class:`ArtifactManifestProperties`] | ||
| :rtype: :class:`~azure.core.paging.ItemPaged` | ||
| :raises: :class:`~azure.core.exceptions.ResourceNotFoundError` | ||
| """ | ||
| name = self.name | ||
| last = kwargs.pop("last", None) | ||
| n = kwargs.pop("results_per_page", None) | ||
| orderby = kwargs.pop("order_by", None) | ||
| cls = kwargs.pop( | ||
| "cls", | ||
| lambda objs: [ | ||
| ArtifactManifestProperties._from_generated(x, repository_name=self.name) # pylint: disable=protected-access | ||
| for x in objs | ||
| ], | ||
| ) | ||
|
|
||
| error_map = {401: ClientAuthenticationError, 404: ResourceNotFoundError, 409: ResourceExistsError} | ||
| error_map.update(kwargs.pop("error_map", {})) | ||
| accept = "application/json" | ||
|
|
||
| def prepare_request(next_link=None): | ||
| # Construct headers | ||
| header_parameters = {} # type: Dict[str, Any] | ||
| header_parameters["Accept"] = self._client._serialize.header( # pylint: disable=protected-access | ||
| "accept", accept, "str" | ||
| ) | ||
|
|
||
| if not next_link: | ||
| # Construct URL | ||
| url = "/acr/v1/{name}/_manifests" | ||
| path_format_arguments = { | ||
| "url": self._client._serialize.url( # pylint: disable=protected-access | ||
| "self._client._config.url", | ||
| self._client._config.url, # pylint: disable=protected-access | ||
| "str", | ||
| skip_quote=True, | ||
| ), | ||
| "name": self._client._serialize.url("name", name, "str"), # pylint: disable=protected-access | ||
| } | ||
| url = self._client._client.format_url(url, **path_format_arguments) # pylint: disable=protected-access | ||
| # Construct parameters | ||
| query_parameters = {} # type: Dict[str, Any] | ||
| if last is not None: | ||
| query_parameters["last"] = self._client._serialize.query( # pylint: disable=protected-access | ||
| "last", last, "str" | ||
| ) | ||
| if n is not None: | ||
| query_parameters["n"] = self._client._serialize.query( # pylint: disable=protected-access | ||
| "n", n, "int" | ||
| ) | ||
| if orderby is not None: | ||
| query_parameters["orderby"] = self._client._serialize.query( # pylint: disable=protected-access | ||
| "orderby", orderby, "str" | ||
| ) | ||
|
|
||
| request = self._client._client.get( # pylint: disable=protected-access | ||
| url, query_parameters, header_parameters | ||
| ) | ||
| else: | ||
| url = next_link | ||
| query_parameters = {} # type: Dict[str, Any] | ||
| path_format_arguments = { | ||
| "url": self._client._serialize.url( # pylint: disable=protected-access | ||
| "self._client._config.url", | ||
| self._client._config.url, # pylint: disable=protected-access | ||
| "str", | ||
| skip_quote=True, | ||
| ), | ||
| "name": self._client._serialize.url("name", name, "str"), # pylint: disable=protected-access | ||
| } | ||
| url = self._client._client.format_url(url, **path_format_arguments) # pylint: disable=protected-access | ||
| request = self._client._client.get( # pylint: disable=protected-access | ||
| url, query_parameters, header_parameters | ||
| ) | ||
| return request | ||
|
|
||
| def extract_data(pipeline_response): | ||
| deserialized = self._client._deserialize( # pylint: disable=protected-access | ||
| "AcrManifests", pipeline_response | ||
| ) | ||
| list_of_elem = deserialized.manifests | ||
| if cls: | ||
| list_of_elem = cls(list_of_elem) | ||
| link = None | ||
| if "Link" in pipeline_response.http_response.headers.keys(): | ||
| link = _parse_next_link(pipeline_response.http_response.headers["Link"]) | ||
| return link, iter(list_of_elem) | ||
|
|
||
| def get_next(next_link=None): | ||
| request = prepare_request(next_link) | ||
|
|
||
| pipeline_response = self._client._client._pipeline.run( # pylint: disable=protected-access | ||
| request, stream=False, **kwargs | ||
| ) | ||
| response = pipeline_response.http_response | ||
|
|
||
| if response.status_code not in [200]: | ||
| error = self._client._deserialize.failsafe_deserialize( # pylint: disable=protected-access | ||
| 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) | ||
|
|
||
| @distributed_trace | ||
| def set_properties(self, properties, **kwargs): | ||
| # type: (RepositoryProperties, Dict[str, Any]) -> RepositoryProperties | ||
| """Set the properties of a repository | ||
|
|
||
| :returns: :class:`~azure.containerregistry.RepositoryProperties` | ||
| :raises: :class:`~azure.core.exceptions.ResourceNotFoundError` | ||
| """ | ||
| return RepositoryProperties._from_generated( # pylint: disable=protected-access | ||
| self._client.container_registry.set_properties( | ||
| self.name, properties._to_generated(), **kwargs # pylint: disable=protected-access | ||
| ) | ||
| ) | ||
|
|
||
| @distributed_trace | ||
| def get_artifact(self, tag_or_digest, **kwargs): | ||
| # type: (str, str, Dict[str, Any]) -> RegistryArtifact | ||
| """Get a Registry Artifact object | ||
|
|
||
| :param str repository_name: Name of the repository | ||
| :param str tag_or_digest: The tag or digest of the artifact | ||
| :returns: :class:`~azure.containerregistry.RegistryArtifact` | ||
| :raises: None | ||
| """ | ||
| _pipeline = Pipeline( | ||
| transport=TransportWrapper(self._client._client._pipeline._transport), # pylint: disable=protected-access | ||
| policies=self._client._client._pipeline._impl_policies, # pylint: disable=protected-access | ||
| ) | ||
| return RegistryArtifact( | ||
| self._endpoint, self.name, tag_or_digest, self._credential, pipeline=_pipeline, **kwargs | ||
| ) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What information do we get back from a delete operation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The manifests and tags deleted as part of the repository delete operation