File: testcase.py

package info (click to toggle)
python-azure 20250603%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 851,724 kB
  • sloc: python: 7,362,925; ansic: 804; javascript: 287; makefile: 195; sh: 145; xml: 109
file content (153 lines) | stat: -rw-r--r-- 6,207 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# coding=utf-8
# ------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------
import logging
import os
import json
from io import BytesIO

from azure.containerregistry import ContainerRegistryClient
from azure.containerregistry._helpers import _is_tag
from azure.identity import AzureAuthorityHosts, ClientSecretCredential

from devtools_testutils import AzureRecordedTestCase, FakeTokenCredential, get_credential

logger = logging.getLogger()


class ContainerRegistryTestClass(AzureRecordedTestCase):
    def import_image(self, endpoint, repository, tags):
        # repository must be a docker hub repository
        # tags is a List of repository/tag combos in the format <repository>:<tag>
        if not self.is_live:
            return
        import_image(endpoint, repository, tags)

    def get_credential(self, authority=None, **kwargs):
        if self.is_live:
            return get_credential(authority=authority, **kwargs)
        return FakeTokenCredential()

    def create_registry_client(self, endpoint, **kwargs):
        authority = get_authority(endpoint)
        audience = kwargs.pop("audience", None)
        if not audience:
            audience = get_audience(authority)
        credential = self.get_credential(authority=authority)
        logger.warning(f"Authority: {authority} \nAuthorization scope: {audience}")
        return ContainerRegistryClient(endpoint=endpoint, credential=credential, audience=audience, **kwargs)

    def create_anon_client(self, endpoint, **kwargs):
        authority = get_authority(endpoint)
        audience = get_audience(authority)
        return ContainerRegistryClient(endpoint=endpoint, audience=audience, **kwargs)

    def set_all_properties(self, properties, value):
        properties.can_delete = value
        properties.can_read = value
        properties.can_write = value
        properties.can_list = value
        return properties

    def assert_all_properties(self, properties, value):
        assert properties.can_delete == value
        assert properties.can_read == value
        assert properties.can_write == value
        assert properties.can_list == value

    def create_fully_qualified_reference(self, registry, repository, digest):
        return f"{registry}/{repository}{':' if _is_tag(digest) else '@'}{digest.split(':')[-1]}"

    def upload_oci_manifest_prerequisites(self, repo, client):
        layer = "654b93f61054e4ce90ed203bb8d556a6200d5f906cf3eca0620738d6dc18cbed"
        config = "config.json"
        base_path = os.path.join(self.get_test_directory(), "data", "oci_artifact")
        # upload config
        client.upload_blob(repo, open(os.path.join(base_path, config), "rb"))
        # upload layers
        client.upload_blob(repo, open(os.path.join(base_path, layer), "rb"))

    def upload_docker_manifest_prerequisites(self, repo, client):
        layer = "2db29710123e3e53a794f2694094b9b4338aa9ee5c40b930cb8063a1be392c54"
        config = "config.json"
        base_path = os.path.join(self.get_test_directory(), "data", "docker_artifact")
        # upload config
        client.upload_blob(repo, open(os.path.join(base_path, config), "rb"))
        # upload layers
        client.upload_blob(repo, open(os.path.join(base_path, layer), "rb"))

    def get_test_directory(self):
        return os.path.join(os.getcwd(), "tests")


def is_public_endpoint(endpoint):
    return ".azurecr.io" in endpoint


def is_china_endpoint(endpoint):
    return ".azurecr.cn" in endpoint


def get_authority(endpoint: str) -> str:
    if ".azurecr.io" in endpoint:
        logger.warning("Public cloud Authority")
        return AzureAuthorityHosts.AZURE_PUBLIC_CLOUD
    if ".azurecr.cn" in endpoint:
        logger.warning("China Authority")
        return AzureAuthorityHosts.AZURE_CHINA
    if ".azurecr.us" in endpoint:
        logger.warning("US Gov Authority")
        return AzureAuthorityHosts.AZURE_GOVERNMENT
    raise ValueError(f"Endpoint ({endpoint}) could not be understood")


def get_audience(authority: str) -> str:
    if authority == AzureAuthorityHosts.AZURE_PUBLIC_CLOUD:
        logger.warning("Public cloud auth audience")
        return "https://management.azure.com"
    if authority == AzureAuthorityHosts.AZURE_CHINA:
        logger.warning("China cloud auth audience")
        return "https://management.chinacloudapi.cn"
    if authority == AzureAuthorityHosts.AZURE_GOVERNMENT:
        logger.warning("US Gov cloud auth audience")
        return "https://management.usgovcloudapi.net"


def import_image(endpoint, repository, tags):
    authority = get_authority(endpoint)
    logger.warning(f"Import image authority: {authority}")
    credential = get_credential(authority=authority)

    with ContainerRegistryClient(endpoint, credential) as client:
        # Upload a layer
        layer = BytesIO(b"Sample layer")
        layer_digest, layer_size = client.upload_blob(repository, layer)
        logger.info(f"Uploaded layer: digest - {layer_digest}, size - {layer_size}")
        # Upload a config
        config = BytesIO(json.dumps({"sample config": "content"}).encode())
        config_digest, config_size = client.upload_blob(repository, config)
        logger.info(f"Uploaded config: digest - {config_digest}, size - {config_size}")
        # Upload images
        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",
                    },
                },
            ],
        }
        for tag in tags:
            manifest_digest = client.set_manifest(repository, oci_manifest, tag=tag)
            logger.info(f"Uploaded manifest: digest - {manifest_digest}")