validation

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 8, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package validation provides shared validation utilities for BubuStack resources.

This package contains validation helpers used by controllers and webhooks, including error aggregation, reason extraction, and JSON schema validation.

Error Aggregation

The Aggregator collects multiple validation errors for bulk status updates:

agg := validation.NewAggregator()
agg.AddFieldError("spec.steps[0].ref", conditions.ReasonEngramReferenceInvalid, "engram not found")
agg.AddFieldError("spec.steps[1].transport", conditions.ReasonTransportReferenceInvalid, "transport not found")
if agg.HasErrors() {
    return nil, agg.ToFieldErrors() // For webhooks
    // OR
    result := agg.ToValidationResult("success") // For controllers
}

Reason Errors

The WrapWithReason function attaches a structured reason to an error:

err := validation.WrapWithReason(conditions.ReasonTemplateNotFound, fmt.Errorf("template not found"))
reason := validation.ExtractReason(err) // Returns conditions.ReasonTemplateNotFound

JSON Schema Validation

The ValidateJSONSchema function validates that bytes represent valid JSON:

if err := validation.ValidateJSONSchema(schemaBytes); err != nil {
    return fmt.Errorf("invalid schema: %w", err)
}

This package is designed for use in admission webhooks and controller reconcile loops that need to collect and report multiple validation errors.

Package validation provides shared validation helpers for controllers and webhooks.

Package validation provides shared validation utilities used across the codebase.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExtractReason

func ExtractReason(err error) string

ExtractReason extracts the reason string from a validation error.

Behavior:

  • Returns the reason from *ReasonError if present.
  • Falls back to substring heuristics (engram/transport/story).
  • Defaults to conditions.ReasonReferenceNotFound when no signal is found.

Arguments:

  • err error: the validation error to analyze.

Returns:

  • string: the event reason string for Kubernetes events.

func ValidateJSONSchema

func ValidateJSONSchema(schemaBytes []byte) error

ValidateJSONSchema performs basic JSON schema validation by attempting to unmarshal the provided bytes as JSON, ensuring the schema is syntactically valid.

Arguments:

  • schemaBytes: raw JSON bytes representing a JSON schema.

Returns:

  • error: nil if the JSON is valid, or an error describing the validation failure.

func WrapWithReason

func WrapWithReason(reason string, err error) error

WrapWithReason attaches a structured reason to a validation error so event emitters can extract consistent Kubernetes event reasons.

Behavior:

  • Returns nil when err is nil (nil-safe).
  • Wraps the error with a reason that can be extracted via errors.As.
  • Preserves original error via Unwrap for errors.Is/errors.As chains.

Arguments:

  • reason string: the event reason to attach (e.g., conditions.ReasonEngramReferenceInvalid).
  • err error: the underlying validation error.

Returns:

  • error: nil when err is nil, otherwise a *ReasonError.

Types

type Aggregator

type Aggregator struct {
	// contains filtered or unexported fields
}

Aggregator collects multiple validation errors for bulk status updates.

Behavior:

  • Collects errors without stopping on the first failure.
  • Converts collected errors to field.ErrorList for webhook responses.
  • Converts collected errors to condition/status for controller status.
  • Thread-safe for single-goroutine use within a reconcile loop.

Usage (controller):

agg := validation.NewAggregator()
agg.AddFieldError("spec.steps[0].ref", conditions.ReasonEngramReferenceInvalid, "engram not found")
agg.AddFieldError("spec.steps[1].transport", conditions.ReasonTransportReferenceInvalid, "transport not found")
if agg.HasErrors() {
    status := agg.ToStatus()
}

Usage (webhook):

agg := validation.NewAggregator()
agg.AddFieldError("spec.steps[0].ref", conditions.ReasonEngramReferenceInvalid, "engram not found")
if agg.HasErrors() {
    return nil, agg.ToFieldErrors()
}

func NewAggregator

func NewAggregator() *Aggregator

NewAggregator creates a new validation error aggregator.

func (*Aggregator) Add

func (a *Aggregator) Add(err *ValidationError)

Add adds an existing ValidationError to the aggregator.

func (*Aggregator) AddError

func (a *Aggregator) AddError(err error)

AddError wraps a generic error and adds it to the aggregator.

Behavior:

  • Extracts reason from *ReasonError if present.
  • Falls back to ExtractReason heuristics if not.

func (*Aggregator) AddFieldError

func (a *Aggregator) AddFieldError(fieldName, reason, message string)

AddFieldError adds a validation error with field path, reason, and message.

func (*Aggregator) AddFieldErrorf

func (a *Aggregator) AddFieldErrorf(fieldName, reason, format string, args ...any)

AddFieldErrorf adds a validation error with formatted message.

func (*Aggregator) CombinedMessage

func (a *Aggregator) CombinedMessage() string

CombinedMessage returns all error messages joined by semicolons.

func (*Aggregator) Errors

func (a *Aggregator) Errors() []*ValidationError

Errors returns the collected validation errors.

func (*Aggregator) FirstError

func (a *Aggregator) FirstError() error

FirstError returns the first error, or nil if empty.

func (*Aggregator) FirstReason

func (a *Aggregator) FirstReason() string

FirstReason returns the reason of the first error, or ReasonReferenceNotFound if empty.

func (*Aggregator) HasErrors

func (a *Aggregator) HasErrors() bool

HasErrors returns true if any validation errors were collected.

func (*Aggregator) Messages

func (a *Aggregator) Messages() []string

Messages returns all error messages as a slice.

func (*Aggregator) ToFieldErrors

func (a *Aggregator) ToFieldErrors() field.ErrorList

ToFieldErrors converts collected errors to field.ErrorList for webhook responses.

Behavior:

  • Creates a field.Error for each ValidationError with Type=Invalid.
  • Uses the field path if provided, otherwise uses an empty path.

func (*Aggregator) ToValidationResult

func (a *Aggregator) ToValidationResult(successMessage string) *ValidationResult

ToValidationResult converts collected errors to a ValidationResult for status updates.

Behavior:

  • Returns Valid status when no errors.
  • Returns Invalid status with aggregated messages when errors exist.
  • Uses the first error's reason for the condition reason.

Arguments:

  • successMessage string: the message to use when validation passes.

type ReasonError

type ReasonError struct {
	// contains filtered or unexported fields
}

ReasonError wraps an error with a structured reason string so callers can emit consistent Kubernetes event reasons while preserving the original error.

Behavior:

  • Error() returns the underlying error message.
  • Unwrap() returns the underlying error for errors.Is/errors.As chains.
  • Reason() returns the structured reason string.

Usage:

err := validation.WrapWithReason(conditions.ReasonEngramReferenceInvalid, originalErr)
var reasonErr *validation.ReasonError
if errors.As(err, &reasonErr) {
    fmt.Println(reasonErr.Reason()) // "EngramReferenceInvalid"
}

func (*ReasonError) Error

func (e *ReasonError) Error() string

Error satisfies the error interface by returning the wrapped error's message.

func (*ReasonError) Reason

func (e *ReasonError) Reason() string

Reason returns the structured reason string for Kubernetes events.

func (*ReasonError) Unwrap

func (e *ReasonError) Unwrap() error

Unwrap returns the underlying error for errors.Is/errors.As traversal.

type ValidationError

type ValidationError struct {
	// Field is the path to the invalid field (e.g., "spec.steps[3].ref").
	Field string

	// Reason is the event reason code (e.g., conditions.ReasonEngramReferenceInvalid).
	Reason string

	// Message is the human-readable error message.
	Message string

	// Err is the underlying error (may be nil).
	Err error
}

ValidationError represents a single validation error with field path and reason.

Behavior:

  • Captures the field path (e.g., "spec.steps[3].ref") for precise error location.
  • Includes a structured reason for Kubernetes events.
  • Provides a human-readable message for users.

func (*ValidationError) Error

func (e *ValidationError) Error() string

Error implements the error interface.

func (*ValidationError) Unwrap

func (e *ValidationError) Unwrap() error

Unwrap returns the underlying error for errors.Is/errors.As.

type ValidationResult

type ValidationResult struct {
	// ValidationStatus is Valid when no errors, Invalid otherwise.
	ValidationStatus enums.ValidationStatus

	// ValidationErrors contains all error messages.
	ValidationErrors []string

	// ConditionStatus is the status for the Ready condition.
	ConditionStatus metav1.ConditionStatus

	// ConditionReason is the reason for the Ready condition.
	ConditionReason string

	// ConditionMessage is the message for the Ready condition.
	ConditionMessage string
}

ValidationResult holds the outcome of validation for controller status updates.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL