github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/vsphere/config.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package vsphere 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/schema" 9 10 "github.com/juju/juju/environs/config" 11 ) 12 13 // The vmware-specific config keys. 14 const ( 15 cfgPrimaryNetwork = "primary-network" 16 cfgExternalNetwork = "external-network" 17 cfgDatastore = "datastore" 18 cfgEnableDiskUUID = "enable-disk-uuid" 19 ) 20 21 // configFields is the spec for each vmware config value's type. 22 var ( 23 configFields = schema.Fields{ 24 cfgExternalNetwork: schema.String(), 25 cfgDatastore: schema.String(), 26 cfgPrimaryNetwork: schema.String(), 27 cfgEnableDiskUUID: schema.Bool(), 28 } 29 30 configDefaults = schema.Defaults{ 31 cfgExternalNetwork: "", 32 cfgDatastore: schema.Omit, 33 cfgPrimaryNetwork: schema.Omit, 34 cfgEnableDiskUUID: true, 35 } 36 37 configRequiredFields = []string{} 38 configImmutableFields = []string{} 39 ) 40 41 type environConfig struct { 42 *config.Config 43 attrs map[string]interface{} 44 } 45 46 // newConfig builds a new environConfig from the provided Config and 47 // returns it. 48 func newConfig(cfg *config.Config) *environConfig { 49 return &environConfig{ 50 Config: cfg, 51 attrs: cfg.UnknownAttrs(), 52 } 53 } 54 55 // newValidConfig builds a new environConfig from the provided Config 56 // and returns it. The resulting config values are validated. 57 func newValidConfig(cfg *config.Config) (*environConfig, error) { 58 // Ensure that the provided config is valid. 59 if err := config.Validate(cfg, nil); err != nil { 60 return nil, errors.Trace(err) 61 } 62 63 // Apply the defaults and coerce/validate the custom config attrs. 64 validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults) 65 if err != nil { 66 return nil, errors.Trace(err) 67 } 68 validCfg, err := cfg.Apply(validated) 69 if err != nil { 70 return nil, errors.Trace(err) 71 } 72 73 // Build the config. 74 ecfg := newConfig(validCfg) 75 76 // Do final validation. 77 if err := ecfg.validate(); err != nil { 78 return nil, errors.Trace(err) 79 } 80 81 return ecfg, nil 82 } 83 84 func (c *environConfig) externalNetwork() string { 85 return c.attrs[cfgExternalNetwork].(string) 86 } 87 88 func (c *environConfig) datastore() string { 89 ds, _ := c.attrs[cfgDatastore].(string) 90 return ds 91 } 92 93 func (c *environConfig) primaryNetwork() string { 94 network, _ := c.attrs[cfgPrimaryNetwork].(string) 95 return network 96 } 97 98 func (c *environConfig) enableDiskUUID() bool { 99 return c.attrs[cfgEnableDiskUUID].(bool) 100 } 101 102 // validate checks vmware-specific config values. 103 func (c environConfig) validate() error { 104 // All fields must be populated, even with just the default. 105 for _, field := range configRequiredFields { 106 if c.attrs[field].(string) == "" { 107 return errors.Errorf("%s: must not be empty", field) 108 } 109 } 110 return nil 111 } 112 113 // update applies changes from the provided config to the env config. 114 // Changes to any immutable attributes result in an error. 115 func (c *environConfig) update(cfg *config.Config) error { 116 // Validate the updates. newValidConfig does not modify the "known" 117 // config attributes so it is safe to call Validate here first. 118 if err := config.Validate(cfg, c.Config); err != nil { 119 return errors.Trace(err) 120 } 121 122 updates, err := newValidConfig(cfg) 123 if err != nil { 124 return errors.Trace(err) 125 } 126 127 // Check that no immutable fields have changed. 128 attrs := updates.UnknownAttrs() 129 for _, field := range configImmutableFields { 130 if attrs[field] != c.attrs[field] { 131 return errors.Errorf("%s: cannot change from %v to %v", field, c.attrs[field], attrs[field]) 132 } 133 } 134 135 // Apply the updates. 136 c.Config = cfg 137 c.attrs = cfg.UnknownAttrs() 138 return nil 139 }