package resolution import ( "strings" "testing" mcat "git.novox.be/novox/mesh-sdk/go/catalogue" ) const oldBackupText = "# lines\n${contribution:node-backup:backup}" const oldDataText = "# data\n${contribution:node-backup:data}" const placedBackupTxt = "# lines\n${backup:lines}" const placedDataTxt = "# data\n${backup:data}" const backupHolder = `{"module":"restic","version":"1","moved":true,"claims":[{"name":"node-backup","scope":"node"}], "build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]}, "resources":[{"id":"declared","type":"file","path":"/etc/backups.conf","template":"files/backups"}, {"id":"data-declared","type":"file","path":"/etc/data.conf","template":"files/data"}]}` func dataModule(name string) string { return `{"module":"` + name + `","version":"1","resources":[{"id":"d","type":"directory","mode":"0700"}], "data":{"own":[{"id":"d","path":"${dir:d}","class":"irreplaceable","why":"the ` + name + ` data"}]}}` } // backupsOn is a machine of a holder whose files say these texts and the modules that declare data. func backupsOn(t *testing.T, lines, data string, modules ...string) mcat.Resolution { t.Helper() all := []mcat.Manifest{held(t, backupHolder, builtWith("restic", map[string]string{"backups": lines, "data": data}))} names := []string{"restic"} for _, name := range modules { all = append(all, mustParse(t, dataModule(name))) names = append(names, name) } r, err := Resolve(shelf(all...), names, workstation(), mcat.World{}) if err != nil { t.Fatal(err) } r.Account = "op" return r } var backupModules = []string{"alpha", "beta", "gamma"} // gammaLeftOut is a machine whose gamma does not place: its lines are kept, best effort. func gammaLeftOut(with mcat.Rendering) mcat.Rendering { with.NotPlaced = map[string]string{"gamma": "its placement setting does not read"} return with } func TestTheBackupPlacementIsTheTextTheOldPlaceholdersRender(t *testing.T) { // The old form is an unmoved holder: its placeholders are the controller's alone. oldHolder := strings.Replace(backupHolder, `"moved":true,`, "", 1) all := []mcat.Manifest{held(t, oldHolder, builtWith("restic", map[string]string{"backups": oldBackupText, "data": oldDataText}))} for _, name := range backupModules { all = append(all, mustParse(t, dataModule(name))) } old, err := Resolve(shelf(all...), append([]string{"restic"}, backupModules...), workstation(), mcat.World{}) if err != nil { t.Fatal(err) } old.Account = "op" wantLines, wantData := fileOf(t, old, gammaLeftOut(mcat.Rendering{}), "restic.declared"), fileOf(t, old, gammaLeftOut(mcat.Rendering{}), "restic.data-declared") if !strings.Contains(wantLines, "# alpha\npath ") || !strings.Contains(wantLines, "# gamma\n") || !strings.Contains(wantData, "item d") { t.Fatalf("the old form renders\n%s\n%s", wantLines, wantData) } moved := backupsOn(t, placedBackupTxt, placedDataTxt, backupModules...) // Not handed: the controller fills the new placeholders with the old text. if got := fileOf(t, moved, gammaLeftOut(mcat.Rendering{}), "restic.declared"); got != wantLines { t.Errorf("not handed, the lines are\n%s\nwant\n%s", got, wantLines) } if got := fileOf(t, moved, gammaLeftOut(mcat.Rendering{}), "restic.data-declared"); got != wantData { t.Errorf("not handed, the data is\n%s\nwant\n%s", got, wantData) } // Handed: the plan carries the same text as placement, and the files are the client's. c, _ := composeWith(t, moved, gammaLeftOut(handingTo("store:5000"))) p := c.Plans["restic"].Placement if got := "# lines\n" + p["backup:lines"]; got != wantLines { t.Errorf("handed, the plan's lines are\n%s\nwant\n%s", got, wantLines) } if got := "# data\n" + p["backup:data"]; got != wantData { t.Errorf("handed, the plan's data is\n%s\nwant\n%s", got, wantData) } if len(p) != 2 { t.Errorf("the plan's placement is %v", p) } } func TestAnUnknownBackupKeyIsRefused(t *testing.T) { r := backupsOn(t, "${backup:rows}", placedDataTxt, backupModules...) if _, err := Compose(r, handingTo("store:5000")); err == nil || !strings.Contains(err.Error(), "backup:rows") { t.Errorf("handed, an unknown key is %v", err) } if _, err := Declaration(r, mcat.Rendering{}); err == nil || !strings.Contains(err.Error(), "backup:rows") { t.Errorf("not handed, an unknown key is %v", err) } } func fileOf(t *testing.T, r mcat.Resolution, with mcat.Rendering, id string) string { t.Helper() out, err := Declaration(r, with) if err != nil { t.Fatal(err) } for _, res := range out { if res["id"] == id { return res["content"].(string) } } t.Fatalf("%s was not composed", id) return "" }