github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/cloudsigma/config.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cloudsigma
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/schema"
     9  
    10  	"github.com/juju/juju/environs/config"
    11  )
    12  
    13  var configFields = schema.Fields{}
    14  
    15  var configDefaultFields = schema.Defaults{}
    16  
    17  var configImmutableFields = []string{}
    18  
    19  func validateConfig(cfg *config.Config, old *environConfig) (*environConfig, error) {
    20  	// Check sanity of juju-level fields.
    21  	var oldCfg *config.Config
    22  	if old != nil {
    23  		oldCfg = old.Config
    24  	}
    25  	if err := config.Validate(cfg, oldCfg); err != nil {
    26  		return nil, errors.Trace(err)
    27  	}
    28  
    29  	// Extract validated provider-specific fields. All of configFields will be
    30  	// present in validated, and defaults will be inserted if necessary. If the
    31  	// schema you passed in doesn't quite express what you need, you can make
    32  	// whatever checks you need here, before continuing.
    33  	// In particular, if you want to extract (say) credentials from the user's
    34  	// shell environment variables, you'll need to allow missing values to pass
    35  	// through the schema by setting a value of schema.Omit in the configFields
    36  	// map, and then to set and check them at this point. These values *must* be
    37  	// stored in newAttrs: a Config will be generated on the user's machine only
    38  	// to begin with, and will subsequently be used on a different machine that
    39  	// will probably not have those variables set.
    40  	newAttrs, err := cfg.ValidateUnknownAttrs(configFields, configDefaultFields)
    41  	if err != nil {
    42  		return nil, errors.Trace(err)
    43  	}
    44  	for field := range configFields {
    45  		if newAttrs[field] == "" {
    46  			return nil, errors.Errorf("%s: must not be empty", field)
    47  		}
    48  	}
    49  
    50  	// If an old config was supplied, check any immutable fields have not changed.
    51  	if old != nil {
    52  		for _, field := range configImmutableFields {
    53  			if old.attrs[field] != newAttrs[field] {
    54  				return nil, errors.Errorf(
    55  					"%s: cannot change from %v to %v",
    56  					field, old.attrs[field], newAttrs[field],
    57  				)
    58  			}
    59  		}
    60  	}
    61  
    62  	// Merge the validated provider-specific fields into the original config,
    63  	// to ensure the object we return is internally consistent.
    64  	newCfg, err := cfg.Apply(newAttrs)
    65  	if err != nil {
    66  		return nil, errors.Trace(err)
    67  	}
    68  	ecfg := &environConfig{
    69  		Config: newCfg,
    70  		attrs:  newAttrs,
    71  	}
    72  
    73  	return ecfg, nil
    74  }
    75  
    76  type environConfig struct {
    77  	*config.Config
    78  	attrs map[string]interface{}
    79  }