diff --git a/cmd/gbrgames/boottest.go b/cmd/gbrgames/boottest.go index 7ad80b4..6fdaadc 100644 --- a/cmd/gbrgames/boottest.go +++ b/cmd/gbrgames/boottest.go @@ -32,6 +32,8 @@ func runBootTestPayload(args []string) error { fs := flag.NewFlagSet("boottest-payload", flag.ExitOnError) gamesDir := fs.String("games", "games", "directory holding one folder per game") out := fs.String("out", "", "file to write (default stdout)") + asDeployed := fs.Bool("as-deployed", false, "settings exactly as a new server gets them: only x-generate fields filled, "+ + "no throwaway passwords (the AI builder boots drafts this way)") fs.Parse(args) if fs.NArg() != 1 { return errors.New("boottest-payload needs a game id") @@ -72,10 +74,11 @@ func runBootTestPayload(args []string) error { } } // Like the panel fills blank x-generate fields on deploy; other blank passwords (which an owner - // would type in, and some games refuse to start without) get a throwaway value too + // would type in, and some games refuse to start without) get a throwaway value too, except + // -as-deployed: a draft must start with exactly what a new server gets for key, p := range schemaProperties(g) { prop, _ := p.(map[string]any) - if prop["x-generate"] == nil && !passwordKey.MatchString(key) { + if prop["x-generate"] == nil && (*asDeployed || !passwordKey.MatchString(key)) { continue } // Only missing or empty text: ports, booleans and other values are never touched diff --git a/cmd/gbrgames/boottest_test.go b/cmd/gbrgames/boottest_test.go index 21e6fb9..4890028 100644 --- a/cmd/gbrgames/boottest_test.go +++ b/cmd/gbrgames/boottest_test.go @@ -63,4 +63,20 @@ configSchema: if c["MOTD"] != "gbr-boot-test on 25565" { t.Errorf("placeholders not resolved: %v", c["MOTD"]) } + + // As a new server gets it (what the AI builder boots): only x-generate is filled, a blank join password stays blank + if err := runBootTestPayload([]string{"-as-deployed", "-games", filepath.Join(dir, "games"), "-out", out, "demo"}); err != nil { + t.Fatal(err) + } + raw, _ = os.ReadFile(out) + payload.GameConfig = nil + if err := json.Unmarshal(raw, &payload); err != nil { + t.Fatal(err) + } + if s, _ := payload.GameConfig["RCON_PASSWORD"].(string); !strings.HasPrefix(s, "boot-") { + t.Errorf("as deployed: x-generate RCON_PASSWORD not filled: %v", payload.GameConfig["RCON_PASSWORD"]) + } + if payload.GameConfig["ServerPassword"] != "" { + t.Errorf("as deployed: ServerPassword should stay empty, got %v", payload.GameConfig["ServerPassword"]) + } } diff --git a/cmd/gbrgames/build.go b/cmd/gbrgames/build.go index fd81ae8..fd26077 100644 --- a/cmd/gbrgames/build.go +++ b/cmd/gbrgames/build.go @@ -240,7 +240,7 @@ func bootCheck(gamesDir, id, agentImage string, wantOutside bool) (problems, ver // and the next deploy under the same name would trip over them runCmd("docker", "rm", "-f", "boottest-"+id) runCmd("docker", "volume", "rm", "-f", "boottest-"+id+"-data") - payloadCmd := exec.Command(self, "boottest-payload", "-games", gamesDir, id) + payloadCmd := exec.Command(self, "boottest-payload", "-as-deployed", "-games", gamesDir, id) var stderr bytes.Buffer payloadCmd.Stderr = &stderr payload, err := payloadCmd.Output() @@ -310,7 +310,9 @@ func bootFailure(output string) string { lines = append(lines[:1], lines[len(lines)-59:]...) } return "booting your template with the node-agent (the real deploy code) failed: " + verdict + - ". Find the cause in the server's output below and fix the template (startup command, settings, " + + ". It was started with your defaults exactly as a new server gets them: settings left empty stay empty " + + "(only x-generate fields are filled), so a server that needs a value must get it from a default or " + + "x-generate. Find the cause in the server's output below and fix the template (startup command, settings, " + "ready pattern, memory):\n" + strings.Join(lines, "\n") }