github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/openstack/provider_test.go (about) 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 IPv4 plus (what HP cloud used to do)", 58 private: []nova.IPAddress{{4, "10.0.0.1"}, {4, "8.8.4.4"}}, 59 networks: []string{"private"}, 60 expected: "8.8.4.4", 61 }, { 62 summary: "public IPv4 only", 63 public: []nova.IPAddress{{4, "8.8.8.8"}}, 64 networks: []string{"", "public"}, 65 expected: "8.8.8.8", 66 }, { 67 summary: "public IPv6 only", 68 public: []nova.IPAddress{{6, "2001:db8::1"}}, 69 networks: []string{"", "public"}, 70 expected: "2001:db8::1", 71 }, { 72 summary: "public only, both IPv4 and IPv6", 73 public: []nova.IPAddress{{4, "8.8.8.8"}, {6, "2001:db8::1"}}, 74 networks: []string{"", "public"}, 75 expected: "8.8.8.8", 76 }, { 77 summary: "public and private both IPv4", 78 private: []nova.IPAddress{{4, "10.0.0.4"}}, 79 public: []nova.IPAddress{{4, "8.8.4.4"}}, 80 networks: []string{"private", "public"}, 81 expected: "8.8.4.4", 82 }, { 83 summary: "public and private both IPv6", 84 private: []nova.IPAddress{{6, "fc00::1"}}, 85 public: []nova.IPAddress{{6, "2001:db8::1"}}, 86 networks: []string{"private", "public"}, 87 expected: "2001:db8::1", 88 }, { 89 summary: "public, private, and localhost IPv4", 90 private: []nova.IPAddress{{4, "127.0.0.4"}, {4, "192.168.0.1"}}, 91 public: []nova.IPAddress{{4, "8.8.8.8"}}, 92 networks: []string{"private", "public"}, 93 expected: "8.8.8.8", 94 }, { 95 summary: "public, private, and localhost IPv6", 96 private: []nova.IPAddress{{6, "::1"}, {6, "fc00::1"}}, 97 public: []nova.IPAddress{{6, "2001:db8::1"}}, 98 networks: []string{"private", "public"}, 99 expected: "2001:db8::1", 100 }, { 101 summary: "public, private, and localhost - both IPv4 and IPv6", 102 private: []nova.IPAddress{{4, "127.0.0.4"}, {4, "192.168.0.1"}, {6, "::1"}, {6, "fc00::1"}}, 103 public: []nova.IPAddress{{4, "8.8.8.8"}, {6, "2001:db8::1"}}, 104 networks: []string{"private", "public"}, 105 expected: "8.8.8.8", 106 }, { 107 summary: "custom only IPv4", 108 private: []nova.IPAddress{{4, "192.168.0.1"}}, 109 networks: []string{"special"}, 110 expected: "192.168.0.1", 111 }, { 112 summary: "custom only IPv6", 113 private: []nova.IPAddress{{6, "fc00::1"}}, 114 networks: []string{"special"}, 115 expected: "fc00::1", 116 }, { 117 summary: "custom only - both IPv4 and IPv6", 118 private: []nova.IPAddress{{4, "192.168.0.1"}, {6, "fc00::1"}}, 119 networks: []string{"special"}, 120 expected: "192.168.0.1", 121 }, { 122 summary: "custom and public IPv4", 123 private: []nova.IPAddress{{4, "172.16.0.1"}}, 124 public: []nova.IPAddress{{4, "8.8.8.8"}}, 125 networks: []string{"special", "public"}, 126 expected: "8.8.8.8", 127 }, { 128 summary: "custom and public IPv6", 129 private: []nova.IPAddress{{6, "fc00::1"}}, 130 public: []nova.IPAddress{{6, "2001:db8::1"}}, 131 networks: []string{"special", "public"}, 132 expected: "2001:db8::1", 133 }, { 134 summary: "custom and public - both IPv4 and IPv6", 135 private: []nova.IPAddress{{4, "172.16.0.1"}, {6, "fc00::1"}}, 136 public: []nova.IPAddress{{4, "8.8.8.8"}, {6, "2001:db8::1"}}, 137 networks: []string{"special", "public"}, 138 expected: "8.8.8.8", 139 }, { 140 summary: "floating and public, same address", 141 floatingIP: "8.8.8.8", 142 public: []nova.IPAddress{{4, "8.8.8.8"}}, 143 networks: []string{"", "public"}, 144 expected: "8.8.8.8", 145 }, { 146 summary: "floating and public, different address", 147 floatingIP: "8.8.4.4", 148 public: []nova.IPAddress{{4, "8.8.8.8"}}, 149 networks: []string{"", "public"}, 150 expected: "8.8.4.4", 151 }, { 152 summary: "floating and private", 153 floatingIP: "8.8.4.4", 154 private: []nova.IPAddress{{4, "10.0.0.1"}}, 155 networks: []string{"private"}, 156 expected: "8.8.4.4", 157 }, { 158 summary: "floating, custom and public", 159 floatingIP: "8.8.4.4", 160 private: []nova.IPAddress{{4, "172.16.0.1"}}, 161 public: []nova.IPAddress{{4, "8.8.8.8"}}, 162 networks: []string{"special", "public"}, 163 expected: "8.8.4.4", 164 }} 165 166 func (t *localTests) TestGetServerAddresses(c *gc.C) { 167 for i, t := range addressTests { 168 c.Logf("#%d. %s -> %s (%v)", i, t.summary, t.expected, t.failure) 169 addresses := make(map[string][]nova.IPAddress) 170 if t.private != nil { 171 if len(t.networks) < 1 { 172 addresses["private"] = t.private 173 } else { 174 addresses[t.networks[0]] = t.private 175 } 176 } 177 if t.public != nil { 178 if len(t.networks) < 2 { 179 addresses["public"] = t.public 180 } else { 181 addresses[t.networks[1]] = t.public 182 } 183 } 184 addr := InstanceAddress(t.floatingIP, addresses) 185 c.Check(addr, gc.Equals, t.expected) 186 } 187 } 188 189 func (*localTests) TestPortsToRuleInfo(c *gc.C) { 190 groupId := "groupid" 191 testCases := []struct { 192 about string 193 ports []network.PortRange 194 expected []nova.RuleInfo 195 }{{ 196 about: "single port", 197 ports: []network.PortRange{{ 198 FromPort: 80, 199 ToPort: 80, 200 Protocol: "tcp", 201 }}, 202 expected: []nova.RuleInfo{{ 203 IPProtocol: "tcp", 204 FromPort: 80, 205 ToPort: 80, 206 Cidr: "0.0.0.0/0", 207 ParentGroupId: groupId, 208 }}, 209 }, { 210 about: "multiple ports", 211 ports: []network.PortRange{{ 212 FromPort: 80, 213 ToPort: 82, 214 Protocol: "tcp", 215 }}, 216 expected: []nova.RuleInfo{{ 217 IPProtocol: "tcp", 218 FromPort: 80, 219 ToPort: 82, 220 Cidr: "0.0.0.0/0", 221 ParentGroupId: groupId, 222 }}, 223 }, { 224 about: "multiple port ranges", 225 ports: []network.PortRange{{ 226 FromPort: 80, 227 ToPort: 82, 228 Protocol: "tcp", 229 }, { 230 FromPort: 100, 231 ToPort: 120, 232 Protocol: "tcp", 233 }}, 234 expected: []nova.RuleInfo{{ 235 IPProtocol: "tcp", 236 FromPort: 80, 237 ToPort: 82, 238 Cidr: "0.0.0.0/0", 239 ParentGroupId: groupId, 240 }, { 241 IPProtocol: "tcp", 242 FromPort: 100, 243 ToPort: 120, 244 Cidr: "0.0.0.0/0", 245 ParentGroupId: groupId, 246 }}, 247 }} 248 249 for i, t := range testCases { 250 c.Logf("test %d: %s", i, t.about) 251 rules := PortsToRuleInfo(groupId, t.ports) 252 c.Check(len(rules), gc.Equals, len(t.expected)) 253 c.Check(rules, gc.DeepEquals, t.expected) 254 } 255 } 256 257 func (*localTests) TestRuleMatchesPortRange(c *gc.C) { 258 proto_tcp := "tcp" 259 proto_udp := "udp" 260 port_80 := 80 261 port_85 := 85 262 263 testCases := []struct { 264 about string 265 ports network.PortRange 266 rule nova.SecurityGroupRule 267 expected bool 268 }{{ 269 about: "single port", 270 ports: network.PortRange{ 271 FromPort: 80, 272 ToPort: 80, 273 Protocol: "tcp", 274 }, 275 rule: nova.SecurityGroupRule{ 276 IPProtocol: &proto_tcp, 277 FromPort: &port_80, 278 ToPort: &port_80, 279 }, 280 expected: true, 281 }, { 282 about: "multiple port", 283 ports: network.PortRange{ 284 FromPort: port_80, 285 ToPort: port_85, 286 Protocol: proto_tcp, 287 }, 288 rule: nova.SecurityGroupRule{ 289 IPProtocol: &proto_tcp, 290 FromPort: &port_80, 291 ToPort: &port_85, 292 }, 293 expected: true, 294 }, { 295 about: "nil rule components", 296 ports: network.PortRange{ 297 FromPort: port_80, 298 ToPort: port_85, 299 Protocol: proto_tcp, 300 }, 301 rule: nova.SecurityGroupRule{ 302 IPProtocol: nil, 303 FromPort: nil, 304 ToPort: nil, 305 }, 306 expected: false, 307 }, { 308 about: "mismatched port range and rule", 309 ports: network.PortRange{ 310 FromPort: port_80, 311 ToPort: port_85, 312 Protocol: proto_tcp, 313 }, 314 rule: nova.SecurityGroupRule{ 315 IPProtocol: &proto_udp, 316 FromPort: &port_80, 317 ToPort: &port_80, 318 }, 319 expected: false, 320 }} 321 for i, t := range testCases { 322 c.Logf("test %d: %s", i, t.about) 323 c.Check(RuleMatchesPortRange(t.rule, t.ports), gc.Equals, t.expected) 324 } 325 } 326 327 func (s *localTests) TestDetectRegionsNoRegionName(c *gc.C) { 328 _, err := s.detectRegions(c) 329 c.Assert(err, gc.ErrorMatches, "OS_REGION_NAME environment variable not set") 330 } 331 332 func (s *localTests) TestDetectRegionsNoAuthURL(c *gc.C) { 333 s.PatchEnvironment("OS_REGION_NAME", "oceania") 334 _, err := s.detectRegions(c) 335 c.Assert(err, gc.ErrorMatches, "OS_AUTH_URL environment variable not set") 336 } 337 338 func (s *localTests) TestDetectRegions(c *gc.C) { 339 s.PatchEnvironment("OS_REGION_NAME", "oceania") 340 s.PatchEnvironment("OS_AUTH_URL", "http://keystone.internal") 341 regions, err := s.detectRegions(c) 342 c.Assert(err, jc.ErrorIsNil) 343 c.Assert(regions, jc.DeepEquals, []cloud.Region{ 344 {Name: "oceania", Endpoint: "http://keystone.internal"}, 345 }) 346 } 347 348 func (s *localTests) detectRegions(c *gc.C) ([]cloud.Region, error) { 349 provider, err := environs.Provider("openstack") 350 c.Assert(err, jc.ErrorIsNil) 351 c.Assert(provider, gc.Implements, new(environs.CloudRegionDetector)) 352 return provider.(environs.CloudRegionDetector).DetectRegions() 353 } 354 355 type providerUnitTests struct{} 356 357 var _ = gc.Suite(&providerUnitTests{}) 358 359 func (s *providerUnitTests) TestIdentityClientVersion_BadURLErrors(c *gc.C) { 360 _, err := identityClientVersion("abc123") 361 c.Check(err, gc.Not(jc.ErrorIsNil)) 362 } 363 364 func (s *providerUnitTests) TestIdentityClientVersion_ParsesGoodURL(c *gc.C) { 365 version, err := identityClientVersion("https://keystone.internal/v2.0") 366 c.Assert(err, jc.ErrorIsNil) 367 c.Check(version, gc.Equals, 2) 368 369 version, err = identityClientVersion("https://keystone.internal/v3.0/") 370 c.Assert(err, jc.ErrorIsNil) 371 c.Check(version, gc.Equals, 3) 372 373 version, err = identityClientVersion("https://keystone.internal/v2/") 374 c.Assert(err, jc.ErrorIsNil) 375 c.Check(version, gc.Equals, 2) 376 }