Files
DoGaMa-serv/internal/instance/configuration_resolver_test.go
T
codex 35c11aff6d
CI / validate (pull_request) Successful in 26m22s
feat(vrising): support template runtime requirements
2026-08-25 22:32:15 +02:00

120 lines
5.3 KiB
Go

package instance_test
import (
"os"
"path/filepath"
"strings"
"testing"
catalogdata "git.zaynet.fr/DoGaMa/DoGaMa-serv/catalog"
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/catalog"
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/instance"
)
func TestResolveConfigurationTargets(t *testing.T) {
template := catalog.Template{}
template.Container.Environment = map[string]string{"STATIC": "kept"}
template.Configuration.Fields = []catalog.ConfigField{
{ID: "name", Type: "string", Target: catalog.ConfigTarget{Kind: "environment", Name: "SERVER_NAME"}},
{ID: "count", Type: "integer", Target: catalog.ConfigTarget{Kind: "argument", Name: "--count"}},
{ID: "public", Type: "boolean", Target: catalog.ConfigTarget{Kind: "argument", Name: "--public"}},
{ID: "private", Type: "boolean", Target: catalog.ConfigTarget{Kind: "argument", Name: "--private={{value}}"}},
{ID: "password", Type: "secret", Target: catalog.ConfigTarget{Kind: "ini", Mount: "saved", File: "Config/server.ini", Section: "server", Key: "password"}},
}
resolved, err := instance.ResolveConfiguration(template, map[string]string{"name": "My server", "count": "4", "public": "true", "private": "false", "password": "secret"})
if err != nil {
t.Fatal(err)
}
if resolved.Environment["STATIC"] != "kept" || resolved.Environment["SERVER_NAME"] != "My server" {
t.Fatalf("environment = %#v", resolved.Environment)
}
if got := strings.Join(resolved.Arguments, " "); got != "--count=4 --public --private=false" {
t.Fatalf("arguments = %q", got)
}
if len(resolved.INI) != 1 || resolved.INI[0].Value != "" || resolved.INI[0].SecretID != "password" {
t.Fatalf("secret leaked in resolved config: %#v", resolved.INI)
}
template.Configuration.Fields[0].Target.Kind = "unknown"
if _, err := instance.ResolveConfiguration(template, map[string]string{"name": "x"}); err == nil {
t.Fatal("unknown target accepted")
}
}
func TestEnvironmentValuesRemainExactAndOptionalValuesAreOmitted(t *testing.T) {
template := catalog.Template{}
template.Configuration.Fields = []catalog.ConfigField{
{ID: "port", Type: "integer", Target: catalog.ConfigTarget{Kind: "environment", Name: "GAME_PORT"}},
{ID: "enabled", Type: "boolean", Target: catalog.ConfigTarget{Kind: "environment", Name: "ENABLED"}},
{ID: "optional", Type: "string", Target: catalog.ConfigTarget{Kind: "environment", Name: "OPTIONAL"}},
}
resolved, err := instance.ResolveConfiguration(template, map[string]string{"port": "9876", "enabled": "true", "optional": ""})
if err != nil {
t.Fatal(err)
}
if resolved.Environment["GAME_PORT"] != "9876" || resolved.Environment["ENABLED"] != "true" {
t.Fatalf("environment values were rewritten: %#v", resolved.Environment)
}
if _, ok := resolved.Environment["OPTIONAL"]; ok {
t.Fatalf("empty optional environment was emitted: %#v", resolved.Environment)
}
for key, value := range resolved.Environment {
if strings.HasPrefix(value, "= ") || strings.HasPrefix(value, "=") {
t.Fatalf("synthetic environment prefix for %s: %q", key, value)
}
}
}
func TestPalworldServerNameIsWrittenBeforeStart(t *testing.T) {
snapshots, err := catalog.LoadFS(catalogdata.Files, ".")
if err != nil {
t.Fatal(err)
}
snapshot := snapshotByID(t, snapshots, "palworld-official")
values, err := instance.ValidateConfiguration(snapshot.Template.Configuration.Fields, map[string]string{"server_name": "Mon serveur", "server_description": "x", "max_players": "8", "rest_api_enabled": "true", "rest_api_port": "8212"}, map[string]string{"admin_password": "secret"})
if err != nil {
t.Fatal(err)
}
values["admin_password"] = "secret" // marker only; resolver does not retain it.
resolved, err := instance.ResolveConfiguration(snapshot.Template, values)
if err != nil {
t.Fatal(err)
}
root := t.TempDir()
if err := instance.ApplyINI([]instance.MountBinding{{ID: "saved", HostPath: root}}, resolved.INI, map[string]string{"admin_password": "secret"}); err != nil {
t.Fatal(err)
}
body, err := os.ReadFile(filepath.Join(root, "Config", "LinuxServer", "PalWorldSettings.ini"))
if err != nil {
t.Fatal(err)
}
if !strings.Contains(string(body), "ServerName=Mon serveur") {
t.Fatalf("Palworld configuration not effective: %s", body)
}
}
func TestApplyINIPreservesContentAndRejectsTraversal(t *testing.T) {
root := t.TempDir()
path := filepath.Join(root, "Config", "server.ini")
if err := os.MkdirAll(filepath.Dir(path), 0o770); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(path, []byte("[other]\nkeep=yes\n\n[server]\nold=value\n"), 0o660); err != nil {
t.Fatal(err)
}
mounts := []instance.MountBinding{{ID: "saved", HostPath: root}}
mutations := []instance.INIMutation{{Mount: "saved", File: "Config/server.ini", Section: "server", Key: "name", Value: "Mon serveur"}, {Mount: "saved", File: "Config/server.ini", Section: "server", Key: "old", Value: "new"}}
if err := instance.ApplyINI(mounts, mutations, nil); err != nil {
t.Fatal(err)
}
body, _ := os.ReadFile(path)
got := string(body)
for _, want := range []string{"[other]", "keep=yes", "old=new", "name=Mon serveur"} {
if !strings.Contains(got, want) {
t.Fatalf("INI missing %q: %s", want, got)
}
}
if err := instance.ApplyINI(mounts, []instance.INIMutation{{Mount: "saved", File: "../escape.ini", Section: "x", Key: "x", Value: "x"}}, nil); err == nil {
t.Fatal("path traversal accepted")
}
}