package main import ( "encoding/json" "strings" "testing" "github.com/novox/mesh-controller/internal/inventory" ) // A module assigned to an adopted machine and never taken runs none of what it declares, and every // surface called that success — a push reporting sent, a journal reporting applied, status reporting // a machine doing what it was told (novox/hq 04-ISSUES/125). The holds were only ever in the // machine's own state file. // heldOn makes a machine report that it is holding resources for a module, the way an adopted node // does after an apply. func heldOn(t *testing.T, open *stores, node, module string, ids ...string) { t.Helper() record, err := open.inventory.NodeByName(t.Context(), node) if err != nil { t.Fatal(err) } held := make([]inventory.Held, 0, len(ids)) for _, id := range ids { held = append(held, inventory.Held{ID: id, Module: module, Kind: "container", Target: id}) } if err := open.inventory.RecordAdoption(t.Context(), record.ID, held, "ufw", nil); err != nil { t.Fatal(err) } } func TestStatusNamesAModuleHeldBecauseNothingTookIt(t *testing.T) { open := aMesh(t) heldOn(t, open, "anchor", "route-proxy", "ca", "certs", "server") asked, err := theThreeQuestions(t.Context(), open) if err != nil { t.Fatal(err) } if got := asked.untaken["anchor"]["route-proxy"]; got != 3 { t.Fatalf("status counted %d resources held for route-proxy, wanted 3", got) } } func TestAHeldModuleStopsTheMeshReadingAsWell(t *testing.T) { // The whole of the fault. "all doing what they were told" was true throughout the outage, and // true is not the same as safe to act on: the machine was doing what it was told, and what it // was told had not started. Asserted against the production condition, not a copy of it. quiet := answers{} if !quiet.well() { t.Fatal("a mesh with nothing to say does not read as well, so nothing below means anything") } holding := answers{untaken: map[string]map[string]int{"anchor": {"route-proxy": 3}}} if holding.well() { t.Fatal("a machine holding a module's resources still reads as doing what it was told, " + "which is the sentence that cost every public name on the machine") } // And being adopted does not suppress it: that is a mode somebody chose, not work outstanding. // Kept as an assertion so the difference between the two is deliberate rather than incidental. if !quiet.well() { t.Fatal("the well condition is not stable") } } func TestAHeldModuleIsFoundFromWhatTheMachineReported(t *testing.T) { // End to end through the store, so the condition above is reached by real data and not only by // a constructed value: the machine reports, the mesh records, status asks. open := aMesh(t) heldOn(t, open, "anchor", "route-proxy", "ca", "server") asked, err := theThreeQuestions(t.Context(), open) if err != nil { t.Fatal(err) } if len(asked.untaken) == 0 { t.Fatal("what the machine reported holding did not reach status") } if asked.well() { t.Fatal("a mesh whose machine reported holds reads as well") } } func TestTheJSONStatusCarriesWhatIsHeldAndForWhichModule(t *testing.T) { open := aMesh(t) heldOn(t, open, "anchor", "route-proxy", "ca", "certs") asked, err := theThreeQuestions(t.Context(), open) if err != nil { t.Fatal(err) } body, err := statusAsJSON(asked) if err != nil { t.Fatal(err) } var doc struct { Untaken []struct { Node string `json:"node"` Module string `json:"module"` Held int `json:"held"` } `json:"untaken"` } if err := json.Unmarshal(body, &doc); err != nil { t.Fatal(err) } if len(doc.Untaken) != 1 { t.Fatalf("the document carries %d untaken rows, wanted 1: %s", len(doc.Untaken), body) } row := doc.Untaken[0] if row.Node != "anchor" || row.Module != "route-proxy" || row.Held != 2 { t.Fatalf("the row is %+v, wanted anchor/route-proxy/2", row) } // Absent rather than empty when nothing is held, so a well mesh's document does not carry a // field a reader has to interpret. clean, err := statusAsJSON(answers{}) if err != nil { t.Fatal(err) } if strings.Contains(string(clean), "untaken") { t.Fatalf("a mesh holding nothing still names untaken: %s", clean) } }