github.com/kotalco/kotal@v0.3.0/apis/shared/resources.go (about)

     1  package shared
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"k8s.io/apimachinery/pkg/api/resource"
     7  	"k8s.io/apimachinery/pkg/util/validation/field"
     8  )
     9  
    10  // Resources is node compute and storage resources
    11  // +k8s:deepcopy-gen=true
    12  type Resources struct {
    13  	// CPU is cpu cores the node requires
    14  	// +kubebuilder:validation:Pattern="^[1-9][0-9]*m?$"
    15  	CPU string `json:"cpu,omitempty"`
    16  	// CPULimit is cpu cores the node is limited to
    17  	// +kubebuilder:validation:Pattern="^[1-9][0-9]*m?$"
    18  	CPULimit string `json:"cpuLimit,omitempty"`
    19  	// Memory is memmory requirements
    20  	// +kubebuilder:validation:Pattern="^[1-9][0-9]*[KMGTPE]i$"
    21  	Memory string `json:"memory,omitempty"`
    22  	// MemoryLimit is cpu cores the node is limited to
    23  	// +kubebuilder:validation:Pattern="^[1-9][0-9]*[KMGTPE]i$"
    24  	MemoryLimit string `json:"memoryLimit,omitempty"`
    25  	// Storage is disk space storage requirements
    26  	// +kubebuilder:validation:Pattern="^[1-9][0-9]*[KMGTPE]i$"
    27  	Storage string `json:"storage,omitempty"`
    28  	// StorageClass is the volume storage class
    29  	StorageClass *string `json:"storageClass,omitempty"`
    30  }
    31  
    32  // validate is the shared validation logic
    33  func (r *Resources) validate() (errors field.ErrorList) {
    34  	cpu := r.CPU
    35  	cpuLimit := r.CPULimit
    36  
    37  	if cpu != cpuLimit {
    38  		// validate cpuLimit can't be less than cpu request
    39  		cpuQuantity := resource.MustParse(cpu)
    40  		cpuLimitQuantity := resource.MustParse(cpuLimit)
    41  		if cpuLimitQuantity.Cmp(cpuQuantity) == -1 {
    42  			msg := fmt.Sprintf("must be greater than or equal to cpu %s", string(cpu))
    43  			err := field.Invalid(field.NewPath("spec").Child("resources").Child("cpuLimit"), cpuLimit, msg)
    44  			errors = append(errors, err)
    45  		}
    46  	}
    47  
    48  	memory := r.Memory
    49  	memoryLimit := r.MemoryLimit
    50  	memoryQuantity := resource.MustParse(memory)
    51  	memoryLimitQuantity := resource.MustParse(memoryLimit)
    52  
    53  	// validate memory limit must be greater than memory
    54  	if memoryLimitQuantity.Cmp(memoryQuantity) != 1 {
    55  		msg := fmt.Sprintf("must be greater than memory %s", string(memory))
    56  		err := field.Invalid(field.NewPath("spec").Child("resources").Child("memoryLimit"), memoryLimit, msg)
    57  		errors = append(errors, err)
    58  	}
    59  
    60  	return
    61  }
    62  
    63  // ValidateCreate validates resources during creation
    64  func (r *Resources) ValidateCreate() (errors field.ErrorList) {
    65  	errors = append(errors, r.validate()...)
    66  	return
    67  }
    68  
    69  // ValidateUpdate validates resources during update
    70  func (r *Resources) ValidateUpdate(oldResources *Resources) (errors field.ErrorList) {
    71  
    72  	oldStorage := oldResources.Storage
    73  	oldStorageClass := oldResources.StorageClass
    74  
    75  	errors = append(errors, r.validate()...)
    76  
    77  	// requested storage can't be decreased
    78  	if oldStorage != r.Storage {
    79  
    80  		oldStorageQuantity := resource.MustParse(oldStorage)
    81  		newStorageQuantity := resource.MustParse(r.Storage)
    82  
    83  		if newStorageQuantity.Cmp(oldStorageQuantity) == -1 {
    84  			msg := fmt.Sprintf("must be greater than or equal to old storage %s", oldStorage)
    85  			err := field.Invalid(field.NewPath("spec").Child("resources").Child("storage"), r.Storage, msg)
    86  			errors = append(errors, err)
    87  		}
    88  
    89  	}
    90  
    91  	// storage class is immutable
    92  	if oldStorageClass != nil && r.StorageClass != nil && *oldStorageClass != *r.StorageClass {
    93  		msg := "field is immutable"
    94  		err := field.Invalid(field.NewPath("spec").Child("resources").Child("storageClass"), *r.StorageClass, msg)
    95  		errors = append(errors, err)
    96  	}
    97  
    98  	return
    99  }