package utils import ( "errors" "fmt" "strings" "k8s.io/apimachinery/pkg/util/validation" ) // ErrInvalidName indicates the name did not pass function name validation. type ErrInvalidFunctionName error // ErrInvalidEnvVarName indicates the name did not pass env var name validation. type ErrInvalidEnvVarName error // ErrInvalidConfigMapKey indicates the key specified for ConfigMap did not pass validation. type ErrInvalidConfigMapKey error // ErrInvalidSecretKey indicates the key specified for ConfigMap did not pass validation. type ErrInvalidSecretKey error // ErrInvalidLabel indicates the name did not pass label key validation, or the value did not pass label value validation. type ErrInvalidLabel error // ValidateFunctionName validates that the input name is a valid function name, ie. valid DNS-1035 label. // It must consist of lower case alphanumeric characters or '-' and start with an alphabetic character and end with an alphanumeric character. // (e.g. 'my-name', or 'abc-1', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?') func ValidateFunctionName(name string) error { if errs := validation.IsDNS1035Label(name); len(errs) > 0 { // In case of invalid name the error is this: // "a DNS-1035 label must consist of lower case alphanumeric characters or '-', // start with an alphabetic character, // and end with an alphanumeric character". // Let's reuse it for our purposes, ie. replace "a DNS-1035 label" substring with "Function name" and the actual function name return ErrInvalidFunctionName(errors.New(strings.Replace(strings.Join(errs, ""), "a DNS-1035 label", fmt.Sprintf("Function name '%v'", name), 1))) } return nil } // ValidateEnvVarName validatest that the input name is a valid Kubernetes Environment Variable name. // It must must consist of alphabetic characters, digits, '_', '-', or '.', and must not start with a digit // (e.g. 'my.env-name', or 'MY_ENV.NAME', or 'MyEnvName1', regex used for validation is '[-._a-zA-Z][-._a-zA-Z0-9]*' func ValidateEnvVarName(name string) error { if errs := validation.IsEnvVarName(name); len(errs) > 0 { return ErrInvalidEnvVarName(errors.New(strings.Join(errs, ""))) } return nil } // ValidateConfigMapKey validatest that the input ConfigMap key is valid. // It must must consist of alphabetic characters, digits, '_', '-', or '.', regex used for validation is '[-._a-zA-Z0-9]+' func ValidateConfigMapKey(key string) error { if errs := validation.IsConfigMapKey(key); len(errs) > 0 { return ErrInvalidConfigMapKey(errors.New(strings.Join(errs, ""))) } return nil } // ValidateSecretKey validatest that the input Secret key is valid. // It must must consist of alphabetic characters, digits, '_', '-', or '.', regex used for validation is '[-._a-zA-Z0-9]+' func ValidateSecretKey(key string) error { if errs := validation.IsConfigMapKey(key); len(errs) > 0 { return ErrInvalidSecretKey(errors.New(strings.Join(errs, ""))) } return nil } // ValidateLabelKey validates that the input name is a valid Kubernetes key. // Valid label names have two segments: an optional prefix and name, separated by a slash (/). // The name segment is required and must be 63 characters or less, beginning and ending with // an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.), and // alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: // a series of DNS labels separated by dots (.), not longer than 253 characters in total, followed // by a slash (/). func ValidateLabelKey(key string) error { errs := validation.IsQualifiedName(key) if len(errs) > 0 { return ErrInvalidLabel(errors.New(strings.Join(errs, ""))) } return nil } // ValidateLabelValue ensures that the input is a Kubernetes label value // Valid label values must be 63 characters or less (can be empty), // unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), // could contain dashes (-), underscores (_), dots (.), and alphanumerics between. // Label values may also come from the environment and therefore, could be enclosed with {{}} // Treat this as a special case. func ValidateLabelValue(value string) error { var errs []string if !strings.HasPrefix(value, "{{") { errs = append(errs, validation.IsValidLabelValue(value)...) } if len(errs) > 0 { return ErrInvalidLabel(errors.New(strings.Join(errs, ""))) } return nil }