Metadata-Version: 2.4
Name: azure-containerregistry
Version: 1.2.1
Summary: Microsoft Corporation Azure Container Registry Client Library for Python
Author-email: Microsoft Corporation <azpysdkhelp@microsoft.com>
License-Expression: MIT
Project-URL: repository, https://github.com/Azure/azure-sdk-for-python
Keywords: azure,azure sdk
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: isodate>=0.6.1
Requires-Dist: azure-core>=1.37.0
Requires-Dist: typing-extensions>=4.6.0
Dynamic: license-file

# Azure Container Registry client library for Python

Azure Container Registry allows you to store and manage container images and artifacts in a private registry for all types of container deployments.

Use the client library for Azure Container Registry to:

- List images or artifacts in a registry
- Obtain metadata for images and artifacts, repositories and tags
- Set read/write/delete properties on registry items
- Delete images and artifacts, repositories and tags

[Source code][source]
| [Package (Pypi)][package]
| [Package (Conda)](https://anaconda.org/microsoft/azure-containerregistry/)
| [API reference documentation][docs]
| [REST API documentation][rest_docs]
| [Product documentation][product_docs]

## Getting started

### Install the package

Install the Azure Container Registry client library for Python with [pip][pip_link]:

```bash
pip install --pre azure-containerregistry
```

### Prerequisites

* Python 3.8 or later is required to use this package.
* You need an [Azure subscription][azure_sub] and a [Container Registry account][container_registry_docs] to use this package.

To create a new Container Registry, you can use the [Azure Portal][container_registry_create_portal],
[Azure PowerShell][container_registry_create_ps], or the [Azure CLI][container_registry_create_cli].
Here's an example using the Azure CLI:

```Powershell
az acr create --name MyContainerRegistry --resource-group MyResourceGroup --location westus --sku Basic
```

### Authenticate the client

The [Azure Identity library][identity] provides easy Azure Active Directory support for authentication. The `DefaultAzureCredential` assumes the `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and `AZURE_CLIENT_SECRET` environment variables are set, for more information refer to the [Azure Identity environment variables section](https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#environment-variables)

```python
# Create a ContainerRegistryClient that will authenticate through Active Directory
from azure.containerregistry import ContainerRegistryClient
from azure.identity import DefaultAzureCredential

endpoint = "https://mycontainerregistry.azurecr.io"
audience = "https://management.azure.com"
client = ContainerRegistryClient(endpoint, DefaultAzureCredential(), audience=audience)
```

## Key concepts

A **registry** stores Docker images and [OCI Artifacts](https://opencontainers.org/).  An image or artifact consists of a **manifest** and **layers**.  An image's manifest describes the layers that make up the image, and is uniquely identified by its **digest**.  An image can also be "tagged" to give it a human-readable alias.  An image or artifact can have zero or more **tags** associated with it, and each tag uniquely identifies the image.  A collection of images that share the same name but have different tags, is referred to as a **repository**.

For more information please see [Container Registry Concepts](https://learn.microsoft.com/azure/container-registry/container-registry-concepts).


## Examples

The following sections provide several code snippets covering some of the most common ACR Service tasks, including:

- Registry operations:
  - [List repositories](#list-repositories "List repositories")
  - [List tags with anonymous access](#list-tags-with-anonymous-access "List tags with anonymous access")
  - [Set artifact properties](#set-artifact-properties "Set artifact properties")
  - [Delete images](#delete-images "Delete images")
- Blob and manifest operations:
  - [Upload images](#upload-images "Upload images")
  - [Download images](#download-images "Download images")
  - [Delete manifests](#delete-manifests "Delete manifests")
  - [Delete blobs](#delete-blobs "Delete blobs")

Please note that each sample assumes there is a `CONTAINERREGISTRY_ENDPOINT` environment variable set to a string containing the `https://` prefix and the name of the login server, for example "https://myregistry.azurecr.io". Anonymous access samples are getting endpoint value from environment variable`CONTAINERREGISTRY_ANONREGISTRY_ENDPOINT`.

### List repositories

Iterate through the collection of repositories in the registry.

<!-- SNIPPET:sample_delete_tags.list_repository_names -->

```python
with ContainerRegistryClient(self.endpoint, self.credential) as client:
    # Iterate through all the repositories
    for repository_name in client.list_repository_names():
        print(repository_name)
```

<!-- END SNIPPET -->

### List tags with anonymous access

Iterate through the collection of tags in the repository with anonymous access.

<!-- SNIPPET:sample_list_tags.list_tags_anonymous -->

```python
with ContainerRegistryClient(endpoint) as anon_client:
    manifest = anon_client.get_manifest_properties("library/hello-world", "latest")
    if manifest.tags:
        print(f"Tags of {manifest.repository_name}: ")
        # Iterate through all the tags
        for tag in manifest.tags:
            print(tag)
```

<!-- END SNIPPET -->

### Set artifact properties

Set properties of an artifact.

<!-- SNIPPET:sample_set_image_properties.update_manifest_properties -->

```python
with ContainerRegistryClient(self.endpoint, self.credential) as client:
    # Set permissions on image "library/hello-world:v1"
    client.update_manifest_properties("library/hello-world", "v1", can_write=False, can_delete=False)
```

<!-- END SNIPPET -->

### Delete images

Delete images older than the first three in the repository.

<!-- SNIPPET:sample_delete_images.delete_manifests -->

```python
with ContainerRegistryClient(self.endpoint, self.credential) as client:
    for repository in client.list_repository_names():
        # Keep the three most recent images, delete everything else
        manifest_count = 0
        for manifest in client.list_manifest_properties(
            repository,
            order_by=ArtifactManifestOrder.LAST_UPDATED_ON_DESCENDING,
        ):
            manifest_count += 1
            if manifest_count > 3:
                # Make sure will have the permission to delete the manifest later
                client.update_manifest_properties(repository, manifest.digest, can_write=True, can_delete=True)
                print(f"Deleting {repository}:{manifest.digest}")
                client.delete_manifest(repository, manifest.digest)
```

<!-- END SNIPPET -->

### Upload images

To upload a full image, we need to upload individual layers and configuration. After that we can upload a manifest which describes an image or artifact and assign it a tag.

<!-- SNIPPET:sample_set_get_image.upload_blob_and_manifest -->

```python
self.repository_name = "sample-oci-image"
layer = BytesIO(b"Sample layer")
config = BytesIO(
    json.dumps(
        {
            "sample config": "content",
        }
    ).encode()
)
with ContainerRegistryClient(self.endpoint, self.credential) as client:
    # Upload a layer
    layer_digest, layer_size = client.upload_blob(self.repository_name, layer)
    print(f"Uploaded layer: digest - {layer_digest}, size - {layer_size}")
    # Upload a config
    config_digest, config_size = client.upload_blob(self.repository_name, config)
    print(f"Uploaded config: digest - {config_digest}, size - {config_size}")
    # Create an oci image with config and layer info
    oci_manifest = {
        "config": {
            "mediaType": "application/vnd.oci.image.config.v1+json",
            "digest": config_digest,
            "sizeInBytes": config_size,
        },
        "schemaVersion": 2,
        "layers": [
            {
                "mediaType": "application/vnd.oci.image.layer.v1.tar",
                "digest": layer_digest,
                "size": layer_size,
                "annotations": {
                    "org.opencontainers.image.ref.name": "artifact.txt",
                },
            },
        ],
    }
    # Set the image with tag "latest"
    manifest_digest = client.set_manifest(self.repository_name, oci_manifest, tag="latest")
    print(f"Uploaded manifest: digest - {manifest_digest}")
```

<!-- END SNIPPET -->

### Download images

To download a full image, we need to download its manifest and then download individual layers and configuration.

<!-- SNIPPET:sample_set_get_image.download_blob_and_manifest -->

```python
with ContainerRegistryClient(self.endpoint, self.credential) as client:
    # Get the image
    get_manifest_result = client.get_manifest(self.repository_name, "latest")
    received_manifest = get_manifest_result.manifest
    print(f"Got manifest:\n{received_manifest}")

    # Download and write out the layers
    for layer in received_manifest["layers"]:
        # Remove the "sha256:" prefix from digest
        layer_file_name = layer["digest"].split(":")[1]
        try:
            stream = client.download_blob(self.repository_name, layer["digest"])
            with open(layer_file_name, "wb") as layer_file:
                for chunk in stream:
                    layer_file.write(chunk)
        except DigestValidationError:
            print(f"Downloaded layer digest value did not match. Deleting file {layer_file_name}.")
            os.remove(layer_file_name)
        print(f"Got layer: {layer_file_name}")
    # Download and write out the config
    config_file_name = "config.json"
    try:
        stream = client.download_blob(self.repository_name, received_manifest["config"]["digest"])
        with open(config_file_name, "wb") as config_file:
            for chunk in stream:
                config_file.write(chunk)
    except DigestValidationError:
        print(f"Downloaded config digest value did not match. Deleting file {config_file_name}.")
        os.remove(config_file_name)
    print(f"Got config: {config_file_name}")
```

<!-- END SNIPPET -->

### Delete manifests

<!-- SNIPPET:sample_set_get_image.delete_manifest -->

```python
with ContainerRegistryClient(self.endpoint, self.credential) as client:
    get_manifest_result = client.get_manifest(self.repository_name, "latest")
    # Delete the image
    client.delete_manifest(self.repository_name, get_manifest_result.digest)
```

<!-- END SNIPPET -->

### Delete blobs

<!-- SNIPPET:sample_set_get_image.delete_blob -->

```python
with ContainerRegistryClient(self.endpoint, self.credential) as client:
    get_manifest_result = client.get_manifest(self.repository_name, "latest")
    received_manifest = get_manifest_result.manifest
    # Delete the layers
    for layer in received_manifest["layers"]:
        client.delete_blob(self.repository_name, layer["digest"])
    # Delete the config
    client.delete_blob(self.repository_name, received_manifest["config"]["digest"])
```

<!-- END SNIPPET -->


## Troubleshooting

For infomation about troubleshooting, refer to the [troubleshooting guide].
### General
ACR client library will raise exceptions defined in [Azure Core][azure_core_exceptions].

### 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 the client or per-operation with the `logging_enable` keyword argument.

See full SDK logging documentation with examples [here][sdk_logging_docs].

### 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.

## Next steps

- Go further with azure.containerregistry and our [samples][samples].
- Watch a [demo or deep dive video](https://azure.microsoft.com/resources/videos/index/?service=container-registry).
- Read more about the [Azure Container Registry service](https://learn.microsoft.com/azure/container-registry/container-registry-intro).

## 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 [cla.microsoft.com][cla].

This project has adopted the [Microsoft Open Source Code of Conduct][coc].
For more information see the [Code of Conduct FAQ][coc_faq]
or contact [opencode@microsoft.com][coc_contact] with any
additional questions or comments.



<!-- LINKS -->
[source]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/containerregistry/azure-containerregistry
[package]: https://pypi.org/project/azure-containerregistry/
[docs]: https://azuresdkdocs.z19.web.core.windows.net/python/azure-containerregistry/latest/index.html
[rest_docs]: https://learn.microsoft.com/rest/api/containerregistry/
[product_docs]:  https://learn.microsoft.com/azure/container-registry
[pip_link]: https://pypi.org
[container_registry_docs]: https://learn.microsoft.com/azure/container-registry/container-registry-intro
[container_registry_create_ps]: https://learn.microsoft.com/azure/container-registry/container-registry-get-started-powershell
[container_registry_create_cli]: https://learn.microsoft.com/azure/container-registry/container-registry-get-started-azure-cli
[container_registry_create_portal]: https://learn.microsoft.com/azure/container-registry/container-registry-get-started-portal
[container_registry_concepts]: https://learn.microsoft.com/azure/container-registry/container-registry-concepts
[azure_cli]: https://learn.microsoft.com/cli/azure
[azure_sub]: https://azure.microsoft.com/free/
[identity]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/identity/azure-identity/README.md
[samples]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/containerregistry/azure-containerregistry/samples
[cla]: https://cla.microsoft.com
[coc]: https://opensource.microsoft.com/codeofconduct/
[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/
[coc_contact]: mailto:opencode@microsoft.com
[azure_core_ref_docs]: https://aka.ms/azsdk/python/core/docs
[azure_core_exceptions]: https://aka.ms/azsdk/python/core/docs#module-azure.core.exceptions
[python_logging]: https://docs.python.org/3/library/logging.html
[sdk_logging_docs]: https://learn.microsoft.com/azure/developer/python/azure-sdk-logging
[troubleshooting guide]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/containerregistry/azure-containerregistry/TROUBLESHOOTING.md

# Release History

## 1.2.1 (Unreleased)

### Features Added

### Breaking Changes

### Bugs Fixed

### Other Changes
- Added support for Python 3.12.
- Python 3.7 is no longer supported. Please use Python version 3.8 or later.

## 1.2.0 (2023-07-11)

### Bugs Fixed
- Fixed a bug when deserializing unknown architecture and os values in `ArtifactManifestProperties` object. ([#28469](https://github.com/Azure/azure-sdk-for-python/issues/28469) [#30077](https://github.com/Azure/azure-sdk-for-python/issues/30077))

### Other Changes
- Enum type properties in `ArtifactManifestProperties` class would be type `str` when its value is not in enum's known list.

## 1.1.0 (2023-05-17)

### Breaking Changes
- Added sanity check for manifest size at download time - if manifest is bigger than 4MB, `ValueError` will be thrown.

### Other Changes
- Changed the digest validation exception type to `DigestValidationError` in `set/get manifest` and `upload/download blob` operations.

## 1.1.0b4 (2023-04-25)

### Features Added
- Added an optional kwarg `media_type` in `set_manifest()` to enable uploading image manifests of any type.

### Breaking Changes
- Renamed `upload_manifest()` to `set_manifest()`, and changed to consume manifest in `JSON` instead of `OCIManifest` type.
- Renamed `download_manifest()` to `get_manifest()`, and changed it's return type from `DownloadManifestResult` to `GetManifestResult`.

### Other Changes
- Changed the default audience to `"https://containerregistry.azure.net"` which works for all clouds.

## 1.1.0b3 (2023-04-04)

### Features Added
- Supported uploading and downding large OCI artifact blobs in synchronous and asynchronous `ContainerRegistryClient`.
- Published model `DownloadManifestResult`, `DownloadBlobStream` and `AsyncDownloadBlobStream`.

### Breaking Changes
- Suppress the response error with status code `404` in `delete_blob()`.
- Added to return blob size in bytes in `upload_blob()`.
- Changed `download_blob()` return type from `DownloadBlobResult` to `DownloadBlobStream` and `AsyncDownloadBlobStream`.

## 1.1.0b2 (2023-03-24)

### Bugs Fixed
- Fixed a `TypeError` when call `list_tag()` in an empty repository. ([#28234](https://github.com/Azure/azure-sdk-for-python/issues/28234))
- Fixed a `TypeError` when call `list_manifest()` in an empty repository. ([#28432](https://github.com/Azure/azure-sdk-for-python/issues/28432))

### Other Changes
- Added default value `"https://management.azure.com"` to kwarg `audience` in `ContainerRegistryClient`. ([#22229](https://github.com/Azure/azure-sdk-for-python/issues/22229))
- Python 3.6 is no longer supported. Please use Python version 3.7 or later.
- Bumped minimum dependency on `azure-core` to `>=1.24.0`
- Dropped `msrest` requirement.
- Added dependency `isodate` with version range `>=0.6.0`(`isodate` was required by `msrest`).

## 1.1.0b1 (2022-05-10)

### Features Added
- Supported uploading and downloading OCI manifests and artifact blobs in synchronous `ContainerRegistryClient`.
### Other Changes

- Fixed a spell error in a property of `RepositoryProperties` to `last_updated_on`.
- Bumped dependency on `azure-core` to `>=1.23.0`.

## 1.0.0 (2022-01-25)

### Features Added

- Supported passing the rest api version via `ContainerRegistryClient`.

### Breaking Changes

- Renamed the property `size` of `ArtifactManifestProperties` to `size_in_bytes`.
- Renamed `TagOrder` to `ArtifactTagOrder`.
- Renamed `ManifestOrder` to `ArtifactManifestOrder`.

### Other Changes

- Python 2.7 is no longer supported. Please use Python version 3.6 or later.

## 1.0.0b7 (2021-11-19)

### Features Added

- Updated the supported rest api version to be the stable "2021-07-01".
- Removed the property `teleport_enabled` in `RepositoryProperties`.

## 1.0.0b6 (2021-09-08)

### Breaking Changes

- Removed `credential_scopes` keyword.
- Added `audience` keyword, which allows customers to select from available audiences or provide their own audience string. This keyword is required when creating a client.

## 1.0.0b5 (2021-08-11)

### Bugs Fixed

- Closed session of `ChallengePolicyClient` in context manager    #20000

### Other Changes

- Bumped dependency on `msrest` to `>=0.6.21`

## 1.0.0b4 (2021-07-07)

### Bugs Fixed

- Fixed a bug where `credential_scopes` keyword on `ContainerRegistryClient` was not passed through and the client could not authenticate with foreign clouds.

## 1.0.0b3 (2021-06-08)

- Removed `DeleteRepositoryResult`. `ContainerRegistryClient.delete_repository` now returns `None`
- Removed `writeable_properties` objects, placing `can_delete/read/write/list` properties on the immediate `Repository/Tag/ArtifactManifestProperties` objects
- Removed `ContainerRepository` and `RegistryArtifact` classes. The methods for acting on a repository and a registry artifact are now contained in the `ContainerRegistryClient` object.
- Parsed refresh token expiration time from returned JWT.
- The `delete_repository` and `get_repository` methods parameters have been renamed from `repository_name` to `repository`.

## 1.0.0b2 (2021-05-11)

- Renamed `DeletedRepositoryResult` to `DeleteRepositoryResult`
- Renamed `DeletedRepositoryResult.deleted_registry_artifact_digests` to `deleted_manifests`
- Renamed `TagProperties` to `ArtifactTagProperties`
- Renamed `ContentPermissions` to `ContentProperties`
- Renamed `content_permissions` attributes on `TagProperties`, `RepositoryProperties`, and `RegistryArtifactProperties` to `writeable_properties`.
- Added anonymous access capabilities to client by passing in `None` to credential.

## 1.0.0b1 (2021-04-06)

- First release of the Azure Container Registry library for Python
