Initial commit: OCI image mounting via containers-storage
slocker-lite validates an OCI Image Layout tar, imports its layers into containers-storage's layer store in order, and mounts the assembled image using fuse-overlayfs, printing the resulting merged path. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user