diff --git a/internal/deploymentconfig/config.go b/internal/deploymentconfig/config.go index 0569f6f..88b174b 100644 --- a/internal/deploymentconfig/config.go +++ b/internal/deploymentconfig/config.go @@ -325,66 +325,72 @@ func rejectUnknownKeys(table map[string]any, parent string, allowed ...string) e // 它依次校验 daemon.environment、backend.systemctl_path 的绝对路径约束,再按 backend.type // 分支精确校验原生或容器槽位的 unit、jar、container_name、health_endpoint 等字段。 func (c Config) Validate() error { - switch c.Daemon.Environment { - case EnvironmentDev, EnvironmentProd: - default: + if c.Daemon.Environment != EnvironmentDev && c.Daemon.Environment != EnvironmentProd { return fmt.Errorf("daemon.environment must be %q or %q", EnvironmentDev, EnvironmentProd) } if err := validateAbsolutePath("backend.systemctl_path", c.Backend.SystemctlPath); err != nil { return err } - if c.Backend.StopGraceSeconds != nil && *c.Backend.StopGraceSeconds <= 0 { + if err := validateBackend(c.Backend); err != nil { + return err + } + return validateNodeSsr(c.NodeSsr) +} + +func validateBackend(backend Backend) error { + if backend.StopGraceSeconds != nil && *backend.StopGraceSeconds <= 0 { return errors.New("backend.stop_grace_seconds must be a positive integer") } - switch c.Backend.Type { + switch backend.Type { case BackendTypeNative: - if c.Backend.Slot.Port8080.ContainerName != "" || c.Backend.Slot.Port8081.ContainerName != "" { + if backend.Slot.Port8080.ContainerName != "" || backend.Slot.Port8081.ContainerName != "" { return errors.New("native backend slots do not accept container_name") } - if c.Backend.ReleaseDir != nativeReleaseDir { + if backend.ReleaseDir != nativeReleaseDir { return fmt.Errorf("backend.release_dir must be %q", nativeReleaseDir) } - if c.Backend.ActiveJAR != nativeActiveJAR { + if backend.ActiveJAR != nativeActiveJAR { return fmt.Errorf("backend.active_jar must be %q", nativeActiveJAR) } - if err := validateNativeSlot("backend.slot.8080", c.Backend.Slot.Port8080, nativeUnit8080, nativeSlotJAR8080, nativeHealthURL8080); err != nil { - return err - } - if err := validateNativeSlot("backend.slot.8081", c.Backend.Slot.Port8081, nativeUnit8081, nativeSlotJAR8081, nativeHealthURL8081); err != nil { - return err - } + return validateNativeBackendSlots(backend.Slot) case BackendTypeContainer: - if c.Backend.ReleaseDir != "" || c.Backend.ActiveJAR != "" { + if backend.ReleaseDir != "" || backend.ActiveJAR != "" { return errors.New("container backend does not accept release_dir or active_jar") } - if c.Backend.Slot.Port8080.Unit != "" || c.Backend.Slot.Port8080.JAR != "" || c.Backend.Slot.Port8081.Unit != "" || c.Backend.Slot.Port8081.JAR != "" { + if backend.Slot.Port8080.Unit != "" || backend.Slot.Port8080.JAR != "" || backend.Slot.Port8081.Unit != "" || backend.Slot.Port8081.JAR != "" { return errors.New("container backend slots do not accept unit or jar") } - if err := validateContainerSlot("backend.slot.8080", c.Backend.Slot.Port8080, containerName8080, nativeHealthURL8080); err != nil { - return err - } - if err := validateContainerSlot("backend.slot.8081", c.Backend.Slot.Port8081, containerName8081, nativeHealthURL8081); err != nil { + if err := validateContainerSlot("backend.slot.8080", backend.Slot.Port8080, containerName8080, nativeHealthURL8080); err != nil { return err } + return validateContainerSlot("backend.slot.8081", backend.Slot.Port8081, containerName8081, nativeHealthURL8081) default: return fmt.Errorf("backend.type must be %q or %q", BackendTypeNative, BackendTypeContainer) } - if c.NodeSsr.Type == "" { + +} + +func validateNativeBackendSlots(slots BackendSlots) error { + if err := validateNativeSlot("backend.slot.8080", slots.Port8080, nativeUnit8080, nativeSlotJAR8080, nativeHealthURL8080); err != nil { + return err + } + return validateNativeSlot("backend.slot.8081", slots.Port8081, nativeUnit8081, nativeSlotJAR8081, nativeHealthURL8081) +} + +func validateNodeSsr(node NodeSsr) error { + if node.Type == "" { return nil } - if c.NodeSsr.Type != BackendTypeContainer { + if node.Type != BackendTypeContainer { return fmt.Errorf("nodeSsr.type must be %q", BackendTypeContainer) } - if c.NodeSsr.StopGraceSeconds != nil && *c.NodeSsr.StopGraceSeconds <= 0 { + if node.StopGraceSeconds != nil && *node.StopGraceSeconds <= 0 { return errors.New("nodeSsr.stop_grace_seconds must be a positive integer") } - if err := validateNodeSsrSlot("nodeSsr.slot.18910", c.NodeSsr.Slot.Port18910, nodeSsrContainerName18910, nodeSsrHealthURL18910); err != nil { + if err := validateNodeSsrSlot("nodeSsr.slot.18910", node.Slot.Port18910, nodeSsrContainerName18910, nodeSsrHealthURL18910); err != nil { return err } - if err := validateNodeSsrSlot("nodeSsr.slot.28910", c.NodeSsr.Slot.Port28910, nodeSsrContainerName28910, nodeSsrHealthURL28910); err != nil { - return err - } - return nil + return validateNodeSsrSlot("nodeSsr.slot.28910", node.Slot.Port28910, nodeSsrContainerName28910, nodeSsrHealthURL28910) } // SlotForNodeSsrPort 返回 Node SSR 宿主端口对应的槽位配置。