#!/usr/bin/env python3 """Writes a minimal one-layer OCI Image Layout tar to the path given as argv[1]. Used by meson.build to produce a fixture for the `meson test` smoke test. """ import gzip import hashlib import io import json import sys import tarfile def sha256_hex(data: bytes) -> str: return hashlib.sha256(data).hexdigest() def add_bytes(tar: tarfile.TarFile, name: str, data: bytes) -> None: info = tarfile.TarInfo(name=name) info.size = len(data) tar.addfile(info, io.BytesIO(data)) def main() -> None: out_path = sys.argv[1] # Uncompressed layer content: a tiny tar with a single file. layer_tar_buf = io.BytesIO() with tarfile.open(fileobj=layer_tar_buf, mode="w") as layer_tar: add_bytes(layer_tar, "hello.txt", b"hello from slocker-lite fixture\n") layer_tar_bytes = layer_tar_buf.getvalue() diff_id = sha256_hex(layer_tar_bytes) layer_gz_bytes = gzip.compress(layer_tar_bytes) layer_digest = sha256_hex(layer_gz_bytes) config = { "architecture": "amd64", "os": "linux", "config": {}, "rootfs": {"type": "layers", "diff_ids": [f"sha256:{diff_id}"]}, } config_bytes = json.dumps(config).encode() config_digest = sha256_hex(config_bytes) manifest = { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.manifest.v1+json", "config": { "mediaType": "application/vnd.oci.image.config.v1+json", "digest": f"sha256:{config_digest}", "size": len(config_bytes), }, "layers": [ { "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "digest": f"sha256:{layer_digest}", "size": len(layer_gz_bytes), } ], } manifest_bytes = json.dumps(manifest).encode() manifest_digest = sha256_hex(manifest_bytes) index = { "schemaVersion": 2, "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": f"sha256:{manifest_digest}", "size": len(manifest_bytes), } ], } index_bytes = json.dumps(index).encode() oci_layout_bytes = json.dumps({"imageLayoutVersion": "1.0.0"}).encode() with tarfile.open(out_path, mode="w") as tar: add_bytes(tar, "oci-layout", oci_layout_bytes) add_bytes(tar, "index.json", index_bytes) add_bytes(tar, f"blobs/sha256/{config_digest}", config_bytes) add_bytes(tar, f"blobs/sha256/{manifest_digest}", manifest_bytes) add_bytes(tar, f"blobs/sha256/{layer_digest}", layer_gz_bytes) if __name__ == "__main__": main()