Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref: created validation funcs for chainlink to support api sdk valida… #17

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions apis/chainlink/v1alpha1/node_validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package v1alpha1

import (
"fmt"
"github.com/kotalco/kotal/apis/shared"
"github.com/kotalco/kotal/helpers/kerrors"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
)

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func ValidateCreate(n *Node) []*kerrors.KErrors {
var allErrors []*kerrors.KErrors

nodelog.Info("validate create", "name", n.Name)

allErrors = append(allErrors, shared.ValidateCreate(&n.Spec.Resources)...)

if len(allErrors) == 0 {
return nil
}

return allErrors
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func ValidateUpdate(n *Node, old runtime.Object) (errors []*kerrors.KErrors) {
oldNode := old.(*Node)

nodelog.Info("validate update", "name", n.Name)

errors = append(errors, shared.ValidateUpdate(&n.Spec.Resources, &oldNode.Spec.Resources)...)

if oldNode.Spec.EthereumChainId != n.Spec.EthereumChainId {
err := field.Invalid(field.NewPath("spec").Child("ethereumChainId"), fmt.Sprintf("%d", n.Spec.EthereumChainId), "field is immutable")
customErr := kerrors.New(*err)
customErr.ChildField = "ethereumChainId"
customErr.CustomMsg = err.Detail
errors = append(errors, customErr)
}

if oldNode.Spec.LinkContractAddress != n.Spec.LinkContractAddress {
err := field.Invalid(field.NewPath("spec").Child("linkContractAddress"), n.Spec.LinkContractAddress, "field is immutable")
customErr := kerrors.New(*err)
customErr.ChildField = "linkContractAddress"
customErr.CustomMsg = err.Detail
errors = append(errors, customErr)
}

return
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func ValidateDelete(n *Node) []*kerrors.KErrors {
nodelog.Info("validate delete", "name", n.Name)
return nil
}
25 changes: 7 additions & 18 deletions apis/chainlink/v1alpha1/node_validation_webhook.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package v1alpha1

import (
"fmt"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand All @@ -20,14 +18,16 @@ func (r *Node) ValidateCreate() error {

nodelog.Info("validate create", "name", r.Name)

allErrors = append(allErrors, r.Spec.Resources.ValidateCreate()...)
errList := ValidateCreate(r)
for _, v := range errList {
allErrors = append(allErrors, &v.FieldErr)
}

if len(allErrors) == 0 {
return nil
}

return apierrors.NewInvalid(schema.GroupKind{}, r.Name, allErrors)

}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
Expand All @@ -37,20 +37,9 @@ func (r *Node) ValidateUpdate(old runtime.Object) error {

nodelog.Info("validate update", "name", r.Name)

allErrors = append(allErrors, r.Spec.Resources.ValidateUpdate(&oldNode.Spec.Resources)...)

if oldNode.Spec.EthereumChainId != r.Spec.EthereumChainId {
err := field.Invalid(field.NewPath("spec").Child("ethereumChainId"), fmt.Sprintf("%d", r.Spec.EthereumChainId), "field is immutable")
allErrors = append(allErrors, err)
}

if oldNode.Spec.LinkContractAddress != r.Spec.LinkContractAddress {
err := field.Invalid(field.NewPath("spec").Child("linkContractAddress"), r.Spec.LinkContractAddress, "field is immutable")
allErrors = append(allErrors, err)
}

if len(allErrors) == 0 {
return nil
errList := ValidateUpdate(r, oldNode)
for _, v := range errList {
allErrors = append(allErrors, &v.FieldErr)
}

return apierrors.NewInvalid(schema.GroupKind{}, r.Name, allErrors)
Expand Down
65 changes: 10 additions & 55 deletions apis/shared/resources.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package shared

import (
"fmt"

"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/validation/field"
)

Expand Down Expand Up @@ -31,69 +28,27 @@ type Resources struct {

// validate is the shared validation logic
func (r *Resources) validate() (errors field.ErrorList) {
cpu := r.CPU
cpuLimit := r.CPULimit

if cpu != cpuLimit {
// validate cpuLimit can't be less than cpu request
cpuQuantity := resource.MustParse(cpu)
cpuLimitQuantity := resource.MustParse(cpuLimit)
if cpuLimitQuantity.Cmp(cpuQuantity) == -1 {
msg := fmt.Sprintf("must be greater than or equal to cpu %s", string(cpu))
err := field.Invalid(field.NewPath("spec").Child("resources").Child("cpuLimit"), cpuLimit, msg)
errors = append(errors, err)
}
}

memory := r.Memory
memoryLimit := r.MemoryLimit
memoryQuantity := resource.MustParse(memory)
memoryLimitQuantity := resource.MustParse(memoryLimit)

// validate memory limit must be greater than memory
if memoryLimitQuantity.Cmp(memoryQuantity) != 1 {
msg := fmt.Sprintf("must be greater than memory %s", string(memory))
err := field.Invalid(field.NewPath("spec").Child("resources").Child("memoryLimit"), memoryLimit, msg)
errors = append(errors, err)
customErrs := validate(r)
for _, v := range customErrs {
errors = append(errors, &v.FieldErr)
}

return
}

// ValidateCreate validates resources during creation
func (r *Resources) ValidateCreate() (errors field.ErrorList) {
errors = append(errors, r.validate()...)
customErrs := ValidateCreate(r)
for _, v := range customErrs {
errors = append(errors, &v.FieldErr)
}
return
}

// ValidateUpdate validates resources during update
func (r *Resources) ValidateUpdate(oldResources *Resources) (errors field.ErrorList) {

oldStorage := oldResources.Storage
oldStorageClass := oldResources.StorageClass

errors = append(errors, r.validate()...)

// requested storage can't be decreased
if oldStorage != r.Storage {

oldStorageQuantity := resource.MustParse(oldStorage)
newStorageQuantity := resource.MustParse(r.Storage)

if newStorageQuantity.Cmp(oldStorageQuantity) == -1 {
msg := fmt.Sprintf("must be greater than or equal to old storage %s", oldStorage)
err := field.Invalid(field.NewPath("spec").Child("resources").Child("storage"), r.Storage, msg)
errors = append(errors, err)
}

}

// storage class is immutable
if oldStorageClass != nil && r.StorageClass != nil && *oldStorageClass != *r.StorageClass {
msg := "field is immutable"
err := field.Invalid(field.NewPath("spec").Child("resources").Child("storageClass"), *r.StorageClass, msg)
errors = append(errors, err)
customErrs := ValidateUpdate(r, oldResources)
for _, v := range customErrs {
errors = append(errors, &v.FieldErr)
}

return
}
90 changes: 90 additions & 0 deletions apis/shared/resources_validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package shared

import (
"fmt"
"github.com/kotalco/kotal/helpers/kerrors"

"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/validation/field"
)

// validate is the shared validation logic
func validate(r *Resources) (errors []*kerrors.KErrors) {
cpu := r.CPU
cpuLimit := r.CPULimit

if cpu != cpuLimit {
// validate cpuLimit can't be less than cpu request
cpuQuantity := resource.MustParse(cpu)
cpuLimitQuantity := resource.MustParse(cpuLimit)
if cpuLimitQuantity.Cmp(cpuQuantity) == -1 {
msg := fmt.Sprintf("must be greater than or equal to cpu %s", string(cpu))
err := field.Invalid(field.NewPath("spec").Child("resources").Child("cpuLimit"), cpuLimit, msg)
customErr := kerrors.New(*err)
customErr.ChildField = "cpuLimit"
customErr.CustomMsg = msg
errors = append(errors, customErr)
}
}

memory := r.Memory
memoryLimit := r.MemoryLimit
memoryQuantity := resource.MustParse(memory)
memoryLimitQuantity := resource.MustParse(memoryLimit)

// validate memory limit must be greater than memory
if memoryLimitQuantity.Cmp(memoryQuantity) != 1 {
msg := fmt.Sprintf("must be greater than memory %s", string(memory))
err := field.Invalid(field.NewPath("spec").Child("resources").Child("memoryLimit"), memoryLimit, msg)
customErr := kerrors.New(*err)
customErr.ChildField = "memoryLimit"
customErr.CustomMsg = msg
errors = append(errors, customErr)
}

return
}

// ValidateCreate validates resources during creation
func ValidateCreate(r *Resources) (errors []*kerrors.KErrors) {
errors = append(errors, validate(r)...)
return
}

// ValidateUpdate validates resources during update
func ValidateUpdate(r *Resources, oldResources *Resources) (errors []*kerrors.KErrors) {

oldStorage := oldResources.Storage
oldStorageClass := oldResources.StorageClass

errors = append(errors, validate(r)...)

// requested storage can't be decreased
if oldStorage != r.Storage {

oldStorageQuantity := resource.MustParse(oldStorage)
newStorageQuantity := resource.MustParse(r.Storage)

if newStorageQuantity.Cmp(oldStorageQuantity) == -1 {
msg := fmt.Sprintf("must be greater than or equal to old storage %s", oldStorage)
err := field.Invalid(field.NewPath("spec").Child("resources").Child("storage"), r.Storage, msg)
customErr := kerrors.New(*err)
customErr.ChildField = "storage"
customErr.CustomMsg = msg
errors = append(errors, customErr)
}

}

// storage class is immutable
if oldStorageClass != nil && r.StorageClass != nil && *oldStorageClass != *r.StorageClass {
msg := "field is immutable"
err := field.Invalid(field.NewPath("spec").Child("resources").Child("storageClass"), *r.StorageClass, msg)
customErr := kerrors.New(*err)
customErr.ChildField = "storage"
customErr.CustomMsg = msg
errors = append(errors, customErr)
}

return
}
15 changes: 15 additions & 0 deletions helpers/kerrors/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package kerrors

import "k8s.io/apimachinery/pkg/util/validation/field"

type KErrors struct {
FieldErr field.Error
ChildField string
CustomMsg string
}

func New(err field.Error) *KErrors {
return &KErrors{
FieldErr: err,
}
}