"""What a snapshot puts on the timeline as a deploy: a unit (a container, or its swarm service) running an image it didn't, a container recreated under its name, a new container; not a swarm task the scheduler moved here, and not a container that only restarted.""" from types import SimpleNamespace as NS from plugins.docker.timeline import _deploy_summary, deploys, short_image def _row(name, image, cid, service=None): return NS(name=name, image=image, container_id=cid, service_name=service) def _c(name, image, cid, service=None, status="running"): return {"name": name, "image": image, "container_id": cid, "service_name": service, "status": status} def test_a_new_image_is_a_deploy_and_names_the_old_one(): [d] = deploys([_row("web", "nginx:1.27", "a1")], [_c("web", "nginx:1.28", "a2")]) assert (d["unit"], d["was"], d["recreated"]) == ("web", "nginx:1.27", False) assert _deploy_summary(d, "h1") == "web on h1: nginx:1.27 → nginx:1.28" def test_a_swarm_service_is_one_unit_and_a_new_build_of_the_same_tag_says_so(): old = [_row("app.1.aaa", "reg/steward:dev@sha256:1111aaaa2222bbbb", "x", "steward_app")] new = [_c("app.1.bbb", "reg/steward:dev@sha256:3333cccc4444dddd", "y", "steward_app"), _c("app.2.ccc", "reg/steward:dev@sha256:3333cccc4444dddd", "z", "steward_app")] [d] = deploys(old, new) # one per service, not per task assert d["unit"] == "steward_app" and d["swarm"] assert _deploy_summary(d, "h1") == "steward_app on h1: new build of steward:dev (3333cccc4444)" def test_a_recreated_container_and_a_new_one_are_deploys(): [d] = deploys([_row("db", "postgres:16", "c1")], [_c("db", "postgres:16", "c2")]) assert d["recreated"] and _deploy_summary(d, "h1") == "db on h1: recreated on postgres:16" [d] = deploys([_row("db", "postgres:16", "c1")], [_c("db", "postgres:16", "c1"), _c("cache", "redis:7", "r1")]) assert _deploy_summary(d, "h1") == "cache on h1: started on redis:7" def test_a_moved_swarm_task_a_restart_and_a_stopped_container_are_not(): assert deploys([], [_c("app.1.aaa", "img:1", "x", "svc")]) == [] # landed here, new to the host assert deploys([_row("web", "nginx:1", "a1")], [_c("web", "nginx:1", "a1")]) == [] assert deploys([_row("web", "nginx:1", "a1")], [_c("web", "nginx:2", "a2", status="exited")]) == [] # A swarm task replaced on the same image (a crash, a reschedule) is not a deploy either. assert deploys([_row("app.1.aaa", "img:1", "x", "svc")], [_c("app.1.bbb", "img:1", "y", "svc")]) == [] def test_short_image(): assert short_image("git.example.com/team/steward:dev@sha256:e12594c948a294693c") == "steward:dev (e12594c948a2)" assert short_image("nginx:1.28") == "nginx:1.28" assert short_image("") == "an unknown image"