Third review of mesh-catalog #147. A unit's name can now come from a setting (a template's instance), so every systemctl call that names a unit passes `--` before it, and a name can never be read as an option. On removal, a unit is started or enabled again only when it is exactly the stopped and disabled the mesh held it to. A masked unit, or one somebody started or enabled since, is left as it is, and the report says why. A restore that fails (the start refused, or the unit not running after it) puts back what this attempt changed and is reported as waiting, so no apply is made fatal by it and the next one tries again. The tests' fake service managers read systemctl's arguments in the shape they were written for (oldShape); internal/system's own test holds the `--`.
68 lines
3.0 KiB
Go
68 lines
3.0 KiB
Go
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 <name>`, unlike
|
|
// `docker container inspect <name>`, 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) {
|
|
args = oldShape(name, args)
|
|
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)
|
|
}
|
|
}
|