~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/provider/openstack/provider_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 2012, 2013 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package openstack
 
5
 
 
6
import (
 
7
        gitjujutesting "github.com/juju/testing"
 
8
        jc "github.com/juju/testing/checkers"
 
9
        gc "gopkg.in/check.v1"
 
10
        "gopkg.in/goose.v1/nova"
 
11
 
 
12
        "github.com/juju/juju/cloud"
 
13
        "github.com/juju/juju/environs"
 
14
        "github.com/juju/juju/network"
 
15
)
 
16
 
 
17
// localTests contains tests which do not require a live service or test double to run.
 
18
type localTests struct {
 
19
        gitjujutesting.IsolationSuite
 
20
}
 
21
 
 
22
var _ = gc.Suite(&localTests{})
 
23
 
 
24
// ported from lp:juju/juju/providers/openstack/tests/test_machine.py
 
25
var addressTests = []struct {
 
26
        summary    string
 
27
        floatingIP string
 
28
        private    []nova.IPAddress
 
29
        public     []nova.IPAddress
 
30
        networks   []string
 
31
        expected   string
 
32
        failure    error
 
33
}{{
 
34
        summary:  "missing",
 
35
        expected: "",
 
36
}, {
 
37
        summary:  "empty",
 
38
        private:  []nova.IPAddress{},
 
39
        networks: []string{"private"},
 
40
        expected: "",
 
41
}, {
 
42
        summary:  "private IPv4 only",
 
43
        private:  []nova.IPAddress{{4, "192.168.0.1"}},
 
44
        networks: []string{"private"},
 
45
        expected: "192.168.0.1",
 
46
}, {
 
47
        summary:  "private IPv6 only",
 
48
        private:  []nova.IPAddress{{6, "fc00::1"}},
 
49
        networks: []string{"private"},
 
50
        expected: "fc00::1",
 
51
}, {
 
52
        summary:  "private only, both IPv4 and IPv6",
 
53
        private:  []nova.IPAddress{{4, "192.168.0.1"}, {6, "fc00::1"}},
 
54
        networks: []string{"private"},
 
55
        expected: "192.168.0.1",
 
56
}, {
 
57
        summary:  "private only, both IPv6 and IPv4",
 
58
        private:  []nova.IPAddress{{6, "fc00::1"}, {4, "192.168.0.1"}},
 
59
        networks: []string{"private"},
 
60
        expected: "fc00::1",
 
61
}, {
 
62
        summary:  "private IPv4 plus (HP cloud)",
 
63
        private:  []nova.IPAddress{{4, "10.0.0.1"}, {4, "8.8.4.4"}},
 
64
        networks: []string{"private"},
 
65
        expected: "8.8.4.4",
 
66
}, {
 
67
        summary:  "public IPv4 only",
 
68
        public:   []nova.IPAddress{{4, "8.8.8.8"}},
 
69
        networks: []string{"", "public"},
 
70
        expected: "8.8.8.8",
 
71
}, {
 
72
        summary:  "public IPv6 only",
 
73
        public:   []nova.IPAddress{{6, "2001:db8::1"}},
 
74
        networks: []string{"", "public"},
 
75
        expected: "2001:db8::1",
 
76
}, {
 
77
        summary:  "public only, both IPv4 and IPv6",
 
78
        public:   []nova.IPAddress{{4, "8.8.8.8"}, {6, "2001:db8::1"}},
 
79
        networks: []string{"", "public"},
 
80
        expected: "8.8.8.8",
 
81
}, {
 
82
        summary:  "public only, both IPv6 and IPv4",
 
83
        public:   []nova.IPAddress{{6, "2001:db8::1"}, {4, "8.8.8.8"}},
 
84
        networks: []string{"", "public"},
 
85
        expected: "2001:db8::1",
 
86
}, {
 
87
        summary:  "public and private both IPv4",
 
88
        private:  []nova.IPAddress{{4, "10.0.0.4"}},
 
89
        public:   []nova.IPAddress{{4, "8.8.4.4"}},
 
90
        networks: []string{"private", "public"},
 
91
        expected: "8.8.4.4",
 
92
}, {
 
93
        summary:  "public and private both IPv6",
 
94
        private:  []nova.IPAddress{{6, "fc00::1"}},
 
95
        public:   []nova.IPAddress{{6, "2001:db8::1"}},
 
96
        networks: []string{"private", "public"},
 
97
        expected: "2001:db8::1",
 
98
}, {
 
99
        summary:  "public, private, and localhost IPv4",
 
100
        private:  []nova.IPAddress{{4, "127.0.0.4"}, {4, "192.168.0.1"}},
 
101
        public:   []nova.IPAddress{{4, "8.8.8.8"}},
 
102
        networks: []string{"private", "public"},
 
103
        expected: "8.8.8.8",
 
104
}, {
 
105
        summary:  "public, private, and localhost IPv6",
 
106
        private:  []nova.IPAddress{{6, "::1"}, {6, "fc00::1"}},
 
107
        public:   []nova.IPAddress{{6, "2001:db8::1"}},
 
108
        networks: []string{"private", "public"},
 
109
        expected: "2001:db8::1",
 
110
}, {
 
111
        summary:  "public, private, and localhost - both IPv4 and IPv6",
 
112
        private:  []nova.IPAddress{{4, "127.0.0.4"}, {4, "192.168.0.1"}, {6, "::1"}, {6, "fc00::1"}},
 
113
        public:   []nova.IPAddress{{4, "8.8.8.8"}, {6, "2001:db8::1"}},
 
114
        networks: []string{"private", "public"},
 
115
        expected: "8.8.8.8",
 
116
}, {
 
117
        summary:  "public, private, and localhost - both IPv6 and IPv4",
 
118
        private:  []nova.IPAddress{{6, "::1"}, {6, "fc00::1"}, {4, "127.0.0.4"}, {4, "192.168.0.1"}},
 
119
        public:   []nova.IPAddress{{6, "2001:db8::1"}, {4, "8.8.8.8"}},
 
120
        networks: []string{"private", "public"},
 
121
        expected: "2001:db8::1",
 
122
}, {
 
123
        summary:  "custom only IPv4",
 
124
        private:  []nova.IPAddress{{4, "192.168.0.1"}},
 
125
        networks: []string{"special"},
 
126
        expected: "192.168.0.1",
 
127
}, {
 
128
        summary:  "custom only IPv6",
 
129
        private:  []nova.IPAddress{{6, "fc00::1"}},
 
130
        networks: []string{"special"},
 
131
        expected: "fc00::1",
 
132
}, {
 
133
        summary:  "custom only - both IPv4 and IPv6",
 
134
        private:  []nova.IPAddress{{4, "192.168.0.1"}, {6, "fc00::1"}},
 
135
        networks: []string{"special"},
 
136
        expected: "192.168.0.1",
 
137
}, {
 
138
        summary:  "custom only - both IPv6 and IPv4",
 
139
        private:  []nova.IPAddress{{6, "fc00::1"}, {4, "192.168.0.1"}},
 
140
        networks: []string{"special"},
 
141
        expected: "fc00::1",
 
142
}, {
 
143
        summary:  "custom and public IPv4",
 
144
        private:  []nova.IPAddress{{4, "172.16.0.1"}},
 
145
        public:   []nova.IPAddress{{4, "8.8.8.8"}},
 
146
        networks: []string{"special", "public"},
 
147
        expected: "8.8.8.8",
 
148
}, {
 
149
        summary:  "custom and public IPv6",
 
150
        private:  []nova.IPAddress{{6, "fc00::1"}},
 
151
        public:   []nova.IPAddress{{6, "2001:db8::1"}},
 
152
        networks: []string{"special", "public"},
 
153
        expected: "2001:db8::1",
 
154
}, {
 
155
        summary:  "custom and public - both IPv4 and IPv6",
 
156
        private:  []nova.IPAddress{{4, "172.16.0.1"}, {6, "fc00::1"}},
 
157
        public:   []nova.IPAddress{{4, "8.8.8.8"}, {6, "2001:db8::1"}},
 
158
        networks: []string{"special", "public"},
 
159
        expected: "8.8.8.8",
 
160
}, {
 
161
        summary:  "custom and public - both IPv6 and IPv4",
 
162
        private:  []nova.IPAddress{{6, "fc00::1"}, {4, "172.16.0.1"}},
 
163
        public:   []nova.IPAddress{{6, "2001:db8::1"}, {4, "8.8.8.8"}},
 
164
        networks: []string{"special", "public"},
 
165
        expected: "2001:db8::1",
 
166
}, {
 
167
        summary:    "floating and public, same address",
 
168
        floatingIP: "8.8.8.8",
 
169
        public:     []nova.IPAddress{{4, "8.8.8.8"}},
 
170
        networks:   []string{"", "public"},
 
171
        expected:   "8.8.8.8",
 
172
}, {
 
173
        summary:    "floating and public, different address",
 
174
        floatingIP: "8.8.4.4",
 
175
        public:     []nova.IPAddress{{4, "8.8.8.8"}},
 
176
        networks:   []string{"", "public"},
 
177
        expected:   "8.8.4.4",
 
178
}, {
 
179
        summary:    "floating and private",
 
180
        floatingIP: "8.8.4.4",
 
181
        private:    []nova.IPAddress{{4, "10.0.0.1"}},
 
182
        networks:   []string{"private"},
 
183
        expected:   "8.8.4.4",
 
184
}, {
 
185
        summary:    "floating, custom and public",
 
186
        floatingIP: "8.8.4.4",
 
187
        private:    []nova.IPAddress{{4, "172.16.0.1"}},
 
188
        public:     []nova.IPAddress{{4, "8.8.8.8"}},
 
189
        networks:   []string{"special", "public"},
 
190
        expected:   "8.8.4.4",
 
191
}}
 
192
 
 
193
func (t *localTests) TestGetServerAddresses(c *gc.C) {
 
194
        for i, t := range addressTests {
 
195
                c.Logf("#%d. %s -> %s (%v)", i, t.summary, t.expected, t.failure)
 
196
                addresses := make(map[string][]nova.IPAddress)
 
197
                if t.private != nil {
 
198
                        if len(t.networks) < 1 {
 
199
                                addresses["private"] = t.private
 
200
                        } else {
 
201
                                addresses[t.networks[0]] = t.private
 
202
                        }
 
203
                }
 
204
                if t.public != nil {
 
205
                        if len(t.networks) < 2 {
 
206
                                addresses["public"] = t.public
 
207
                        } else {
 
208
                                addresses[t.networks[1]] = t.public
 
209
                        }
 
210
                }
 
211
                addr := InstanceAddress(t.floatingIP, addresses)
 
212
                c.Assert(addr, gc.Equals, t.expected)
 
213
        }
 
214
}
 
215
 
 
216
func (*localTests) TestPortsToRuleInfo(c *gc.C) {
 
217
        groupId := "groupid"
 
218
        testCases := []struct {
 
219
                about    string
 
220
                ports    []network.PortRange
 
221
                expected []nova.RuleInfo
 
222
        }{{
 
223
                about: "single port",
 
224
                ports: []network.PortRange{{
 
225
                        FromPort: 80,
 
226
                        ToPort:   80,
 
227
                        Protocol: "tcp",
 
228
                }},
 
229
                expected: []nova.RuleInfo{{
 
230
                        IPProtocol:    "tcp",
 
231
                        FromPort:      80,
 
232
                        ToPort:        80,
 
233
                        Cidr:          "0.0.0.0/0",
 
234
                        ParentGroupId: groupId,
 
235
                }},
 
236
        }, {
 
237
                about: "multiple ports",
 
238
                ports: []network.PortRange{{
 
239
                        FromPort: 80,
 
240
                        ToPort:   82,
 
241
                        Protocol: "tcp",
 
242
                }},
 
243
                expected: []nova.RuleInfo{{
 
244
                        IPProtocol:    "tcp",
 
245
                        FromPort:      80,
 
246
                        ToPort:        82,
 
247
                        Cidr:          "0.0.0.0/0",
 
248
                        ParentGroupId: groupId,
 
249
                }},
 
250
        }, {
 
251
                about: "multiple port ranges",
 
252
                ports: []network.PortRange{{
 
253
                        FromPort: 80,
 
254
                        ToPort:   82,
 
255
                        Protocol: "tcp",
 
256
                }, {
 
257
                        FromPort: 100,
 
258
                        ToPort:   120,
 
259
                        Protocol: "tcp",
 
260
                }},
 
261
                expected: []nova.RuleInfo{{
 
262
                        IPProtocol:    "tcp",
 
263
                        FromPort:      80,
 
264
                        ToPort:        82,
 
265
                        Cidr:          "0.0.0.0/0",
 
266
                        ParentGroupId: groupId,
 
267
                }, {
 
268
                        IPProtocol:    "tcp",
 
269
                        FromPort:      100,
 
270
                        ToPort:        120,
 
271
                        Cidr:          "0.0.0.0/0",
 
272
                        ParentGroupId: groupId,
 
273
                }},
 
274
        }}
 
275
 
 
276
        for i, t := range testCases {
 
277
                c.Logf("test %d: %s", i, t.about)
 
278
                rules := PortsToRuleInfo(groupId, t.ports)
 
279
                c.Check(len(rules), gc.Equals, len(t.expected))
 
280
                c.Check(rules, gc.DeepEquals, t.expected)
 
281
        }
 
282
}
 
283
 
 
284
func (*localTests) TestRuleMatchesPortRange(c *gc.C) {
 
285
        proto_tcp := "tcp"
 
286
        proto_udp := "udp"
 
287
        port_80 := 80
 
288
        port_85 := 85
 
289
 
 
290
        testCases := []struct {
 
291
                about    string
 
292
                ports    network.PortRange
 
293
                rule     nova.SecurityGroupRule
 
294
                expected bool
 
295
        }{{
 
296
                about: "single port",
 
297
                ports: network.PortRange{
 
298
                        FromPort: 80,
 
299
                        ToPort:   80,
 
300
                        Protocol: "tcp",
 
301
                },
 
302
                rule: nova.SecurityGroupRule{
 
303
                        IPProtocol: &proto_tcp,
 
304
                        FromPort:   &port_80,
 
305
                        ToPort:     &port_80,
 
306
                },
 
307
                expected: true,
 
308
        }, {
 
309
                about: "multiple port",
 
310
                ports: network.PortRange{
 
311
                        FromPort: port_80,
 
312
                        ToPort:   port_85,
 
313
                        Protocol: proto_tcp,
 
314
                },
 
315
                rule: nova.SecurityGroupRule{
 
316
                        IPProtocol: &proto_tcp,
 
317
                        FromPort:   &port_80,
 
318
                        ToPort:     &port_85,
 
319
                },
 
320
                expected: true,
 
321
        }, {
 
322
                about: "nil rule components",
 
323
                ports: network.PortRange{
 
324
                        FromPort: port_80,
 
325
                        ToPort:   port_85,
 
326
                        Protocol: proto_tcp,
 
327
                },
 
328
                rule: nova.SecurityGroupRule{
 
329
                        IPProtocol: nil,
 
330
                        FromPort:   nil,
 
331
                        ToPort:     nil,
 
332
                },
 
333
                expected: false,
 
334
        }, {
 
335
                about: "mismatched port range and rule",
 
336
                ports: network.PortRange{
 
337
                        FromPort: port_80,
 
338
                        ToPort:   port_85,
 
339
                        Protocol: proto_tcp,
 
340
                },
 
341
                rule: nova.SecurityGroupRule{
 
342
                        IPProtocol: &proto_udp,
 
343
                        FromPort:   &port_80,
 
344
                        ToPort:     &port_80,
 
345
                },
 
346
                expected: false,
 
347
        }}
 
348
        for i, t := range testCases {
 
349
                c.Logf("test %d: %s", i, t.about)
 
350
                c.Check(RuleMatchesPortRange(t.rule, t.ports), gc.Equals, t.expected)
 
351
        }
 
352
}
 
353
 
 
354
func (s *localTests) TestDetectRegionsNoRegionName(c *gc.C) {
 
355
        _, err := s.detectRegions(c)
 
356
        c.Assert(err, gc.ErrorMatches, "OS_REGION_NAME environment variable not set")
 
357
}
 
358
 
 
359
func (s *localTests) TestDetectRegionsNoAuthURL(c *gc.C) {
 
360
        s.PatchEnvironment("OS_REGION_NAME", "oceania")
 
361
        _, err := s.detectRegions(c)
 
362
        c.Assert(err, gc.ErrorMatches, "OS_AUTH_URL environment variable not set")
 
363
}
 
364
 
 
365
func (s *localTests) TestDetectRegions(c *gc.C) {
 
366
        s.PatchEnvironment("OS_REGION_NAME", "oceania")
 
367
        s.PatchEnvironment("OS_AUTH_URL", "http://keystone.internal")
 
368
        regions, err := s.detectRegions(c)
 
369
        c.Assert(err, jc.ErrorIsNil)
 
370
        c.Assert(regions, jc.DeepEquals, []cloud.Region{
 
371
                {Name: "oceania", Endpoint: "http://keystone.internal"},
 
372
        })
 
373
}
 
374
 
 
375
func (s *localTests) detectRegions(c *gc.C) ([]cloud.Region, error) {
 
376
        provider, err := environs.Provider("openstack")
 
377
        c.Assert(err, jc.ErrorIsNil)
 
378
        c.Assert(provider, gc.Implements, new(environs.CloudRegionDetector))
 
379
        return provider.(environs.CloudRegionDetector).DetectRegions()
 
380
}
 
381
 
 
382
type providerUnitTests struct{}
 
383
 
 
384
var _ = gc.Suite(&providerUnitTests{})
 
385
 
 
386
func (s *providerUnitTests) TestIdentityClientVersion_BadURLErrors(c *gc.C) {
 
387
        _, err := identityClientVersion("abc123")
 
388
        c.Check(err, gc.Not(jc.ErrorIsNil))
 
389
}
 
390
 
 
391
func (s *providerUnitTests) TestIdentityClientVersion_ParsesGoodURL(c *gc.C) {
 
392
        version, err := identityClientVersion("https://keystone.internal/v2.0")
 
393
        c.Assert(err, jc.ErrorIsNil)
 
394
        c.Check(version, gc.Equals, 2)
 
395
 
 
396
        version, err = identityClientVersion("https://keystone.internal/v3.0/")
 
397
        c.Assert(err, jc.ErrorIsNil)
 
398
        c.Check(version, gc.Equals, 3)
 
399
 
 
400
        version, err = identityClientVersion("https://keystone.internal/v2/")
 
401
        c.Assert(err, jc.ErrorIsNil)
 
402
        c.Check(version, gc.Equals, 2)
 
403
}