Publish curated ITWorx_MCP_Hub source from 55011066f84f073ceabb35c99ddd5b65745e34f6
This commit is contained in:
1 parent
020282a4b5
commit
b35324a665
6 files changed
+653
-11
No files matched your search
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
@@ -123,6 +124,8 @@ def _write_archive_fixture(path: Path, members: dict[str, bytes | None]) -> None
|
||||
|
||||
def _docker29_oci_fixture(
|
||||
tmp_path: Path,
|
||||
*,
|
||||
layer_count: int = 1,
|
||||
) -> tuple[Path, dict[str, bytes | None], dict[str, dict[str, str]], dict[str, str]]:
|
||||
tmp_path.mkdir(parents=True, exist_ok=True)
|
||||
revision = "a" * 40
|
||||
@@ -143,6 +146,19 @@ def _docker29_oci_fixture(
|
||||
layer_digest = "sha256:" + hashlib.sha256(layer).hexdigest()
|
||||
layer_name = "blobs/sha256/" + layer_digest.split(":", 1)[1]
|
||||
members: dict[str, bytes | None] = {"blobs": None, "blobs/sha256": None, layer_name: layer}
|
||||
layer_rows = [(layer_digest, layer_name, layer)]
|
||||
if layer_count == 2:
|
||||
stream = io.BytesIO()
|
||||
with tarfile.open(fileobj=stream, mode="w:", format=tarfile.USTAR_FORMAT) as archive:
|
||||
content = b"second layer verifies prefix chain and legacy parent binding"
|
||||
info = tarfile.TarInfo("second.txt")
|
||||
info.size = len(content)
|
||||
archive.addfile(info, io.BytesIO(content))
|
||||
payload = stream.getvalue()
|
||||
digest = "sha256:" + hashlib.sha256(payload).hexdigest()
|
||||
name = "blobs/sha256/" + digest.split(":", 1)[1]
|
||||
members[name] = payload
|
||||
layer_rows.append((digest, name, payload))
|
||||
images: dict[str, dict[str, str]] = {}
|
||||
docker_manifest: list[dict[str, object]] = []
|
||||
index_descriptors: list[dict[str, object]] = []
|
||||
@@ -169,7 +185,7 @@ def _docker29_oci_fixture(
|
||||
"architecture": "amd64",
|
||||
"os": "linux",
|
||||
"config": {"User": "10001:10001", "Labels": labels, "Cmd": [service]},
|
||||
"rootfs": {"type": "layers", "diff_ids": [layer_digest]},
|
||||
"rootfs": {"type": "layers", "diff_ids": [row[0] for row in layer_rows]},
|
||||
}
|
||||
config_bytes = json.dumps(config, sort_keys=True, separators=(",", ":")).encode()
|
||||
image_id = "sha256:" + hashlib.sha256(config_bytes).hexdigest()
|
||||
@@ -180,13 +196,14 @@ def _docker29_oci_fixture(
|
||||
{
|
||||
"Config": config_name,
|
||||
"RepoTags": [reference],
|
||||
"Layers": [layer_name],
|
||||
"Layers": [row[1] for row in layer_rows],
|
||||
"LayerSources": {
|
||||
layer_digest: {
|
||||
digest: {
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar",
|
||||
"size": len(layer),
|
||||
"digest": layer_digest,
|
||||
"size": len(data),
|
||||
"digest": digest,
|
||||
}
|
||||
for digest, _name, data in layer_rows
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -201,9 +218,10 @@ def _docker29_oci_fixture(
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": "application/vnd.oci.image.layer.v1.tar",
|
||||
"digest": layer_digest,
|
||||
"size": len(layer),
|
||||
"digest": digest,
|
||||
"size": len(data),
|
||||
}
|
||||
for digest, _name, data in layer_rows
|
||||
],
|
||||
}
|
||||
image_manifest_bytes = json.dumps(
|
||||
@@ -466,6 +484,174 @@ def test_docker_oci_index_can_canonicalize_external_reference_aliases(tmp_path:
|
||||
assert normalized.is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"case",
|
||||
json.loads((ROOT / "tests/fixtures/moby_v1_golden.json").read_text(encoding="utf-8"))["cases"],
|
||||
)
|
||||
def test_independent_go_reference_matches_exact_legacy_wire_bytes(case):
|
||||
expected = {
|
||||
row["name"]: base64.b64decode(row["payloadBase64"], validate=True) for row in case["blobs"]
|
||||
}
|
||||
actual = producer._moby_v1_metadata(
|
||||
case["config"], legacy_onbuild=case["dialect"] == "onbuild_null"
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_go_reference_fixture_is_bound_to_its_reproducible_generator():
|
||||
fixture = json.loads((ROOT / "tests/fixtures/moby_v1_golden.json").read_text(encoding="utf-8"))
|
||||
assert fixture["schema"] == "itworx.moby-v1-wire-golden/v1"
|
||||
assert fixture["goVersion"] == "go1.27.2"
|
||||
assert (
|
||||
fixture["referenceMainSha256"]
|
||||
== hashlib.sha256(
|
||||
(ROOT / "tests/fixtures/moby_v1_reference/main.go").read_bytes()
|
||||
).hexdigest()
|
||||
)
|
||||
assert fixture["sourceCommits"] == [
|
||||
"89c5e8fd66634b6128fc4c0e6f1236e2540e46e0",
|
||||
"5834c866f83c0bae2d0be28f38b92f32cd07ca38",
|
||||
]
|
||||
|
||||
|
||||
def _moby_v1_fixture(members, *, legacy_onbuild=True):
|
||||
# Faithful classic Moby saveConfig/CreateID serialization for the fixed
|
||||
# single-layer images above, independent of the production normalizer.
|
||||
zero = {
|
||||
"Hostname": "",
|
||||
"Domainname": "",
|
||||
"User": "",
|
||||
"AttachStdin": False,
|
||||
"AttachStdout": False,
|
||||
"AttachStderr": False,
|
||||
"Tty": False,
|
||||
"OpenStdin": False,
|
||||
"StdinOnce": False,
|
||||
"Env": None,
|
||||
"Cmd": None,
|
||||
"Image": "",
|
||||
"Volumes": None,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": None,
|
||||
"OnBuild": None,
|
||||
"Labels": None,
|
||||
}
|
||||
if not legacy_onbuild:
|
||||
del zero["OnBuild"]
|
||||
result = dict(members)
|
||||
added = []
|
||||
for row in json.loads(members["manifest.json"]):
|
||||
config = json.loads(members[row["Config"]])
|
||||
runtime = {**zero, **config["config"]}
|
||||
parent = ""
|
||||
chain = ""
|
||||
diffs = config["rootfs"]["diff_ids"]
|
||||
for index, diff in enumerate(diffs):
|
||||
chain = (
|
||||
diff
|
||||
if not chain
|
||||
else "sha256:" + hashlib.sha256((chain + " " + diff).encode()).hexdigest()
|
||||
)
|
||||
if index == len(diffs) - 1:
|
||||
body = {
|
||||
"created": None,
|
||||
"container_config": zero,
|
||||
"config": runtime,
|
||||
"architecture": "amd64",
|
||||
"os": "linux",
|
||||
}
|
||||
else:
|
||||
body = {"created": "1970-01-01T00:00:00Z", "container_config": zero}
|
||||
preimage = {**body, "layer_id": chain}
|
||||
if parent:
|
||||
preimage["parent"] = "sha256:" + parent
|
||||
preimage = dict(sorted(preimage.items()))
|
||||
legacy_id = hashlib.sha256(
|
||||
json.dumps(preimage, separators=(",", ":")).encode()
|
||||
).hexdigest()
|
||||
saved = {"id": legacy_id}
|
||||
if parent:
|
||||
saved["parent"] = parent
|
||||
saved.update(body)
|
||||
saved["os"] = "linux"
|
||||
payload = json.dumps(saved, separators=(",", ":")).encode()
|
||||
name = "blobs/sha256/" + hashlib.sha256(payload).hexdigest()
|
||||
result[name] = payload
|
||||
added.append(name)
|
||||
parent = legacy_id
|
||||
return result, added
|
||||
|
||||
|
||||
@pytest.mark.parametrize("legacy_onbuild", [True, False])
|
||||
@pytest.mark.parametrize("layer_count", [1, 2])
|
||||
def test_moby_v1_compatibility_metadata_preserves_exact_importer_bytes(
|
||||
tmp_path, legacy_onbuild, layer_count
|
||||
):
|
||||
raw, members, images, metadata = _docker29_oci_fixture(tmp_path, layer_count=layer_count)
|
||||
expected = tmp_path / "expected.tar"
|
||||
producer._normalize_docker_archive(raw, expected, images, metadata=metadata)
|
||||
extended, _added = _moby_v1_fixture(members, legacy_onbuild=legacy_onbuild)
|
||||
raw_compat = tmp_path / "with-compat.tar"
|
||||
_write_archive_fixture(raw_compat, extended)
|
||||
actual = tmp_path / "actual.tar"
|
||||
producer._normalize_docker_archive(raw_compat, actual, images, metadata=metadata)
|
||||
assert actual.read_bytes() == expected.read_bytes()
|
||||
|
||||
|
||||
def test_content_addressed_foreign_json_is_still_rejected(tmp_path):
|
||||
_raw, members, images, metadata = _docker29_oci_fixture(tmp_path)
|
||||
extended, _added = _moby_v1_fixture(members)
|
||||
payload = b'{"id":"foreign","created":null,"os":"linux"}'
|
||||
extended["blobs/sha256/" + hashlib.sha256(payload).hexdigest()] = payload
|
||||
raw = tmp_path / "foreign.tar"
|
||||
_write_archive_fixture(raw, extended)
|
||||
output = tmp_path / "foreign-output.tar"
|
||||
with pytest.raises(producer.BuildRejected):
|
||||
producer._normalize_docker_archive(raw, output, images, metadata=metadata)
|
||||
assert not output.exists()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"change", ["default", "unknown", "parent", "chain", "config", "order", "id"]
|
||||
)
|
||||
def test_self_consistent_foreign_v1_metadata_never_extends_archive_inventory(tmp_path, change):
|
||||
_raw, members, images, metadata = _docker29_oci_fixture(tmp_path, layer_count=2)
|
||||
extended, added = _moby_v1_fixture(members)
|
||||
original_name = added[-1]
|
||||
body = json.loads(extended.pop(original_name))
|
||||
first = json.loads(members["manifest.json"])[0]
|
||||
diffs = json.loads(members[first["Config"]])["rootfs"]["diff_ids"]
|
||||
chain = "sha256:" + hashlib.sha256((diffs[0] + " " + diffs[1]).encode()).hexdigest()
|
||||
if change == "default":
|
||||
body["container_config"]["Tty"] = True
|
||||
elif change == "unknown":
|
||||
body["unexpected"] = "fixture-sensitive-foreign-field"
|
||||
elif change == "parent":
|
||||
body["parent"] = "e" * 64
|
||||
elif change == "chain":
|
||||
chain = "sha256:" + "e" * 64
|
||||
elif change == "config":
|
||||
body["config"]["User"] = "root"
|
||||
elif change == "order":
|
||||
body["container_config"] = dict(sorted(body["container_config"].items()))
|
||||
preimage = {key: value for key, value in body.items() if key not in {"id", "parent"}}
|
||||
preimage.update(layer_id=chain, parent="sha256:" + body["parent"])
|
||||
body["id"] = hashlib.sha256(
|
||||
json.dumps(dict(sorted(preimage.items())), separators=(",", ":")).encode()
|
||||
).hexdigest()
|
||||
if change == "id":
|
||||
body["id"] = "e" * 64
|
||||
payload = json.dumps(body, separators=(",", ":")).encode()
|
||||
extended["blobs/sha256/" + hashlib.sha256(payload).hexdigest()] = payload
|
||||
raw = tmp_path / "spoof.tar"
|
||||
_write_archive_fixture(raw, extended)
|
||||
output = tmp_path / "spoof-output.tar"
|
||||
with pytest.raises(producer.BuildRejected) as error:
|
||||
producer._normalize_docker_archive(raw, output, images, metadata=metadata)
|
||||
assert "fixture-sensitive" not in str(error.value)
|
||||
assert not output.exists()
|
||||
|
||||
|
||||
def test_docker29_oci_normalizer_rejects_unreferenced_blobs_and_config_mismatch(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
|
||||
Reference in new issue
Block a user