1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
7
gitjujutesting "github.com/juju/testing"
8
jc "github.com/juju/testing/checkers"
10
"gopkg.in/goose.v1/nova"
12
"github.com/juju/juju/cloud"
13
"github.com/juju/juju/environs"
14
"github.com/juju/juju/network"
17
// localTests contains tests which do not require a live service or test double to run.
18
type localTests struct {
19
gitjujutesting.IsolationSuite
22
var _ = gc.Suite(&localTests{})
24
// ported from lp:juju/juju/providers/openstack/tests/test_machine.py
25
var addressTests = []struct {
28
private []nova.IPAddress
29
public []nova.IPAddress
38
private: []nova.IPAddress{},
39
networks: []string{"private"},
42
summary: "private IPv4 only",
43
private: []nova.IPAddress{{4, "192.168.0.1"}},
44
networks: []string{"private"},
45
expected: "192.168.0.1",
47
summary: "private IPv6 only",
48
private: []nova.IPAddress{{6, "fc00::1"}},
49
networks: []string{"private"},
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",
57
summary: "private only, both IPv6 and IPv4",
58
private: []nova.IPAddress{{6, "fc00::1"}, {4, "192.168.0.1"}},
59
networks: []string{"private"},
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"},
67
summary: "public IPv4 only",
68
public: []nova.IPAddress{{4, "8.8.8.8"}},
69
networks: []string{"", "public"},
72
summary: "public IPv6 only",
73
public: []nova.IPAddress{{6, "2001:db8::1"}},
74
networks: []string{"", "public"},
75
expected: "2001:db8::1",
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"},
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",
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"},
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",
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"},
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",
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"},
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",
123
summary: "custom only IPv4",
124
private: []nova.IPAddress{{4, "192.168.0.1"}},
125
networks: []string{"special"},
126
expected: "192.168.0.1",
128
summary: "custom only IPv6",
129
private: []nova.IPAddress{{6, "fc00::1"}},
130
networks: []string{"special"},
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",
138
summary: "custom only - both IPv6 and IPv4",
139
private: []nova.IPAddress{{6, "fc00::1"}, {4, "192.168.0.1"}},
140
networks: []string{"special"},
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"},
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",
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"},
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",
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"},
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"},
179
summary: "floating and private",
180
floatingIP: "8.8.4.4",
181
private: []nova.IPAddress{{4, "10.0.0.1"}},
182
networks: []string{"private"},
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"},
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
201
addresses[t.networks[0]] = t.private
205
if len(t.networks) < 2 {
206
addresses["public"] = t.public
208
addresses[t.networks[1]] = t.public
211
addr := InstanceAddress(t.floatingIP, addresses)
212
c.Assert(addr, gc.Equals, t.expected)
216
func (*localTests) TestPortsToRuleInfo(c *gc.C) {
218
testCases := []struct {
220
ports []network.PortRange
221
expected []nova.RuleInfo
223
about: "single port",
224
ports: []network.PortRange{{
229
expected: []nova.RuleInfo{{
234
ParentGroupId: groupId,
237
about: "multiple ports",
238
ports: []network.PortRange{{
243
expected: []nova.RuleInfo{{
248
ParentGroupId: groupId,
251
about: "multiple port ranges",
252
ports: []network.PortRange{{
261
expected: []nova.RuleInfo{{
266
ParentGroupId: groupId,
272
ParentGroupId: groupId,
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)
284
func (*localTests) TestRuleMatchesPortRange(c *gc.C) {
290
testCases := []struct {
292
ports network.PortRange
293
rule nova.SecurityGroupRule
296
about: "single port",
297
ports: network.PortRange{
302
rule: nova.SecurityGroupRule{
303
IPProtocol: &proto_tcp,
309
about: "multiple port",
310
ports: network.PortRange{
315
rule: nova.SecurityGroupRule{
316
IPProtocol: &proto_tcp,
322
about: "nil rule components",
323
ports: network.PortRange{
328
rule: nova.SecurityGroupRule{
335
about: "mismatched port range and rule",
336
ports: network.PortRange{
341
rule: nova.SecurityGroupRule{
342
IPProtocol: &proto_udp,
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)
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")
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")
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"},
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()
382
type providerUnitTests struct{}
384
var _ = gc.Suite(&providerUnitTests{})
386
func (s *providerUnitTests) TestIdentityClientVersion_BadURLErrors(c *gc.C) {
387
_, err := identityClientVersion("abc123")
388
c.Check(err, gc.Not(jc.ErrorIsNil))
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)
396
version, err = identityClientVersion("https://keystone.internal/v3.0/")
397
c.Assert(err, jc.ErrorIsNil)
398
c.Check(version, gc.Equals, 3)
400
version, err = identityClientVersion("https://keystone.internal/v2/")
401
c.Assert(err, jc.ErrorIsNil)
402
c.Check(version, gc.Equals, 2)