github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/storage/provider/k8s_validation.go (about) 1 // Copyright 2022 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provider 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "github.com/juju/schema" 11 12 "github.com/juju/juju/storage" 13 ) 14 15 // checkK8sConfig checks that the attributes in a configuration 16 // are valid for a K8s deployment. 17 func checkK8sConfig(attributes map[string]any) error { 18 if mediumValue, ok := attributes[storage.K8sStorageMediumConst]; ok { 19 medium := fmt.Sprintf("%v", mediumValue) 20 if medium != storage.K8sStorageMediumMemory && medium != storage.K8sStorageMediumHugePages { 21 return errors.NotValidf("storage medium %q", mediumValue) 22 } 23 } 24 25 if err := validateStorageAttributes(attributes); err != nil { 26 return errors.Trace(err) 27 } 28 29 return nil 30 } 31 32 func validateStorageAttributes(attributes map[string]any) error { 33 if err := validateStorageConfig(attributes); err != nil { 34 return errors.Trace(err) 35 } 36 if err := validateStorageMode(attributes); err != nil { 37 return errors.Trace(err) 38 } 39 return nil 40 } 41 42 var storageConfigFields = schema.Fields{ 43 storage.K8sStorageClass: schema.String(), 44 storage.K8sStorageProvisioner: schema.String(), 45 } 46 47 var storageConfigChecker = schema.FieldMap( 48 storageConfigFields, 49 schema.Defaults{ 50 storage.K8sStorageClass: schema.Omit, 51 storage.K8sStorageProvisioner: schema.Omit, 52 }, 53 ) 54 55 // validateStorageConfig returns issues in the configuration if any. 56 func validateStorageConfig(attrs map[string]any) error { 57 out, err := storageConfigChecker.Coerce(attrs, nil) 58 if err != nil { 59 return errors.Annotate(err, "validating storage config") 60 } 61 coerced := out.(map[string]any) 62 63 if coerced[storage.K8sStorageProvisioner] != "" && coerced[storage.K8sStorageClass] == "" { 64 return errors.New("storage-class must be specified if storage-provisioner is specified") 65 } 66 67 return nil 68 } 69 70 var storageModeFields = schema.Fields{ 71 storage.K8sStorageMode: schema.String(), 72 } 73 74 var storageModeChecker = schema.FieldMap( 75 storageModeFields, 76 schema.Defaults{ 77 storage.K8sStorageMode: "ReadWriteOnce", 78 }, 79 ) 80 81 // validateStorageMode returns an error if the K8s persistent 82 // volume is not configured correctly. 83 func validateStorageMode(attrs map[string]any) error { 84 out, err := storageModeChecker.Coerce(attrs, nil) 85 if err != nil { 86 return errors.Annotate(err, "validating storage mode") 87 } 88 coerced := out.(map[string]any) 89 mode := coerced[storage.K8sStorageMode] 90 switch coerced[storage.K8sStorageMode] { 91 case "ReadOnlyMany", "ROX": 92 case "ReadWriteMany", "RWX": 93 case "ReadWriteOnce", "RWO": 94 default: 95 return errors.NotSupportedf("storage mode %q", mode) 96 } 97 98 return nil 99 }