A repeat assignment says nothing changed (ADR 0115)

One assignment of a module per node is now the rule, not a limitation —
the operator dropped the multi-assignment requirement, and the schema's
(node, module) key has been the decision since migration 0005. What
changed: Assign reports whether the assignment was new, and the command
says 'already runs — one node runs one of each (ADR 0115); nothing
changed' instead of printing 'is assigned' for a no-op, which read as
an action that happened. Idempotence stays: a repeat is exit 0, because
a script stating what is already true is not wrong.
This commit is contained in:
2026-09-26 19:02:35 +02:00
parent 95426e25cf
commit 50734095b8
9 changed files with 51 additions and 25 deletions
+19 -9
View File
@@ -77,7 +77,7 @@ func TestAModuleAMachineIsRunningCannotBeForgotten(t *testing.T) {
if err := inv.RegisterModule(t.Context(), manifest("thing", nil, nil), Source{}); err != nil {
t.Fatal(err)
}
if err := inv.Assign(t.Context(), "laptop", "thing"); err != nil {
if _, err := inv.Assign(t.Context(), "laptop", "thing"); err != nil {
t.Fatal(err)
}
@@ -104,7 +104,7 @@ func TestRemovingANodeTakesItsAssignments(t *testing.T) {
if err := inv.RegisterModule(t.Context(), manifest("thing", nil, nil), Source{}); err != nil {
t.Fatal(err)
}
if err := inv.Assign(t.Context(), "laptop", "thing"); err != nil {
if _, err := inv.Assign(t.Context(), "laptop", "thing"); err != nil {
t.Fatal(err)
}
if _, err := inv.store.Pool().Exec(t.Context(), `delete from node where id = $1`, node.ID); err != nil {
@@ -136,14 +136,16 @@ func TestAssigningAModuleTheMeshDoesNotKnowIsRefused(t *testing.T) {
if _, err := inv.AddNode(t.Context(), "laptop"); err != nil {
t.Fatal(err)
}
err := inv.Assign(t.Context(), "laptop", "not-a-module")
_, err := inv.Assign(t.Context(), "laptop", "not-a-module")
if !errors.Is(err, ErrNoSuchModule) {
t.Fatalf("assigning an unknown module gave %v", err)
}
}
func TestAssigningTwiceIsNotAnError(t *testing.T) {
// It is a statement of what should be true, and it already is.
func TestAssigningTwiceIsNotAnErrorAndSaysSo(t *testing.T) {
// It is a statement of what should be true, and it already is — one assignment of a module
// per node is the rule (novox/hq ADR 0115), so a repeat is absorbed, audibly: the caller is
// told nothing was new.
inv := fresh(t)
if _, err := inv.AddNode(t.Context(), "laptop"); err != nil {
t.Fatal(err)
@@ -151,10 +153,18 @@ func TestAssigningTwiceIsNotAnError(t *testing.T) {
if err := inv.RegisterModule(t.Context(), manifest("thing", nil, nil), Source{}); err != nil {
t.Fatal(err)
}
for i := 0; i < 3; i++ {
if err := inv.Assign(t.Context(), "laptop", "thing"); err != nil {
first, err := inv.Assign(t.Context(), "laptop", "thing")
if err != nil || !first {
t.Fatalf("the first assignment is the new one; got fresh=%v err=%v", first, err)
}
for i := 0; i < 2; i++ {
again, err := inv.Assign(t.Context(), "laptop", "thing")
if err != nil {
t.Fatalf("assigning again failed: %v", err)
}
if again {
t.Fatal("a repeat must say nothing was new")
}
}
assigned, err := inv.Assigned(t.Context(), "laptop")
if err != nil {
@@ -277,7 +287,7 @@ func TestBeingBehindNamesTheMachinesRunningTheOldOne(t *testing.T) {
t.Fatal(err)
}
for _, n := range []string{"laptop", "workstation"} {
if err := inv.Assign(t.Context(), n, "thing"); err != nil {
if _, err := inv.Assign(t.Context(), n, "thing"); err != nil {
t.Fatal(err)
}
}
@@ -451,7 +461,7 @@ func TestTheCatalogueSaysWhereEachModuleCameFromAndWhoRunsIt(t *testing.T) {
t.Fatal(err)
}
for _, n := range []string{"workstation", "laptop"} {
if err := inv.Assign(ctx, n, "shell"); err != nil {
if _, err := inv.Assign(ctx, n, "shell"); err != nil {
t.Fatal(err)
}
}