github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/provider/azure/config.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package azure 5 6 import ( 7 "encoding/pem" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "os" 12 13 "github.com/juju/schema" 14 15 "github.com/juju/juju/environs/config" 16 ) 17 18 var configFields = schema.Fields{ 19 "location": schema.String(), 20 "management-subscription-id": schema.String(), 21 "management-certificate-path": schema.String(), 22 "management-certificate": schema.String(), 23 "storage-account-name": schema.String(), 24 "force-image-name": schema.String(), 25 "availability-sets-enabled": schema.Bool(), 26 } 27 var configDefaults = schema.Defaults{ 28 "location": "", 29 "management-certificate": "", 30 "management-certificate-path": "", 31 "force-image-name": "", 32 // availability-sets-enabled is set to Omit (equivalent 33 // to false) for backwards compatibility. 34 "availability-sets-enabled": schema.Omit, 35 } 36 37 type azureEnvironConfig struct { 38 *config.Config 39 attrs map[string]interface{} 40 } 41 42 func (cfg *azureEnvironConfig) location() string { 43 return cfg.attrs["location"].(string) 44 } 45 46 func (cfg *azureEnvironConfig) managementSubscriptionId() string { 47 return cfg.attrs["management-subscription-id"].(string) 48 } 49 50 func (cfg *azureEnvironConfig) managementCertificate() string { 51 return cfg.attrs["management-certificate"].(string) 52 } 53 54 func (cfg *azureEnvironConfig) storageAccountName() string { 55 return cfg.attrs["storage-account-name"].(string) 56 } 57 58 func (cfg *azureEnvironConfig) forceImageName() string { 59 return cfg.attrs["force-image-name"].(string) 60 } 61 62 func (cfg *azureEnvironConfig) availabilitySetsEnabled() bool { 63 enabled, _ := cfg.attrs["availability-sets-enabled"].(bool) 64 return enabled 65 } 66 67 func (prov azureEnvironProvider) newConfig(cfg *config.Config) (*azureEnvironConfig, error) { 68 validCfg, err := prov.Validate(cfg, nil) 69 if err != nil { 70 return nil, err 71 } 72 result := new(azureEnvironConfig) 73 result.Config = validCfg 74 result.attrs = validCfg.UnknownAttrs() 75 return result, nil 76 } 77 78 // Validate ensures that config is a valid configuration for this 79 // provider like specified in the EnvironProvider interface. 80 func (prov azureEnvironProvider) Validate(cfg, oldCfg *config.Config) (*config.Config, error) { 81 // Validate base configuration change before validating Azure specifics. 82 err := config.Validate(cfg, oldCfg) 83 if err != nil { 84 return nil, err 85 } 86 87 // User cannot change availability-sets-enabled after environment is prepared. 88 if oldCfg != nil { 89 if oldCfg.AllAttrs()["availability-sets-enabled"] != cfg.AllAttrs()["availability-sets-enabled"] { 90 return nil, fmt.Errorf("cannot change availability-sets-enabled") 91 } 92 } 93 94 validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults) 95 if err != nil { 96 return nil, err 97 } 98 envCfg := new(azureEnvironConfig) 99 envCfg.Config = cfg 100 envCfg.attrs = validated 101 102 cert := envCfg.managementCertificate() 103 if cert == "" { 104 certPath := envCfg.attrs["management-certificate-path"].(string) 105 pemData, err := readPEMFile(certPath) 106 if err != nil { 107 return nil, fmt.Errorf("invalid management-certificate-path: %s", err) 108 } 109 envCfg.attrs["management-certificate"] = string(pemData) 110 } else { 111 if block, _ := pem.Decode([]byte(cert)); block == nil { 112 return nil, fmt.Errorf("invalid management-certificate: not a PEM encoded certificate") 113 } 114 } 115 delete(envCfg.attrs, "management-certificate-path") 116 117 if envCfg.location() == "" { 118 return nil, fmt.Errorf("environment has no location; you need to set one. E.g. 'West US'") 119 } 120 return cfg.Apply(envCfg.attrs) 121 } 122 123 func readPEMFile(path string) ([]byte, error) { 124 f, err := os.Open(path) 125 if err != nil { 126 return nil, err 127 } 128 defer f.Close() 129 130 // 640K ought to be enough for anybody. 131 data, err := ioutil.ReadAll(io.LimitReader(f, 1024*640)) 132 if err != nil { 133 return nil, err 134 } 135 block, _ := pem.Decode(data) 136 if block == nil { 137 return nil, fmt.Errorf("%q is not a PEM encoded certificate file", path) 138 } 139 return data, nil 140 } 141 142 var boilerplateYAML = ` 143 # https://juju.ubuntu.com/docs/config-azure.html 144 azure: 145 type: azure 146 147 # location specifies the place where instances will be started, 148 # for example: West US, North Europe. 149 # 150 location: West US 151 152 # The following attributes specify Windows Azure Management 153 # information. See: 154 # http://msdn.microsoft.com/en-us/library/windowsazure 155 # for details. 156 # 157 management-subscription-id: 00000000-0000-0000-0000-000000000000 158 management-certificate-path: /home/me/azure.pem 159 160 # storage-account-name holds Windows Azure Storage info. 161 # 162 storage-account-name: abcdefghijkl 163 164 # force-image-name overrides the OS image selection to use a fixed 165 # image for all deployments. Most useful for developers. 166 # 167 # force-image-name: b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-13_10-amd64-server-DEVELOPMENT-20130713-Juju_ALPHA-en-us-30GB 168 169 # image-stream chooses a simplestreams stream from which to select 170 # OS images, for example daily or released images (or any other stream 171 # available on simplestreams). 172 # 173 # image-stream: "released" 174 175 # agent-stream chooses a simplestreams stream from which to select tools, 176 # for example released or proposed tools (or any other stream available 177 # on simplestreams). 178 # 179 # agent-stream: "released" 180 181 # Whether or not to refresh the list of available updates for an 182 # OS. The default option of true is recommended for use in 183 # production systems, but disabling this can speed up local 184 # deployments for development or testing. 185 # 186 # enable-os-refresh-update: true 187 188 # Whether or not to perform OS upgrades when machines are 189 # provisioned. The default option of true is recommended for use 190 # in production systems, but disabling this can speed up local 191 # deployments for development or testing. 192 # 193 # enable-os-upgrade: true 194 195 `[1:] 196 197 func (prov azureEnvironProvider) BoilerplateConfig() string { 198 return boilerplateYAML 199 } 200 201 // SecretAttrs is specified in the EnvironProvider interface. 202 func (prov azureEnvironProvider) SecretAttrs(cfg *config.Config) (map[string]string, error) { 203 secretAttrs := make(map[string]string) 204 azureCfg, err := prov.newConfig(cfg) 205 if err != nil { 206 return nil, err 207 } 208 secretAttrs["management-certificate"] = azureCfg.managementCertificate() 209 return secretAttrs, nil 210 }