Merge lp:~allenap/juju-core/maas-environment-uuid-use into lp:~go-bot/juju-core/trunk

Proposed by Gavin Panella
Status: Merged
Approved by: Ian Booth
Approved revision: no longer in the source branch.
Merged at revision: 1985
Proposed branch: lp:~allenap/juju-core/maas-environment-uuid-use
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 712 lines (+186/-76)
9 files modified
provider/maas/config.go (+16/-2)
provider/maas/config_test.go (+17/-3)
provider/maas/environ.go (+4/-2)
provider/maas/environ_test.go (+29/-34)
provider/maas/environprovider.go (+21/-1)
provider/maas/environprovider_test.go (+44/-3)
provider/maas/instance_test.go (+15/-13)
provider/maas/maas_test.go (+24/-2)
provider/maas/storage_test.go (+16/-16)
To merge this branch: bzr merge lp:~allenap/juju-core/maas-environment-uuid-use
Reviewer Review Type Date Requested Status
Tim Penhey (community) conditional Approve
Review via email: mp+191249@code.launchpad.net

Commit message

Use environment-uuid when interacting with MAAS

The environment-uuid is passed - as agent_name - to MAAS when acquiring
and listing nodes. This will allow multiple Juju environments to coexist
in a single MAAS user's account.

In addition, it prevents environment-uuid from being set in
environments.yaml, and returns an appropriate error message. This is
intended to stop people from inadvertently clobbering existing
environments.

It also starts cleaning up MAAS's providerSuite by dropping the environ
attribute in favour of makeEnviron(). The former was initialised to a
half-working environ that caused strange test failures.

https://codereview.appspot.com/14644045/

Description of the change

Use environment-uuid when interacting with MAAS

The environment-uuid is passed - as agent_name - to MAAS when acquiring
and listing nodes. This will allow multiple Juju environments to coexist
in a single MAAS user's account.

In addition, it prevents environment-uuid from being set in
environments.yaml, and returns an appropriate error message. This is
intended to stop people from inadvertently clobbering existing
environments.

It also starts cleaning up MAAS's providerSuite by dropping the environ
attribute in favour of makeEnviron(). The former was initialised to a
half-working environ that caused strange test failures.

https://codereview.appspot.com/14644045/

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

Reviewers: mp+191249_code.launchpad.net,

Message:
Please take a look.

Description:
Use environment-uuid when interacting with MAAS

The environment-uuid is passed - as agent_name - to MAAS when acquiring
and listing nodes. This will allow multiple Juju environments to coexist
in a single MAAS user's account.

In addition, it prevents environment-uuid from being set in
environments.yaml, and returns an appropriate error message. This is
intended to stop people from inadvertently clobbering existing
environments.

It also starts cleaning up MAAS's providerSuite by dropping the environ
attribute in favour of makeEnviron(). The former was initialised to a
half-working environ that caused strange test failures.

https://code.launchpad.net/~allenap/juju-core/maas-environment-uuid-use/+merge/191249

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/14644045/

Affected files (+188, -76 lines):
   A [revision details]
   M provider/maas/config.go
   M provider/maas/config_test.go
   M provider/maas/environ.go
   M provider/maas/environ_test.go
   M provider/maas/environprovider.go
   M provider/maas/environprovider_test.go
   M provider/maas/instance_test.go
   M provider/maas/maas_test.go
   M provider/maas/storage_test.go

Revision history for this message
Gavin Panella (allenap) wrote :
Revision history for this message
Tim Penhey (thumper) wrote :

LGTM - with one question and one concern.

What does older MAAS installs do with unexpected GET parameters? When
the new agent_name field is passed through, is this going to cause
problems with older systems? Also, I wonder where we should document
the required versions.

I foresee a problem when a new juju is running against an older MAAS,
the new agent_name is passed through, and also passed through as a
filter when listing. Is the unknown field similarly ignored by the
filter code?

https://codereview.appspot.com/14644045/diff/4001/provider/maas/config.go
File provider/maas/config.go (right):

https://codereview.appspot.com/14644045/diff/4001/provider/maas/config.go#newcode23
provider/maas/config.go:23: "environment-uuid": schema.String(),
I do think that we should move this into the general environ config, but
this can happen later. For expediency, I'm happy to have this just in
MAAS for now.

https://codereview.appspot.com/14644045/diff/4001/provider/maas/environ.go
File provider/maas/environ.go (right):

https://codereview.appspot.com/14644045/diff/4001/provider/maas/environ.go#newcode174
provider/maas/environ.go:174: acquireParams.Add("agent_name",
environ.ecfg().maasEnvironmentUUID())
Is "agent_name" a new MAAS parameter? The current docs don't list it.

https://codereview.appspot.com/14644045/diff/4001/provider/maas/environ.go#newcode326
provider/maas/environ.go:326: filter.Add("agent_name",
environ.ecfg().maasEnvironmentUUID())
Beautiful :-)

https://codereview.appspot.com/14644045/diff/4001/provider/maas/environprovider.go
File provider/maas/environprovider.go (right):

https://codereview.appspot.com/14644045/diff/4001/provider/maas/environprovider.go#newcode45
provider/maas/environprovider.go:45: attrs := cfg.UnknownAttrs()
Didn't this bit land as r1984 on lp:juju-core?

https://codereview.appspot.com/14644045/diff/4001/provider/maas/instance_test.go
File provider/maas/instance_test.go (right):

https://codereview.appspot.com/14644045/diff/4001/provider/maas/instance_test.go#newcode39
provider/maas/instance_test.go:39: func (s *instanceTest)
TestStringWithoutHostname(c *gc.C) {
Thank you. There is a tendency in some juju tests to have too much
tested in one test.

https://codereview.appspot.com/14644045/

Revision history for this message
Tim Penhey (thumper) wrote :

As long as the "agent_name" is ignored by older MAAS versions, this should be fine.

review: Approve (conditional)
Revision history for this message
Julian Edwards (julian-edwards) wrote :

It will be ignored, by design. This is a good thing, it basically leaves the functionality unaltered on old maases.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'provider/maas/config.go'
--- provider/maas/config.go 2013-08-09 04:58:34 +0000
+++ provider/maas/config.go 2013-10-15 16:59:34 +0000
@@ -18,8 +18,15 @@
18 // maas-oauth is a colon-separated triplet of:18 // maas-oauth is a colon-separated triplet of:
19 // consumer-key:resource-token:resource-secret19 // consumer-key:resource-token:resource-secret
20 "maas-oauth": schema.String(),20 "maas-oauth": schema.String(),
21}21 // environment-uuid is an optional UUID to group the machines
22var configDefaults = schema.Defaults{}22 // acquired from MAAS, to support multiple environments per MAAS user.
23 "environment-uuid": schema.String(),
24}
25var configDefaults = schema.Defaults{
26 // For backward-compatibility, environment-uuid is the empty string
27 // by default. However, new environments should all use a UUID.
28 "environment-uuid": "",
29}
2330
24type maasEnvironConfig struct {31type maasEnvironConfig struct {
25 *config.Config32 *config.Config
@@ -34,6 +41,13 @@
34 return cfg.attrs["maas-oauth"].(string)41 return cfg.attrs["maas-oauth"].(string)
35}42}
3643
44func (cfg *maasEnvironConfig) maasEnvironmentUUID() string {
45 if uuid, ok := cfg.attrs["environment-uuid"].(string); ok {
46 return uuid
47 }
48 return ""
49}
50
37func (prov maasEnvironProvider) newConfig(cfg *config.Config) (*maasEnvironConfig, error) {51func (prov maasEnvironProvider) newConfig(cfg *config.Config) (*maasEnvironConfig, error) {
38 validCfg, err := prov.Validate(cfg, nil)52 validCfg, err := prov.Validate(cfg, nil)
39 if err != nil {53 if err != nil {
4054
=== modified file 'provider/maas/config_test.go'
--- provider/maas/config_test.go 2013-09-20 02:33:04 +0000
+++ provider/maas/config_test.go 2013-10-15 16:59:34 +0000
@@ -9,6 +9,7 @@
9 "launchpad.net/juju-core/environs"9 "launchpad.net/juju-core/environs"
10 "launchpad.net/juju-core/testing"10 "launchpad.net/juju-core/testing"
11 "launchpad.net/juju-core/testing/testbase"11 "launchpad.net/juju-core/testing/testbase"
12 "launchpad.net/juju-core/utils"
12)13)
1314
14type configSuite struct {15type configSuite struct {
@@ -43,17 +44,30 @@
43 server := "http://maas.testing.invalid/maas/"44 server := "http://maas.testing.invalid/maas/"
44 oauth := "consumer-key:resource-token:resource-secret"45 oauth := "consumer-key:resource-token:resource-secret"
45 future := "futurama"46 future := "futurama"
47 uuid, err := utils.NewUUID()
48 c.Assert(err, gc.IsNil)
46 ecfg, err := newConfig(map[string]interface{}{49 ecfg, err := newConfig(map[string]interface{}{
47 "maas-server": server,50 "maas-server": server,
48 "maas-oauth": oauth,51 "maas-oauth": oauth,
49 "future-key": future,52 "environment-uuid": uuid.String(),
53 "future-key": future,
50 })54 })
51 c.Assert(err, gc.IsNil)55 c.Assert(err, gc.IsNil)
52 c.Check(ecfg.maasServer(), gc.Equals, server)56 c.Check(ecfg.maasServer(), gc.Equals, server)
53 c.Check(ecfg.maasOAuth(), gc.DeepEquals, oauth)57 c.Check(ecfg.maasOAuth(), gc.DeepEquals, oauth)
58 c.Check(ecfg.maasEnvironmentUUID(), gc.Equals, uuid.String())
54 c.Check(ecfg.UnknownAttrs()["future-key"], gc.DeepEquals, future)59 c.Check(ecfg.UnknownAttrs()["future-key"], gc.DeepEquals, future)
55}60}
5661
62func (*configSuite) TestEnvironmentUUIDDefault(c *gc.C) {
63 ecfg, err := newConfig(map[string]interface{}{
64 "maas-server": "http://maas.testing.invalid/maas/",
65 "maas-oauth": "consumer-key:resource-token:resource-secret",
66 })
67 c.Assert(err, gc.IsNil)
68 c.Check(ecfg.maasEnvironmentUUID(), gc.Equals, "")
69}
70
57func (*configSuite) TestChecksWellFormedMaasServer(c *gc.C) {71func (*configSuite) TestChecksWellFormedMaasServer(c *gc.C) {
58 _, err := newConfig(map[string]interface{}{72 _, err := newConfig(map[string]interface{}{
59 "maas-server": "This should have been a URL.",73 "maas-server": "This should have been a URL.",
6074
=== modified file 'provider/maas/environ.go'
--- provider/maas/environ.go 2013-10-02 00:29:29 +0000
+++ provider/maas/environ.go 2013-10-15 16:59:34 +0000
@@ -170,12 +170,13 @@
170170
171// acquireNode allocates a node from the MAAS.171// acquireNode allocates a node from the MAAS.
172func (environ *maasEnviron) acquireNode(cons constraints.Value, possibleTools tools.List) (gomaasapi.MAASObject, *tools.Tools, error) {172func (environ *maasEnviron) acquireNode(cons constraints.Value, possibleTools tools.List) (gomaasapi.MAASObject, *tools.Tools, error) {
173 constraintsParams := convertConstraints(cons)173 acquireParams := convertConstraints(cons)
174 acquireParams.Add("agent_name", environ.ecfg().maasEnvironmentUUID())
174 var result gomaasapi.JSONObject175 var result gomaasapi.JSONObject
175 var err error176 var err error
176 for a := shortAttempt.Start(); a.Next(); {177 for a := shortAttempt.Start(); a.Next(); {
177 client := environ.getMAASClient().GetSubObject("nodes/")178 client := environ.getMAASClient().GetSubObject("nodes/")
178 result, err = client.CallPost("acquire", constraintsParams)179 result, err = client.CallPost("acquire", acquireParams)
179 if err == nil {180 if err == nil {
180 break181 break
181 }182 }
@@ -322,6 +323,7 @@
322func (environ *maasEnviron) instances(ids []instance.Id) ([]instance.Instance, error) {323func (environ *maasEnviron) instances(ids []instance.Id) ([]instance.Instance, error) {
323 nodeListing := environ.getMAASClient().GetSubObject("nodes")324 nodeListing := environ.getMAASClient().GetSubObject("nodes")
324 filter := getSystemIdValues(ids)325 filter := getSystemIdValues(ids)
326 filter.Add("agent_name", environ.ecfg().maasEnvironmentUUID())
325 listNodeObjects, err := nodeListing.CallGet("list", filter)327 listNodeObjects, err := nodeListing.CallGet("list", filter)
326 if err != nil {328 if err != nil {
327 return nil, err329 return nil, err
328330
=== modified file 'provider/maas/environ_test.go'
--- provider/maas/environ_test.go 2013-10-01 12:03:33 +0000
+++ provider/maas/environ_test.go 2013-10-15 16:59:34 +0000
@@ -26,7 +26,6 @@
26 "launchpad.net/juju-core/instance"26 "launchpad.net/juju-core/instance"
27 "launchpad.net/juju-core/juju/testing"27 "launchpad.net/juju-core/juju/testing"
28 "launchpad.net/juju-core/provider/common"28 "launchpad.net/juju-core/provider/common"
29 coretesting "launchpad.net/juju-core/testing"
30 jc "launchpad.net/juju-core/testing/checkers"29 jc "launchpad.net/juju-core/testing/checkers"
31 "launchpad.net/juju-core/tools"30 "launchpad.net/juju-core/tools"
32 "launchpad.net/juju-core/utils"31 "launchpad.net/juju-core/utils"
@@ -54,31 +53,12 @@
54 return ecfg.Config53 return ecfg.Config
55}54}
5655
57// makeEnviron creates a functional maasEnviron for a test.
58func (suite *environSuite) makeEnviron() *maasEnviron {
59 attrs := coretesting.FakeConfig().Merge(coretesting.Attrs{
60 "name": suite.environ.Name(),
61 "type": "maas",
62 "maas-oauth": "a:b:c",
63 "maas-server": suite.testMAASObject.TestServer.URL,
64 })
65 cfg, err := config.New(config.NoDefaults, attrs)
66 if err != nil {
67 panic(err)
68 }
69 env, err := NewEnviron(cfg)
70 if err != nil {
71 panic(err)
72 }
73 return env
74}
75
76func (suite *environSuite) setupFakeProviderStateFile(c *gc.C) {56func (suite *environSuite) setupFakeProviderStateFile(c *gc.C) {
77 suite.testMAASObject.TestServer.NewFile(common.StateFile, []byte("test file content"))57 suite.testMAASObject.TestServer.NewFile(common.StateFile, []byte("test file content"))
78}58}
7959
80func (suite *environSuite) setupFakeTools(c *gc.C) {60func (suite *environSuite) setupFakeTools(c *gc.C) {
81 stor := NewStorage(suite.environ)61 stor := NewStorage(suite.makeEnviron())
82 envtesting.UploadFakeTools(c, stor)62 envtesting.UploadFakeTools(c, stor)
83}63}
8464
@@ -139,7 +119,7 @@
139 resourceURI, _ := node.GetField("resource_uri")119 resourceURI, _ := node.GetField("resource_uri")
140 instanceIds := []instance.Id{instance.Id(resourceURI)}120 instanceIds := []instance.Id{instance.Id(resourceURI)}
141121
142 instances, err := suite.environ.Instances(instanceIds)122 instances, err := suite.makeEnviron().Instances(instanceIds)
143123
144 c.Check(err, gc.IsNil)124 c.Check(err, gc.IsNil)
145 c.Check(len(instances), gc.Equals, 1)125 c.Check(len(instances), gc.Equals, 1)
@@ -149,7 +129,7 @@
149func (suite *environSuite) TestInstancesReturnsErrNoInstancesIfEmptyParameter(c *gc.C) {129func (suite *environSuite) TestInstancesReturnsErrNoInstancesIfEmptyParameter(c *gc.C) {
150 input := `{"system_id": "test"}`130 input := `{"system_id": "test"}`
151 suite.testMAASObject.TestServer.NewNode(input)131 suite.testMAASObject.TestServer.NewNode(input)
152 instances, err := suite.environ.Instances([]instance.Id{})132 instances, err := suite.makeEnviron().Instances([]instance.Id{})
153133
154 c.Check(err, gc.Equals, environs.ErrNoInstances)134 c.Check(err, gc.Equals, environs.ErrNoInstances)
155 c.Check(instances, gc.IsNil)135 c.Check(instances, gc.IsNil)
@@ -158,14 +138,14 @@
158func (suite *environSuite) TestInstancesReturnsErrNoInstancesIfNilParameter(c *gc.C) {138func (suite *environSuite) TestInstancesReturnsErrNoInstancesIfNilParameter(c *gc.C) {
159 input := `{"system_id": "test"}`139 input := `{"system_id": "test"}`
160 suite.testMAASObject.TestServer.NewNode(input)140 suite.testMAASObject.TestServer.NewNode(input)
161 instances, err := suite.environ.Instances(nil)141 instances, err := suite.makeEnviron().Instances(nil)
162142
163 c.Check(err, gc.Equals, environs.ErrNoInstances)143 c.Check(err, gc.Equals, environs.ErrNoInstances)
164 c.Check(instances, gc.IsNil)144 c.Check(instances, gc.IsNil)
165}145}
166146
167func (suite *environSuite) TestInstancesReturnsErrNoInstancesIfNoneFound(c *gc.C) {147func (suite *environSuite) TestInstancesReturnsErrNoInstancesIfNoneFound(c *gc.C) {
168 _, err := suite.environ.Instances([]instance.Id{"unknown"})148 _, err := suite.makeEnviron().Instances([]instance.Id{"unknown"})
169 c.Check(err, gc.Equals, environs.ErrNoInstances)149 c.Check(err, gc.Equals, environs.ErrNoInstances)
170}150}
171151
@@ -174,7 +154,7 @@
174 node := suite.testMAASObject.TestServer.NewNode(input)154 node := suite.testMAASObject.TestServer.NewNode(input)
175 resourceURI, _ := node.GetField("resource_uri")155 resourceURI, _ := node.GetField("resource_uri")
176156
177 instances, err := suite.environ.AllInstances()157 instances, err := suite.makeEnviron().AllInstances()
178158
179 c.Check(err, gc.IsNil)159 c.Check(err, gc.IsNil)
180 c.Check(len(instances), gc.Equals, 1)160 c.Check(len(instances), gc.Equals, 1)
@@ -182,7 +162,7 @@
182}162}
183163
184func (suite *environSuite) TestAllInstancesReturnsEmptySliceIfNoInstance(c *gc.C) {164func (suite *environSuite) TestAllInstancesReturnsEmptySliceIfNoInstance(c *gc.C) {
185 instances, err := suite.environ.AllInstances()165 instances, err := suite.makeEnviron().AllInstances()
186166
187 c.Check(err, gc.IsNil)167 c.Check(err, gc.IsNil)
188 c.Check(len(instances), gc.Equals, 0)168 c.Check(len(instances), gc.Equals, 0)
@@ -198,7 +178,7 @@
198 instanceId2 := instance.Id("unknown systemID")178 instanceId2 := instance.Id("unknown systemID")
199 instanceIds := []instance.Id{instanceId1, instanceId2}179 instanceIds := []instance.Id{instanceId1, instanceId2}
200180
201 instances, err := suite.environ.Instances(instanceIds)181 instances, err := suite.makeEnviron().Instances(instanceIds)
202182
203 c.Check(err, gc.Equals, environs.ErrPartialInstances)183 c.Check(err, gc.Equals, environs.ErrPartialInstances)
204 c.Check(len(instances), gc.Equals, 1)184 c.Check(len(instances), gc.Equals, 1)
@@ -298,7 +278,7 @@
298}278}
299279
300func (suite *environSuite) TestAcquireNode(c *gc.C) {280func (suite *environSuite) TestAcquireNode(c *gc.C) {
301 stor := NewStorage(suite.environ)281 stor := NewStorage(suite.makeEnviron())
302 fakeTools := envtesting.MustUploadFakeToolsVersions(stor, version.Current)[0]282 fakeTools := envtesting.MustUploadFakeToolsVersions(stor, version.Current)[0]
303 env := suite.makeEnviron()283 env := suite.makeEnviron()
304 suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`)284 suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
@@ -313,7 +293,7 @@
313}293}
314294
315func (suite *environSuite) TestAcquireNodeTakesConstraintsIntoAccount(c *gc.C) {295func (suite *environSuite) TestAcquireNodeTakesConstraintsIntoAccount(c *gc.C) {
316 stor := NewStorage(suite.environ)296 stor := NewStorage(suite.makeEnviron())
317 fakeTools := envtesting.MustUploadFakeToolsVersions(stor, version.Current)[0]297 fakeTools := envtesting.MustUploadFakeToolsVersions(stor, version.Current)[0]
318 env := suite.makeEnviron()298 env := suite.makeEnviron()
319 suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`)299 suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
@@ -329,6 +309,21 @@
329 c.Assert(nodeRequestValues[0].Get("mem"), gc.Equals, "1024")309 c.Assert(nodeRequestValues[0].Get("mem"), gc.Equals, "1024")
330}310}
331311
312func (suite *environSuite) TestAcquireNodePassedEnvironmentUUID(c *gc.C) {
313 stor := NewStorage(suite.makeEnviron())
314 fakeTools := envtesting.MustUploadFakeToolsVersions(stor, version.Current)[0]
315 env := suite.makeEnviron()
316 suite.testMAASObject.TestServer.NewNode(`{"system_id": "node0", "hostname": "host0"}`)
317
318 _, _, err := env.acquireNode(constraints.Value{}, tools.List{fakeTools})
319
320 c.Check(err, gc.IsNil)
321 requestValues := suite.testMAASObject.TestServer.NodeOperationRequestValues()
322 nodeRequestValues, found := requestValues["node0"]
323 c.Assert(found, gc.Equals, true)
324 c.Assert(nodeRequestValues[0].Get("agent_name"), gc.Equals, exampleUUID)
325}
326
332func (*environSuite) TestConvertConstraints(c *gc.C) {327func (*environSuite) TestConvertConstraints(c *gc.C) {
333 var testValues = []struct {328 var testValues = []struct {
334 constraints constraints.Value329 constraints constraints.Value
@@ -352,13 +347,13 @@
352func (suite *environSuite) getInstance(systemId string) *maasInstance {347func (suite *environSuite) getInstance(systemId string) *maasInstance {
353 input := `{"system_id": "` + systemId + `"}`348 input := `{"system_id": "` + systemId + `"}`
354 node := suite.testMAASObject.TestServer.NewNode(input)349 node := suite.testMAASObject.TestServer.NewNode(input)
355 return &maasInstance{&node, suite.environ}350 return &maasInstance{&node, suite.makeEnviron()}
356}351}
357352
358func (suite *environSuite) TestStopInstancesReturnsIfParameterEmpty(c *gc.C) {353func (suite *environSuite) TestStopInstancesReturnsIfParameterEmpty(c *gc.C) {
359 suite.getInstance("test1")354 suite.getInstance("test1")
360355
361 err := suite.environ.StopInstances([]instance.Instance{})356 err := suite.makeEnviron().StopInstances([]instance.Instance{})
362 c.Check(err, gc.IsNil)357 c.Check(err, gc.IsNil)
363 operations := suite.testMAASObject.TestServer.NodeOperations()358 operations := suite.testMAASObject.TestServer.NodeOperations()
364 c.Check(operations, gc.DeepEquals, map[string][]string{})359 c.Check(operations, gc.DeepEquals, map[string][]string{})
@@ -370,7 +365,7 @@
370 suite.getInstance("test3")365 suite.getInstance("test3")
371 instances := []instance.Instance{instance1, instance2}366 instances := []instance.Instance{instance1, instance2}
372367
373 err := suite.environ.StopInstances(instances)368 err := suite.makeEnviron().StopInstances(instances)
374369
375 c.Check(err, gc.IsNil)370 c.Check(err, gc.IsNil)
376 operations := suite.testMAASObject.TestServer.NodeOperations()371 operations := suite.testMAASObject.TestServer.NodeOperations()
@@ -383,7 +378,7 @@
383 hostname := "test"378 hostname := "test"
384 input := `{"system_id": "system_id", "hostname": "` + hostname + `"}`379 input := `{"system_id": "system_id", "hostname": "` + hostname + `"}`
385 node := suite.testMAASObject.TestServer.NewNode(input)380 node := suite.testMAASObject.TestServer.NewNode(input)
386 testInstance := &maasInstance{&node, suite.environ}381 testInstance := &maasInstance{&node, suite.makeEnviron()}
387 err := common.SaveState(382 err := common.SaveState(
388 env.Storage(),383 env.Storage(),
389 &common.BootstrapState{StateInstances: []instance.Id{testInstance.Id()}})384 &common.BootstrapState{StateInstances: []instance.Id{testInstance.Id()}})
390385
=== modified file 'provider/maas/environprovider.go'
--- provider/maas/environprovider.go 2013-10-11 14:05:04 +0000
+++ provider/maas/environprovider.go 2013-10-15 16:59:34 +0000
@@ -4,6 +4,7 @@
4package maas4package maas
55
6import (6import (
7 "errors"
7 "os"8 "os"
89
9 "launchpad.net/loggo"10 "launchpad.net/loggo"
@@ -37,8 +38,27 @@
37 return env, nil38 return env, nil
38}39}
3940
41var errUUIDAlreadySet = errors.New(
42 "environment-uuid is already set; this should not be set by hand")
43
40func (p maasEnvironProvider) Prepare(cfg *config.Config) (environs.Environ, error) {44func (p maasEnvironProvider) Prepare(cfg *config.Config) (environs.Environ, error) {
41 // TODO any attributes to prepare?45 attrs := cfg.UnknownAttrs()
46 uuid, found := attrs["environment-uuid"]
47 if found {
48 if uuid != "" {
49 return nil, errUUIDAlreadySet
50 }
51 } else {
52 uuid, err := utils.NewUUID()
53 if err != nil {
54 return nil, err
55 }
56 attrs["environment-uuid"] = uuid.String()
57 }
58 cfg, err := cfg.Apply(attrs)
59 if err != nil {
60 return nil, err
61 }
42 return p.Open(cfg)62 return p.Open(cfg)
43}63}
4464
4565
=== modified file 'provider/maas/environprovider_test.go'
--- provider/maas/environprovider_test.go 2013-09-25 17:04:52 +0000
+++ provider/maas/environprovider_test.go 2013-10-15 16:59:34 +0000
@@ -11,6 +11,7 @@
1111
12 "launchpad.net/juju-core/environs/config"12 "launchpad.net/juju-core/environs/config"
13 "launchpad.net/juju-core/testing"13 "launchpad.net/juju-core/testing"
14 "launchpad.net/juju-core/utils"
14)15)
1516
16type EnvironProviderSuite struct {17type EnvironProviderSuite struct {
@@ -31,13 +32,53 @@
31 config, err := config.New(config.NoDefaults, attrs)32 config, err := config.New(config.NoDefaults, attrs)
32 c.Assert(err, gc.IsNil)33 c.Assert(err, gc.IsNil)
3334
34 secretAttrs, err := suite.environ.Provider().SecretAttrs(config)35 secretAttrs, err := suite.makeEnviron().Provider().SecretAttrs(config)
35 c.Assert(err, gc.IsNil)36 c.Assert(err, gc.IsNil)
3637
37 expectedAttrs := map[string]string{"maas-oauth": oauth}38 expectedAttrs := map[string]string{"maas-oauth": oauth}
38 c.Check(secretAttrs, gc.DeepEquals, expectedAttrs)39 c.Check(secretAttrs, gc.DeepEquals, expectedAttrs)
39}40}
4041
42func (suite *EnvironProviderSuite) TestUnknownAttrsContainEnvironmentUUID(c *gc.C) {
43 testJujuHome := c.MkDir()
44 defer config.SetJujuHome(config.SetJujuHome(testJujuHome))
45 attrs := testing.FakeConfig().Merge(testing.Attrs{
46 "type": "maas",
47 "maas-oauth": "aa:bb:cc",
48 "maas-server": "http://maas.testing.invalid/maas/",
49 })
50 config, err := config.New(config.NoDefaults, attrs)
51 c.Assert(err, gc.IsNil)
52
53 environ, err := suite.makeEnviron().Provider().Prepare(config)
54 c.Assert(err, gc.IsNil)
55
56 preparedConfig := environ.Config()
57 unknownAttrs := preparedConfig.UnknownAttrs()
58
59 uuid, ok := unknownAttrs["environment-uuid"]
60 c.Assert(ok, gc.Equals, true)
61
62 _, err = utils.UUIDFromString(uuid.(string))
63 c.Assert(err, gc.IsNil)
64}
65
66func (suite *EnvironProviderSuite) TestEnvironmentUUIDShouldNotBeSetByHand(c *gc.C) {
67 testJujuHome := c.MkDir()
68 defer config.SetJujuHome(config.SetJujuHome(testJujuHome))
69 attrs := testing.FakeConfig().Merge(testing.Attrs{
70 "type": "maas",
71 "maas-oauth": "aa:bb:cc",
72 "maas-server": "http://maas.testing.invalid/maas/",
73 "environment-uuid": "foobar",
74 })
75 config, err := config.New(config.NoDefaults, attrs)
76 c.Assert(err, gc.IsNil)
77
78 _, err = suite.makeEnviron().Provider().Prepare(config)
79 c.Assert(err, gc.Equals, errUUIDAlreadySet)
80}
81
41// create a temporary file with the given content. The file will be cleaned82// create a temporary file with the given content. The file will be cleaned
42// up at the end of the test calling this method.83// up at the end of the test calling this method.
43func createTempFile(c *gc.C, content []byte) string {84func createTempFile(c *gc.C, content []byte) string {
@@ -65,7 +106,7 @@
65 _MAASInstanceFilename = filename106 _MAASInstanceFilename = filename
66 defer func() { _MAASInstanceFilename = old_MAASInstanceFilename }()107 defer func() { _MAASInstanceFilename = old_MAASInstanceFilename }()
67108
68 provider := suite.environ.Provider()109 provider := suite.makeEnviron().Provider()
69 publicAddress, err := provider.PublicAddress()110 publicAddress, err := provider.PublicAddress()
70 c.Assert(err, gc.IsNil)111 c.Assert(err, gc.IsNil)
71 c.Check(publicAddress, gc.Equals, hostname)112 c.Check(publicAddress, gc.Equals, hostname)
@@ -85,7 +126,7 @@
85 })126 })
86 config, err := config.New(config.NoDefaults, attrs)127 config, err := config.New(config.NoDefaults, attrs)
87 c.Assert(err, gc.IsNil)128 c.Assert(err, gc.IsNil)
88 env, err := suite.environ.Provider().Open(config)129 env, err := suite.makeEnviron().Provider().Open(config)
89 // When Open() fails (i.e. returns a non-nil error), it returns an130 // When Open() fails (i.e. returns a non-nil error), it returns an
90 // environs.Environ interface object with a nil value and a nil131 // environs.Environ interface object with a nil value and a nil
91 // type.132 // type.
92133
=== modified file 'provider/maas/instance_test.go'
--- provider/maas/instance_test.go 2013-10-10 11:40:54 +0000
+++ provider/maas/instance_test.go 2013-10-15 16:59:34 +0000
@@ -21,7 +21,7 @@
21 jsonValue := `{"system_id": "system_id", "test": "test"}`21 jsonValue := `{"system_id": "system_id", "test": "test"}`
22 obj := s.testMAASObject.TestServer.NewNode(jsonValue)22 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
23 resourceURI, _ := obj.GetField("resource_uri")23 resourceURI, _ := obj.GetField("resource_uri")
24 instance := maasInstance{&obj, s.environ}24 instance := maasInstance{&obj, s.makeEnviron()}
2525
26 c.Check(string(instance.Id()), gc.Equals, resourceURI)26 c.Check(string(instance.Id()), gc.Equals, resourceURI)
27}27}
@@ -29,19 +29,21 @@
29func (s *instanceTest) TestString(c *gc.C) {29func (s *instanceTest) TestString(c *gc.C) {
30 jsonValue := `{"hostname": "thethingintheplace", "system_id": "system_id", "test": "test"}`30 jsonValue := `{"hostname": "thethingintheplace", "system_id": "system_id", "test": "test"}`
31 obj := s.testMAASObject.TestServer.NewNode(jsonValue)31 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
32 instance := &maasInstance{&obj, s.environ}32 instance := &maasInstance{&obj, s.makeEnviron()}
33 hostname, err := instance.DNSName()33 hostname, err := instance.DNSName()
34 c.Assert(err, gc.IsNil)34 c.Assert(err, gc.IsNil)
35 expected := hostname + ":" + string(instance.Id())35 expected := hostname + ":" + string(instance.Id())
36 c.Assert(fmt.Sprint(instance), gc.Equals, expected)36 c.Assert(fmt.Sprint(instance), gc.Equals, expected)
37}
3738
39func (s *instanceTest) TestStringWithoutHostname(c *gc.C) {
38 // For good measure, test what happens if we don't have a hostname.40 // For good measure, test what happens if we don't have a hostname.
39 jsonValue = `{"system_id": "system_id", "test": "test"}`41 jsonValue := `{"system_id": "system_id", "test": "test"}`
40 obj = s.testMAASObject.TestServer.NewNode(jsonValue)42 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
41 instance = &maasInstance{&obj, s.environ}43 instance := &maasInstance{&obj, s.makeEnviron()}
42 hostname, err = instance.DNSName()44 _, err := instance.DNSName()
43 c.Assert(err, gc.NotNil)45 c.Assert(err, gc.NotNil)
44 expected = fmt.Sprintf("<DNSName failed: %q>", err) + ":" + string(instance.Id())46 expected := fmt.Sprintf("<DNSName failed: %q>", err) + ":" + string(instance.Id())
45 c.Assert(fmt.Sprint(instance), gc.Equals, expected)47 c.Assert(fmt.Sprint(instance), gc.Equals, expected)
46}48}
4749
@@ -49,7 +51,7 @@
49 jsonValue := `{"system_id": "system_id", "test": "test"}`51 jsonValue := `{"system_id": "system_id", "test": "test"}`
50 obj := s.testMAASObject.TestServer.NewNode(jsonValue)52 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
51 s.testMAASObject.TestServer.ChangeNode("system_id", "test2", "test2")53 s.testMAASObject.TestServer.ChangeNode("system_id", "test2", "test2")
52 instance := maasInstance{&obj, s.environ}54 instance := maasInstance{&obj, s.makeEnviron()}
5355
54 err := instance.refreshInstance()56 err := instance.refreshInstance()
5557
@@ -62,7 +64,7 @@
62func (s *instanceTest) TestDNSName(c *gc.C) {64func (s *instanceTest) TestDNSName(c *gc.C) {
63 jsonValue := `{"hostname": "DNS name", "system_id": "system_id"}`65 jsonValue := `{"hostname": "DNS name", "system_id": "system_id"}`
64 obj := s.testMAASObject.TestServer.NewNode(jsonValue)66 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
65 instance := maasInstance{&obj, s.environ}67 instance := maasInstance{&obj, s.makeEnviron()}
6668
67 dnsName, err := instance.DNSName()69 dnsName, err := instance.DNSName()
6870
@@ -83,7 +85,7 @@
83 "ip_addresses": [ "1.2.3.4", "fe80::d806:dbff:fe23:1199" ]85 "ip_addresses": [ "1.2.3.4", "fe80::d806:dbff:fe23:1199" ]
84 }`86 }`
85 obj := s.testMAASObject.TestServer.NewNode(jsonValue)87 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
86 inst := maasInstance{&obj, s.environ}88 inst := maasInstance{&obj, s.makeEnviron()}
8789
88 expected := []instance.Address{90 expected := []instance.Address{
89 {Value: "testing.invalid", Type: instance.HostName, NetworkScope: instance.NetworkPublic},91 {Value: "testing.invalid", Type: instance.HostName, NetworkScope: instance.NetworkPublic},
@@ -105,7 +107,7 @@
105 "system_id": "system_id"107 "system_id": "system_id"
106 }`108 }`
107 obj := s.testMAASObject.TestServer.NewNode(jsonValue)109 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
108 inst := maasInstance{&obj, s.environ}110 inst := maasInstance{&obj, s.makeEnviron()}
109111
110 addr, err := inst.Addresses()112 addr, err := inst.Addresses()
111 c.Assert(err, gc.IsNil)113 c.Assert(err, gc.IsNil)
@@ -121,7 +123,7 @@
121 "ip_addresses": "incompatible"123 "ip_addresses": "incompatible"
122 }`124 }`
123 obj := s.testMAASObject.TestServer.NewNode(jsonValue)125 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
124 inst := maasInstance{&obj, s.environ}126 inst := maasInstance{&obj, s.makeEnviron()}
125127
126 _, err := inst.Addresses()128 _, err := inst.Addresses()
127 c.Assert(err, gc.NotNil)129 c.Assert(err, gc.NotNil)
@@ -134,7 +136,7 @@
134 "ip_addresses": [42]136 "ip_addresses": [42]
135 }`137 }`
136 obj := s.testMAASObject.TestServer.NewNode(jsonValue)138 obj := s.testMAASObject.TestServer.NewNode(jsonValue)
137 inst := maasInstance{&obj, s.environ}139 inst := maasInstance{&obj, s.makeEnviron()}
138140
139 _, err := inst.Addresses()141 _, err := inst.Addresses()
140 c.Assert(err, gc.NotNil)142 c.Assert(err, gc.NotNil)
141143
=== modified file 'provider/maas/maas_test.go'
--- provider/maas/maas_test.go 2013-09-20 02:53:59 +0000
+++ provider/maas/maas_test.go 2013-10-15 16:59:34 +0000
@@ -9,7 +9,9 @@
9 gc "launchpad.net/gocheck"9 gc "launchpad.net/gocheck"
10 "launchpad.net/gomaasapi"10 "launchpad.net/gomaasapi"
1111
12 "launchpad.net/juju-core/environs/config"
12 envtesting "launchpad.net/juju-core/environs/testing"13 envtesting "launchpad.net/juju-core/environs/testing"
14 coretesting "launchpad.net/juju-core/testing"
13 "launchpad.net/juju-core/testing/testbase"15 "launchpad.net/juju-core/testing/testbase"
14)16)
1517
@@ -20,7 +22,6 @@
20type providerSuite struct {22type providerSuite struct {
21 testbase.LoggingSuite23 testbase.LoggingSuite
22 envtesting.ToolsFixture24 envtesting.ToolsFixture
23 environ *maasEnviron
24 testMAASObject *gomaasapi.TestMAASObject25 testMAASObject *gomaasapi.TestMAASObject
25 restoreTimeouts func()26 restoreTimeouts func()
26}27}
@@ -32,7 +33,6 @@
32 s.LoggingSuite.SetUpSuite(c)33 s.LoggingSuite.SetUpSuite(c)
33 TestMAASObject := gomaasapi.NewTestMAAS("1.0")34 TestMAASObject := gomaasapi.NewTestMAAS("1.0")
34 s.testMAASObject = TestMAASObject35 s.testMAASObject = TestMAASObject
35 s.environ = &maasEnviron{name: "test env", maasClientUnlocked: &TestMAASObject.MAASObject}
36}36}
3737
38func (s *providerSuite) SetUpTest(c *gc.C) {38func (s *providerSuite) SetUpTest(c *gc.C) {
@@ -51,3 +51,25 @@
51 s.restoreTimeouts()51 s.restoreTimeouts()
52 s.LoggingSuite.TearDownSuite(c)52 s.LoggingSuite.TearDownSuite(c)
53}53}
54
55const exampleUUID = "dfb69555-0bc4-4d1f-85f2-4ee390974984"
56
57// makeEnviron creates a functional maasEnviron for a test.
58func (suite *providerSuite) makeEnviron() *maasEnviron {
59 attrs := coretesting.FakeConfig().Merge(coretesting.Attrs{
60 "name": "test env",
61 "type": "maas",
62 "maas-oauth": "a:b:c",
63 "maas-server": suite.testMAASObject.TestServer.URL,
64 "environment-uuid": exampleUUID,
65 })
66 cfg, err := config.New(config.NoDefaults, attrs)
67 if err != nil {
68 panic(err)
69 }
70 env, err := NewEnviron(cfg)
71 if err != nil {
72 panic(err)
73 }
74 return env
75}
5476
=== modified file 'provider/maas/storage_test.go'
--- provider/maas/storage_test.go 2013-09-18 22:54:32 +0000
+++ provider/maas/storage_test.go 2013-10-15 16:59:34 +0000
@@ -144,20 +144,20 @@
144144
145func (s *storageSuite) TestGetReturnsNotFoundErrorIfNotFound(c *gc.C) {145func (s *storageSuite) TestGetReturnsNotFoundErrorIfNotFound(c *gc.C) {
146 const filename = "lost-data"146 const filename = "lost-data"
147 stor := NewStorage(s.environ)147 stor := NewStorage(s.makeEnviron())
148 _, err := storage.Get(stor, filename)148 _, err := storage.Get(stor, filename)
149 c.Assert(err, jc.Satisfies, errors.IsNotFoundError)149 c.Assert(err, jc.Satisfies, errors.IsNotFoundError)
150}150}
151151
152func (s *storageSuite) TestListReturnsEmptyIfNoFilesStored(c *gc.C) {152func (s *storageSuite) TestListReturnsEmptyIfNoFilesStored(c *gc.C) {
153 stor := NewStorage(s.environ)153 stor := NewStorage(s.makeEnviron())
154 listing, err := storage.List(stor, "")154 listing, err := storage.List(stor, "")
155 c.Assert(err, gc.IsNil)155 c.Assert(err, gc.IsNil)
156 c.Check(listing, gc.DeepEquals, []string{})156 c.Check(listing, gc.DeepEquals, []string{})
157}157}
158158
159func (s *storageSuite) TestListReturnsAllFilesIfPrefixEmpty(c *gc.C) {159func (s *storageSuite) TestListReturnsAllFilesIfPrefixEmpty(c *gc.C) {
160 stor := NewStorage(s.environ)160 stor := NewStorage(s.makeEnviron())
161 files := []string{"1a", "2b", "3c"}161 files := []string{"1a", "2b", "3c"}
162 for _, name := range files {162 for _, name := range files {
163 s.fakeStoredFile(stor, name)163 s.fakeStoredFile(stor, name)
@@ -169,7 +169,7 @@
169}169}
170170
171func (s *storageSuite) TestListSortsResults(c *gc.C) {171func (s *storageSuite) TestListSortsResults(c *gc.C) {
172 stor := NewStorage(s.environ)172 stor := NewStorage(s.makeEnviron())
173 files := []string{"4d", "1a", "3c", "2b"}173 files := []string{"4d", "1a", "3c", "2b"}
174 for _, name := range files {174 for _, name := range files {
175 s.fakeStoredFile(stor, name)175 s.fakeStoredFile(stor, name)
@@ -181,7 +181,7 @@
181}181}
182182
183func (s *storageSuite) TestListReturnsNoFilesIfNoFilesMatchPrefix(c *gc.C) {183func (s *storageSuite) TestListReturnsNoFilesIfNoFilesMatchPrefix(c *gc.C) {
184 stor := NewStorage(s.environ)184 stor := NewStorage(s.makeEnviron())
185 s.fakeStoredFile(stor, "foo")185 s.fakeStoredFile(stor, "foo")
186186
187 listing, err := storage.List(stor, "bar")187 listing, err := storage.List(stor, "bar")
@@ -190,7 +190,7 @@
190}190}
191191
192func (s *storageSuite) TestListReturnsOnlyFilesWithMatchingPrefix(c *gc.C) {192func (s *storageSuite) TestListReturnsOnlyFilesWithMatchingPrefix(c *gc.C) {
193 stor := NewStorage(s.environ)193 stor := NewStorage(s.makeEnviron())
194 s.fakeStoredFile(stor, "abc")194 s.fakeStoredFile(stor, "abc")
195 s.fakeStoredFile(stor, "xyz")195 s.fakeStoredFile(stor, "xyz")
196196
@@ -200,7 +200,7 @@
200}200}
201201
202func (s *storageSuite) TestListMatchesPrefixOnly(c *gc.C) {202func (s *storageSuite) TestListMatchesPrefixOnly(c *gc.C) {
203 stor := NewStorage(s.environ)203 stor := NewStorage(s.makeEnviron())
204 s.fakeStoredFile(stor, "abc")204 s.fakeStoredFile(stor, "abc")
205 s.fakeStoredFile(stor, "xabc")205 s.fakeStoredFile(stor, "xabc")
206206
@@ -210,7 +210,7 @@
210}210}
211211
212func (s *storageSuite) TestListOperatesOnFlatNamespace(c *gc.C) {212func (s *storageSuite) TestListOperatesOnFlatNamespace(c *gc.C) {
213 stor := NewStorage(s.environ)213 stor := NewStorage(s.makeEnviron())
214 s.fakeStoredFile(stor, "a/b/c/d")214 s.fakeStoredFile(stor, "a/b/c/d")
215215
216 listing, err := storage.List(stor, "a/b")216 listing, err := storage.List(stor, "a/b")
@@ -233,7 +233,7 @@
233233
234func (s *storageSuite) TestURLReturnsURLCorrespondingToFile(c *gc.C) {234func (s *storageSuite) TestURLReturnsURLCorrespondingToFile(c *gc.C) {
235 const filename = "my-file.txt"235 const filename = "my-file.txt"
236 stor := NewStorage(s.environ).(*maasStorage)236 stor := NewStorage(s.makeEnviron()).(*maasStorage)
237 file := s.fakeStoredFile(stor, filename)237 file := s.fakeStoredFile(stor, filename)
238 // The file contains an anon_resource_uri, which lacks a network part238 // The file contains an anon_resource_uri, which lacks a network part
239 // (but will probably contain a query part). anonURL will be the239 // (but will probably contain a query part). anonURL will be the
@@ -256,7 +256,7 @@
256 const filename = "broken-toaster.jpg"256 const filename = "broken-toaster.jpg"
257 contents := []byte("Contents here")257 contents := []byte("Contents here")
258 length := int64(len(contents))258 length := int64(len(contents))
259 stor := NewStorage(s.environ)259 stor := NewStorage(s.makeEnviron())
260260
261 err := stor.Put(filename, bytes.NewReader(contents), length)261 err := stor.Put(filename, bytes.NewReader(contents), length)
262262
@@ -271,7 +271,7 @@
271271
272func (s *storageSuite) TestPutOverwritesFile(c *gc.C) {272func (s *storageSuite) TestPutOverwritesFile(c *gc.C) {
273 const filename = "foo.bar"273 const filename = "foo.bar"
274 stor := NewStorage(s.environ)274 stor := NewStorage(s.makeEnviron())
275 s.fakeStoredFile(stor, filename)275 s.fakeStoredFile(stor, filename)
276 newContents := []byte("Overwritten")276 newContents := []byte("Overwritten")
277277
@@ -292,7 +292,7 @@
292 const filename = "xyzzyz.2.xls"292 const filename = "xyzzyz.2.xls"
293 const length = 5293 const length = 5
294 contents := []byte("abcdefghijklmnopqrstuvwxyz")294 contents := []byte("abcdefghijklmnopqrstuvwxyz")
295 stor := NewStorage(s.environ)295 stor := NewStorage(s.makeEnviron())
296296
297 err := stor.Put(filename, bytes.NewReader(contents), length)297 err := stor.Put(filename, bytes.NewReader(contents), length)
298 c.Assert(err, gc.IsNil)298 c.Assert(err, gc.IsNil)
@@ -310,7 +310,7 @@
310 const filename = "a-file-which-is-mine"310 const filename = "a-file-which-is-mine"
311 oldContents := []byte("abcdefghijklmnopqrstuvwxyz")311 oldContents := []byte("abcdefghijklmnopqrstuvwxyz")
312 newContents := []byte("xyz")312 newContents := []byte("xyz")
313 stor := NewStorage(s.environ)313 stor := NewStorage(s.makeEnviron())
314 err := stor.Put(filename, bytes.NewReader(oldContents), int64(len(oldContents)))314 err := stor.Put(filename, bytes.NewReader(oldContents), int64(len(oldContents)))
315 c.Assert(err, gc.IsNil)315 c.Assert(err, gc.IsNil)
316316
@@ -329,7 +329,7 @@
329329
330func (s *storageSuite) TestRemoveDeletesFile(c *gc.C) {330func (s *storageSuite) TestRemoveDeletesFile(c *gc.C) {
331 const filename = "doomed.txt"331 const filename = "doomed.txt"
332 stor := NewStorage(s.environ)332 stor := NewStorage(s.makeEnviron())
333 s.fakeStoredFile(stor, filename)333 s.fakeStoredFile(stor, filename)
334334
335 err := stor.Remove(filename)335 err := stor.Remove(filename)
@@ -345,7 +345,7 @@
345345
346func (s *storageSuite) TestRemoveIsIdempotent(c *gc.C) {346func (s *storageSuite) TestRemoveIsIdempotent(c *gc.C) {
347 const filename = "half-a-file"347 const filename = "half-a-file"
348 stor := NewStorage(s.environ)348 stor := NewStorage(s.makeEnviron())
349 s.fakeStoredFile(stor, filename)349 s.fakeStoredFile(stor, filename)
350350
351 err := stor.Remove(filename)351 err := stor.Remove(filename)
@@ -358,7 +358,7 @@
358func (s *storageSuite) TestNamesMayHaveSlashes(c *gc.C) {358func (s *storageSuite) TestNamesMayHaveSlashes(c *gc.C) {
359 const filename = "name/with/slashes"359 const filename = "name/with/slashes"
360 content := []byte("File contents")360 content := []byte("File contents")
361 stor := NewStorage(s.environ)361 stor := NewStorage(s.makeEnviron())
362362
363 err := stor.Put(filename, bytes.NewReader(content), int64(len(content)))363 err := stor.Put(filename, bytes.NewReader(content), int64(len(content)))
364 c.Assert(err, gc.IsNil)364 c.Assert(err, gc.IsNil)

Subscribers

People subscribed via source and target branches

to status/vote changes: