package pipeline import "fmt" type ProducerStructuralFailureAction string const ( ProducerStructuralFailureFailRun ProducerStructuralFailureAction = "fail_run" ProducerStructuralFailureRejectOutput ProducerStructuralFailureAction = "reject_output" ) type SemanticRejectionAction string const ( SemanticRejectionFailRun SemanticRejectionAction = "fail_run" SemanticRejectionRejectOutput SemanticRejectionAction = "reject_output" ) type ValidatorFailureAction string const ( ValidatorFailureWarnContinue ValidatorFailureAction = "warn_continue" ValidatorFailureFailRun ValidatorFailureAction = "fail_run" ) // ValidationPolicyOverride records only explicitly configured terminal-policy // values. Nil fields inherit independently from the pipeline or application. type ValidationPolicyOverride struct { ProducerStructuralFailure *ProducerStructuralFailureAction `json:"producer_structural_failure,omitempty"` SemanticRejection *SemanticRejectionAction `json:"semantic_rejection,omitempty"` ValidatorFailure *ValidatorFailureAction `json:"validator_failure,omitempty"` } // ValidationPolicy is the concrete terminal policy retained by each resolved // producer. It contains no inherited pointers. type ValidationPolicy struct { ProducerStructuralFailure ProducerStructuralFailureAction `json:"producer_structural_failure"` SemanticRejection SemanticRejectionAction `json:"semantic_rejection"` ValidatorFailure ValidatorFailureAction `json:"validator_failure"` } func DefaultValidationPolicy() ValidationPolicy { return ValidationPolicy{ ProducerStructuralFailure: ProducerStructuralFailureFailRun, SemanticRejection: SemanticRejectionFailRun, ValidatorFailure: ValidatorFailureWarnContinue, } } func (override ValidationPolicyOverride) Validate() error { if override.ProducerStructuralFailure != nil { switch *override.ProducerStructuralFailure { case ProducerStructuralFailureFailRun, ProducerStructuralFailureRejectOutput: default: return fmt.Errorf("producer_structural_failure must be fail_run or reject_output") } } if override.SemanticRejection != nil { switch *override.SemanticRejection { case SemanticRejectionFailRun, SemanticRejectionRejectOutput: default: return fmt.Errorf("semantic_rejection must be fail_run or reject_output") } } if override.ValidatorFailure != nil { switch *override.ValidatorFailure { case ValidatorFailureWarnContinue, ValidatorFailureFailRun: default: return fmt.Errorf("validator_failure must be warn_continue or fail_run") } } return nil } func ResolveValidationPolicy(binding, pipeline *ValidationPolicyOverride) ValidationPolicy { resolved := DefaultValidationPolicy() applyValidationPolicyOverride(&resolved, pipeline) applyValidationPolicyOverride(&resolved, binding) return resolved } func cloneValidationPolicyOverride(override *ValidationPolicyOverride) *ValidationPolicyOverride { if override == nil { return nil } out := *override if override.ProducerStructuralFailure != nil { value := *override.ProducerStructuralFailure out.ProducerStructuralFailure = &value } if override.SemanticRejection != nil { value := *override.SemanticRejection out.SemanticRejection = &value } if override.ValidatorFailure != nil { value := *override.ValidatorFailure out.ValidatorFailure = &value } return &out } func applyValidationPolicyOverride(policy *ValidationPolicy, override *ValidationPolicyOverride) { if override == nil { return } if override.ProducerStructuralFailure != nil { policy.ProducerStructuralFailure = *override.ProducerStructuralFailure } if override.SemanticRejection != nil { policy.SemanticRejection = *override.SemanticRejection } if override.ValidatorFailure != nil { policy.ValidatorFailure = *override.ValidatorFailure } }