LEFT | RIGHT |
(no file at all) | |
| 1 package openstack |
| 2 |
| 3 import ( |
| 4 "fmt" |
| 5 "launchpad.net/juju-core/environs/config" |
| 6 "launchpad.net/juju-core/schema" |
| 7 "net/url" |
| 8 "os" |
| 9 ) |
| 10 |
| 11 var configChecker = schema.StrictFieldMap( |
| 12 schema.Fields{ |
| 13 "username": schema.String(), |
| 14 "password": schema.String(), |
| 15 "tenant-name": schema.String(), |
| 16 "auth-url": schema.String(), |
| 17 "region": schema.String(), |
| 18 "control-bucket": schema.String(), |
| 19 }, |
| 20 schema.Defaults{ |
| 21 "username": "", |
| 22 "password": "", |
| 23 "tenant-name": "", |
| 24 "auth-url": "", |
| 25 "region": "", |
| 26 "control-bucket": "", |
| 27 }, |
| 28 ) |
| 29 |
| 30 type environConfig struct { |
| 31 *config.Config |
| 32 attrs map[string]interface{} |
| 33 } |
| 34 |
| 35 func (c *environConfig) region() string { |
| 36 return c.attrs["region"].(string) |
| 37 } |
| 38 |
| 39 func (c *environConfig) username() string { |
| 40 return c.attrs["username"].(string) |
| 41 } |
| 42 |
| 43 func (c *environConfig) password() string { |
| 44 return c.attrs["password"].(string) |
| 45 } |
| 46 |
| 47 func (c *environConfig) tenantName() string { |
| 48 return c.attrs["tenant-name"].(string) |
| 49 } |
| 50 |
| 51 func (c *environConfig) authURL() string { |
| 52 return c.attrs["auth-url"].(string) |
| 53 } |
| 54 |
| 55 func (c *environConfig) controlBucket() string { |
| 56 return c.attrs["control-bucket"].(string) |
| 57 } |
| 58 |
| 59 func (p environProvider) newConfig(cfg *config.Config) (*environConfig, error) { |
| 60 valid, err := p.Validate(cfg, nil) |
| 61 if err != nil { |
| 62 return nil, err |
| 63 } |
| 64 return &environConfig{valid, valid.UnknownAttrs()}, nil |
| 65 } |
| 66 |
| 67 func (p environProvider) Validate(cfg, old *config.Config) (valid *config.Config
, err error) { |
| 68 v, err := configChecker.Coerce(cfg.UnknownAttrs(), nil) |
| 69 if err != nil { |
| 70 return nil, err |
| 71 } |
| 72 ecfg := &environConfig{cfg, v.(map[string]interface{})} |
| 73 |
| 74 if ecfg.authURL() != "" { |
| 75 parts, err := url.Parse(ecfg.authURL()) |
| 76 if err != nil || parts.Host == "" || parts.Scheme == "" { |
| 77 return nil, fmt.Errorf("invalid auth-url value %q", ecfg
.authURL()) |
| 78 } |
| 79 } |
| 80 |
| 81 if ecfg.username() == "" || ecfg.password() == "" || ecfg.tenantName() =
= "" || ecfg.authURL() == "" { |
| 82 // TODO(dimitern): get goose client to handle this |
| 83 auth, ok := getEnvAuth() |
| 84 if !ok { |
| 85 return nil, fmt.Errorf("OpenStack environment has no use
rname, password, tenant-name, or auth-url") |
| 86 } |
| 87 ecfg.attrs["username"] = auth.username |
| 88 ecfg.attrs["password"] = auth.password |
| 89 ecfg.attrs["tenant-name"] = auth.tenantName |
| 90 ecfg.attrs["auth-url"] = auth.authURL |
| 91 } |
| 92 // We cannot validate the region name, since each OS installation |
| 93 // can have its own region names - only after authentication the |
| 94 // region names are known (from the service endpoints) |
| 95 if ecfg.region() == "" { |
| 96 region := os.Getenv("OS_REGION_NAME") |
| 97 if region != "" { |
| 98 ecfg.attrs["region"] = region |
| 99 } else { |
| 100 return nil, fmt.Errorf("OpenStack environment has no reg
ion") |
| 101 } |
| 102 } |
| 103 |
| 104 if old != nil { |
| 105 attrs := old.UnknownAttrs() |
| 106 if region, _ := attrs["region"].(string); ecfg.region() != regio
n { |
| 107 return nil, fmt.Errorf("cannot change region from %q to
%q", region, ecfg.region()) |
| 108 } |
| 109 if controlBucket, _ := attrs["control-bucket"].(string); ecfg.co
ntrolBucket() != controlBucket { |
| 110 return nil, fmt.Errorf("cannot change control-bucket fro
m %q to %q", controlBucket, ecfg.controlBucket()) |
| 111 } |
| 112 } |
| 113 |
| 114 switch cfg.FirewallMode() { |
| 115 case config.FwDefault: |
| 116 ecfg.attrs["firewall-mode"] = config.FwInstance |
| 117 case config.FwInstance, config.FwGlobal: |
| 118 default: |
| 119 return nil, fmt.Errorf("unsupported firewall mode: %q", cfg.Fire
wallMode()) |
| 120 } |
| 121 |
| 122 return cfg.Apply(ecfg.attrs) |
| 123 } |
| 124 |
| 125 // TODO(dimitern): temporarily here, until goose client handles this |
| 126 type envAuth struct { |
| 127 username, password, tenantName, authURL string |
| 128 } |
| 129 |
| 130 func getEnvAuth() (auth envAuth, ok bool) { |
| 131 auth = envAuth{ |
| 132 username: os.Getenv("OS_USERNAME"), |
| 133 password: os.Getenv("OS_PASSWORD"), |
| 134 tenantName: os.Getenv("OS_TENANT_NAME"), |
| 135 authURL: os.Getenv("OS_AUTH_URL"), |
| 136 } |
| 137 if auth.username == "" || auth.password == "" || auth.tenantName == "" |
| auth.authURL == "" { |
| 138 return auth, false |
| 139 } |
| 140 return auth, true |
| 141 } |
LEFT | RIGHT |