84 lines
3.3 KiB
Python
84 lines
3.3 KiB
Python
"""Exercise the exact image update helper used by the publishing workflow."""
|
|
|
|
import importlib.util
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "update_gitops_image.py"
|
|
SPEC = importlib.util.spec_from_file_location("update_gitops_image", SCRIPT)
|
|
assert SPEC is not None and SPEC.loader is not None
|
|
MODULE = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(MODULE)
|
|
REPOSITORY = "tea.ahmza.com/ahmza/blog-ahmza-com"
|
|
IMAGE = REPOSITORY + "@sha256:" + "a" * 64
|
|
|
|
|
|
class UpdateImageTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.directory = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.directory.cleanup)
|
|
self.manifest = Path(self.directory.name) / "deployment.yaml"
|
|
|
|
def test_replaces_only_blog_image_and_preserves_other_fields(self):
|
|
original = (
|
|
"spec:\n"
|
|
" containers:\n"
|
|
" - name: blog\n"
|
|
f" image: {REPOSITORY}:latest\n"
|
|
" - name: other\n"
|
|
" image: example.org/other:latest\n"
|
|
)
|
|
self.manifest.write_text(original)
|
|
self.assertTrue(MODULE.update_image(self.manifest, IMAGE))
|
|
self.assertEqual(
|
|
self.manifest.read_text(), original.replace(REPOSITORY + ":latest", IMAGE)
|
|
)
|
|
|
|
def test_existing_digest_update_preserves_comment(self):
|
|
self.manifest.write_text(
|
|
" image: " + REPOSITORY + "@sha256:" + "b" * 64 + " # keep\n"
|
|
)
|
|
self.assertTrue(MODULE.update_image(self.manifest, IMAGE))
|
|
self.assertEqual(self.manifest.read_text(), " image: " + IMAGE + " # keep\n")
|
|
|
|
def test_same_digest_is_noop(self):
|
|
text = " image: " + IMAGE + "\n"
|
|
self.manifest.write_text(text)
|
|
self.assertFalse(MODULE.update_image(self.manifest, IMAGE))
|
|
self.assertEqual(self.manifest.read_text(), text)
|
|
|
|
def test_missing_or_duplicate_image_fails_without_modification(self):
|
|
for text in ["spec: {}\n", (" image: " + IMAGE + "\n") * 2]:
|
|
with self.subTest(text=text):
|
|
self.manifest.write_text(text)
|
|
with self.assertRaises(ValueError):
|
|
MODULE.update_image(self.manifest, IMAGE)
|
|
self.assertEqual(self.manifest.read_text(), text)
|
|
|
|
def test_rejects_unexpected_or_mutable_image_input(self):
|
|
text = " image: " + REPOSITORY + ":latest\n"
|
|
self.manifest.write_text(text)
|
|
for image in [
|
|
REPOSITORY + ":latest",
|
|
REPOSITORY + "@sha256:short",
|
|
"example.org/untrusted@sha256:" + "a" * 64,
|
|
IMAGE + "\nimage: injected",
|
|
REPOSITORY + "@sha256:" + "A" * 64,
|
|
]:
|
|
with self.subTest(image=image):
|
|
with self.assertRaises(ValueError):
|
|
MODULE.update_image(self.manifest, image)
|
|
self.assertEqual(self.manifest.read_text(), text)
|
|
|
|
def test_refuses_partial_repository_match(self):
|
|
text = " image: " + REPOSITORY + "-other:latest\n"
|
|
self.manifest.write_text(text)
|
|
with self.assertRaises(ValueError):
|
|
MODULE.update_image(self.manifest, IMAGE)
|
|
self.assertEqual(self.manifest.read_text(), text)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|