104 lines
4.4 KiB
Go
104 lines
4.4 KiB
Go
package validator
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"browser.local/platform/domain"
|
|
)
|
|
|
|
func ValidateRunControlHello(hello domain.RunControlHello) error {
|
|
var violations []string
|
|
violations = appendRequired(violations, "registrationToken", hello.RegistrationToken)
|
|
violations = appendRequired(violations, "runEndpointId", hello.RunEndpointID)
|
|
violations = appendRequired(violations, "displayName", hello.DisplayName)
|
|
violations = appendRequired(violations, "version", hello.Version)
|
|
if hello.Architecture != "" {
|
|
if !validDistributionTargetOS(hello.Platform) {
|
|
violations = append(violations, "platform is invalid")
|
|
}
|
|
if !validDistributionTargetArch(hello.Architecture) {
|
|
violations = append(violations, "architecture is invalid")
|
|
}
|
|
}
|
|
if (hello.UpdateJobID == "") != (hello.UpdateOutcome == "") {
|
|
violations = append(violations, "updateJobId and updateOutcome must be provided together")
|
|
}
|
|
if hello.UpdateOutcome != "" && hello.UpdateOutcome != "succeeded" && hello.UpdateOutcome != "rolled-back" {
|
|
violations = append(violations, "updateOutcome is invalid")
|
|
}
|
|
violations = appendRequired(violations, "capabilityReport.fingerprint", hello.CapabilityReport.Fingerprint)
|
|
if hello.ServerInstanceID != "" || hello.PluginID != "" || hello.ComponentKind != "" || hello.ComponentKey != "" || hello.KeyGeneration != 0 {
|
|
violations = appendRequired(violations, "serverInstanceId", hello.ServerInstanceID)
|
|
violations = appendRequired(violations, "pluginId", hello.PluginID)
|
|
if hello.ComponentKind != domain.DistributionComponentRun && hello.ComponentKind != domain.DistributionComponentClientManager {
|
|
violations = append(violations, "componentKind is invalid")
|
|
}
|
|
if hello.KeyGeneration <= 0 {
|
|
violations = append(violations, "keyGeneration must be positive")
|
|
}
|
|
}
|
|
if !validRunControlStatus(hello.Status) {
|
|
violations = append(violations, "status is invalid")
|
|
}
|
|
violations = appendCapacityViolations(violations, hello.Capacity)
|
|
violations = appendCapabilitiesViolations(violations, "capabilityReport.capabilities", hello.CapabilityReport.Capabilities)
|
|
return finish(violations)
|
|
}
|
|
|
|
func ValidateRunControlHeartbeat(heartbeat domain.RunControlHeartbeat) error {
|
|
var violations []string
|
|
violations = appendRequired(violations, "runEndpointId", heartbeat.RunEndpointID)
|
|
violations = appendRequired(violations, "sessionToken", heartbeat.SessionToken)
|
|
violations = appendRequired(violations, "version", heartbeat.Version)
|
|
violations = appendRequired(violations, "capabilityFingerprint", heartbeat.CapabilityFingerprint)
|
|
if !validRunControlStatus(heartbeat.Status) {
|
|
violations = append(violations, "status is invalid")
|
|
}
|
|
violations = appendCapacityViolations(violations, heartbeat.Capacity)
|
|
return finish(violations)
|
|
}
|
|
|
|
func ValidateRunControlStreamRequest(request domain.RunControlStreamRequest) error {
|
|
var violations []string
|
|
violations = appendRequired(violations, "runEndpointId", request.RunEndpointID)
|
|
violations = appendRequired(violations, "sessionToken", request.SessionToken)
|
|
return finish(violations)
|
|
}
|
|
|
|
func appendCapacityViolations(violations []string, capacity domain.RunCapacity) []string {
|
|
if capacity.MaxJobs < 0 || capacity.RunningJobs < 0 || capacity.QueuedJobs < 0 || capacity.LogBacklogBatches < 0 || capacity.ArtifactBacklogChunks < 0 {
|
|
violations = append(violations, "capacity counts must not be negative")
|
|
}
|
|
if capacity.MaxJobs > 0 && capacity.RunningJobs > capacity.MaxJobs {
|
|
violations = append(violations, "runningJobs must not exceed maxJobs")
|
|
}
|
|
for i, code := range capacity.PressureCodes {
|
|
if strings.TrimSpace(code) == "" || strings.ContainsAny(code, " \t\r\n") || containsUnsafeRuntimeSecret(code) || looksLikeRawHostPath(code) {
|
|
violations = append(violations, fmt.Sprintf("pressureCodes[%d] is invalid", i))
|
|
}
|
|
}
|
|
return violations
|
|
}
|
|
|
|
func appendCapabilitiesViolations(violations []string, field string, capabilities []string) []string {
|
|
if len(capabilities) == 0 {
|
|
violations = append(violations, field+" must not be empty")
|
|
}
|
|
for i, capability := range capabilities {
|
|
if strings.TrimSpace(capability) == "" {
|
|
violations = append(violations, fmt.Sprintf("%s[%d] is required", field, i))
|
|
}
|
|
}
|
|
return violations
|
|
}
|
|
|
|
func validRunControlStatus(status domain.RunEndpointStatus) bool {
|
|
switch status {
|
|
case domain.RunEndpointStatusOnline, domain.RunEndpointStatusDegraded, domain.RunEndpointStatusOffline:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|