Review round 1 of the bus want: a removal keeps the bus server, the have says a server made anew runs the want's fingerprint, the old build is read before the first write, and an unanswered inspect fails the apply rather than replacing the server (ADR 0594 §2, §4)
mesh/delivery-group group feat/774-bus-want rejected: composed together: the checker's verdict at the members' heads (a0ab6ce2e316): novox
mesh/delivery closed: the pull request closed unmerged
mesh/check failed: novox: not composed on novox: nats has not been built for this mesh: server is its "server" artifact… | 2c5f818d1522 on 798d73eb11e9
mesh/delivery-group group feat/774-bus-want rejected: composed together: the checker's verdict at the members' heads (a0ab6ce2e316): novox
mesh/delivery closed: the pull request closed unmerged
mesh/check failed: novox: not composed on novox: nats has not been built for this mesh: server is its "server" artifact… | 2c5f818d1522 on 798d73eb11e9
This commit is contained in:
@@ -2,9 +2,10 @@ package apply
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -225,8 +226,24 @@ func TestAResourceThatMovedToItsModulesCompositionIsLeftByTheNodesOwnApply(t *te
|
||||
// while the bus was folded. Kept (a want without the warrant's mark), the server's container and its program archive
|
||||
// are left as they run, whatever the build changed in them, and become nats's; its files and the tools' account file
|
||||
// are written. Not kept, the same apply replaces the container.
|
||||
for _, keep := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("the bus server kept %v", keep), func(t *testing.T) {
|
||||
// Review of 774, round 1: the keep is decided once before anything moves, by the runtime's answer for the server. A
|
||||
// server not there is made and its archives applied with it, none said kept; a runtime that does not answer fails the
|
||||
// apply, nothing written and nothing replaced; a removal of the bus removes the rest and leaves the server.
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
keep bool
|
||||
gone bool // the server is not on the machine
|
||||
mute bool // the runtime does not answer the server's inspect
|
||||
remove bool // the bus module's want is removed
|
||||
}{
|
||||
{name: "kept", keep: true},
|
||||
{name: "not kept"},
|
||||
{name: "kept, the server not there", keep: true, gone: true},
|
||||
{name: "kept, the runtime does not answer", keep: true, mute: true},
|
||||
{name: "kept, the bus removed", keep: true, remove: true},
|
||||
} {
|
||||
t.Run("the bus server "+tc.name, func(t *testing.T) {
|
||||
keep := tc.keep && !tc.gone
|
||||
dir := t.TempDir()
|
||||
conf, account, program := filepath.Join(dir, "nats.conf"), filepath.Join(dir, "tools", "account"), filepath.Join(dir, "program")
|
||||
bus := func(env, confBody, programBody, module string) *declaration.Declaration {
|
||||
@@ -250,29 +267,54 @@ func TestAResourceThatMovedToItsModulesCompositionIsLeftByTheNodesOwnApply(t *te
|
||||
if made == nil {
|
||||
t.Fatalf("the node's own made no server: %v", m.asked)
|
||||
}
|
||||
if tc.gone {
|
||||
delete(m.containers, "mesh-broker-nats")
|
||||
}
|
||||
m.asked = nil
|
||||
run := m.run
|
||||
if tc.mute {
|
||||
run = func(ctx context.Context, name string, args ...string) (string, error) {
|
||||
if name == "docker" && len(args) > 1 && args[0] == "container" && args[1] == "inspect" {
|
||||
m.asked = append(m.asked, "docker "+strings.Join(args, " "))
|
||||
return "", errors.New("Cannot connect to the Docker daemon at unix:///var/run/docker.sock")
|
||||
}
|
||||
return m.run(ctx, name, args...)
|
||||
}
|
||||
}
|
||||
next := bus("2", "b", "two", "nats")
|
||||
next.Resources = append(next.Resources, declare(t, `{"id":"nats.tools-account","type":"file","path":"`+account+
|
||||
`","content":"tools","module":"nats"}`).Resources...)
|
||||
scope := Scope{Module: "nats", Placed: map[string]bool{"nats": true}}
|
||||
if keep {
|
||||
if tc.keep {
|
||||
scope.Keep = map[string]bool{"nats.server": true, "nats.program-snapshot": true}
|
||||
}
|
||||
moved := func() []string {
|
||||
var out []string
|
||||
for _, a := range m.asked {
|
||||
for _, verb := range []string{"docker rm", "docker run", "docker create", "docker stop", "docker restart", "docker rename"} {
|
||||
if strings.HasPrefix(a, verb+" ") {
|
||||
out = append(out, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
report, after, err := ApplyModule(context.Background(), archHost(t), next, scope, state,
|
||||
store.OriginDeclared, m.run, nil, nil, nil, nil)
|
||||
store.OriginDeclared, run, nil, nil, nil, nil)
|
||||
if tc.mute {
|
||||
if err == nil || !strings.Contains(err.Error(), "did not say whether the bus server") {
|
||||
t.Fatalf("an unanswered inspect did not fail the apply: %v", err)
|
||||
}
|
||||
if got, _ := os.ReadFile(conf); string(got) != "a" || len(moved()) > 0 {
|
||||
t.Errorf("an apply that could not tell whether the server runs wrote %q and moved %v", got, moved())
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var moved []string
|
||||
for _, a := range m.asked {
|
||||
for _, verb := range []string{"docker rm", "docker run", "docker create", "docker stop", "docker restart"} {
|
||||
if strings.HasPrefix(a, verb+" ") {
|
||||
moved = append(moved, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if keep == (len(moved) > 0) {
|
||||
t.Fatalf("kept %v, and the server was moved by %v", keep, moved)
|
||||
if keep == (len(moved()) > 0) {
|
||||
t.Fatalf("kept %v, and the server was moved by %v", keep, moved())
|
||||
}
|
||||
if got, _ := os.ReadFile(conf); string(got) != "b" {
|
||||
t.Errorf("the server's file holds %q", got)
|
||||
@@ -283,7 +325,8 @@ func TestAResourceThatMovedToItsModulesCompositionIsLeftByTheNodesOwnApply(t *te
|
||||
if got, _ := os.ReadFile(filepath.Join(program, "snapshot")); keep != (string(got) == "one") {
|
||||
t.Errorf("kept %v, and the server's program is %q", keep, got)
|
||||
}
|
||||
for _, id := range []string{"nats.server", "nats.program-snapshot"} {
|
||||
var kept []string
|
||||
for _, id := range []string{"nats.program-snapshot", "nats.server"} {
|
||||
rec, ok := after.Find(id)
|
||||
if !ok || rec.Module != "nats" {
|
||||
t.Errorf("%s is recorded %+v, not as nats's", id, rec)
|
||||
@@ -291,10 +334,35 @@ func TestAResourceThatMovedToItsModulesCompositionIsLeftByTheNodesOwnApply(t *te
|
||||
if o := outcomeOf(report, id); keep != (o.Action == keptAsItRuns) {
|
||||
t.Errorf("kept %v, and %s was %s: %s", keep, id, o.Action, o.Detail)
|
||||
}
|
||||
if keep {
|
||||
kept = append(kept, id)
|
||||
}
|
||||
}
|
||||
if keep && report.Changed() == false {
|
||||
if !slices.Equal(report.Kept, kept) && !(len(kept) == 0 && len(report.Kept) == 0) {
|
||||
t.Errorf("the report says it kept %v, want %v", report.Kept, kept)
|
||||
}
|
||||
if tc.keep && report.Changed() == false {
|
||||
t.Error("an apply that wrote the server's files says nothing changed")
|
||||
}
|
||||
if !tc.remove {
|
||||
return
|
||||
}
|
||||
m.asked = nil
|
||||
gone, last, err := ApplyModule(context.Background(), archHost(t), &declaration.Declaration{}, scope, after,
|
||||
store.OriginDeclared, run, nil, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(moved()) > 0 || m.containers["mesh-broker-nats"] == nil || !exists(filepath.Join(program, "snapshot")) {
|
||||
t.Errorf("the bus's removal removed its server: %v", moved())
|
||||
}
|
||||
if exists(conf) || exists(account) {
|
||||
t.Errorf("the bus's removal left the rest of it: conf %v, account %v", exists(conf), exists(account))
|
||||
}
|
||||
if _, ok := last.Find("nats.server"); !ok || !slices.Equal(gone.Kept, []string{"nats.program-snapshot", "nats.server"}) &&
|
||||
!slices.Equal(gone.Kept, []string{"nats.server", "nats.program-snapshot"}) {
|
||||
t.Errorf("the removal kept %v, the server recorded %v", gone.Kept, ok)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user