#!/usr/bin/env python3 """R-746: image_digest.resolve honours a `@digest` — it asks the registry for THAT manifest and never answers the tag's current digest. No network: urlopen is replaced by a fake registry that serves one tag and one digest. COMPANION RED-PROOF: with the pre-fix resolve (it dropped the digest and asked for the tag), the absent-digest case answers the tag's digest and this test fails ("a digest the registry does not serve was resolved").""" import io import os import sys import unittest import urllib.error sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import image_digest # noqa: E402 SERVED = "sha256:" + "a" * 64 GONE = "sha256:" + "0" * 64 class _Resp: def __init__(self, digest): self.headers = {"Docker-Content-Digest": digest} self.status = 200 def __enter__(self): return self def __exit__(self, *a): return False class FakeRegistry: def __init__(self): self.urls = [] def __call__(self, req, timeout=30): url = req.full_url self.urls.append(url) last = url.rsplit("/", 1)[-1] if last in ("7-alpine", SERVED): # the tag and the digest it serves return _Resp(SERVED) raise urllib.error.HTTPError(url, 404, "not found", {}, io.BytesIO(b"")) class ResolveDigest(unittest.TestCase): def setUp(self): self.fake = FakeRegistry() self.orig = image_digest.urllib.request.urlopen image_digest.urllib.request.urlopen = self.fake def tearDown(self): image_digest.urllib.request.urlopen = self.orig def test_plain_tag_unchanged(self): self.assertEqual(image_digest.resolve("redis:7-alpine"), (SERVED, None)) self.assertTrue(self.fake.urls[-1].endswith("/manifests/7-alpine")) def test_served_digest_is_asked_by_digest(self): d, why = image_digest.resolve("redis:7-alpine@" + SERVED) self.assertEqual(d, SERVED, why) self.assertTrue(self.fake.urls[-1].endswith("/manifests/" + SERVED), self.fake.urls) def test_absent_digest_is_refused(self): d, why = image_digest.resolve("redis:7-alpine@" + GONE) self.assertIsNone(d, "a digest the registry does not serve was resolved (to %s)" % d) self.assertIn("404", why) def test_malformed_digest_is_refused(self): d, why = image_digest.resolve("redis:7-alpine@sha256:abc") self.assertIsNone(d) self.assertEqual(self.fake.urls, [], "a malformed digest must not reach the registry") if __name__ == "__main__": unittest.main()