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 }