LEFT | RIGHT |
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package juju_test | 4 package juju_test |
5 | 5 |
6 import ( | 6 import ( |
7 "fmt" | 7 "fmt" |
| 8 "os" |
8 "time" | 9 "time" |
9 | 10 |
10 gc "launchpad.net/gocheck" | 11 gc "launchpad.net/gocheck" |
11 | 12 |
12 "launchpad.net/juju-core/constraints" | 13 "launchpad.net/juju-core/constraints" |
13 "launchpad.net/juju-core/environs" | 14 "launchpad.net/juju-core/environs" |
14 "launchpad.net/juju-core/environs/bootstrap" | 15 "launchpad.net/juju-core/environs/bootstrap" |
15 "launchpad.net/juju-core/environs/config" | 16 "launchpad.net/juju-core/environs/config" |
16 "launchpad.net/juju-core/environs/configstore" | 17 "launchpad.net/juju-core/environs/configstore" |
17 envtesting "launchpad.net/juju-core/environs/testing" | 18 envtesting "launchpad.net/juju-core/environs/testing" |
18 "launchpad.net/juju-core/errors" | |
19 "launchpad.net/juju-core/juju" | 19 "launchpad.net/juju-core/juju" |
20 "launchpad.net/juju-core/provider/dummy" | 20 "launchpad.net/juju-core/provider/dummy" |
21 "launchpad.net/juju-core/state/api" | 21 "launchpad.net/juju-core/state/api" |
22 coretesting "launchpad.net/juju-core/testing" | 22 coretesting "launchpad.net/juju-core/testing" |
23 jc "launchpad.net/juju-core/testing/checkers" | 23 jc "launchpad.net/juju-core/testing/checkers" |
24 "launchpad.net/juju-core/testing/testbase" | 24 "launchpad.net/juju-core/testing/testbase" |
25 ) | 25 ) |
26 | 26 |
27 type NewAPIConnSuite struct { | 27 type NewAPIConnSuite struct { |
28 testbase.LoggingSuite | 28 testbase.LoggingSuite |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 } | 71 } |
72 | 72 |
73 func (*NewAPIClientSuite) TestNameDefault(c *gc.C) { | 73 func (*NewAPIClientSuite) TestNameDefault(c *gc.C) { |
74 defer coretesting.MakeMultipleEnvHome(c).Restore() | 74 defer coretesting.MakeMultipleEnvHome(c).Restore() |
75 // The connection logic should not delay the config connection | 75 // The connection logic should not delay the config connection |
76 // at all when there is no environment info available. | 76 // at all when there is no environment info available. |
77 // Make sure of that by providing a suitably long delay | 77 // Make sure of that by providing a suitably long delay |
78 // and checking that the connection happens within that | 78 // and checking that the connection happens within that |
79 // time. | 79 // time. |
80 defer testbase.PatchValue(juju.ProviderConnectDelay, coretesting.LongWai
t).Restore() | 80 defer testbase.PatchValue(juju.ProviderConnectDelay, coretesting.LongWai
t).Restore() |
81 » bootstrapEnv(c, coretesting.SampleEnvName) | 81 » bootstrapEnv(c, coretesting.SampleEnvName, nil) |
82 | 82 |
83 startTime := time.Now() | 83 startTime := time.Now() |
84 apiclient, err := juju.NewAPIClientFromName("") | 84 apiclient, err := juju.NewAPIClientFromName("") |
85 c.Assert(err, gc.IsNil) | 85 c.Assert(err, gc.IsNil) |
86 defer apiclient.Close() | 86 defer apiclient.Close() |
87 c.Assert(time.Since(startTime), jc.LessThan, coretesting.LongWait) | 87 c.Assert(time.Since(startTime), jc.LessThan, coretesting.LongWait) |
88 | 88 |
89 // We should get the default sample environment if we ask for "" | 89 // We should get the default sample environment if we ask for "" |
90 assertEnvironmentName(c, apiclient, coretesting.SampleEnvName) | 90 assertEnvironmentName(c, apiclient, coretesting.SampleEnvName) |
91 } | 91 } |
92 | 92 |
93 func (*NewAPIClientSuite) TestNameNotDefault(c *gc.C) { | 93 func (*NewAPIClientSuite) TestNameNotDefault(c *gc.C) { |
94 defer coretesting.MakeMultipleEnvHome(c).Restore() | 94 defer coretesting.MakeMultipleEnvHome(c).Restore() |
95 » // The default environment is "erewhemos", make sure we get the other on
e. | 95 » envName := coretesting.SampleCertName + "-2" |
96 » const envName = "erewhemos-2" | 96 » bootstrapEnv(c, envName, nil) |
97 » bootstrapEnv(c, envName) | |
98 apiclient, err := juju.NewAPIClientFromName(envName) | 97 apiclient, err := juju.NewAPIClientFromName(envName) |
99 c.Assert(err, gc.IsNil) | 98 c.Assert(err, gc.IsNil) |
100 defer apiclient.Close() | 99 defer apiclient.Close() |
101 assertEnvironmentName(c, apiclient, envName) | 100 assertEnvironmentName(c, apiclient, envName) |
102 } | 101 } |
103 | 102 |
104 func (*NewAPIClientSuite) TestWithInfoOnly(c *gc.C) { | 103 func (*NewAPIClientSuite) TestWithInfoOnly(c *gc.C) { |
105 defer coretesting.MakeEmptyFakeHome(c).Restore() | 104 defer coretesting.MakeEmptyFakeHome(c).Restore() |
106 creds := configstore.APICredentials{ | |
107 User: "foo", | |
108 Password: "foopass", | |
109 } | |
110 endpoint := configstore.APIEndpoint{ | |
111 Addresses: []string{"foo.com"}, | |
112 CACert: "certificated", | |
113 } | |
114 store := newConfigStore("noconfig", &environInfo{ | 105 store := newConfigStore("noconfig", &environInfo{ |
115 » » creds: creds, | 106 » » creds: configstore.APICredentials{ |
116 » » endpoint: endpoint, | 107 » » » User: "foo", |
| 108 » » » Password: "foopass", |
| 109 » » }, |
| 110 » » endpoint: configstore.APIEndpoint{ |
| 111 » » » Addresses: []string{"foo.com"}, |
| 112 » » » CACert: "certificated", |
| 113 » » }, |
117 }) | 114 }) |
118 | 115 |
119 called := 0 | 116 called := 0 |
120 expectState := new(api.State) | 117 expectState := new(api.State) |
121 apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (*api.State, error
) { | 118 apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (*api.State, error
) { |
122 c.Check(apiInfo.Tag, gc.Equals, "user-foo") | 119 c.Check(apiInfo.Tag, gc.Equals, "user-foo") |
123 c.Check(string(apiInfo.CACert), gc.Equals, "certificated") | 120 c.Check(string(apiInfo.CACert), gc.Equals, "certificated") |
124 c.Check(apiInfo.Tag, gc.Equals, "user-foo") | 121 c.Check(apiInfo.Tag, gc.Equals, "user-foo") |
125 c.Check(apiInfo.Password, gc.Equals, "foopass") | 122 c.Check(apiInfo.Password, gc.Equals, "foopass") |
126 c.Check(opts, gc.DeepEquals, api.DefaultDialOpts()) | 123 c.Check(opts, gc.DeepEquals, api.DefaultDialOpts()) |
127 called++ | 124 called++ |
128 return expectState, nil | 125 return expectState, nil |
129 } | 126 } |
130 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore() | 127 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore() |
131 st, err := juju.NewAPIFromName("noconfig", store) | 128 st, err := juju.NewAPIFromName("noconfig", store) |
132 c.Assert(err, gc.IsNil) | 129 c.Assert(err, gc.IsNil) |
133 c.Assert(st, gc.Equals, expectState) | 130 c.Assert(st, gc.Equals, expectState) |
134 c.Assert(called, gc.Equals, 1) | 131 c.Assert(called, gc.Equals, 1) |
135 } | 132 } |
136 | 133 |
137 func (*NewAPIClientSuite) TestWithInfoError(c *gc.C) { | 134 func (*NewAPIClientSuite) TestWithInfoError(c *gc.C) { |
138 defer coretesting.MakeEmptyFakeHome(c).Restore() | 135 defer coretesting.MakeEmptyFakeHome(c).Restore() |
139 expectErr := fmt.Errorf("an error") | 136 expectErr := fmt.Errorf("an error") |
140 » store := newConfigStore("noconfig", &environInfo{ | 137 » store := newConfigStoreWithError(expectErr) |
141 » » err: expectErr, | |
142 » }) | |
143 defer testbase.PatchValue(juju.APIOpen, panicAPIOpen).Restore() | 138 defer testbase.PatchValue(juju.APIOpen, panicAPIOpen).Restore() |
144 client, err := juju.NewAPIFromName("noconfig", store) | 139 client, err := juju.NewAPIFromName("noconfig", store) |
145 c.Assert(err, gc.Equals, expectErr) | 140 c.Assert(err, gc.Equals, expectErr) |
146 c.Assert(client, gc.IsNil) | 141 c.Assert(client, gc.IsNil) |
147 } | 142 } |
148 | 143 |
149 func panicAPIOpen(apiInfo *api.Info, opts api.DialOpts) (*api.State, error) { | 144 func panicAPIOpen(apiInfo *api.Info, opts api.DialOpts) (*api.State, error) { |
150 panic("api.Open called unexpectedly") | 145 panic("api.Open called unexpectedly") |
151 } | 146 } |
152 | 147 |
153 func (*NewAPIClientSuite) TestWithInfoNoAddresses(c *gc.C) { | 148 func (*NewAPIClientSuite) TestWithInfoNoAddresses(c *gc.C) { |
154 defer coretesting.MakeEmptyFakeHome(c).Restore() | 149 defer coretesting.MakeEmptyFakeHome(c).Restore() |
155 endpoint := configstore.APIEndpoint{ | |
156 Addresses: []string{}, | |
157 CACert: "certificated", | |
158 } | |
159 store := newConfigStore("noconfig", &environInfo{ | 150 store := newConfigStore("noconfig", &environInfo{ |
160 » » endpoint: endpoint, | 151 » » endpoint: configstore.APIEndpoint{ |
| 152 » » » Addresses: []string{}, |
| 153 » » » CACert: "certificated", |
| 154 » » }, |
161 }) | 155 }) |
162 defer testbase.PatchValue(juju.APIOpen, panicAPIOpen).Restore() | 156 defer testbase.PatchValue(juju.APIOpen, panicAPIOpen).Restore() |
163 | 157 |
164 st, err := juju.NewAPIFromName("noconfig", store) | 158 st, err := juju.NewAPIFromName("noconfig", store) |
165 c.Assert(err, gc.ErrorMatches, `environment "noconfig" not found`) | 159 c.Assert(err, gc.ErrorMatches, `environment "noconfig" not found`) |
166 c.Assert(st, gc.IsNil) | 160 c.Assert(st, gc.IsNil) |
167 } | 161 } |
168 | 162 |
169 func (*NewAPIClientSuite) TestWithInfoAPIOpenError(c *gc.C) { | 163 func (*NewAPIClientSuite) TestWithInfoAPIOpenError(c *gc.C) { |
170 defer coretesting.MakeEmptyFakeHome(c).Restore() | 164 defer coretesting.MakeEmptyFakeHome(c).Restore() |
171 endpoint := configstore.APIEndpoint{ | |
172 Addresses: []string{"foo.com"}, | |
173 } | |
174 store := newConfigStore("noconfig", &environInfo{ | 165 store := newConfigStore("noconfig", &environInfo{ |
175 » » endpoint: endpoint, | 166 » » endpoint: configstore.APIEndpoint{ |
| 167 » » » Addresses: []string{"foo.com"}, |
| 168 » » }, |
176 }) | 169 }) |
177 | 170 |
178 expectErr := fmt.Errorf("an error") | 171 expectErr := fmt.Errorf("an error") |
179 apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (*api.State, error
) { | 172 apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (*api.State, error
) { |
180 return nil, expectErr | 173 return nil, expectErr |
181 } | 174 } |
182 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore() | 175 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore() |
183 st, err := juju.NewAPIFromName("noconfig", store) | 176 st, err := juju.NewAPIFromName("noconfig", store) |
184 c.Assert(err, gc.Equals, expectErr) | 177 c.Assert(err, gc.Equals, expectErr) |
185 c.Assert(st, gc.IsNil) | 178 c.Assert(st, gc.IsNil) |
186 } | 179 } |
187 | 180 |
188 func (*NewAPIClientSuite) TestWithSlowInfoConnect(c *gc.C) { | 181 func (*NewAPIClientSuite) TestWithSlowInfoConnect(c *gc.C) { |
189 defer coretesting.MakeSampleHome(c).Restore() | 182 defer coretesting.MakeSampleHome(c).Restore() |
190 » bootstrapEnv(c, coretesting.SampleEnvName) | 183 » bootstrapEnv(c, coretesting.SampleEnvName, nil) |
191 » endpoint := configstore.APIEndpoint{ | |
192 » » Addresses: []string{"infoapi.com"}, | |
193 » } | |
194 store := newConfigStore(coretesting.SampleEnvName, &environInfo{ | 184 store := newConfigStore(coretesting.SampleEnvName, &environInfo{ |
195 » » endpoint: endpoint, | 185 » » endpoint: configstore.APIEndpoint{ |
| 186 » » » Addresses: []string{"infoapi.com"}, |
| 187 » » }, |
196 }) | 188 }) |
197 | 189 |
198 infoOpenedState := new(api.State) | 190 infoOpenedState := new(api.State) |
199 infoEndpointOpened := make(chan struct{}) | 191 infoEndpointOpened := make(chan struct{}) |
200 cfgOpenedState := new(api.State) | 192 cfgOpenedState := new(api.State) |
201 // On a sample run with no delay, the logic took 45ms to run, so | 193 // On a sample run with no delay, the logic took 45ms to run, so |
202 // we make the delay slightly more than that, so that if the | 194 // we make the delay slightly more than that, so that if the |
203 // logic doesn't delay at all, the test will fail reasonably consistentl
y. | 195 // logic doesn't delay at all, the test will fail reasonably consistentl
y. |
204 defer testbase.PatchValue(juju.ProviderConnectDelay, 50*time.Millisecond
).Restore() | 196 defer testbase.PatchValue(juju.ProviderConnectDelay, 50*time.Millisecond
).Restore() |
205 apiOpen := func(info *api.Info, opts api.DialOpts) (*api.State, error) { | 197 apiOpen := func(info *api.Info, opts api.DialOpts) (*api.State, error) { |
(...skipping 26 matching lines...) Expand all Loading... |
232 select { | 224 select { |
233 case st := <-stateClosed: | 225 case st := <-stateClosed: |
234 c.Assert(st, gc.Equals, infoOpenedState) | 226 c.Assert(st, gc.Equals, infoOpenedState) |
235 case <-time.After(coretesting.LongWait): | 227 case <-time.After(coretesting.LongWait): |
236 c.Errorf("timed out waiting for state to be closed") | 228 c.Errorf("timed out waiting for state to be closed") |
237 } | 229 } |
238 } | 230 } |
239 | 231 |
240 func (*NewAPIClientSuite) TestWithSlowConfigConnect(c *gc.C) { | 232 func (*NewAPIClientSuite) TestWithSlowConfigConnect(c *gc.C) { |
241 defer coretesting.MakeSampleHome(c).Restore() | 233 defer coretesting.MakeSampleHome(c).Restore() |
242 » bootstrapEnv(c, coretesting.SampleEnvName) | 234 » bootstrapEnv(c, coretesting.SampleEnvName, nil) |
243 » endpoint := configstore.APIEndpoint{ | |
244 » » Addresses: []string{"infoapi.com"}, | |
245 » } | |
246 store := newConfigStore(coretesting.SampleEnvName, &environInfo{ | 235 store := newConfigStore(coretesting.SampleEnvName, &environInfo{ |
247 » » endpoint: endpoint, | 236 » » endpoint: configstore.APIEndpoint{ |
| 237 » » » Addresses: []string{"infoapi.com"}, |
| 238 » » }, |
248 }) | 239 }) |
249 | 240 |
250 infoOpenedState := new(api.State) | 241 infoOpenedState := new(api.State) |
251 infoEndpointOpened := make(chan struct{}) | 242 infoEndpointOpened := make(chan struct{}) |
252 cfgOpenedState := new(api.State) | 243 cfgOpenedState := new(api.State) |
253 cfgEndpointOpened := make(chan struct{}) | 244 cfgEndpointOpened := make(chan struct{}) |
254 | 245 |
255 defer testbase.PatchValue(juju.ProviderConnectDelay, 0*time.Second).Rest
ore() | 246 defer testbase.PatchValue(juju.ProviderConnectDelay, 0*time.Second).Rest
ore() |
256 apiOpen := func(info *api.Info, opts api.DialOpts) (*api.State, error) { | 247 apiOpen := func(info *api.Info, opts api.DialOpts) (*api.State, error) { |
257 if info.Addrs[0] == "infoapi.com" { | 248 if info.Addrs[0] == "infoapi.com" { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 select { | 293 select { |
303 case st := <-stateClosed: | 294 case st := <-stateClosed: |
304 c.Assert(st, gc.Equals, cfgOpenedState) | 295 c.Assert(st, gc.Equals, cfgOpenedState) |
305 case <-time.After(coretesting.LongWait): | 296 case <-time.After(coretesting.LongWait): |
306 c.Errorf("timed out waiting for state to be closed") | 297 c.Errorf("timed out waiting for state to be closed") |
307 } | 298 } |
308 } | 299 } |
309 | 300 |
310 func (*NewAPIClientSuite) TestBothErrror(c *gc.C) { | 301 func (*NewAPIClientSuite) TestBothErrror(c *gc.C) { |
311 defer coretesting.MakeSampleHome(c).Restore() | 302 defer coretesting.MakeSampleHome(c).Restore() |
312 » bootstrapEnv(c, coretesting.SampleEnvName) | 303 » bootstrapEnv(c, coretesting.SampleEnvName, nil) |
313 » endpoint := configstore.APIEndpoint{ | |
314 » » Addresses: []string{"infoapi.com"}, | |
315 » } | |
316 store := newConfigStore(coretesting.SampleEnvName, &environInfo{ | 304 store := newConfigStore(coretesting.SampleEnvName, &environInfo{ |
317 » » endpoint: endpoint, | 305 » » endpoint: configstore.APIEndpoint{ |
| 306 » » » Addresses: []string{"infoapi.com"}, |
| 307 » » }, |
318 }) | 308 }) |
319 | 309 |
320 defer testbase.PatchValue(juju.ProviderConnectDelay, 0*time.Second).Rest
ore() | 310 defer testbase.PatchValue(juju.ProviderConnectDelay, 0*time.Second).Rest
ore() |
321 apiOpen := func(info *api.Info, opts api.DialOpts) (*api.State, error) { | 311 apiOpen := func(info *api.Info, opts api.DialOpts) (*api.State, error) { |
322 if info.Addrs[0] == "infoapi.com" { | 312 if info.Addrs[0] == "infoapi.com" { |
323 return nil, fmt.Errorf("info connect failed") | 313 return nil, fmt.Errorf("info connect failed") |
324 } | 314 } |
325 return nil, fmt.Errorf("config connect failed") | 315 return nil, fmt.Errorf("config connect failed") |
326 } | 316 } |
327 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore() | 317 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore() |
328 st, err := juju.NewAPIFromName(coretesting.SampleEnvName, store) | 318 st, err := juju.NewAPIFromName(coretesting.SampleEnvName, store) |
329 c.Check(err, gc.ErrorMatches, "config connect failed") | 319 c.Check(err, gc.ErrorMatches, "config connect failed") |
330 c.Check(st, gc.IsNil) | 320 c.Check(st, gc.IsNil) |
331 } | 321 } |
332 | 322 |
333 // TODO(jam): 2013-08-27 This should move somewhere in api.* | 323 // TODO(jam): 2013-08-27 This should move somewhere in api.* |
334 func (*NewAPIClientSuite) TestMultipleCloseOk(c *gc.C) { | 324 func (*NewAPIClientSuite) TestMultipleCloseOk(c *gc.C) { |
335 defer coretesting.MakeSampleHome(c).Restore() | 325 defer coretesting.MakeSampleHome(c).Restore() |
336 » bootstrapEnv(c, "") | 326 » bootstrapEnv(c, "", nil) |
337 client, _ := juju.NewAPIClientFromName("") | 327 client, _ := juju.NewAPIClientFromName("") |
338 c.Assert(client.Close(), gc.IsNil) | 328 c.Assert(client.Close(), gc.IsNil) |
339 c.Assert(client.Close(), gc.IsNil) | 329 c.Assert(client.Close(), gc.IsNil) |
340 c.Assert(client.Close(), gc.IsNil) | 330 c.Assert(client.Close(), gc.IsNil) |
| 331 } |
| 332 |
| 333 func (*NewAPIClientSuite) TestWithBootstrapConfigAndNoEnvironmentsFile(c *gc.C)
{ |
| 334 defer coretesting.MakeSampleHome(c).Restore() |
| 335 store := configstore.NewMem() |
| 336 bootstrapEnv(c, coretesting.SampleEnvName, store) |
| 337 info, err := store.ReadInfo(coretesting.SampleEnvName) |
| 338 c.Assert(err, gc.IsNil) |
| 339 c.Assert(info.BootstrapConfig(), gc.NotNil) |
| 340 c.Assert(info.APIEndpoint().Addresses, gc.HasLen, 0) |
| 341 |
| 342 err = os.Remove(config.JujuHomePath("environments.yaml")) |
| 343 c.Assert(err, gc.IsNil) |
| 344 |
| 345 st, err := juju.NewAPIFromName(coretesting.SampleEnvName, store) |
| 346 c.Check(err, gc.IsNil) |
| 347 st.Close() |
| 348 } |
| 349 |
| 350 func (*NewAPIClientSuite) TestWithBootstrapConfigTakesPrecedence(c *gc.C) { |
| 351 // We want to make sure that the code is using the bootstrap |
| 352 // config rather than information from environments.yaml, |
| 353 // even when there is an entry in environments.yaml |
| 354 // We can do that by changing the info bootstrap config |
| 355 // so it has a different environment name. |
| 356 defer coretesting.MakeMultipleEnvHome(c).Restore() |
| 357 |
| 358 store := configstore.NewMem() |
| 359 bootstrapEnv(c, coretesting.SampleEnvName, store) |
| 360 info, err := store.ReadInfo(coretesting.SampleEnvName) |
| 361 c.Assert(err, gc.IsNil) |
| 362 |
| 363 envName2 := coretesting.SampleCertName + "-2" |
| 364 info2, err := store.CreateInfo(envName2) |
| 365 c.Assert(err, gc.IsNil) |
| 366 info2.SetBootstrapConfig(info.BootstrapConfig()) |
| 367 err = info2.Write() |
| 368 c.Assert(err, gc.IsNil) |
| 369 |
| 370 // Now we have info for envName2 which will actually |
| 371 // cause a connection to the originally bootstrapped |
| 372 // state. |
| 373 st, err := juju.NewAPIFromName(envName2, store) |
| 374 c.Check(err, gc.IsNil) |
| 375 st.Close() |
| 376 |
| 377 // Sanity check that connecting to the envName2 |
| 378 // but with no info fails. |
| 379 // Currently this panics with an "environment not prepared" error. |
| 380 // Disable for now until an upcoming branch fixes it. |
| 381 // err = info2.Destroy() |
| 382 // c.Assert(err, gc.IsNil) |
| 383 // st, err = juju.NewAPIFromName(envName2, store) |
| 384 // if err == nil { |
| 385 // st.Close() |
| 386 // } |
| 387 // c.Assert(err, gc.ErrorMatches, "fooobie") |
341 } | 388 } |
342 | 389 |
343 func assertEnvironmentName(c *gc.C, client *api.Client, expectName string) { | 390 func assertEnvironmentName(c *gc.C, client *api.Client, expectName string) { |
344 envInfo, err := client.EnvironmentInfo() | 391 envInfo, err := client.EnvironmentInfo() |
345 c.Assert(err, gc.IsNil) | 392 c.Assert(err, gc.IsNil) |
346 c.Assert(envInfo.Name, gc.Equals, expectName) | 393 c.Assert(envInfo.Name, gc.Equals, expectName) |
347 } | 394 } |
348 | 395 |
349 func setAPIClosed() (<-chan *api.State, testbase.Restorer) { | 396 func setAPIClosed() (<-chan *api.State, testbase.Restorer) { |
350 stateClosed := make(chan *api.State) | 397 stateClosed := make(chan *api.State) |
351 apiClose := func(st *api.State) error { | 398 apiClose := func(st *api.State) error { |
352 stateClosed <- st | 399 stateClosed <- st |
353 return nil | 400 return nil |
354 } | 401 } |
355 return stateClosed, testbase.PatchValue(juju.APIClose, apiClose) | 402 return stateClosed, testbase.PatchValue(juju.APIClose, apiClose) |
356 } | 403 } |
357 | 404 |
| 405 // newConfigStoreWithError that will return the given |
| 406 // error from ReadInfo. |
| 407 func newConfigStoreWithError(err error) configstore.Storage { |
| 408 return &errorConfigStorage{ |
| 409 Storage: configstore.NewMem(), |
| 410 err: err, |
| 411 } |
| 412 } |
| 413 |
| 414 type errorConfigStorage struct { |
| 415 configstore.Storage |
| 416 err error |
| 417 } |
| 418 |
| 419 func (store *errorConfigStorage) ReadInfo(envName string) (configstore.EnvironIn
fo, error) { |
| 420 return nil, store.err |
| 421 } |
| 422 |
| 423 type environInfo struct { |
| 424 creds configstore.APICredentials |
| 425 endpoint configstore.APIEndpoint |
| 426 bootstrapConfig map[string]interface{} |
| 427 } |
| 428 |
| 429 // newConfigStore returns a storage that contains information |
| 430 // for the environment name. |
358 func newConfigStore(envName string, info *environInfo) configstore.Storage { | 431 func newConfigStore(envName string, info *environInfo) configstore.Storage { |
359 » return &configStorage{ | 432 » store := configstore.NewMem() |
360 » » envs: map[string]*environInfo{ | 433 » newInfo, err := store.CreateInfo(envName) |
361 » » » envName: info, | 434 » if err != nil { |
362 » » }, | 435 » » panic(err) |
363 » } | 436 » } |
364 } | 437 » newInfo.SetAPICredentials(info.creds) |
365 | 438 » newInfo.SetAPIEndpoint(info.endpoint) |
366 type environInfo struct { | 439 » newInfo.SetBootstrapConfig(info.bootstrapConfig) |
367 » configstore.EnvironInfo // panic on methods we don't care about | 440 » err = newInfo.Write() |
368 » creds configstore.APICredentials | 441 » if err != nil { |
369 » endpoint configstore.APIEndpoint | 442 » » panic(err) |
370 » bootstrapConfig map[string]interface{} | 443 » } |
371 » err error | 444 » return store |
372 } | 445 } |
373 | |
374 type configStorage struct { | |
375 » configstore.Storage // panic on methods we don't care about | |
376 » envs map[string]*environInfo | |
377 } | |
378 | |
379 func (store *configStorage) ReadInfo(envName string) (configstore.EnvironInfo, e
rror) { | |
380 » info := store.envs[envName] | |
381 » if info == nil { | |
382 » » return nil, errors.NotFoundf("info on environment %q", envName) | |
383 » } | |
384 » if info.err != nil { | |
385 » » return nil, info.err | |
386 » } | |
387 » return info, nil | |
388 } | |
389 | |
390 func (info *environInfo) APICredentials() configstore.APICredentials { | |
391 » return info.creds | |
392 } | |
393 | |
394 func (info *environInfo) APIEndpoint() configstore.APIEndpoint { | |
395 » return info.endpoint | |
396 } | |
397 | |
398 func (info *environInfo) BootstrapConfig() map[string]interface{} { | |
399 » return info.bootstrapConfig | |
400 } | |
LEFT | RIGHT |