validation

package
v0.19.0 Latest Latest
Warning

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

Go to latest
Published: Feb 29, 2024 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package validation implements tools to validate data objects.

These might be used from the CLI and/or the controller.

This package shoul not, under any circumtance, include specific validation logic. Only the tools to operate that logic should live here.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsRemediable

func IsRemediable(err error) bool

IsRemediable checks if an error has a remediation.

func NewRemediableErr

func NewRemediableErr(err, remediation string) error

NewRemediableErr returns a new Remediable error.

func Remediation

func Remediation(err error) string

Remediation returns the Remediation message for an error if it has it. Otherwise it returns an empty string.

func WithRemediation

func WithRemediation(err error, remediation string) error

WithRemediation makes an error Remediable.

Types

type Remediable

type Remediable interface {
	Remediation() string
}

Remediable is an error that provides a possible remediation.

type Runner

type Runner[O Validatable[O]] struct {
	// contains filtered or unexported fields
}

Runner allows to compose and run validations.

func NewRunner

func NewRunner[O Validatable[O]](opts ...RunnerOpt) *Runner[O]

NewRunner constructs a new Runner.

func (*Runner[O]) Register

func (r *Runner[O]) Register(validations ...Validation[O])

Register adds validations to the Runner.

func (*Runner[O]) RunAll

func (r *Runner[O]) RunAll(ctx context.Context, obj O) errors.Aggregate

RunAll runs all validations concurrently and waits until they all finish, aggregating the errors if present. obj must not be modified. If it is, this indicates a programming error and the method will panic.

Example (Validations)
package main

import (
	"context"
	"errors"
	"fmt"

	"github.com/go-logr/logr"

	"github.com/aws/eks-anywhere/internal/test"
	anywherev1 "github.com/aws/eks-anywhere/pkg/api/v1alpha1"
	"github.com/aws/eks-anywhere/pkg/cli"
	"github.com/aws/eks-anywhere/pkg/cluster"
	eksaerrors "github.com/aws/eks-anywhere/pkg/errors"
	"github.com/aws/eks-anywhere/pkg/validation"
)

func main() {
	log := test.NewNullLogger()
	r := validation.NewRunner[*cluster.Spec](validation.WithMaxJobs(10))
	cpValidator := newControlPlaneValidator(log)

	r.Register(
		func(ctx context.Context, spec *cluster.Spec) error {
			if spec.Cluster.Spec.KubernetesVersion == "" {
				return errors.New("kubernetesVersion can't be empty")
			}

			return nil
		},
		validation.Sequentially(
			func(ctx context.Context, spec *cluster.Spec) error {
				if spec.Cluster.Name == "" {
					return validation.WithRemediation(
						errors.New("cluster name is empty"),
						"set a name for your cluster",
					)
				}

				return nil
			},
			cpValidator.validateCount,
		),
	)

	ctx := context.Background()
	spec := test.NewClusterSpec(func(s *cluster.Spec) {
		s.Cluster.Name = ""
		s.Cluster.Spec.KubernetesVersion = anywherev1.Kube124
		s.Cluster.Spec.ControlPlaneConfiguration.Count = 0
	})
	agg := r.RunAll(ctx, spec)
	if agg != nil {
		printErrors(agg)
		return
	}

	fmt.Println("Cluster config is valid")

}

func printErrors(agg eksaerrors.Aggregate) {
	fmt.Println("Invalid cluster config")
	for _, err := range agg.Errors() {
		msg := "- " + err.Error()
		if validation.IsRemediable(err) {
			msg += ". Try to " + validation.Remediation(err)
		}
		fmt.Println(msg)
	}
}

type controlPlaneValidator struct {
	log logr.Logger
}

func newControlPlaneValidator(log logr.Logger) *controlPlaneValidator {
	return &controlPlaneValidator{log: log}
}

func (v *controlPlaneValidator) validateCount(ctx context.Context, spec *cluster.Spec) error {
	if spec.Cluster.Spec.ControlPlaneConfiguration.Count == 0 {
		cli.ValidationFailed(v.log, "Control plane invalid")
		return errors.New("control plane node count can't be 0")
	}

	cli.ValidationPassed(v.log, "Control plane valid")
	return nil
}
Output:

Invalid cluster config
- cluster name is empty. Try to set a name for your cluster
- control plane node count can't be 0

type RunnerConfig

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

RunnerConfig contains the configuration for a Runner.

type RunnerOpt

type RunnerOpt func(*RunnerConfig)

RunnerOpt allows to configure a Runner with optional parameters.

func WithMaxJobs

func WithMaxJobs(m int) RunnerOpt

WithMaxJobs sets the maximun number of concurrent routines the runner will use.

type Validatable

type Validatable[O any] interface {
	DeepCopy() O
}

Validatable is anything that can be validated.

type Validation

type Validation[O Validatable[O]] func(ctx context.Context, obj O) error

Validation is the logic for a validation of a type O.

func Sequentially

func Sequentially[O Validatable[O]](validations ...Validation[O]) Validation[O]

Sequentially composes a set of validations into one which will run them sequentially and in order.

Jump to

Keyboard shortcuts

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