diff --git a/internal/manifest/validate.go b/internal/manifest/validate.go index af1d34db5..547a82da5 100644 --- a/internal/manifest/validate.go +++ b/internal/manifest/validate.go @@ -1,9 +1,11 @@ package manifest import ( + "bytes" + "errors" "fmt" - "github.com/go-playground/validator/v10" + "strings" ) // Validate validates the parsed manifest data. @@ -42,3 +44,48 @@ func (m *Manifest) Validate() error { return nil } + +type validationErrors []error + +func (v validationErrors) Error() string { + buffer := bytes.NewBufferString("") + + for _, e := range v { + buffer.WriteString(e.Error()) + buffer.WriteString("; ") + } + + return strings.TrimSpace(buffer.String()) +} + +func prettyPrintValidationError(err error) error { + var validationErr validator.ValidationErrors + errors.As(err, &validationErr) + + if validationErr == nil { + return err + } + + var out validationErrors + for _, err := range validationErr { + var nerr error + switch err.Tag() { + case "max": + nerr = fmt.Errorf("field '%s' must have a maximum length of %s", err.StructField(), err.Param()) + case "min": + nerr = fmt.Errorf("field '%s' must have a minimum length of %s", err.StructField(), err.Param()) + case "len": + nerr = fmt.Errorf("field '%s' must have exact length of %s", err.StructField(), err.Param()) + case "required": + nerr = fmt.Errorf("field '%s' is required to be defined", err.StructField()) + case "ip_addr": + nerr = fmt.Errorf("field '%s' is required to have a valid IPv4 address value", err.StructField()) + case "cidrv4": + nerr = fmt.Errorf("field '%s' is required to have a valid CIDRv4 value", err.StructField()) + case "ver": + nerr = fmt.Errorf("field '%s' is required to have a kubernetes version of: 1.27.x, 1.28.x, 1.29.x", err.StructField()) + } + out = append(out, nerr) + } + return out +} diff --git a/internal/manifest/validate_kubernetes.go b/internal/manifest/validate_kubernetes.go index fda3f8664..69d75afe6 100644 --- a/internal/manifest/validate_kubernetes.go +++ b/internal/manifest/validate_kubernetes.go @@ -1,7 +1,6 @@ package manifest import ( - "errors" "fmt" "regexp" "strings" @@ -33,15 +32,6 @@ func (k *Kubernetes) Validate(m *Manifest) error { for _, cluster := range k.Clusters { if err := cluster.Validate(); err != nil { - var ve validator.ValidationErrors - if errors.As(err, &ve) { - for _, fe := range ve { - if fe.Tag() == "ver" { - errMsg := "incorrect Kubernetes version, the supported versions are: 1.25.x, 1.26.x, 1.27.x" - return fmt.Errorf("failed to validate kubernetes cluster %s:%s", cluster.Name, errMsg) - } - } - } return fmt.Errorf("failed to validate kubernetes cluster %s: %w", cluster.Name, err) } @@ -71,7 +61,10 @@ func (c *Cluster) Validate() error { return err } - return validate.Struct(c) + if err := validate.Struct(c); err != nil { + return prettyPrintValidationError(err) + } + return nil } func validateVersion(fl validator.FieldLevel) bool { diff --git a/internal/manifest/validate_load_balancer.go b/internal/manifest/validate_load_balancer.go index da7e2f740..9bb203e5f 100644 --- a/internal/manifest/validate_load_balancer.go +++ b/internal/manifest/validate_load_balancer.go @@ -176,8 +176,19 @@ func (l *LoadBalancer) Validate(m *Manifest) error { return nil } -func (r *Role) Validate() error { return validator.New().Struct(r) } -func (c *LoadBalancerCluster) Validate() error { return validator.New().Struct(c) } +func (r *Role) Validate() error { + if err := validator.New().Struct(r); err != nil { + return prettyPrintValidationError(err) + } + return nil +} + +func (c *LoadBalancerCluster) Validate() error { + if err := validator.New().Struct(c); err != nil { + return prettyPrintValidationError(err) + } + return nil +} func validateLBStaticNodePool(m *Manifest, clusters []LoadBalancerCluster) error { for _, cluster := range clusters { diff --git a/internal/manifest/validate_node_pool.go b/internal/manifest/validate_node_pool.go index 3bf49fa6e..8008ca36c 100644 --- a/internal/manifest/validate_node_pool.go +++ b/internal/manifest/validate_node_pool.go @@ -140,10 +140,18 @@ func (d *DynamicNodePool) Validate(m *Manifest) error { } }, DynamicNodePool{}) - return validate.Struct(d) + if err := validate.Struct(d); err != nil { + return prettyPrintValidationError(err) + } + return nil } -func (s *StaticNodePool) Validate() error { return validator.New().Struct(s) } +func (s *StaticNodePool) Validate() error { + if err := validator.New().Struct(s); err != nil { + return prettyPrintValidationError(err) + } + return nil +} func (a *AutoscalerConfig) isDefined() bool { return a.Min >= 0 && a.Max > 0 } diff --git a/manifests/claudie/kustomization.yaml b/manifests/claudie/kustomization.yaml index af4ec584a..1e16270d3 100644 --- a/manifests/claudie/kustomization.yaml +++ b/manifests/claudie/kustomization.yaml @@ -58,20 +58,20 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: - name: ghcr.io/berops/claudie/ansibler - newTag: 5a44806-2799 + newTag: 43f201d-2805 - name: ghcr.io/berops/claudie/autoscaler-adapter newTag: 688726a-1932 - name: ghcr.io/berops/claudie/builder - newTag: 5a44806-2799 + newTag: 43f201d-2805 - name: ghcr.io/berops/claudie/claudie-operator - newTag: 5a44806-2799 + newTag: 43f201d-2805 - name: ghcr.io/berops/claudie/context-box - newTag: 5a44806-2799 + newTag: 43f201d-2805 - name: ghcr.io/berops/claudie/kube-eleven - newTag: 5a44806-2799 + newTag: 43f201d-2805 - name: ghcr.io/berops/claudie/kuber - newTag: 5a44806-2799 + newTag: 43f201d-2805 - name: ghcr.io/berops/claudie/scheduler - newTag: 5a44806-2799 + newTag: 43f201d-2805 - name: ghcr.io/berops/claudie/terraformer - newTag: 5a44806-2799 + newTag: 43f201d-2805 diff --git a/manifests/testing-framework/kustomization.yaml b/manifests/testing-framework/kustomization.yaml index 75dd3eeba..cf90079b9 100644 --- a/manifests/testing-framework/kustomization.yaml +++ b/manifests/testing-framework/kustomization.yaml @@ -37,4 +37,4 @@ secretGenerator: images: - name: ghcr.io/berops/claudie/testing-framework - newTag: 5a44806-2799 + newTag: 43f201d-2805