~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/worker/discoverspaces/worker_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2016 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package discoverspaces_test
 
5
 
 
6
import (
 
7
        "sync/atomic"
 
8
        "time"
 
9
 
 
10
        jc "github.com/juju/testing/checkers"
 
11
        gc "gopkg.in/check.v1"
 
12
        "gopkg.in/juju/names.v2"
 
13
 
 
14
        "github.com/juju/juju/api"
 
15
        apidiscoverspaces "github.com/juju/juju/api/discoverspaces"
 
16
        "github.com/juju/juju/apiserver/params"
 
17
        "github.com/juju/juju/environs"
 
18
        "github.com/juju/juju/juju/testing"
 
19
        "github.com/juju/juju/network"
 
20
        "github.com/juju/juju/provider/dummy"
 
21
        "github.com/juju/juju/state"
 
22
        "github.com/juju/juju/state/stateenvirons"
 
23
        coretesting "github.com/juju/juju/testing"
 
24
        "github.com/juju/juju/worker"
 
25
        "github.com/juju/juju/worker/discoverspaces"
 
26
        "github.com/juju/juju/worker/gate"
 
27
        "github.com/juju/juju/worker/workertest"
 
28
)
 
29
 
 
30
type WorkerSuite struct {
 
31
        // TODO(fwereade): we *really* should not be using
 
32
        // JujuConnSuite in new code.
 
33
        testing.JujuConnSuite
 
34
 
 
35
        APIConnection api.Connection
 
36
        API           *checkingFacade
 
37
 
 
38
        numCreateSpaceCalls uint32
 
39
        numAddSubnetsCalls  uint32
 
40
}
 
41
 
 
42
type checkingFacade struct {
 
43
        apidiscoverspaces.API
 
44
 
 
45
        createSpacesCallback func()
 
46
        addSubnetsCallback   func()
 
47
}
 
48
 
 
49
func (cf *checkingFacade) CreateSpaces(args params.CreateSpacesParams) (results params.ErrorResults, err error) {
 
50
        if cf.createSpacesCallback != nil {
 
51
                cf.createSpacesCallback()
 
52
        }
 
53
        return cf.API.CreateSpaces(args)
 
54
}
 
55
 
 
56
func (cf *checkingFacade) AddSubnets(args params.AddSubnetsParams) (params.ErrorResults, error) {
 
57
        if cf.addSubnetsCallback != nil {
 
58
                cf.addSubnetsCallback()
 
59
        }
 
60
        return cf.API.AddSubnets(args)
 
61
}
 
62
 
 
63
var _ = gc.Suite(&WorkerSuite{})
 
64
 
 
65
func (s *WorkerSuite) SetUpTest(c *gc.C) {
 
66
        s.JujuConnSuite.SetUpTest(c)
 
67
 
 
68
        // Unbreak dummy provider methods.
 
69
        s.AssertConfigParameterUpdated(c, "broken", "")
 
70
 
 
71
        s.APIConnection, _ = s.OpenAPIAsNewMachine(c, state.JobManageModel)
 
72
 
 
73
        realAPI := s.APIConnection.DiscoverSpaces()
 
74
        s.API = &checkingFacade{
 
75
                API: *realAPI,
 
76
                createSpacesCallback: func() {
 
77
                        atomic.AddUint32(&s.numCreateSpaceCalls, 1)
 
78
                },
 
79
                addSubnetsCallback: func() {
 
80
                        atomic.AddUint32(&s.numAddSubnetsCalls, 1)
 
81
                },
 
82
        }
 
83
}
 
84
 
 
85
func (s *WorkerSuite) TearDownTest(c *gc.C) {
 
86
        if s.APIConnection != nil {
 
87
                c.Check(s.APIConnection.Close(), jc.ErrorIsNil)
 
88
        }
 
89
        s.JujuConnSuite.TearDownTest(c)
 
90
}
 
91
 
 
92
func (s *WorkerSuite) TestSupportsSpaceDiscoveryBroken(c *gc.C) {
 
93
        s.AssertConfigParameterUpdated(c, "broken", "SupportsSpaceDiscovery")
 
94
 
 
95
        worker, lock := s.startWorker(c)
 
96
        err := workertest.CheckKilled(c, worker)
 
97
        c.Assert(err, gc.ErrorMatches, "dummy.SupportsSpaceDiscovery is broken")
 
98
 
 
99
        select {
 
100
        case <-time.After(coretesting.ShortWait):
 
101
        case <-lock.Unlocked():
 
102
                c.Fatalf("gate unlocked despite worker failure")
 
103
        }
 
104
}
 
105
 
 
106
func (s *WorkerSuite) TestSpacesBroken(c *gc.C) {
 
107
        dummy.SetSupportsSpaceDiscovery(true)
 
108
        s.AssertConfigParameterUpdated(c, "broken", "Spaces")
 
109
 
 
110
        worker, lock := s.startWorker(c)
 
111
        err := workertest.CheckKilled(c, worker)
 
112
        c.Assert(err, gc.ErrorMatches, "dummy.Spaces is broken")
 
113
 
 
114
        select {
 
115
        case <-time.After(coretesting.ShortWait):
 
116
        case <-lock.Unlocked():
 
117
                c.Fatalf("gate unlocked despite worker failure")
 
118
        }
 
119
}
 
120
 
 
121
func (s *WorkerSuite) TestWorkerSupportsNetworkingFalse(c *gc.C) {
 
122
        // We set SupportsSpaceDiscovery to true so that spaces *would* be
 
123
        // discovered if networking was supported. So we know that if they're
 
124
        // discovered it must be because networking is not supported.
 
125
        dummy.SetSupportsSpaceDiscovery(true)
 
126
 
 
127
        // TODO(fwereade): monkey-patching remote packages is even worse
 
128
        // than monkey-patching local packages, please don't do it.
 
129
        noNetworking := func(environs.Environ) (environs.NetworkingEnviron, bool) {
 
130
                return nil, false
 
131
        }
 
132
        s.PatchValue(&environs.SupportsNetworking, noNetworking)
 
133
 
 
134
        s.unlockCheck(c, s.assertDiscoveredNoSpaces)
 
135
}
 
136
 
 
137
func (s *WorkerSuite) TestWorkerSupportsSpaceDiscoveryFalse(c *gc.C) {
 
138
        s.unlockCheck(c, s.assertDiscoveredNoSpaces)
 
139
}
 
140
 
 
141
func (s *WorkerSuite) TestWorkerDiscoversSpaces(c *gc.C) {
 
142
        dummy.SetSupportsSpaceDiscovery(true)
 
143
        s.unlockCheck(c, func(*gc.C) {
 
144
                s.assertDiscoveredSpaces(c)
 
145
                s.assertNumCalls(c, 1, 1)
 
146
        })
 
147
}
 
148
 
 
149
func (s *WorkerSuite) TestWorkerIdempotent(c *gc.C) {
 
150
        dummy.SetSupportsSpaceDiscovery(true)
 
151
        s.unlockCheck(c, s.assertDiscoveredSpaces)
 
152
        s.unlockCheck(c, func(*gc.C) {
 
153
                s.assertDiscoveredSpaces(c)
 
154
                s.assertNumCalls(c, 2, 2)
 
155
        })
 
156
}
 
157
 
 
158
func (s *WorkerSuite) TestWorkerIgnoresExistingSpacesAndSubnets(c *gc.C) {
 
159
        dummy.SetSupportsSpaceDiscovery(true)
 
160
        spaceTag := names.NewSpaceTag("foo")
 
161
        args := params.CreateSpacesParams{
 
162
                Spaces: []params.CreateSpaceParams{{
 
163
                        Public:     false,
 
164
                        SpaceTag:   spaceTag.String(),
 
165
                        ProviderId: "foo",
 
166
                }}}
 
167
        result, err := s.API.CreateSpaces(args)
 
168
        c.Assert(err, jc.ErrorIsNil)
 
169
        c.Assert(result.Results, gc.HasLen, 1)
 
170
        c.Assert(result.Results[0].Error, gc.IsNil)
 
171
 
 
172
        subnetArgs := params.AddSubnetsParams{
 
173
                Subnets: []params.AddSubnetParams{{
 
174
                        SubnetProviderId: "1",
 
175
                        SpaceTag:         spaceTag.String(),
 
176
                        Zones:            []string{"zone1"},
 
177
                }}}
 
178
        subnetResult, err := s.API.AddSubnets(subnetArgs)
 
179
        c.Assert(err, jc.ErrorIsNil)
 
180
        c.Assert(subnetResult.Results, gc.HasLen, 1)
 
181
        c.Assert(subnetResult.Results[0].Error, gc.IsNil)
 
182
 
 
183
        s.unlockCheck(c, func(c *gc.C) {
 
184
                spaces, err := s.State.AllSpaces()
 
185
                c.Assert(err, jc.ErrorIsNil)
 
186
                c.Assert(spaces, gc.HasLen, 5)
 
187
        })
 
188
}
 
189
 
 
190
func (s *WorkerSuite) startWorker(c *gc.C) (worker.Worker, gate.Lock) {
 
191
        // create fresh environ to see any injected broken-ness
 
192
        environ, err := stateenvirons.GetNewEnvironFunc(environs.New)(s.State)
 
193
        c.Assert(err, jc.ErrorIsNil)
 
194
 
 
195
        lock := gate.NewLock()
 
196
        worker, err := discoverspaces.NewWorker(discoverspaces.Config{
 
197
                Facade:   s.API,
 
198
                Environ:  environ,
 
199
                NewName:  network.ConvertSpaceName,
 
200
                Unlocker: lock,
 
201
        })
 
202
        c.Assert(err, jc.ErrorIsNil)
 
203
        return worker, lock
 
204
}
 
205
 
 
206
func (s *WorkerSuite) unlockCheck(c *gc.C, check func(c *gc.C)) {
 
207
        worker, lock := s.startWorker(c)
 
208
        defer workertest.CleanKill(c, worker)
 
209
        select {
 
210
        case <-time.After(coretesting.LongWait):
 
211
                c.Fatalf("discovery never completed")
 
212
        case <-lock.Unlocked():
 
213
                check(c)
 
214
        }
 
215
        workertest.CheckAlive(c, worker)
 
216
}
 
217
 
 
218
func (s *WorkerSuite) assertDiscoveredNoSpaces(c *gc.C) {
 
219
        spaces, err := s.State.AllSpaces()
 
220
        c.Assert(err, jc.ErrorIsNil)
 
221
        c.Check(spaces, gc.HasLen, 0)
 
222
}
 
223
 
 
224
func (s *WorkerSuite) assertDiscoveredSpaces(c *gc.C) {
 
225
        spaces, err := s.State.AllSpaces()
 
226
        c.Assert(err, jc.ErrorIsNil)
 
227
        c.Assert(spaces, gc.HasLen, 4)
 
228
        expectedSpaces := []network.SpaceInfo{{
 
229
                Name:       "foo",
 
230
                ProviderId: network.Id("0"),
 
231
                Subnets: []network.SubnetInfo{{
 
232
                        ProviderId:        network.Id("1"),
 
233
                        CIDR:              "192.168.1.0/24",
 
234
                        AvailabilityZones: []string{"zone1"},
 
235
                }, {
 
236
                        ProviderId:        network.Id("2"),
 
237
                        CIDR:              "192.168.2.0/24",
 
238
                        AvailabilityZones: []string{"zone1"},
 
239
                }}}, {
 
240
                Name:       "another-foo-99",
 
241
                ProviderId: network.Id("1"),
 
242
                Subnets: []network.SubnetInfo{{
 
243
                        ProviderId:        network.Id("3"),
 
244
                        CIDR:              "192.168.3.0/24",
 
245
                        AvailabilityZones: []string{"zone1"},
 
246
                }}}, {
 
247
                Name:       "foo-2",
 
248
                ProviderId: network.Id("2"),
 
249
                Subnets: []network.SubnetInfo{{
 
250
                        ProviderId:        network.Id("4"),
 
251
                        CIDR:              "192.168.4.0/24",
 
252
                        AvailabilityZones: []string{"zone1"},
 
253
                }}}, {
 
254
                Name:       "empty",
 
255
                ProviderId: network.Id("3"),
 
256
                Subnets: []network.SubnetInfo{{
 
257
                        ProviderId:        network.Id("5"),
 
258
                        CIDR:              "192.168.5.0/24",
 
259
                        AvailabilityZones: []string{"zone1"},
 
260
                }}}}
 
261
        expectedSpaceMap := make(map[string]network.SpaceInfo)
 
262
        for _, space := range expectedSpaces {
 
263
                expectedSpaceMap[space.Name] = space
 
264
        }
 
265
        for _, space := range spaces {
 
266
                expected, ok := expectedSpaceMap[space.Name()]
 
267
                if !c.Check(ok, jc.IsTrue) {
 
268
                        continue
 
269
                }
 
270
                c.Check(space.ProviderId(), gc.Equals, expected.ProviderId)
 
271
                subnets, err := space.Subnets()
 
272
                if !c.Check(err, jc.ErrorIsNil) {
 
273
                        continue
 
274
                }
 
275
                if !c.Check(len(subnets), gc.Equals, len(expected.Subnets)) {
 
276
                        continue
 
277
                }
 
278
                for i, subnet := range subnets {
 
279
                        expectedSubnet := expected.Subnets[i]
 
280
                        c.Check(subnet.ProviderId(), gc.Equals, expectedSubnet.ProviderId)
 
281
                        c.Check([]string{subnet.AvailabilityZone()}, jc.DeepEquals, expectedSubnet.AvailabilityZones)
 
282
                        c.Check(subnet.CIDR(), gc.Equals, expectedSubnet.CIDR)
 
283
                }
 
284
        }
 
285
}
 
286
 
 
287
func (s *WorkerSuite) assertNumCalls(c *gc.C, expectedNumCreateSpaceCalls, expectedNumAddSubnetsCalls int) {
 
288
        c.Check(atomic.LoadUint32(&s.numCreateSpaceCalls), gc.Equals, uint32(expectedNumCreateSpaceCalls))
 
289
        c.Check(atomic.LoadUint32(&s.numAddSubnetsCalls), gc.Equals, uint32(expectedNumAddSubnetsCalls))
 
290
}