package apply import ( "context" "errors" "testing" ) // A name is not unique across object kinds: a module regularly names a network the same as the // container that joins it (keycloak does this today, ordinarily). `docker inspect `, unlike // `docker container inspect `, resolves across every kind — so when the container does not // exist yet but a same-named network does, the bare form answers with the network's JSON instead // of reporting the container absent. containerState and inspectFound must ask by kind, or a // same-named network makes them unable to tell "not here yet" from "the runtime is broken" // (novox/hq ADR 0100's refusal, tripped by nothing wrong). // // dockerLikeByKind is Docker's real behaviour, not the bug: `container inspect` only ever // answers from the container namespace. A fake that also answered the bare, unscoped form would // not catch a regression back to it — this one refuses to, on purpose. func dockerLikeByKind(containers map[string]bool) func(context.Context, string, ...string) (string, error) { return func(_ context.Context, name string, args ...string) (string, error) { if name != "docker" { return "", errors.New("unexpected program: " + name) } if len(args) > 0 && args[0] == "info" { // containerRuntime's probe, answered so inspectFound gets past it to the check under // test. return "27.0\n", nil } if len(args) < 2 || args[0] != "container" || args[1] != "inspect" { return "", errors.New("unexpected command: only `docker container inspect` is modelled here") } target := args[len(args)-1] if !containers[target] { return "", errors.New("Error: No such container: " + target) } return "false\t\n", nil } } func TestContainerStateAsksTheContainerNamespaceNotTheBareForm(t *testing.T) { // "minio" exists only as a network in this scenario — never in `containers` — matching the // live failure this guards: a module's network and its container share a name, and the // container does not exist yet. run := dockerLikeByKind(map[string]bool{"keycloak": true}) if _, err := containerState(context.Background(), "minio", run); err == nil { t.Fatal("a container that does not exist should report absent, not be mistaken for found") } if state, err := containerState(context.Background(), "keycloak", run); err != nil { t.Fatalf("a container that does exist should be found: %v", err) } else if state.Running { t.Errorf("the fake said not running; containerState disagreed: %+v", state) } } func TestInspectFoundAsksTheContainerNamespaceNotTheBareForm(t *testing.T) { run := dockerLikeByKind(map[string]bool{"keycloak": true}) if _, exists, err := inspectFound(context.Background(), "minio", run); err != nil || exists { t.Fatalf("a container that does not exist should be reported absent cleanly, not refused: exists=%v err=%v", exists, err) } if _, exists, err := inspectFound(context.Background(), "keycloak", run); err != nil || !exists { t.Fatalf("a container that does exist should be found: exists=%v err=%v", exists, err) } }