github.com/kubesphere/s2irun@v3.2.1+incompatible/pkg/api/validation/validation.go (about) 1 package validation 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/docker/distribution/reference" 8 9 "github.com/kubesphere/s2irun/pkg/api" 10 ) 11 12 // ValidateConfig returns a list of error from validation. 13 func ValidateConfig(config *api.Config) []Error { 14 allErrs := []Error{} 15 if len(config.BuilderImage) == 0 { 16 allErrs = append(allErrs, NewFieldRequired("builderImage")) 17 } 18 switch config.BuilderPullPolicy { 19 case api.PullNever, api.PullAlways, api.PullIfNotPresent: 20 default: 21 allErrs = append(allErrs, NewFieldInvalidValueObj("builderPullPolicy", config.BuilderPullPolicy)) 22 } 23 if config.DockerConfig == nil || len(config.DockerConfig.Endpoint) == 0 { 24 allErrs = append(allErrs, NewFieldRequired("dockerConfig.endpoint")) 25 } 26 if config.DockerNetworkMode != "" && !validateDockerNetworkMode(config.DockerNetworkMode) { 27 allErrs = append(allErrs, NewFieldInvalidValueObj("dockerNetworkMode", config.DockerNetworkMode)) 28 } 29 if config.Labels != nil { 30 for k := range config.Labels { 31 if len(k) == 0 { 32 allErrs = append(allErrs, NewFieldInvalidValueWithReason("labels", "contains empty label")) 33 } 34 } 35 } 36 if config.Tag != "" { 37 if err := validateDockerReference(config.Tag); err != nil { 38 allErrs = append(allErrs, NewFieldInvalidValueWithReasonAndValue("tag", err.Error(), config.Tag)) 39 } 40 } 41 return allErrs 42 } 43 44 // validateDockerNetworkMode checks wether the network mode conforms to the docker remote API specification (v1.19) 45 // Supported values are: bridge, host, container:<name|id>, and netns:/proc/<pid>/ns/net 46 func validateDockerNetworkMode(mode api.DockerNetworkMode) bool { 47 switch mode { 48 case api.DockerNetworkModeBridge, api.DockerNetworkModeHost: 49 return true 50 } 51 if strings.HasPrefix(string(mode), api.DockerNetworkModeContainerPrefix) { 52 return true 53 } 54 if strings.HasPrefix(string(mode), api.DockerNetworkModeNetworkNamespacePrefix) { 55 return true 56 } 57 return false 58 } 59 60 func validateDockerReference(ref string) error { 61 _, err := reference.Parse(ref) 62 return err 63 } 64 65 // NewFieldRequired returns a *ValidationError indicating "value required" 66 func NewFieldRequired(field string) Error { 67 return Error{Type: ErrorTypeRequired, Field: field} 68 } 69 70 // NewFieldInvalidValue returns a ValidationError indicating "invalid value" 71 func NewFieldInvalidValue(field string) Error { 72 return Error{Type: ErrorInvalidValue, Field: field} 73 } 74 75 // NewFieldInvalidValueObj returns a ValidationError indicating "invalid value" 76 func NewFieldInvalidValueObj(field string, value interface{}) Error { 77 return Error{Type: ErrorInvalidValue, Field: field, Value: value} 78 } 79 80 // NewFieldInvalidValueWithReason returns a ValidationError indicating "invalid value" and a reason for the error 81 func NewFieldInvalidValueWithReason(field, reason string) Error { 82 return Error{Type: ErrorInvalidValue, Field: field, Reason: reason} 83 } 84 85 // NewFieldInvalidValueWithReasonAndValue returns a ValidationError indicating the value and reason 86 func NewFieldInvalidValueWithReasonAndValue(field, reason string, value interface{}) Error { 87 return Error{Type: ErrorInvalidValue, Field: field, Value: value, Reason: reason} 88 } 89 90 // ErrorType is a machine readable value providing more detail about why a field 91 // is invalid. 92 type ErrorType string 93 94 const ( 95 // ErrorTypeRequired is used to report required values that are not provided 96 // (e.g. empty strings, null values, or empty arrays). 97 ErrorTypeRequired ErrorType = "FieldValueRequired" 98 99 // ErrorInvalidValue is used to report values that do not conform to the 100 // expected schema. 101 ErrorInvalidValue ErrorType = "InvalidValue" 102 ) 103 104 // Error is an implementation of the 'error' interface, which represents an 105 // error of validation. 106 type Error struct { 107 Type ErrorType 108 Field string 109 Value interface{} 110 Reason string 111 } 112 113 func (v Error) Error() string { 114 var msg string 115 switch v.Type { 116 case ErrorInvalidValue: 117 msg = fmt.Sprintf("Invalid value specified for %q, value: %v", v.Field, v.Value) 118 case ErrorTypeRequired: 119 msg = fmt.Sprintf("Required value not specified for %q", v.Field) 120 default: 121 msg = fmt.Sprintf("%s: %s", v.Type, v.Field) 122 } 123 if len(v.Reason) > 0 { 124 msg = fmt.Sprintf("%s: %s", msg, v.Reason) 125 } 126 return msg 127 }