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  }