Complete SCUM controlled deployment lifecycle
This commit is contained in:
@@ -1757,7 +1757,7 @@ func validPluginRunCapability(capability string) bool {
|
||||
domain.JobCapabilityRemoteRunDBMySQLQuery, domain.JobCapabilityRemoteRunDBSQLiteQuery,
|
||||
domain.JobCapabilityRemoteRunLogsTransfer, domain.JobCapabilityRemoteRunRCONCommand,
|
||||
domain.JobCapabilityRunSelfUpdate, domain.JobCapabilityDependenciesCheck, domain.JobCapabilityDependenciesInstall,
|
||||
domain.JobCapabilityDeploymentPlan, domain.JobCapabilityDeploymentShellPosix, domain.JobCapabilityDeploymentShellPowerShell, domain.JobCapabilityDeploymentShellCmd,
|
||||
domain.JobCapabilityDeploymentPlan, domain.JobCapabilitySCUMDeploymentPlan, domain.JobCapabilityDeploymentShellPosix, domain.JobCapabilityDeploymentShellPowerShell, domain.JobCapabilityDeploymentShellCmd,
|
||||
domain.JobCapabilityClientManagerDeploy, domain.JobCapabilityClientManagerControl, domain.JobCapabilityClientManagerUpdate,
|
||||
domain.JobCapabilityClientManagerRollback, domain.JobCapabilityClientManagerUninstall,
|
||||
"artifacts.read", "artifacts.write", "artifact.read", "artifact.write",
|
||||
|
||||
@@ -29,6 +29,7 @@ func ValidateGamePluginRuntimeProfiles(profiles domain.GamePluginRuntimeProfiles
|
||||
discoveryKeys := map[string]struct{}{}
|
||||
dependencyKeys := map[string]struct{}{}
|
||||
installPlanKeys := map[string]struct{}{}
|
||||
serverDeploymentKeys := map[string]struct{}{}
|
||||
logSourceKeys := map[string]struct{}{}
|
||||
logSourceRetentions := map[string]int{}
|
||||
logEventKeys := map[string]struct{}{}
|
||||
@@ -150,6 +151,76 @@ func ValidateGamePluginRuntimeProfiles(profiles domain.GamePluginRuntimeProfiles
|
||||
}
|
||||
violations = append(violations, validateRuntimePlatforms(prefix+".platforms", plan.Platforms)...)
|
||||
}
|
||||
for i, profile := range profiles.ServerDeployments {
|
||||
prefix := fmt.Sprintf("runtimeProfiles.serverDeployments[%d]", i)
|
||||
violations = append(violations, validateProfileKey(prefix+".key", profile.Key)...)
|
||||
violations = append(violations, recordRuntimeProfileKey(serverDeploymentKeys, prefix+".key", profile.Key)...)
|
||||
if !validSemanticVersion(profile.Version) {
|
||||
violations = append(violations, prefix+".version must be semantic")
|
||||
}
|
||||
if !regexp.MustCompile(`^[0-9]{1,12}$`).MatchString(profile.SteamAppID) {
|
||||
violations = append(violations, prefix+".steamAppId must be numeric")
|
||||
}
|
||||
for field, value := range map[string]string{"executableKey": profile.ExecutableKey, "installRootKey": profile.InstallRootKey, "configKey": profile.ConfigKey} {
|
||||
violations = append(violations, validateProfileKey(prefix+"."+field, value)...)
|
||||
}
|
||||
if profile.ConfigFormat != "ini" && profile.ConfigFormat != "json" && profile.ConfigFormat != "yaml" && profile.ConfigFormat != "properties" {
|
||||
violations = append(violations, prefix+".configFormat is invalid")
|
||||
}
|
||||
if len(profile.SupportedTargets) == 0 {
|
||||
violations = append(violations, prefix+".supportedTargets must not be empty")
|
||||
}
|
||||
for j, target := range profile.SupportedTargets {
|
||||
if !validPluginSupportedOS(target.OS) || !oneOf(target.Arch, "amd64", "arm64") {
|
||||
violations = append(violations, fmt.Sprintf("%s.supportedTargets[%d] is invalid", prefix, j))
|
||||
}
|
||||
}
|
||||
mappingKeys := map[string]struct{}{}
|
||||
for j, mapping := range profile.ConfigMappings {
|
||||
mappingPrefix := fmt.Sprintf("%s.configMappings[%d]", prefix, j)
|
||||
if !regexp.MustCompile(`^[A-Za-z][A-Za-z0-9._/-]{0,79}$`).MatchString(mapping.FieldKey) {
|
||||
violations = append(violations, mappingPrefix+".fieldKey is invalid")
|
||||
}
|
||||
violations = append(violations, validateProfileKey(mappingPrefix+".configKey", mapping.ConfigKey)...)
|
||||
if _, exists := mappingKeys[mapping.FieldKey]; exists {
|
||||
violations = append(violations, mappingPrefix+".fieldKey duplicates another mapping")
|
||||
}
|
||||
mappingKeys[mapping.FieldKey] = struct{}{}
|
||||
if !oneOf(mapping.ValueType, "text", "integer", "number", "boolean", "port") {
|
||||
violations = append(violations, mappingPrefix+".valueType is invalid")
|
||||
}
|
||||
}
|
||||
markerKeys := map[string]struct{}{}
|
||||
for j, marker := range profile.DiscoveryMarkers {
|
||||
markerPrefix := fmt.Sprintf("%s.discoveryMarkers[%d]", prefix, j)
|
||||
violations = append(violations, validateProfileKey(markerPrefix+".key", marker.Key)...)
|
||||
violations = append(violations, validateProfileKey(markerPrefix+".targetKey", marker.TargetKey)...)
|
||||
if _, exists := markerKeys[marker.Key]; exists {
|
||||
violations = append(violations, markerPrefix+".key duplicates another marker")
|
||||
}
|
||||
markerKeys[marker.Key] = struct{}{}
|
||||
if !oneOf(marker.Kind, "file.exists", "command.version", "port.open", "steam.app") {
|
||||
violations = append(violations, markerPrefix+".kind is invalid")
|
||||
}
|
||||
violations = append(violations, validateSafeRuntimeValue(markerPrefix+".expected", marker.Expected)...)
|
||||
}
|
||||
checkKeys := map[string]struct{}{}
|
||||
for j, check := range profile.VerificationChecks {
|
||||
checkPrefix := fmt.Sprintf("%s.verificationChecks[%d]", prefix, j)
|
||||
violations = append(violations, validateProfileKey(checkPrefix+".key", check.Key)...)
|
||||
violations = append(violations, validateProfileKey(checkPrefix+".targetKey", check.TargetKey)...)
|
||||
if _, exists := checkKeys[check.Key]; exists {
|
||||
violations = append(violations, checkPrefix+".key duplicates another check")
|
||||
}
|
||||
checkKeys[check.Key] = struct{}{}
|
||||
if !oneOf(check.Kind, "executable.present", "version.matches", "port.bound", "config.readable", "process.healthy") {
|
||||
violations = append(violations, checkPrefix+".kind is invalid")
|
||||
}
|
||||
}
|
||||
if len(profile.VerificationChecks) == 0 || !containsRequiredVerification(profile.VerificationChecks) {
|
||||
violations = append(violations, prefix+".verificationChecks must include executable, config, port, and process checks")
|
||||
}
|
||||
}
|
||||
for i, source := range profiles.LogSources {
|
||||
prefix := fmt.Sprintf("runtimeProfiles.logSources[%d]", i)
|
||||
violations = append(violations, validateProfileKey(prefix+".key", source.Key)...)
|
||||
@@ -396,6 +467,23 @@ func ValidateGamePluginRuntimeProfiles(profiles domain.GamePluginRuntimeProfiles
|
||||
return finish(violations)
|
||||
}
|
||||
|
||||
func containsRequiredVerification(checks []domain.RuntimeServerVerificationCheck) bool {
|
||||
required := map[string]bool{"executable.present": false, "version.matches": false, "port.bound": false, "config.readable": false, "process.healthy": false}
|
||||
for _, check := range checks {
|
||||
if check.Required {
|
||||
if _, ok := required[check.Kind]; ok {
|
||||
required[check.Kind] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, present := range required {
|
||||
if !present {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func validateRuntimeDLLExtensionProfile(prefix string, extension domain.RuntimeDLLExtensionProfile) []string {
|
||||
var violations []string
|
||||
if extension.Kind != "ue4ss-dll" || extension.Activation != "server-start" {
|
||||
|
||||
Reference in New Issue
Block a user