def test___new__():
    """Test that a formatted SHA256 can be instantiated."""
    digest = "0123456789012345678901234567890123456789012345678901234567890123"
    formattedsha256 = FormattedSHA256(digest)
    assert formattedsha256
    assert formattedsha256.sha256 == digest  # pylint: disable=no-member
    assert str(formattedsha256) == f"sha256:{digest}"

    digest = "sha256:0123456789012345678901234567890123456789012345678901234567890123"
    formattedsha256 = FormattedSHA256(digest)
    assert formattedsha256
    assert formattedsha256.sha256 == digest[7:]  # pylint: disable=no-member
    assert str(formattedsha256) == digest

    with pytest.raises(ValueError) as exc_info:
        FormattedSHA256(None)
    assert "None" in str(exc_info.value)

    digest = "012345678901234567890123456789012345678901234567890123456789012"
    with pytest.raises(ValueError) as exc_info:
        FormattedSHA256(digest)
    assert digest in str(exc_info.value)

    digest = "sha1:0123456789012345678901234567890123456789012345678901234567890123"
    with pytest.raises(ValueError) as exc_info:
        FormattedSHA256(digest)
    assert digest in str(exc_info.value)
Пример #2
0
def get_test_data_local() -> Generator[TypingGetTestDataLocal, None, None]:
    """Dynamically initializes test data for a local mutable registry."""
    images = [
        {
            "image": "{0}/library/python",
            "tag": "3.7.2-slim-stretch",
            "digests": {
                DockerMediaTypes.DISTRIBUTION_MANIFEST_V2:
                FormattedSHA256(
                    "0005ba40bf87e486d7061ca0112123270e4a6088b5071223c8d467db3dbba908"
                ),
            },
            "original_endpoint": Indices.DOCKERHUB,
            "protocol": "http",
        },
        {
            "image": "{0}/library/busybox",
            "tag": "1.30.1",
            "digests": {
                DockerMediaTypes.DISTRIBUTION_MANIFEST_V2:
                FormattedSHA256(
                    "4fe8827f51a5e11bb83afa8227cbccb402df840d32c6b633b7ad079bc8144100"
                ),
            },
            "original_endpoint": Indices.DOCKERHUB,
            "protocol": "http",
        },
    ]
    for image in images:
        yield image
def test_set_tag(archive_repositories: ArchiveRepositories,
                 image_name: ImageName, name: str):
    """Test repository tag assignment."""
    tag = archive_repositories.get_tag(image_name)
    assert tag
    assert FormattedSHA256(tag) == image_name.digest

    digest = FormattedSHA256.calculate(name.encode("utf-8"))
    name = ImageName.parse(name)
    archive_repositories.set_tag(name, digest)
    assert FormattedSHA256(archive_repositories.get_tag(name)) == digest
Пример #4
0
async def chunk_file(
    file_in, file_out, *, file_in_is_async: bool = True, file_out_is_async: bool = True
) -> UtilChunkFile:
    """
    Copies chunkcs from one file to another.

    Args:
        file_in: The file from which to retrieve the file chunks.
        file_out: The file to which to store the file chunks.
        file_in_is_async: If True, all file_in IO operations will be awaited.
        file_out_is_async: If True, all file_out IO operations will be awaited.

    Returns:
        dict:
            digest: The digest value of the chunked data.
            size: The byte size of the chunked data in bytes.
    """
    coroutine_read = file_in.read if file_in_is_async else async_wrap(file_in.read)
    coroutine_write = (
        file_out.write if file_out_is_async else async_wrap(file_out.write)
    )
    hasher = hashlib.sha256()
    size = 0
    while True:
        chunk = await coroutine_read(CHUNK_SIZE)
        if not chunk:
            break
        await coroutine_write(chunk)
        hasher.update(chunk)
        size += len(chunk)

    await be_kind_rewind(file_out, file_is_async=file_out_is_async)

    return {"digest": FormattedSHA256(hasher.hexdigest()), "size": size}
def test_get_config_digest(registry_v2_manifest: RegistryV2Manifest):
    """Test image configuration digest retrieval."""
    formattedsha256 = FormattedSHA256(
        "8f1196ff19e7b5c5861de192ae77e8d7a692fcbca2dd3174d324980f72ab49bf")
    assert registry_v2_manifest.get_config_digest() == formattedsha256
    assert (registry_v2_manifest.get_config_digest(
        ImageName.parse("ignored")) == formattedsha256)
def test_get_tag(archive_repositories: ArchiveRepositories,
                 image_name: ImageName):
    """Test repository tag retrieval."""
    tag = archive_repositories.get_tag(image_name)
    assert tag
    assert FormattedSHA256(tag) == image_name.digest
    assert not archive_repositories.get_tag(ImageName("does_not_exist"))
    assert not archive_repositories.get_tag(ImageName("does_not", tag="exist"))
Пример #7
0
    def layer_to_digest(layer: str) -> FormattedSHA256:
        """
        Coverts a archive layer identifier to a digest value.

        Args:
            layer: The archive layer identifier (relative tar path).

        Returns:
            The corresponding digest value in the form: <hash type>:<digest value>.
        """
        return FormattedSHA256(layer[:-10])
Пример #8
0
async def test_layer_exists(
    registry_v2_image_source: RegistryV2ImageSource,
    known_good_image: TypingKnownGoodImage,
    **kwargs,
):
    """Test layer existence."""
    LOGGER.debug("Retrieving manifest for: %s ...",
                 known_good_image["image_name"])
    manifest = await registry_v2_image_source.get_manifest(
        known_good_image["image_name"], **kwargs)
    layer = manifest.get_layers()[-1]
    assert await registry_v2_image_source.layer_exists(
        known_good_image["image_name"], layer, **kwargs)
    assert not await registry_v2_image_source.layer_exists(
        known_good_image["image_name"], FormattedSHA256("0" * 64), **kwargs)
 async def put_image_layer_from_disk(self, image_name: ImageName, file,
                                     **kwargs) -> FormattedSHA256:
     # TODO: Convert to async
     if self.dry_run:
         LOGGER.debug("Dry Run: skipping put_image_layer_from_disk")
         return FormattedSHA256("0" * 64)
     # TODO: Do we really want to use random garbage here???
     #       Look into moby/.../save.go to find what to use instead.
     digest = FormattedSHA256.calculate("{0}{1}{2}".format(
         str(image_name), datetime.datetime.now(),
         random.randint(1, 101)).encode("utf-8"))
     layer = ArchiveManifest.digest_to_layer(digest)
     with open(self.archive, "rb+") as file_out:
         tar_mkdir(file_out, os.path.dirname(layer))
         file_out.seek(0)
         tar(file_out, layer, file)
     return digest
Пример #10
0
async def test_layer_exists(
    registry_v2_image_source: RegistryV2ImageSource,
    known_good_image_local: Dict,
    **kwargs,
):
    """Test layer existence."""
    if "protocol" in known_good_image_local:
        kwargs["protocol"] = known_good_image_local["protocol"]
    LOGGER.debug("Retrieving manifest for: %s ...",
                 known_good_image_local["image_name"])
    manifest = await registry_v2_image_source.get_manifest(
        known_good_image_local["image_name"], **kwargs)
    layer = manifest.get_layers()[-1]
    assert await registry_v2_image_source.layer_exists(
        known_good_image_local["image_name"], layer, **kwargs)
    assert not await registry_v2_image_source.layer_exists(
        known_good_image_local["image_name"], FormattedSHA256("0" * 64), **
        kwargs)
def test_remove_tags(archive_changeset: ArchiveChangeset):
    """Test repository tag removal"""
    image_name = ImageName(
        "base",
        digest=FormattedSHA256(
            "adecf4209bb9dd67d96393774cbd7f8bd2bad3596da42cde33daa0c41b14ac62"
        ),
        tag="7.2",
    )
    tag = ArchiveChangeset.get_repository_tag(image_name)
    manifest = archive_changeset.get_manifest(image_name)
    assert tag in manifest.get_tags()

    archive_changeset.remove_tags(["dummy"])
    manifest = archive_changeset.get_manifest(image_name)
    assert tag in manifest.get_tags()

    archive_changeset.remove_tags([tag])
    manifest = archive_changeset.get_manifest(image_name)
    assert not manifest.get_tags()
Пример #12
0
    def append_manifest(self, manifest: "ArchiveManifest"):
        """
        Appends an archive manifest to the archive changeset.

        Args:
            manifest: The archive manifest to be appended.
        """
        # Remove the image if it already exists
        self.remove_manifest(
            FormattedSHA256(manifest.get_json()["Config"][:-5]))

        # Remove all tags being assigned to the new image ...
        tags = ArchiveChangeset.normalize_tags(manifest.get_tags())
        if tags:
            self.remove_tags(tags)

        # Append the new image configuration ...
        _json = self.get_json()
        _json.append(manifest.get_json())
        self._set_json(_json)
def formattedsha256() -> FormattedSHA256:
    """Provides a FormattedSHA256 instance with a distinct digest value."""
    return FormattedSHA256(
        "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789")
Пример #14
0
 def get_config_digest(self,
                       image_name: ImageName = None) -> FormattedSHA256:
     config = self.get_config(image_name)
     return FormattedSHA256(config["Config"][:-5])
Пример #15
0
 def get_config_digest(self,
                       image_name: ImageName = None) -> FormattedSHA256:
     return FormattedSHA256(self.get_json()["Config"][:-5])