github.com/kotalco/kotal@v0.3.0/apis/ethereum2/v1alpha1/beacon_node_validation_webhook.go (about)

     1  package v1alpha1
     2  
     3  import (
     4  	"fmt"
     5  
     6  	apierrors "k8s.io/apimachinery/pkg/api/errors"
     7  	runtime "k8s.io/apimachinery/pkg/runtime"
     8  	"k8s.io/apimachinery/pkg/runtime/schema"
     9  	"k8s.io/apimachinery/pkg/util/validation/field"
    10  	"sigs.k8s.io/controller-runtime/pkg/webhook"
    11  	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
    12  )
    13  
    14  // +kubebuilder:webhook:verbs=create;update,path=/validate-ethereum2-kotal-io-v1alpha1-beaconnode,mutating=false,failurePolicy=fail,groups=ethereum2.kotal.io,resources=beaconnodes,versions=v1alpha1,name=validate-ethereum2-v1alpha1-beaconnode.kb.io,sideEffects=None,admissionReviewVersions=v1
    15  
    16  var _ webhook.Validator = &BeaconNode{}
    17  
    18  // validate is the shared validate create and update logic
    19  func (r *BeaconNode) validate() field.ErrorList {
    20  	var nodeErrors field.ErrorList
    21  
    22  	path := field.NewPath("spec")
    23  
    24  	// rest is supported by all clients except prysm
    25  	if r.Spec.REST && r.Spec.Client == PrysmClient {
    26  		err := field.Invalid(path.Child("rest"), r.Spec.REST, fmt.Sprintf("not supported by %s client", r.Spec.Client))
    27  		nodeErrors = append(nodeErrors, err)
    28  	}
    29  
    30  	// rpc is supported by prysm only
    31  	if r.Spec.RPC && r.Spec.Client != PrysmClient {
    32  		err := field.Invalid(path.Child("rpc"), r.Spec.RPC, fmt.Sprintf("not supported by %s client", r.Spec.Client))
    33  		nodeErrors = append(nodeErrors, err)
    34  	}
    35  
    36  	// validate verbosity level support
    37  	if !r.Spec.Client.SupportsVerbosityLevel(r.Spec.Logging, false) {
    38  		err := field.Invalid(path.Child("logging"), r.Spec.Logging, fmt.Sprintf("not supported by %s client", r.Spec.Client))
    39  		nodeErrors = append(nodeErrors, err)
    40  	}
    41  
    42  	// grpc is supported by prysm only
    43  	if r.Spec.GRPC && r.Spec.Client != PrysmClient {
    44  		err := field.Invalid(path.Child("grpc"), r.Spec.GRPC, fmt.Sprintf("not supported by %s client", r.Spec.Client))
    45  		nodeErrors = append(nodeErrors, err)
    46  	}
    47  
    48  	// validate cert secret name is supported by prysm only
    49  	if r.Spec.CertSecretName != "" && r.Spec.Client != PrysmClient {
    50  		err := field.Invalid(path.Child("certSecretName"), r.Spec.CertSecretName, fmt.Sprintf("not supported by %s client", r.Spec.Client))
    51  		nodeErrors = append(nodeErrors, err)
    52  	}
    53  
    54  	// rpc is always on in prysm
    55  	if r.Spec.Client == PrysmClient && !r.Spec.RPC {
    56  		err := field.Invalid(path.Child("rpc"), r.Spec.RPC, "can't be disabled in prysm client")
    57  		nodeErrors = append(nodeErrors, err)
    58  	}
    59  
    60  	return nodeErrors
    61  }
    62  
    63  // ValidateCreate implements webhook.Validator so a webhook will be registered for the type
    64  func (r *BeaconNode) ValidateCreate() (admission.Warnings, error) {
    65  	var allErrors field.ErrorList
    66  
    67  	nodelog.Info("validate create", "name", r.Name)
    68  
    69  	allErrors = append(allErrors, r.validate()...)
    70  	allErrors = append(allErrors, r.Spec.Resources.ValidateCreate()...)
    71  
    72  	if len(allErrors) == 0 {
    73  		return nil, nil
    74  	}
    75  
    76  	return nil, apierrors.NewInvalid(schema.GroupKind{}, r.Name, allErrors)
    77  
    78  }
    79  
    80  // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
    81  func (r *BeaconNode) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
    82  	var allErrors field.ErrorList
    83  	oldNode := old.(*BeaconNode)
    84  	path := field.NewPath("spec")
    85  
    86  	nodelog.Info("validate update", "name", r.Name)
    87  
    88  	allErrors = append(allErrors, r.validate()...)
    89  	allErrors = append(allErrors, r.Spec.Resources.ValidateUpdate(&oldNode.Spec.Resources)...)
    90  
    91  	if oldNode.Spec.Client != r.Spec.Client {
    92  		err := field.Invalid(path.Child("client"), r.Spec.Client, "field is immutable")
    93  		allErrors = append(allErrors, err)
    94  	}
    95  
    96  	if oldNode.Spec.Network != r.Spec.Network {
    97  		err := field.Invalid(path.Child("network"), r.Spec.Network, "field is immutable")
    98  		allErrors = append(allErrors, err)
    99  	}
   100  
   101  	if len(allErrors) == 0 {
   102  		return nil, nil
   103  	}
   104  
   105  	return nil, apierrors.NewInvalid(schema.GroupKind{}, r.Name, allErrors)
   106  }
   107  
   108  // ValidateDelete implements webhook.Validator so a webhook will be registered for the type
   109  func (r *BeaconNode) ValidateDelete() (admission.Warnings, error) {
   110  	nodelog.Info("validate delete", "name", r.Name)
   111  
   112  	return nil, nil
   113  }