package inventory import ( "bytes" "encoding/json" "reflect" "strings" "testing" "time" "github.com/novox/mesh-controller/internal/catalogue" ) // APlan is a whole plan, as design 57 P6 composes one for a module handed to the provisioner. func aPlan() Provisioning { return Provisioning{ Templates: TemplatesArchive{Source: "artifacts/dunst/files.tar.gz", Digest: "sha256:" + strings.Repeat("ab", 32)}, Files: []ProvisionedFile{{ID: "dunstrc", Path: "/home/nox/.config/dunst/dunstrc", Template: "dunstrc", OwnerAtRuntime: "owned", Takes: "reload-on"}}, Placement: map[string]string{"machine:account-home": "/home/nox", "dir:state": "/var/lib/dunst"}, } } // **An assignment with no plan is the bytes it was** (design 57 P5, issue 671): the plan joins the value of a // module handed to the provisioner alone, so no other assignment's key is written again. func TestAnAssignmentWithoutAPlanIsMirroredAsBefore(t *testing.T) { at := time.Date(2026, 10, 14, 20, 0, 0, 0, time.UTC) values, err := AssignmentValues([]AssignmentMirrored{{Node: "g14", Module: "zsh", Assigned: at}}, nil) if err != nil { t.Fatal(err) } if got, want := string(values["g14.zsh"]), `{"node":"g14","module":"zsh","assigned":"2026-10-14T20:00:00Z"}`; got != want { t.Errorf("an assignment without a plan is mirrored as %s, want %s", got, want) } } // **A handed module's assignment carries its plan**, whole, under `provisioning`, as the client reads it. func TestAHandedModulesAssignmentCarriesItsPlan(t *testing.T) { at := time.Date(2026, 10, 14, 20, 0, 0, 0, time.UTC) values, err := AssignmentValues([]AssignmentMirrored{{Node: "g14", Module: "dunst", Assigned: at}, {Node: "g14", Module: "zsh", Assigned: at}}, map[string]Provisioning{"g14.dunst": aPlan()}) if err != nil { t.Fatal(err) } var got AssignmentMirrored if err := json.Unmarshal(values["g14.dunst"], &got); err != nil { t.Fatal(err) } if got.Provisioning == nil || got.Provisioning.Files[0].Path != "/home/nox/.config/dunst/dunstrc" || got.Provisioning.Placement["dir:state"] != "/var/lib/dunst" { t.Fatalf("the plan is mirrored as %s", values["g14.dunst"]) } for _, field := range []string{`"templates":{"source":`, `"digest":"sha256:`, `"owner-at-runtime":"owned"`, `"template":"dunstrc"`, `"takes":"reload-on"`} { if !strings.Contains(string(values["g14.dunst"]), field) { t.Errorf("the plan's value lacks %s: %s", field, values["g14.dunst"]) } } if strings.Contains(string(values["g14.zsh"]), "provisioning") { t.Errorf("an assignment with no plan carries one: %s", values["g14.zsh"]) } } // **A plan the client would have to guess at is refused, by name**, and so is one for a module not assigned // there: nothing is written rather than something wrong. func TestAPlanWithAProblemIsRefusedByName(t *testing.T) { at := time.Now().UTC() assigned := []AssignmentMirrored{{Node: "g14", Module: "dunst", Assigned: at}} cases := map[string]func(*Provisioning){ "templates.digest": func(p *Provisioning) { p.Templates.Digest = "sha256:short" }, "templates.source": func(p *Provisioning) { p.Templates.Source = "" }, "files and items are empty": func(p *Provisioning) { p.Files = nil }, `collection "Shell"`: func(p *Provisioning) { p.Items = []ProvisionedItem{{Collection: "Shell", Template: "x"}} }, "collection a is contributed to twice": func(p *Provisioning) { p.Items = []ProvisionedItem{{Collection: "a", Template: "x"}, {Collection: "a", Template: "y"}} }, `items[0]: template "/x"`: func(p *Provisioning) { p.Items = []ProvisionedItem{{Collection: "a", Template: "/x"}} }, "collections[1]: a is named twice": func(p *Provisioning) { p.Collections = []ProvisionedCollection{{Name: "a"}, {Name: "a"}} }, "the comment of a holds a line break": func(p *Provisioning) { p.Collections = []ProvisionedCollection{{Name: "a", Comment: "#\n"}} }, "not a clean": func(p *Provisioning) { p.Files[0].Path = "relative/dunstrc" }, "inside the templates": func(p *Provisioning) { p.Files[0].Template = "../dunstrc" }, "owner-at-runtime": func(p *Provisioning) { p.Files[0].OwnerAtRuntime = "mine" }, "takes": func(p *Provisioning) { p.Files[0].Takes = "now" }, `placement "secret`: func(p *Provisioning) { p.Placement["secret:token"] = "x" }, `placement "dir:"`: func(p *Provisioning) { p.Placement["dir:"] = "x" }, "is named twice": func(p *Provisioning) { p.Files = append(p.Files, p.Files[0]) }, "not a resource id": func(p *Provisioning) { p.Files[0].ID = "Dunst RC" }, `secret "Token"`: func(p *Provisioning) { p.Secrets = []ProvisionedSecret{{Name: "Token"}} }, "secret token is named twice": func(p *Provisioning) { p.Secrets = []ProvisionedSecret{{Name: "token"}, {Name: "token"}} }, `secret token: path "rel/token"`: func(p *Provisioning) { p.Secrets = []ProvisionedSecret{{Name: "token", Path: "rel/token"}} }, "secret token: path /home/nox/.config/dunst/dunstrc is named twice": func(p *Provisioning) { p.Secrets = []ProvisionedSecret{{Name: "token", Path: "/home/nox/.config/dunst/dunstrc"}} }, } for want, spoil := range cases { p := aPlan() spoil(&p) _, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": p}) if err == nil || !strings.Contains(err.Error(), want) || !strings.Contains(err.Error(), "g14.dunst") { t.Errorf("%s: refused with %v", want, err) } } if _, err := AssignmentValues(assigned, map[string]Provisioning{"shanks.dunst": aPlan()}); err == nil || !strings.Contains(err.Error(), "shanks.dunst: a plan for a module not assigned there") { t.Errorf("a plan for a module not assigned there: %v", err) } } // **A plan names the module's own secrets its declaration names there** (design 57 V4, issue 647): each by name, and // a secret kept in a file of its own with that file's path; the vault hands a node's client a secret only when the // plan names it. Names, never a value. func TestAPlanNamesTheModulesSecretsAndNoValue(t *testing.T) { p := aPlan() p.Secrets = []ProvisionedSecret{{Name: "token"}, {Name: "db-password", Path: "/var/lib/dunst/db"}} values, err := AssignmentValues([]AssignmentMirrored{{Node: "g14", Module: "dunst", Assigned: time.Now().UTC()}}, map[string]Provisioning{"g14.dunst": p}) if err != nil { t.Fatal(err) } if want := `"secrets":[{"name":"token"},{"name":"db-password","path":"/var/lib/dunst/db"}]`; !strings.Contains( string(values["g14.dunst"]), want) { t.Errorf("the plan's value is %s, want it to carry %s", values["g14.dunst"], want) } plain := aPlan() values, err = AssignmentValues([]AssignmentMirrored{{Node: "g14", Module: "dunst", Assigned: time.Now().UTC()}}, map[string]Provisioning{"g14.dunst": plain}) if err != nil { t.Fatal(err) } if strings.Contains(string(values["g14.dunst"]), "secrets") { t.Errorf("a plan naming no secret says secrets: %s", values["g14.dunst"]) } } // **A contributor's plan may fill no file** (design 57 L1, issue 684): its item is its part on the node; and a // collector's names the collections its files read, the old namespaces' by their own names. func TestAPlanMayContributeAnItemAndNameItsCollections(t *testing.T) { p := aPlan() p.Files = nil p.Items = []ProvisionedItem{{Collection: "shell:zsh:normal", Template: "zsh"}} p.Collections = []ProvisionedCollection{{Name: "widgets", Comment: "#"}, {Name: "contribution:node-hotkeys:trigger"}} values, err := AssignmentValues([]AssignmentMirrored{{Node: "g14", Module: "prompt", Assigned: time.Now()}}, map[string]Provisioning{"g14.prompt": p}) if err != nil { t.Fatal(err) } var back AssignmentMirrored if err := json.Unmarshal(values["g14.prompt"], &back); err != nil || back.Provisioning == nil || len(back.Provisioning.Items) != 1 || len(back.Provisioning.Collections) != 2 { t.Fatalf("mirrored %s (%v)", values["g14.prompt"], err) } } // **A plan names the credentials of what the module requires that the vault keeps for it alone** (issue 757): each // by the name its files call it, its provision, its provider and its file; never a value. Read as strictly as the // rest of the plan. func TestAPlanNamesTheCredentialsIssuedForTheModuleAndNoValue(t *testing.T) { assigned := []AssignmentMirrored{{Node: "g14", Module: "dunst", Assigned: time.Now().UTC()}} good := ProvisionedCredential{Name: "gitea-read", Provision: "gitea-read", Provider: "novox", ProviderModule: "gitea", Path: "/var/lib/dunst/gitea-read.secret"} p := aPlan() p.Provisions = []ProvisionedCredential{good} values, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": p}) if err != nil { t.Fatal(err) } if want := `"provisions":[{"name":"gitea-read","provision":"gitea-read","provider":"novox",` + `"provider-module":"gitea","path":"/var/lib/dunst/gitea-read.secret"}]`; !strings.Contains(string(values["g14.dunst"]), want) { t.Errorf("the plan's value is %s, want it to carry %s", values["g14.dunst"], want) } plain, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": aPlan()}) if err != nil || strings.Contains(string(plain["g14.dunst"]), "provisions") { t.Errorf("a plan naming no credential says provisions: %s (%v)", plain["g14.dunst"], err) } for want, spoil := range map[string]func(*ProvisionedCredential){ `provision credential "Gitea Read"`: func(c *ProvisionedCredential) { c.Name = "Gitea Read" }, `provision ""`: func(c *ProvisionedCredential) { c.Provision = "" }, `provider "../ace"`: func(c *ProvisionedCredential) { c.Provider = "../ace" }, `path "rel"`: func(c *ProvisionedCredential) { c.Path = "rel" }, "is named twice": func(c *ProvisionedCredential) { c.Path = "/home/nox/.config/dunst/dunstrc" }, } { c := good spoil(&c) bad := aPlan() bad.Provisions = []ProvisionedCredential{c} if _, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": bad}); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("%s: refused with %v", want, err) } } twice := aPlan() twice.Secrets = []ProvisionedSecret{{Name: "gitea-read"}} twice.Provisions = []ProvisionedCredential{good} if _, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": twice}); err == nil || !strings.Contains(err.Error(), "secret gitea-read is named twice") { t.Errorf("a credential named as an own secret too: %v", err) } } // **A module only pulled in by another has a value of its own** (issue 765): where the machine runs a handed module // that nothing assigned there, its plan is mirrored under `.` like an assigned one's, saying which // module requires it and no time it was assigned. A plan for a module neither assigned nor required there is still // refused, and a module assigned there is mirrored as an assignment whatever else requires it. func TestAModulePulledInHasAValueOfItsOwnWithItsPlan(t *testing.T) { at := time.Date(2026, 10, 14, 20, 0, 0, 0, time.UTC) assigned := []AssignmentMirrored{{Node: "g14", Module: "zsh", Assigned: at}} pulled := aPlan() pulled.RequiredBy = "desk" both := aPlan() both.RequiredBy = "desk" values, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": pulled, "g14.zsh": both}) if err != nil { t.Fatal(err) } if got := string(values["g14.dunst"]); !strings.HasPrefix(got, `{"node":"g14","module":"dunst","required-by":"desk",`+ `"provisioning":{"templates":{"source":"artifacts/dunst/files.tar.gz",`) || strings.Contains(got, "assigned") { t.Errorf("a pulled-in module is mirrored as %s", got) } var got AssignmentMirrored if err := json.Unmarshal(values["g14.dunst"], &got); err != nil || got.Provisioning == nil || got.Provisioning.Files[0].Path != "/home/nox/.config/dunst/dunstrc" { t.Fatalf("the pulled-in module's plan is mirrored as %s (%v)", values["g14.dunst"], err) } if zsh := string(values["g14.zsh"]); !strings.HasPrefix(zsh, `{"node":"g14","module":"zsh","assigned":"2026-10-14T20:00:00Z",`+ `"provisioning":`) || strings.Contains(zsh, "required-by") { t.Errorf("an assigned module also required is mirrored as %s", zsh) } if len(values) != 2 { t.Errorf("the mirror holds %d values, want 2", len(values)) } spoilt := pulled spoilt.Templates.Digest = "sha256:short" if _, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": spoilt}); err == nil || !strings.Contains(err.Error(), "g14.dunst: templates.digest") { t.Errorf("a pulled-in module's spoilt plan: %v", err) } if _, err := AssignmentValues(assigned, map[string]Provisioning{"shanks.dunst": aPlan()}); err == nil || !strings.Contains(err.Error(), "shanks.dunst: a plan for a module not assigned there") { t.Errorf("a plan for a module neither assigned nor required there: %v", err) } } // **A plan names the provider serving each provision its module requires** (design 57 V5a, issue 760): machine, // module and local name, so the vault reading the mirror sees a bind and an unbind; an entry with no credential // to fill has no name and no file. Read as strictly as the rest of the plan. func TestAPlanNamesTheProviderOfEachProvision(t *testing.T) { assigned := []AssignmentMirrored{{Node: "g14", Module: "dunst", Assigned: time.Now().UTC()}} p := aPlan() p.Provisions = []ProvisionedCredential{ {Provision: "postgres-database", Provider: "novox", ProviderModule: "postgres"}, {Provision: "s3-bucket", Local: "hot", Provider: "ace", ProviderModule: "minio"}} values, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": p}) if err != nil { t.Fatal(err) } if want := `"provisions":[{"provision":"postgres-database","provider":"novox","provider-module":"postgres"},` + `{"provision":"s3-bucket","local":"hot","provider":"ace","provider-module":"minio"}]`; !strings.Contains( string(values["g14.dunst"]), want) { t.Errorf("the plan's value is %s, want it to carry %s", values["g14.dunst"], want) } for want, provisions := range map[string][]ProvisionedCredential{ `postgres-database: provider-module ""`: {{Provision: "postgres-database", Provider: "novox"}}, `postgres-database: provider ""`: {{Provision: "postgres-database", ProviderModule: "postgres"}}, "s3-bucket (hot): its provider is named twice": { {Provision: "s3-bucket", Local: "hot", Provider: "ace", ProviderModule: "minio"}, {Provision: "s3-bucket", Local: "hot", Provider: "novox", ProviderModule: "minio"}}, `postgres-database: path "/var/lib/dunst/db" names a file and no credential`: {{Provision: "postgres-database", Provider: "novox", ProviderModule: "postgres", Path: "/var/lib/dunst/db"}}, } { bad := aPlan() bad.Provisions = provisions if _, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": bad}); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("%s: refused with %v", want, err) } } } // The plan a composition makes (catalogue.Plan) is the plan the mirror carries, its provisions whole: kept with the // send as the one and read back as the other, nothing is dropped and nothing is unknown. func TestAComposedPlansProvisionsAreTheMirroredPlans(t *testing.T) { composed := catalogue.Plan{Templates: catalogue.PlanTemplates{Source: "s", Digest: "d"}, Provisions: []catalogue.PlanProvision{{Name: "db-hot", Provision: "postgres-database", Local: "hot", Provider: "novox", ProviderModule: "postgres", CredentialForm: catalogue.CredentialFormPair, Path: "/var/lib/x/hot"}}} raw, err := json.Marshal(composed) if err != nil { t.Fatal(err) } var mirrored Provisioning dec := json.NewDecoder(bytes.NewReader(raw)) dec.DisallowUnknownFields() if err := dec.Decode(&mirrored); err != nil { t.Fatal(err) } want := []ProvisionedCredential{{Name: "db-hot", Provision: "postgres-database", Local: "hot", Provider: "novox", ProviderModule: "postgres", CredentialForm: "pair", Path: "/var/lib/x/hot"}} if !reflect.DeepEqual(mirrored.Provisions, want) { t.Fatalf("the mirrored plan's provisions are %+v, want %+v", mirrored.Provisions, want) } } // **A plan names the credential form of each provider's offer** (issue 768), so the vault makes a first value in // that form for a provider it holds no row of: carried as written, and refused when it is not a form. func TestAPlanNamesTheCredentialFormOfEachProvidersOffer(t *testing.T) { assigned := []AssignmentMirrored{{Node: "g14", Module: "dunst", Assigned: time.Now().UTC()}} p := aPlan() p.Provisions = []ProvisionedCredential{ {Provision: "postgres-database", Provider: "novox", ProviderModule: "postgres", CredentialForm: "pair"}, {Provision: "sonarr-api", Provider: "ace", ProviderModule: "sonarr", CredentialForm: "shared"}} values, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": p}) if err != nil { t.Fatal(err) } if want := `{"provision":"postgres-database","provider":"novox","provider-module":"postgres",` + `"credential-form":"pair"},{"provision":"sonarr-api","provider":"ace","provider-module":"sonarr",` + `"credential-form":"shared"}`; !strings.Contains(string(values["g14.dunst"]), want) { t.Errorf("the plan's value is %s, want it to carry %s", values["g14.dunst"], want) } bad := aPlan() bad.Provisions = []ProvisionedCredential{{Provision: "postgres-database", Provider: "novox", ProviderModule: "postgres", CredentialForm: "one-for-all"}} if _, err := AssignmentValues(assigned, map[string]Provisioning{"g14.dunst": bad}); err == nil || !strings.Contains(err.Error(), `credential-form "one-for-all"`) { t.Errorf("a credential form that is not one was refused with %v", err) } } func TestAPlanMayHoldSeveralNamedItemsOfOneCollectionAndRefusesABadOne(t *testing.T) { p := aPlan() p.Items = []ProvisionedItem{ {Collection: "blocks", Name: "a", Attributes: map[string]string{"bar": "top"}, Template: "a"}, {Collection: "blocks", Name: "b", Template: "b"}} if problems := p.Problems(); len(problems) != 0 { t.Fatalf("a plan with two named items is refused: %v", problems) } p.Items = append(p.Items, ProvisionedItem{Collection: "blocks", Name: "b", Template: "c"}, ProvisionedItem{Collection: "blocks", Name: "c", Attributes: map[string]string{"Bar": "x y"}, Template: "d"}) got := strings.Join(p.Problems(), "; ") for _, want := range []string{"item blocks/b is contributed to twice", "attribute Bar"} { if !strings.Contains(got, want) { t.Errorf("the problems %q lack %q", got, want) } } }