github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/vsphere/config.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // +build !gccgo 5 6 package vsphere 7 8 import ( 9 "fmt" 10 "net/url" 11 12 "github.com/juju/errors" 13 "github.com/juju/schema" 14 15 "github.com/juju/juju/environs/config" 16 ) 17 18 // The vmware-specific config keys. 19 const ( 20 cfgDatacenter = "datacenter" 21 cfgHost = "host" 22 cfgUser = "user" 23 cfgPassword = "password" 24 cfgExternalNetwork = "external-network" 25 ) 26 27 // configFields is the spec for each vmware config value's type. 28 var configFields = schema.Fields{ 29 cfgHost: schema.String(), 30 cfgUser: schema.String(), 31 cfgPassword: schema.String(), 32 cfgDatacenter: schema.String(), 33 cfgExternalNetwork: schema.String(), 34 } 35 36 var requiredFields = []string{ 37 cfgHost, 38 cfgUser, 39 cfgPassword, 40 cfgDatacenter, 41 } 42 43 var configDefaults = schema.Defaults{ 44 cfgExternalNetwork: "", 45 } 46 47 var configSecretFields = []string{ 48 cfgPassword, 49 } 50 51 var configImmutableFields = []string{ 52 cfgHost, 53 cfgDatacenter, 54 } 55 56 type environConfig struct { 57 *config.Config 58 attrs map[string]interface{} 59 } 60 61 // newConfig builds a new environConfig from the provided Config and 62 // returns it. 63 func newConfig(cfg *config.Config) *environConfig { 64 return &environConfig{ 65 Config: cfg, 66 attrs: cfg.UnknownAttrs(), 67 } 68 } 69 70 // newValidConfig builds a new environConfig from the provided Config 71 // and returns it. The resulting config values are validated. 72 func newValidConfig(cfg *config.Config, defaults map[string]interface{}) (*environConfig, error) { 73 // Ensure that the provided config is valid. 74 if err := config.Validate(cfg, nil); err != nil { 75 return nil, errors.Trace(err) 76 } 77 78 // Apply the defaults and coerce/validate the custom config attrs. 79 validated, err := cfg.ValidateUnknownAttrs(configFields, defaults) 80 if err != nil { 81 return nil, errors.Trace(err) 82 } 83 validCfg, err := cfg.Apply(validated) 84 if err != nil { 85 return nil, errors.Trace(err) 86 } 87 88 // Build the config. 89 ecfg := newConfig(validCfg) 90 91 // Do final validation. 92 if err := ecfg.validate(); err != nil { 93 return nil, errors.Trace(err) 94 } 95 96 return ecfg, nil 97 } 98 99 func (c *environConfig) datacenter() string { 100 return c.attrs[cfgDatacenter].(string) 101 } 102 103 func (c *environConfig) host() string { 104 return c.attrs[cfgHost].(string) 105 } 106 107 func (c *environConfig) user() string { 108 return c.attrs[cfgUser].(string) 109 } 110 111 func (c *environConfig) password() string { 112 return c.attrs[cfgPassword].(string) 113 } 114 115 func (c *environConfig) externalNetwork() string { 116 return c.attrs[cfgExternalNetwork].(string) 117 } 118 119 func (c *environConfig) url() (*url.URL, error) { 120 return url.Parse(fmt.Sprintf("https://%s:%s@%s/sdk", c.user(), c.password(), c.host())) 121 } 122 123 // secret gathers the "secret" config values and returns them. 124 func (c *environConfig) secret() map[string]string { 125 secretAttrs := make(map[string]string, len(configSecretFields)) 126 for _, key := range configSecretFields { 127 secretAttrs[key] = c.attrs[key].(string) 128 } 129 return secretAttrs 130 } 131 132 // validate checks vmware-specific config values. 133 func (c environConfig) validate() error { 134 // All fields must be populated, even with just the default. 135 for _, field := range requiredFields { 136 if c.attrs[field].(string) == "" { 137 return errors.Errorf("%s: must not be empty", field) 138 } 139 } 140 if _, err := c.url(); err != nil { 141 return errors.Trace(err) 142 } 143 144 return nil 145 } 146 147 // update applies changes from the provided config to the env config. 148 // Changes to any immutable attributes result in an error. 149 func (c *environConfig) update(cfg *config.Config) error { 150 // Validate the updates. newValidConfig does not modify the "known" 151 // config attributes so it is safe to call Validate here first. 152 if err := config.Validate(cfg, c.Config); err != nil { 153 return errors.Trace(err) 154 } 155 156 updates, err := newValidConfig(cfg, configDefaults) 157 if err != nil { 158 return errors.Trace(err) 159 } 160 161 // Check that no immutable fields have changed. 162 attrs := updates.UnknownAttrs() 163 for _, field := range configImmutableFields { 164 if attrs[field] != c.attrs[field] { 165 return errors.Errorf("%s: cannot change from %v to %v", field, c.attrs[field], attrs[field]) 166 } 167 } 168 169 // Apply the updates. 170 c.Config = cfg 171 c.attrs = cfg.UnknownAttrs() 172 return nil 173 }