Example #1
0
    def _generate_layers(self, allow_missing_ids=False):
        """
        Returns a generator of objects that have the blobSum and v1Compatibility keys in them,
        starting from the base image and working toward the leaf node.
        """
        for blob_sum_obj, history_obj in reversed(
            list(
                zip(
                    self._parsed[DOCKER_SCHEMA1_FS_LAYERS_KEY],
                    self._parsed[DOCKER_SCHEMA1_HISTORY_KEY],
                )
            )
        ):

            try:
                image_digest = digest_tools.Digest.parse_digest(
                    blob_sum_obj[DOCKER_SCHEMA1_BLOB_SUM_KEY]
                )
            except digest_tools.InvalidDigestException:
                raise MalformedSchema1Manifest(
                    "could not parse manifest digest: %s"
                    % blob_sum_obj[DOCKER_SCHEMA1_BLOB_SUM_KEY]
                )

            metadata_string = history_obj[DOCKER_SCHEMA1_V1_COMPAT_KEY]

            try:
                v1_metadata = json.loads(metadata_string)
            except (ValueError, TypeError):
                raise MalformedSchema1Manifest(
                    "Could not parse metadata string: %s" % metadata_string
                )

            v1_metadata = v1_metadata or {}
            container_config = v1_metadata.get("container_config") or {}
            command_list = container_config.get("Cmd", None)
            command = to_canonical_json(command_list) if command_list else None

            if not allow_missing_ids and not "id" in v1_metadata:
                raise MalformedSchema1Manifest("id field missing from v1Compatibility JSON")

            labels = v1_metadata.get("config", {}).get("Labels", {}) or {}
            extracted = Schema1V1Metadata(
                image_id=v1_metadata.get("id"),
                parent_image_id=v1_metadata.get("parent"),
                created=v1_metadata.get("created"),
                comment=v1_metadata.get("comment"),
                author=v1_metadata.get("author"),
                command=command,
                labels=labels,
            )

            compressed_size = v1_metadata.get("Size")
            yield Schema1Layer(
                image_digest, extracted, metadata_string, compressed_size, False, None
            )
Example #2
0
def _updated_v1_metadata(v1_metadata_json, updated_id_map):
    """
    Updates v1_metadata with new image IDs.
    """
    parsed = json.loads(v1_metadata_json)
    parsed["id"] = updated_id_map[parsed["id"]]

    if parsed.get("parent") and parsed["parent"] in updated_id_map:
        parsed["parent"] = updated_id_map[parsed["parent"]]

    if parsed.get("container_config", {}).get("Image"):
        existing_image = parsed["container_config"]["Image"]
        if existing_image in updated_id_map:
            parsed["container_config"]["image"] = updated_id_map[existing_image]

    return to_canonical_json(parsed)
Example #3
0
def test_to_canonical_json(input, expected_output):
    result = to_canonical_json(input)
    assert result == expected_output

    # Ensure the result is utf-8.
    assert isinstance(result, str)