215 lines
5.5 KiB
Go
215 lines
5.5 KiB
Go
package provision
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
|
|
"zlh-agent/internal/provision/addons"
|
|
"zlh-agent/internal/provision/devcontainer"
|
|
"zlh-agent/internal/provision/minecraft"
|
|
"zlh-agent/internal/provision/steam"
|
|
"zlh-agent/internal/state"
|
|
)
|
|
|
|
/*
|
|
ProvisionAll — unified entrypoint for provisioning.
|
|
IMPORTANT:
|
|
- This function ONLY performs installation.
|
|
- Validation/verification happens in ensureProvisioned().
|
|
- state.Config is treated as immutable desired state.
|
|
*/
|
|
func ProvisionAll(cfg state.Config) error {
|
|
normalizeMinecraftConfig(&cfg)
|
|
|
|
/* ---------------------------------------------------------
|
|
BASE ROLE PROVISIONING
|
|
--------------------------------------------------------- */
|
|
if cfg.ContainerType == "dev" {
|
|
|
|
if err := devcontainer.Provision(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
} else {
|
|
|
|
// Legacy / default behavior assumes game containers
|
|
game := strings.ToLower(cfg.Game)
|
|
variant := strings.ToLower(cfg.Variant)
|
|
runtime := strings.ToLower(cfg.Runtime)
|
|
|
|
/* ---------------------------------------------------------
|
|
MINECRAFT
|
|
--------------------------------------------------------- */
|
|
if game == "minecraft" {
|
|
|
|
// 1. Install Java (runtime)
|
|
if err := InstallJava(cfg); err != nil {
|
|
return fmt.Errorf("java install failed: %w", err)
|
|
}
|
|
|
|
// 2. Game variant install
|
|
switch variant {
|
|
case "vanilla":
|
|
if runtime != "fabric" {
|
|
return fmt.Errorf("unsupported runtime: %s", cfg.Runtime)
|
|
}
|
|
if err := minecraft.InstallFabric(cfg); err != nil {
|
|
return err
|
|
}
|
|
if err := minecraft.InjectFabricProxyLite(cfg); err != nil {
|
|
return fmt.Errorf("fabricproxy-lite injection failed: %w", err)
|
|
}
|
|
|
|
case "fabric":
|
|
if err := minecraft.InstallFabric(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
case "paper", "purpur", "quilt":
|
|
if err := minecraft.InstallMinecraftJar(cfg); err != nil {
|
|
return fmt.Errorf("minecraft jar install failed: %w", err)
|
|
}
|
|
|
|
case "forge":
|
|
if err := minecraft.InstallMinecraftForge(cfg); err != nil {
|
|
return fmt.Errorf("forge install failed: %w", err)
|
|
}
|
|
|
|
case "neoforge":
|
|
if err := minecraft.InstallMinecraftNeoForge(cfg); err != nil {
|
|
return fmt.Errorf("neoforge install failed: %w", err)
|
|
}
|
|
|
|
default:
|
|
return fmt.Errorf("unsupported minecraft variant: %s", variant)
|
|
}
|
|
|
|
// 3. Config files generated AFTER variant installer
|
|
if err := WriteEula(cfg); err != nil {
|
|
return err
|
|
}
|
|
if err := WriteServerProperties(cfg); err != nil {
|
|
return err
|
|
}
|
|
if err := WriteStartScript(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
} else if IsSteamGame(game) {
|
|
|
|
/* ---------------------------------------------------------
|
|
STEAM GAMES
|
|
--------------------------------------------------------- */
|
|
|
|
// 1. SteamCMD install
|
|
if err := steam.EnsureSteamCMD(); err != nil {
|
|
return fmt.Errorf("steamcmd install failed: %w", err)
|
|
}
|
|
|
|
// 2. Install game-specific content
|
|
switch game {
|
|
|
|
case "valheim":
|
|
if err := steam.InstallValheim(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
case "rust":
|
|
if err := steam.InstallRust(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
case "terraria":
|
|
if err := steam.InstallTerraria(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
case "projectzomboid":
|
|
if err := steam.InstallProjectZomboid(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
default:
|
|
return fmt.Errorf("unsupported steam game: %s", game)
|
|
}
|
|
|
|
// 3. Start script
|
|
if err := WriteStartScript(cfg); err != nil {
|
|
return err
|
|
}
|
|
|
|
} else {
|
|
return fmt.Errorf(
|
|
"unsupported container identity (containerType=%q game=%q)",
|
|
cfg.ContainerType,
|
|
cfg.Game,
|
|
)
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------
|
|
ADDONS (OPTIONAL, ROLE-AGNOSTIC)
|
|
--------------------------------------------------------- */
|
|
if strings.EqualFold(cfg.ContainerType, "dev") && CodeServerRequested(cfg) {
|
|
seen := false
|
|
for _, addon := range cfg.Addons {
|
|
if strings.EqualFold(addon, "codeserver") {
|
|
seen = true
|
|
break
|
|
}
|
|
}
|
|
if !seen {
|
|
cfg.Addons = append(cfg.Addons, "codeserver")
|
|
}
|
|
}
|
|
|
|
if len(cfg.Addons) > 0 {
|
|
if err := addons.Provision(cfg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func CodeServerRequested(cfg state.Config) bool {
|
|
if cfg.EnableCodeServer {
|
|
return true
|
|
}
|
|
for _, addon := range cfg.Addons {
|
|
if strings.EqualFold(addon, "codeserver") {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func normalizeMinecraftConfig(cfg *state.Config) {
|
|
if cfg == nil {
|
|
return
|
|
}
|
|
if !strings.EqualFold(cfg.ContainerType, "game") {
|
|
return
|
|
}
|
|
if !strings.EqualFold(cfg.Game, "minecraft") {
|
|
return
|
|
}
|
|
variant := strings.ToLower(strings.TrimSpace(cfg.Variant))
|
|
switch variant {
|
|
case "vanilla":
|
|
cfg.Runtime = "fabric"
|
|
cfg.InternalProfile = "vanilla-fabric"
|
|
cfg.ArtifactPath = fmt.Sprintf("minecraft/fabric/%s/server.jar", strings.TrimSpace(cfg.Version))
|
|
log.Printf("[provision] vmid=%d action=normalize original_variant=vanilla runtime=fabric profile=vanilla-fabric", cfg.VMID)
|
|
log.Printf("[provision] vmid=%d variant=vanilla normalized_runtime=fabric", cfg.VMID)
|
|
log.Printf("[provision] vmid=%d artifact_override=true source=fabric path=%s", cfg.VMID, cfg.ArtifactPath)
|
|
case "fabric":
|
|
cfg.Runtime = "fabric"
|
|
cfg.InternalProfile = ""
|
|
cfg.ArtifactPath = fmt.Sprintf("minecraft/fabric/%s/server.jar", strings.TrimSpace(cfg.Version))
|
|
log.Printf("[provision] vmid=%d action=normalize variant=fabric runtime=fabric profile=none", cfg.VMID)
|
|
log.Printf("[provision] vmid=%d artifact_override=true source=fabric path=%s", cfg.VMID, cfg.ArtifactPath)
|
|
}
|
|
}
|