github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/provider/ec2/config.go (about) 1 // Copyright 2011, 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package ec2 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/juju/schema" 11 "gopkg.in/amz.v3/aws" 12 "gopkg.in/juju/environschema.v1" 13 14 "github.com/juju/juju/environs/config" 15 ) 16 17 var configSchema = environschema.Fields{ 18 "access-key": { 19 Description: "The EC2 access key", 20 EnvVar: "AWS_ACCESS_KEY_ID", 21 Type: environschema.Tstring, 22 Mandatory: true, 23 Group: environschema.AccountGroup, 24 }, 25 "secret-key": { 26 Description: "The EC2 secret key", 27 EnvVar: "AWS_SECRET_ACCESS_KEY", 28 Type: environschema.Tstring, 29 Mandatory: true, 30 Secret: true, 31 Group: environschema.AccountGroup, 32 }, 33 "region": { 34 Description: "The EC2 region to use", 35 Type: environschema.Tstring, 36 }, 37 "vpc-id": { 38 Description: "Use a specific AWS VPC ID (optional). When not specified, Juju requires a default VPC to exist the chosen EC2 account/region.", 39 Example: "vpc-a1b2c3d4", 40 Type: environschema.Tstring, 41 Group: environschema.AccountGroup, 42 Immutable: true, 43 }, 44 "vpc-id-force": { 45 Description: "Force Juju to use the AWS VPC ID specified with vpc-id, when it fails the minimum validation criteria. Not accepted without vpc-id", 46 Type: environschema.Tbool, 47 Group: environschema.AccountGroup, 48 Immutable: true, 49 }, 50 } 51 52 var configFields = func() schema.Fields { 53 fs, _, err := configSchema.ValidationSchema() 54 if err != nil { 55 panic(err) 56 } 57 return fs 58 }() 59 60 var configDefaults = schema.Defaults{ 61 "access-key": "", 62 "secret-key": "", 63 "region": "us-east-1", 64 "vpc-id": "", 65 "vpc-id-force": false, 66 } 67 68 type environConfig struct { 69 *config.Config 70 attrs map[string]interface{} 71 } 72 73 func (c *environConfig) region() string { 74 return c.attrs["region"].(string) 75 } 76 77 func (c *environConfig) accessKey() string { 78 return c.attrs["access-key"].(string) 79 } 80 81 func (c *environConfig) secretKey() string { 82 return c.attrs["secret-key"].(string) 83 } 84 85 func (c *environConfig) vpcID() string { 86 return c.attrs["vpc-id"].(string) 87 } 88 89 func (c *environConfig) forceVPCID() bool { 90 return c.attrs["vpc-id-force"].(bool) 91 } 92 93 func (p environProvider) newConfig(cfg *config.Config) (*environConfig, error) { 94 valid, err := p.Validate(cfg, nil) 95 if err != nil { 96 return nil, err 97 } 98 return &environConfig{valid, valid.UnknownAttrs()}, nil 99 } 100 101 // Schema returns the configuration schema for an environment. 102 func (environProvider) Schema() environschema.Fields { 103 fields, err := config.Schema(configSchema) 104 if err != nil { 105 panic(err) 106 } 107 return fields 108 } 109 110 func validateConfig(cfg, old *config.Config) (*environConfig, error) { 111 // Check for valid changes for the base config values. 112 if err := config.Validate(cfg, old); err != nil { 113 return nil, err 114 } 115 validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults) 116 if err != nil { 117 return nil, err 118 } 119 ecfg := &environConfig{cfg, validated} 120 121 if ecfg.accessKey() == "" || ecfg.secretKey() == "" { 122 auth, err := aws.EnvAuth() 123 if err != nil || ecfg.accessKey() != "" || ecfg.secretKey() != "" { 124 return nil, fmt.Errorf("model has no access-key or secret-key") 125 } 126 ecfg.attrs["access-key"] = auth.AccessKey 127 ecfg.attrs["secret-key"] = auth.SecretKey 128 } 129 130 if _, ok := aws.Regions[ecfg.region()]; !ok { 131 return nil, fmt.Errorf("invalid region name %q", ecfg.region()) 132 } 133 134 if vpcID := ecfg.vpcID(); vpcID != "" && !strings.HasPrefix(vpcID, "vpc-") { 135 return nil, fmt.Errorf("vpc-id: %q is not a valid AWS VPC ID", vpcID) 136 } else if vpcID == "" && ecfg.forceVPCID() { 137 return nil, fmt.Errorf("cannot use vpc-id-force without specifying vpc-id as well") 138 } 139 140 if old != nil { 141 attrs := old.UnknownAttrs() 142 if region, _ := attrs["region"].(string); ecfg.region() != region { 143 return nil, fmt.Errorf("cannot change region from %q to %q", region, ecfg.region()) 144 } 145 146 if vpcID, _ := attrs["vpc-id"].(string); vpcID != ecfg.vpcID() { 147 return nil, fmt.Errorf("cannot change vpc-id from %q to %q", vpcID, ecfg.vpcID()) 148 } 149 150 if forceVPCID, _ := attrs["vpc-id-force"].(bool); forceVPCID != ecfg.forceVPCID() { 151 return nil, fmt.Errorf("cannot change vpc-id-force from %v to %v", forceVPCID, ecfg.forceVPCID()) 152 } 153 } 154 155 // ssl-hostname-verification cannot be disabled 156 if !ecfg.SSLHostnameVerification() { 157 return nil, fmt.Errorf("disabling ssh-hostname-verification is not supported") 158 } 159 return ecfg, nil 160 }