github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/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/altoros/gosigma"
     8  	"github.com/juju/errors"
     9  	"github.com/juju/schema"
    10  
    11  	"github.com/juju/juju/environs/config"
    12  )
    13  
    14  var configFields = schema.Fields{
    15  	"username": schema.String(),
    16  	"password": schema.String(),
    17  	"region":   schema.String(),
    18  	"endpoint": schema.String(),
    19  }
    20  
    21  var configDefaultFields = schema.Defaults{
    22  	"username": "",
    23  	"password": "",
    24  	"region":   gosigma.DefaultRegion,
    25  	"endpoint": "",
    26  }
    27  
    28  var configSecretFields = []string{
    29  	"password",
    30  }
    31  
    32  var configImmutableFields = []string{
    33  	"region",
    34  	"endpoint",
    35  }
    36  
    37  func validateConfig(cfg *config.Config, old *environConfig) (*environConfig, error) {
    38  	// Check sanity of juju-level fields.
    39  	var oldCfg *config.Config
    40  	if old != nil {
    41  		oldCfg = old.Config
    42  	}
    43  	if err := config.Validate(cfg, oldCfg); err != nil {
    44  		return nil, errors.Trace(err)
    45  	}
    46  
    47  	// Extract validated provider-specific fields. All of configFields will be
    48  	// present in validated, and defaults will be inserted if necessary. If the
    49  	// schema you passed in doesn't quite express what you need, you can make
    50  	// whatever checks you need here, before continuing.
    51  	// In particular, if you want to extract (say) credentials from the user's
    52  	// shell environment variables, you'll need to allow missing values to pass
    53  	// through the schema by setting a value of schema.Omit in the configFields
    54  	// map, and then to set and check them at this point. These values *must* be
    55  	// stored in newAttrs: a Config will be generated on the user's machine only
    56  	// to begin with, and will subsequently be used on a different machine that
    57  	// will probably not have those variables set.
    58  	newAttrs, err := cfg.ValidateUnknownAttrs(configFields, configDefaultFields)
    59  	if err != nil {
    60  		return nil, errors.Trace(err)
    61  	}
    62  	for field := range configFields {
    63  		if newAttrs[field] == "" {
    64  			return nil, errors.Errorf("%s: must not be empty", field)
    65  		}
    66  	}
    67  
    68  	// If an old config was supplied, check any immutable fields have not changed.
    69  	if old != nil {
    70  		for _, field := range configImmutableFields {
    71  			if old.attrs[field] != newAttrs[field] {
    72  				return nil, errors.Errorf(
    73  					"%s: cannot change from %v to %v",
    74  					field, old.attrs[field], newAttrs[field],
    75  				)
    76  			}
    77  		}
    78  	}
    79  
    80  	// Merge the validated provider-specific fields into the original config,
    81  	// to ensure the object we return is internally consistent.
    82  	newCfg, err := cfg.Apply(newAttrs)
    83  	if err != nil {
    84  		return nil, errors.Trace(err)
    85  	}
    86  	ecfg := &environConfig{
    87  		Config: newCfg,
    88  		attrs:  newAttrs,
    89  	}
    90  
    91  	return ecfg, nil
    92  }
    93  
    94  // configChanged checks if CloudSigma client environment configuration is changed
    95  func (c environConfig) clientConfigChanged(newConfig *environConfig) bool {
    96  	// compare
    97  	if newConfig.region() != c.region() || newConfig.username() != c.username() ||
    98  		newConfig.password() != c.password() {
    99  		return true
   100  	}
   101  
   102  	return false
   103  }
   104  
   105  type environConfig struct {
   106  	*config.Config
   107  	attrs map[string]interface{}
   108  }
   109  
   110  func (c environConfig) region() string {
   111  	return c.attrs["region"].(string)
   112  }
   113  
   114  func (c environConfig) endpoint() string {
   115  	return c.attrs["endpoint"].(string)
   116  }
   117  
   118  func (c environConfig) username() string {
   119  	return c.attrs["username"].(string)
   120  }
   121  
   122  func (c environConfig) password() string {
   123  	return c.attrs["password"].(string)
   124  }