Record whether a node is adopted and which modules were taken on it (hq ADR 0100)
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// novox/hq ADR 0100: a node is adopted or converged, and the controller records which.
|
||||
|
||||
func TestANodeAddedWithoutSayingIsConverged(t *testing.T) {
|
||||
inv := fresh(t)
|
||||
if _, err := inv.AddNode(t.Context(), "anchor"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n, err := inv.NodeByName(t.Context(), "anchor")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n.Adopted || !n.AdoptedSince.IsZero() {
|
||||
t.Fatalf("a node nobody said anything about reads as adopted: %+v", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnAdoptedNodeRoundTripsThroughEveryReading(t *testing.T) {
|
||||
inv := fresh(t)
|
||||
made, err := inv.AddNodeAs(t.Context(), "anchor", true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !made.Adopted || made.AdoptedSince.IsZero() {
|
||||
t.Fatalf("added adopted, got %+v", made)
|
||||
}
|
||||
byName, err := inv.NodeByName(t.Context(), "anchor")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
all, err := inv.Nodes(t.Context())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !byName.Adopted || len(all) != 1 || !all[0].Adopted {
|
||||
t.Fatalf("adoption did not survive reading back: %+v %+v", byName, all)
|
||||
}
|
||||
|
||||
// And through a token: enrolment reads the node from the token it spends.
|
||||
issued, err := inv.IssueToken(t.Context(), "anchor", 60e9)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
claimed, err := inv.Claim(t.Context(), issued.Secret, "a-key", false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !claimed.Adopted {
|
||||
t.Fatal("the node a token claims lost its mode")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTakingIsRefusedOnAConvergedNodeAndForAnUnassignedModule(t *testing.T) {
|
||||
inv := fresh(t)
|
||||
if err := inv.RegisterModule(t.Context(), manifest("hello-web", nil, nil), Source{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := inv.AddNode(t.Context(), "converged"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := inv.Assign(t.Context(), "converged", "hello-web"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := inv.Take(t.Context(), "converged", "hello-web"); !errors.Is(err, ErrNotAdopted) {
|
||||
t.Fatalf("taking on a converged node gave %v", err)
|
||||
}
|
||||
|
||||
if _, err := inv.AddNodeAs(t.Context(), "anchor", true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := inv.Take(t.Context(), "anchor", "hello-web"); !errors.Is(err, ErrNotAssigned) {
|
||||
t.Fatalf("taking an unassigned module gave %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestATakenModuleOutlivesItsAssignmentAndReturningToAdopted(t *testing.T) {
|
||||
inv := fresh(t)
|
||||
for _, m := range []string{"hello-web", "postgres"} {
|
||||
if err := inv.RegisterModule(t.Context(), manifest(m, nil, nil), Source{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if _, err := inv.AddNodeAs(t.Context(), "anchor", true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, m := range []string{"hello-web", "postgres"} {
|
||||
if err := inv.Assign(t.Context(), "anchor", m); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err := inv.Take(t.Context(), "anchor", "postgres"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := inv.Take(t.Context(), "anchor", "postgres"); err != nil {
|
||||
t.Fatalf("taking twice is not an error: %v", err)
|
||||
}
|
||||
if err := inv.Unassign(t.Context(), "anchor", "postgres"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
taken, err := inv.Taken(t.Context(), "anchor")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(taken, []string{"postgres"}) {
|
||||
t.Fatalf("unassigning un-took it: %v", taken)
|
||||
}
|
||||
|
||||
took, err := inv.Converge(t.Context(), "anchor")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(took, []string{"hello-web"}) {
|
||||
t.Fatalf("converging took %v; it takes every assigned module not yet taken", took)
|
||||
}
|
||||
n, _ := inv.NodeByName(t.Context(), "anchor")
|
||||
if n.Adopted {
|
||||
t.Fatal("converged node still reads adopted")
|
||||
}
|
||||
|
||||
if err := inv.SetAdopted(t.Context(), "anchor", true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
taken, _ = inv.Taken(t.Context(), "anchor")
|
||||
if !reflect.DeepEqual(taken, []string{"hello-web", "postgres"}) {
|
||||
t.Fatalf("returning to adopted lost what was taken: %v", taken)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user