ci: publish templates to the control panel on main #1
No files matched your search
@@ -21,6 +21,10 @@ const bootTestNetwork = "gbr-boottest"
|
|||||||
var publicPort = regexp.MustCompile(`\{PUBLIC_PORT_(\d+)\}`)
|
var publicPort = regexp.MustCompile(`\{PUBLIC_PORT_(\d+)\}`)
|
||||||
var savedValue = regexp.MustCompile(`\{saved:[A-Za-z0-9_.-]+\}`)
|
var savedValue = regexp.MustCompile(`\{saved:[A-Za-z0-9_.-]+\}`)
|
||||||
|
|
||||||
|
// Narrower than the validator's sensitiveKey: that one also matches settings like RCON_PORT, which
|
||||||
|
// are fine to flag as "don't put secrets here" but must never be overwritten with a password.
|
||||||
|
var passwordKey = regexp.MustCompile(`(?i)(pass(word)?|secret|token)`)
|
||||||
|
|
||||||
// runBootTestPayload writes the DEPLOY_SERVER message the panel would send for this game, plus the
|
// runBootTestPayload writes the DEPLOY_SERVER message the panel would send for this game, plus the
|
||||||
// boot-test settings the node-agent's BootTest reads. Secrets come from environment variables named
|
// boot-test settings the node-agent's BootTest reads. Secrets come from environment variables named
|
||||||
// in test.yaml's 'secrets'.
|
// in test.yaml's 'secrets'.
|
||||||
@@ -71,10 +75,12 @@ func runBootTestPayload(args []string) error {
|
|||||||
// 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
|
||||||
for key, p := range schemaProperties(g) {
|
for key, p := range schemaProperties(g) {
|
||||||
prop, _ := p.(map[string]any)
|
prop, _ := p.(map[string]any)
|
||||||
if prop["x-generate"] != nil || sensitiveKey.MatchString(key) {
|
if prop["x-generate"] == nil && !passwordKey.MatchString(key) {
|
||||||
if s, _ := config[key].(string); s == "" {
|
continue
|
||||||
config[key] = "boot-" + randomSuffix()
|
}
|
||||||
}
|
// Only missing or empty text: ports, booleans and other values are never touched
|
||||||
|
if v, present := config[key]; !present || v == "" {
|
||||||
|
config[key] = "boot-" + randomSuffix()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for k, v := range config {
|
for k, v := range config {
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBootTestPayloadOnlyFillsBlankPasswords(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
game := filepath.Join(dir, "games", "demo")
|
||||||
|
if err := os.MkdirAll(game, 0o755); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
os.WriteFile(filepath.Join(game, "game.yaml"), []byte(`id: demo
|
||||||
|
name: Demo
|
||||||
|
defaultDockerImage: debian:12
|
||||||
|
installMethod: NONE
|
||||||
|
defaultConfig:
|
||||||
|
RCON_PORT: 25575
|
||||||
|
ENABLE_RCON: true
|
||||||
|
RCON_PASSWORD: ""
|
||||||
|
ServerPassword: ""
|
||||||
|
AdminPassword: kept-by-owner
|
||||||
|
MOTD: "{SERVER_NAME} on {PUBLIC_PORT_25565}"
|
||||||
|
configSchema:
|
||||||
|
properties:
|
||||||
|
RCON_PORT: {type: integer}
|
||||||
|
ENABLE_RCON: {type: boolean}
|
||||||
|
RCON_PASSWORD: {type: string, x-generate: {type: password}}
|
||||||
|
ServerPassword: {type: string}
|
||||||
|
AdminPassword: {type: string}
|
||||||
|
MOTD: {type: string}
|
||||||
|
`), 0o644)
|
||||||
|
|
||||||
|
out := filepath.Join(dir, "payload.json")
|
||||||
|
if err := runBootTestPayload([]string{"-games", filepath.Join(dir, "games"), "-out", out, "demo"}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
raw, _ := os.ReadFile(out)
|
||||||
|
var payload struct{ GameConfig map[string]any }
|
||||||
|
if err := json.Unmarshal(raw, &payload); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
c := payload.GameConfig
|
||||||
|
|
||||||
|
if c["RCON_PORT"] != float64(25575) {
|
||||||
|
t.Errorf("RCON_PORT changed to %v", c["RCON_PORT"])
|
||||||
|
}
|
||||||
|
if c["ENABLE_RCON"] != true {
|
||||||
|
t.Errorf("ENABLE_RCON changed to %v", c["ENABLE_RCON"])
|
||||||
|
}
|
||||||
|
for _, k := range []string{"RCON_PASSWORD", "ServerPassword"} {
|
||||||
|
if s, _ := c[k].(string); !strings.HasPrefix(s, "boot-") {
|
||||||
|
t.Errorf("%s not filled: %v", k, c[k])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c["AdminPassword"] != "kept-by-owner" {
|
||||||
|
t.Errorf("AdminPassword overwritten: %v", c["AdminPassword"])
|
||||||
|
}
|
||||||
|
if c["MOTD"] != "gbr-boot-test on 25565" {
|
||||||
|
t.Errorf("placeholders not resolved: %v", c["MOTD"])
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user