Retain current production image and one rollback baseline
This commit is contained in:
@@ -111,6 +111,10 @@ def test_deploy_rolls_back_exact_baseline_without_deleting_data(
|
||||
monkeypatch.setattr(
|
||||
tool, "state_io", lambda state: saved.append(json.loads(json.dumps(state)))
|
||||
)
|
||||
cleanup = []
|
||||
monkeypatch.setattr(
|
||||
tool, "cleanup_images", lambda: cleanup.append(saved[-1]["status"])
|
||||
)
|
||||
verifies = []
|
||||
|
||||
def verify(config):
|
||||
@@ -125,11 +129,13 @@ def test_deploy_rolls_back_exact_baseline_without_deleting_data(
|
||||
if failure:
|
||||
with pytest.raises(RuntimeError):
|
||||
tool.deploy()
|
||||
assert cleanup == []
|
||||
assert activated == [new, old]
|
||||
assert saved[0]["previous"] == old
|
||||
assert ("unlock" in calls) is (failure != "rollback")
|
||||
else:
|
||||
tool.deploy()
|
||||
assert cleanup == ["success"]
|
||||
assert activated == [new]
|
||||
assert saved[-1]["status"] == "success"
|
||||
assert not any(
|
||||
@@ -243,3 +249,53 @@ def test_lock_conflict_never_activates_production(tool, monkeypatch):
|
||||
monkeypatch.setattr(tool, "run", fail)
|
||||
with pytest.raises(RuntimeError):
|
||||
tool.deploy()
|
||||
|
||||
|
||||
def test_image_retention_protects_containers_rollback_and_other_tags(tool, monkeypatch):
|
||||
tool.state = {"previous_image": "previous"}
|
||||
release = "pigway-frame-flow:release-" + "a" * 40 + "-" + "b" * 8
|
||||
rollback = "pigway-frame-flow:rollback-" + "c" * 32
|
||||
images = [
|
||||
{"Id": "current", "RepoTags": [release]},
|
||||
{"Id": "previous", "RepoTags": [rollback]},
|
||||
{"Id": "stopped", "RepoTags": [release]},
|
||||
{"Id": "obsolete", "RepoTags": [release, rollback]},
|
||||
{"Id": "shared", "RepoTags": [release, "other:latest"]},
|
||||
{"Id": "ci", "RepoTags": ["ffci-fixture:latest"]},
|
||||
]
|
||||
calls = []
|
||||
|
||||
def run(*args, **kwargs):
|
||||
calls.append(args)
|
||||
if args == ("ps", "-aq"):
|
||||
data = "container1 container2"
|
||||
elif args[0] == "inspect":
|
||||
data = json.dumps([{"Image": "current"}, {"Image": "stopped"}])
|
||||
elif args[:2] == ("image", "ls"):
|
||||
data = "current previous stopped obsolete shared ci"
|
||||
elif args[:2] == ("image", "inspect"):
|
||||
data = json.dumps(images)
|
||||
else:
|
||||
data = ""
|
||||
return SimpleNamespace(stdout=data.encode(), returncode=0)
|
||||
|
||||
monkeypatch.setattr(tool, "run", run)
|
||||
tool.cleanup_images()
|
||||
assert [c for c in calls if c[:2] == ("image", "rm")] == [
|
||||
("image", "rm", release, rollback)
|
||||
]
|
||||
|
||||
|
||||
def test_image_retention_failure_does_not_fail_verified_deploy(
|
||||
tool, monkeypatch, capsys
|
||||
):
|
||||
tool.state = {"previous_image": "previous"}
|
||||
|
||||
def unavailable(*args, **kwargs):
|
||||
raise RuntimeError("private diagnostic")
|
||||
|
||||
monkeypatch.setattr(tool, "run", unavailable)
|
||||
tool.cleanup_images()
|
||||
output = capsys.readouterr().out
|
||||
assert "cleanup deferred" in output
|
||||
assert "private diagnostic" not in output
|
||||
|
||||
Reference in New Issue
Block a user