Files
browser/platform/validator/control.go
T

92 lines
3.7 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 appendCapacityViolations(violations []string, capacity domain.RunCapacity) []string {
if capacity.MaxJobs < 0 || capacity.RunningJobs < 0 || capacity.QueuedJobs < 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")
}
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
}
}