github.com/gophercloud/gophercloud@v1.11.0/internal/acceptance/openstack/loadbalancer/v2/loadbalancer.go (about) 1 package v2 2 3 import ( 4 "fmt" 5 "strings" 6 "testing" 7 8 "github.com/gophercloud/gophercloud" 9 "github.com/gophercloud/gophercloud/internal/acceptance/clients" 10 "github.com/gophercloud/gophercloud/internal/acceptance/tools" 11 "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavorprofiles" 12 "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/flavors" 13 "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/l7policies" 14 "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners" 15 "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers" 16 "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors" 17 "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools" 18 th "github.com/gophercloud/gophercloud/testhelper" 19 ) 20 21 // CreateListener will create a listener for a given load balancer on a random 22 // port with a random name. An error will be returned if the listener could not 23 // be created. 24 func CreateListener(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer) (*listeners.Listener, error) { 25 listenerName := tools.RandomString("TESTACCT-", 8) 26 listenerDescription := tools.RandomString("TESTACCT-DESC-", 8) 27 listenerPort := tools.RandomInt(1, 100) 28 29 t.Logf("Attempting to create listener %s on port %d", listenerName, listenerPort) 30 31 createOpts := listeners.CreateOpts{ 32 Name: listenerName, 33 Description: listenerDescription, 34 LoadbalancerID: lb.ID, 35 Protocol: listeners.ProtocolTCP, 36 ProtocolPort: listenerPort, 37 } 38 39 listener, err := listeners.Create(client, createOpts).Extract() 40 if err != nil { 41 return listener, err 42 } 43 44 t.Logf("Successfully created listener %s", listenerName) 45 46 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 47 return listener, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 48 } 49 50 th.AssertEquals(t, listener.Name, listenerName) 51 th.AssertEquals(t, listener.Description, listenerDescription) 52 th.AssertEquals(t, listener.Loadbalancers[0].ID, lb.ID) 53 th.AssertEquals(t, listener.Protocol, string(listeners.ProtocolTCP)) 54 th.AssertEquals(t, listener.ProtocolPort, listenerPort) 55 56 return listener, nil 57 } 58 59 // CreateListenerHTTP will create an HTTP-based listener for a given load 60 // balancer on a random port with a random name. An error will be returned 61 // if the listener could not be created. 62 func CreateListenerHTTP(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer) (*listeners.Listener, error) { 63 tlsVersions := []listeners.TLSVersion{} 64 tlsVersionsExp := []string(nil) 65 listenerName := tools.RandomString("TESTACCT-", 8) 66 listenerDescription := tools.RandomString("TESTACCT-DESC-", 8) 67 listenerPort := tools.RandomInt(1, 100) 68 69 t.Logf("Attempting to create listener %s on port %d", listenerName, listenerPort) 70 71 headers := map[string]string{ 72 "X-Forwarded-For": "true", 73 } 74 75 // tls_version is only supported in microversion v2.17 introduced in victoria 76 if clients.IsCurrentAbove(t, "stable/ussuri") { 77 tlsVersions = []listeners.TLSVersion{"TLSv1.2", "TLSv1.3"} 78 tlsVersionsExp = []string{"TLSv1.2", "TLSv1.3"} 79 } 80 81 createOpts := listeners.CreateOpts{ 82 Name: listenerName, 83 Description: listenerDescription, 84 LoadbalancerID: lb.ID, 85 InsertHeaders: headers, 86 Protocol: listeners.ProtocolHTTP, 87 ProtocolPort: listenerPort, 88 TLSVersions: tlsVersions, 89 } 90 91 listener, err := listeners.Create(client, createOpts).Extract() 92 if err != nil { 93 return listener, err 94 } 95 96 t.Logf("Successfully created listener %s", listenerName) 97 98 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 99 return listener, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 100 } 101 102 th.AssertEquals(t, listener.Name, listenerName) 103 th.AssertEquals(t, listener.Description, listenerDescription) 104 th.AssertEquals(t, listener.Loadbalancers[0].ID, lb.ID) 105 th.AssertEquals(t, listener.Protocol, string(listeners.ProtocolHTTP)) 106 th.AssertEquals(t, listener.ProtocolPort, listenerPort) 107 th.AssertDeepEquals(t, listener.InsertHeaders, headers) 108 th.AssertDeepEquals(t, listener.TLSVersions, tlsVersionsExp) 109 110 return listener, nil 111 } 112 113 // CreateLoadBalancer will create a load balancer with a random name on a given 114 // subnet. An error will be returned if the loadbalancer could not be created. 115 func CreateLoadBalancer(t *testing.T, client *gophercloud.ServiceClient, subnetID string, tags []string, policyID string) (*loadbalancers.LoadBalancer, error) { 116 lbName := tools.RandomString("TESTACCT-", 8) 117 lbDescription := tools.RandomString("TESTACCT-DESC-", 8) 118 119 t.Logf("Attempting to create loadbalancer %s on subnet %s", lbName, subnetID) 120 121 createOpts := loadbalancers.CreateOpts{ 122 Name: lbName, 123 Description: lbDescription, 124 VipSubnetID: subnetID, 125 AdminStateUp: gophercloud.Enabled, 126 } 127 if len(tags) > 0 { 128 createOpts.Tags = tags 129 } 130 131 if len(policyID) > 0 { 132 createOpts.VipQosPolicyID = policyID 133 } 134 135 lb, err := loadbalancers.Create(client, createOpts).Extract() 136 if err != nil { 137 return lb, err 138 } 139 140 t.Logf("Successfully created loadbalancer %s on subnet %s", lbName, subnetID) 141 t.Logf("Waiting for loadbalancer %s to become active", lbName) 142 143 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 144 return lb, err 145 } 146 147 t.Logf("LoadBalancer %s is active", lbName) 148 149 th.AssertEquals(t, lb.Name, lbName) 150 th.AssertEquals(t, lb.Description, lbDescription) 151 th.AssertEquals(t, lb.VipSubnetID, subnetID) 152 th.AssertEquals(t, lb.AdminStateUp, true) 153 154 if len(tags) > 0 { 155 th.AssertDeepEquals(t, lb.Tags, tags) 156 } 157 158 if len(policyID) > 0 { 159 th.AssertEquals(t, lb.VipQosPolicyID, policyID) 160 } 161 162 return lb, nil 163 } 164 165 // CreateLoadBalancerFullyPopulated will create a fully populated load balancer with a random name on a given 166 // subnet. It will contain a listener, l7policy, l7rule, pool, member and health monitor. 167 // An error will be returned if the loadbalancer could not be created. 168 func CreateLoadBalancerFullyPopulated(t *testing.T, client *gophercloud.ServiceClient, subnetID string, tags []string) (*loadbalancers.LoadBalancer, error) { 169 lbName := tools.RandomString("TESTACCT-", 8) 170 lbDescription := tools.RandomString("TESTACCT-DESC-", 8) 171 listenerName := tools.RandomString("TESTACCT-", 8) 172 listenerDescription := tools.RandomString("TESTACCT-DESC-", 8) 173 listenerPort := tools.RandomInt(1, 100) 174 policyName := tools.RandomString("TESTACCT-", 8) 175 policyDescription := tools.RandomString("TESTACCT-DESC-", 8) 176 poolName := tools.RandomString("TESTACCT-", 8) 177 poolDescription := tools.RandomString("TESTACCT-DESC-", 8) 178 memberName := tools.RandomString("TESTACCT-", 8) 179 memberPort := tools.RandomInt(100, 1000) 180 memberWeight := tools.RandomInt(1, 10) 181 182 t.Logf("Attempting to create fully populated loadbalancer %s on subnet %s which contains listener: %s, l7Policy: %s, pool %s, member %s", 183 lbName, subnetID, listenerName, policyName, poolName, memberName) 184 185 createOpts := loadbalancers.CreateOpts{ 186 Name: lbName, 187 Description: lbDescription, 188 VipSubnetID: subnetID, 189 AdminStateUp: gophercloud.Enabled, 190 Listeners: []listeners.CreateOpts{{ 191 Name: listenerName, 192 Description: listenerDescription, 193 Protocol: listeners.ProtocolHTTP, 194 ProtocolPort: listenerPort, 195 DefaultPool: &pools.CreateOpts{ 196 Name: poolName, 197 Description: poolDescription, 198 Protocol: pools.ProtocolHTTP, 199 LBMethod: pools.LBMethodLeastConnections, 200 Members: []pools.BatchUpdateMemberOpts{{ 201 Name: &memberName, 202 ProtocolPort: memberPort, 203 Weight: &memberWeight, 204 Address: "1.2.3.4", 205 SubnetID: &subnetID, 206 }}, 207 Monitor: &monitors.CreateOpts{ 208 Delay: 10, 209 Timeout: 5, 210 MaxRetries: 5, 211 MaxRetriesDown: 4, 212 Type: monitors.TypeHTTP, 213 }, 214 }, 215 L7Policies: []l7policies.CreateOpts{{ 216 Name: policyName, 217 Description: policyDescription, 218 Action: l7policies.ActionRedirectToURL, 219 RedirectURL: "http://www.example.com", 220 Rules: []l7policies.CreateRuleOpts{{ 221 RuleType: l7policies.TypePath, 222 CompareType: l7policies.CompareTypeStartWith, 223 Value: "/api", 224 }}, 225 }}, 226 }}, 227 } 228 if len(tags) > 0 { 229 createOpts.Tags = tags 230 } 231 232 lb, err := loadbalancers.Create(client, createOpts).Extract() 233 if err != nil { 234 return lb, err 235 } 236 237 t.Logf("Successfully created loadbalancer %s on subnet %s", lbName, subnetID) 238 t.Logf("Waiting for loadbalancer %s to become active", lbName) 239 240 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 241 return lb, err 242 } 243 244 t.Logf("LoadBalancer %s is active", lbName) 245 246 th.AssertEquals(t, lb.Name, lbName) 247 th.AssertEquals(t, lb.Description, lbDescription) 248 th.AssertEquals(t, lb.VipSubnetID, subnetID) 249 th.AssertEquals(t, lb.AdminStateUp, true) 250 251 th.AssertEquals(t, len(lb.Listeners), 1) 252 th.AssertEquals(t, lb.Listeners[0].Name, listenerName) 253 th.AssertEquals(t, lb.Listeners[0].Description, listenerDescription) 254 th.AssertEquals(t, lb.Listeners[0].ProtocolPort, listenerPort) 255 256 th.AssertEquals(t, len(lb.Listeners[0].L7Policies), 1) 257 th.AssertEquals(t, lb.Listeners[0].L7Policies[0].Name, policyName) 258 th.AssertEquals(t, lb.Listeners[0].L7Policies[0].Description, policyDescription) 259 th.AssertEquals(t, lb.Listeners[0].L7Policies[0].Description, policyDescription) 260 th.AssertEquals(t, len(lb.Listeners[0].L7Policies[0].Rules), 1) 261 262 th.AssertEquals(t, len(lb.Pools), 1) 263 th.AssertEquals(t, lb.Pools[0].Name, poolName) 264 th.AssertEquals(t, lb.Pools[0].Description, poolDescription) 265 266 th.AssertEquals(t, len(lb.Pools[0].Members), 1) 267 th.AssertEquals(t, lb.Pools[0].Members[0].Name, memberName) 268 th.AssertEquals(t, lb.Pools[0].Members[0].ProtocolPort, memberPort) 269 th.AssertEquals(t, lb.Pools[0].Members[0].Weight, memberWeight) 270 271 if len(tags) > 0 { 272 th.AssertDeepEquals(t, lb.Tags, tags) 273 } 274 275 return lb, nil 276 } 277 278 // CreateMember will create a member with a random name, port, address, and 279 // weight. An error will be returned if the member could not be created. 280 func CreateMember(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer, pool *pools.Pool, subnetID, subnetCIDR string) (*pools.Member, error) { 281 memberName := tools.RandomString("TESTACCT-", 8) 282 memberPort := tools.RandomInt(100, 1000) 283 memberWeight := tools.RandomInt(1, 10) 284 285 cidrParts := strings.Split(subnetCIDR, "/") 286 subnetParts := strings.Split(cidrParts[0], ".") 287 memberAddress := fmt.Sprintf("%s.%s.%s.%d", subnetParts[0], subnetParts[1], subnetParts[2], tools.RandomInt(10, 100)) 288 289 t.Logf("Attempting to create member %s", memberName) 290 291 createOpts := pools.CreateMemberOpts{ 292 Name: memberName, 293 ProtocolPort: memberPort, 294 Weight: &memberWeight, 295 Address: memberAddress, 296 SubnetID: subnetID, 297 } 298 299 t.Logf("Member create opts: %#v", createOpts) 300 301 member, err := pools.CreateMember(client, pool.ID, createOpts).Extract() 302 if err != nil { 303 return member, err 304 } 305 306 t.Logf("Successfully created member %s", memberName) 307 308 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 309 return member, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 310 } 311 312 th.AssertEquals(t, member.Name, memberName) 313 314 return member, nil 315 } 316 317 // CreateMonitor will create a monitor with a random name for a specific pool. 318 // An error will be returned if the monitor could not be created. 319 func CreateMonitor(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer, pool *pools.Pool) (*monitors.Monitor, error) { 320 monitorName := tools.RandomString("TESTACCT-", 8) 321 322 t.Logf("Attempting to create monitor %s", monitorName) 323 324 createOpts := monitors.CreateOpts{ 325 PoolID: pool.ID, 326 Name: monitorName, 327 Delay: 10, 328 Timeout: 5, 329 MaxRetries: 5, 330 MaxRetriesDown: 4, 331 Type: monitors.TypePING, 332 } 333 334 monitor, err := monitors.Create(client, createOpts).Extract() 335 if err != nil { 336 return monitor, err 337 } 338 339 t.Logf("Successfully created monitor: %s", monitorName) 340 341 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 342 return monitor, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 343 } 344 345 th.AssertEquals(t, monitor.Name, monitorName) 346 th.AssertEquals(t, monitor.Type, monitors.TypePING) 347 th.AssertEquals(t, monitor.Delay, 10) 348 th.AssertEquals(t, monitor.Timeout, 5) 349 th.AssertEquals(t, monitor.MaxRetries, 5) 350 th.AssertEquals(t, monitor.MaxRetriesDown, 4) 351 352 return monitor, nil 353 } 354 355 // CreatePool will create a pool with a random name with a specified listener 356 // and loadbalancer. An error will be returned if the pool could not be 357 // created. 358 func CreatePool(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer) (*pools.Pool, error) { 359 poolName := tools.RandomString("TESTACCT-", 8) 360 poolDescription := tools.RandomString("TESTACCT-DESC-", 8) 361 362 t.Logf("Attempting to create pool %s", poolName) 363 364 createOpts := pools.CreateOpts{ 365 Name: poolName, 366 Description: poolDescription, 367 Protocol: pools.ProtocolTCP, 368 LoadbalancerID: lb.ID, 369 LBMethod: pools.LBMethodLeastConnections, 370 } 371 372 pool, err := pools.Create(client, createOpts).Extract() 373 if err != nil { 374 return pool, err 375 } 376 377 t.Logf("Successfully created pool %s", poolName) 378 379 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 380 return pool, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 381 } 382 383 th.AssertEquals(t, pool.Name, poolName) 384 th.AssertEquals(t, pool.Description, poolDescription) 385 th.AssertEquals(t, pool.Protocol, string(pools.ProtocolTCP)) 386 th.AssertEquals(t, pool.Loadbalancers[0].ID, lb.ID) 387 th.AssertEquals(t, pool.LBMethod, string(pools.LBMethodLeastConnections)) 388 389 return pool, nil 390 } 391 392 // CreatePoolHTTP will create an HTTP-based pool with a random name with a 393 // specified listener and loadbalancer. An error will be returned if the pool 394 // could not be created. 395 func CreatePoolHTTP(t *testing.T, client *gophercloud.ServiceClient, lb *loadbalancers.LoadBalancer) (*pools.Pool, error) { 396 poolName := tools.RandomString("TESTACCT-", 8) 397 poolDescription := tools.RandomString("TESTACCT-DESC-", 8) 398 399 t.Logf("Attempting to create pool %s", poolName) 400 401 createOpts := pools.CreateOpts{ 402 Name: poolName, 403 Description: poolDescription, 404 Protocol: pools.ProtocolHTTP, 405 LoadbalancerID: lb.ID, 406 LBMethod: pools.LBMethodLeastConnections, 407 } 408 409 pool, err := pools.Create(client, createOpts).Extract() 410 if err != nil { 411 return pool, err 412 } 413 414 t.Logf("Successfully created pool %s", poolName) 415 416 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 417 return pool, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 418 } 419 420 th.AssertEquals(t, pool.Name, poolName) 421 th.AssertEquals(t, pool.Description, poolDescription) 422 th.AssertEquals(t, pool.Protocol, string(pools.ProtocolHTTP)) 423 th.AssertEquals(t, pool.Loadbalancers[0].ID, lb.ID) 424 th.AssertEquals(t, pool.LBMethod, string(pools.LBMethodLeastConnections)) 425 426 return pool, nil 427 } 428 429 // CreateL7Policy will create a l7 policy with a random name with a specified listener 430 // and loadbalancer. An error will be returned if the l7 policy could not be 431 // created. 432 func CreateL7Policy(t *testing.T, client *gophercloud.ServiceClient, listener *listeners.Listener, lb *loadbalancers.LoadBalancer) (*l7policies.L7Policy, error) { 433 policyName := tools.RandomString("TESTACCT-", 8) 434 policyDescription := tools.RandomString("TESTACCT-DESC-", 8) 435 436 t.Logf("Attempting to create l7 policy %s", policyName) 437 438 createOpts := l7policies.CreateOpts{ 439 Name: policyName, 440 Description: policyDescription, 441 ListenerID: listener.ID, 442 Action: l7policies.ActionRedirectToURL, 443 RedirectURL: "http://www.example.com", 444 } 445 446 policy, err := l7policies.Create(client, createOpts).Extract() 447 if err != nil { 448 return policy, err 449 } 450 451 t.Logf("Successfully created l7 policy %s", policyName) 452 453 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 454 return policy, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 455 } 456 457 th.AssertEquals(t, policy.Name, policyName) 458 th.AssertEquals(t, policy.Description, policyDescription) 459 th.AssertEquals(t, policy.ListenerID, listener.ID) 460 th.AssertEquals(t, policy.Action, string(l7policies.ActionRedirectToURL)) 461 th.AssertEquals(t, policy.RedirectURL, "http://www.example.com") 462 463 return policy, nil 464 } 465 466 // CreateL7Rule creates a l7 rule for specified l7 policy. 467 func CreateL7Rule(t *testing.T, client *gophercloud.ServiceClient, policyID string, lb *loadbalancers.LoadBalancer) (*l7policies.Rule, error) { 468 t.Logf("Attempting to create l7 rule for policy %s", policyID) 469 470 createOpts := l7policies.CreateRuleOpts{ 471 RuleType: l7policies.TypePath, 472 CompareType: l7policies.CompareTypeStartWith, 473 Value: "/api", 474 } 475 476 rule, err := l7policies.CreateRule(client, policyID, createOpts).Extract() 477 if err != nil { 478 return rule, err 479 } 480 481 t.Logf("Successfully created l7 rule for policy %s", policyID) 482 483 if err := WaitForLoadBalancerState(client, lb.ID, "ACTIVE"); err != nil { 484 return rule, fmt.Errorf("Timed out waiting for loadbalancer to become active: %s", err) 485 } 486 487 th.AssertEquals(t, rule.RuleType, string(l7policies.TypePath)) 488 th.AssertEquals(t, rule.CompareType, string(l7policies.CompareTypeStartWith)) 489 th.AssertEquals(t, rule.Value, "/api") 490 491 return rule, nil 492 } 493 494 // DeleteL7Policy will delete a specified l7 policy. A fatal error will occur if 495 // the l7 policy could not be deleted. This works best when used as a deferred 496 // function. 497 func DeleteL7Policy(t *testing.T, client *gophercloud.ServiceClient, lbID, policyID string) { 498 t.Logf("Attempting to delete l7 policy %s", policyID) 499 500 if err := l7policies.Delete(client, policyID).ExtractErr(); err != nil { 501 if _, ok := err.(gophercloud.ErrDefault404); !ok { 502 t.Fatalf("Unable to delete l7 policy: %v", err) 503 } 504 } 505 506 if err := WaitForLoadBalancerState(client, lbID, "ACTIVE"); err != nil { 507 t.Fatalf("Timed out waiting for loadbalancer to become active: %s", err) 508 } 509 510 t.Logf("Successfully deleted l7 policy %s", policyID) 511 } 512 513 // DeleteL7Rule will delete a specified l7 rule. A fatal error will occur if 514 // the l7 rule could not be deleted. This works best when used as a deferred 515 // function. 516 func DeleteL7Rule(t *testing.T, client *gophercloud.ServiceClient, lbID, policyID, ruleID string) { 517 t.Logf("Attempting to delete l7 rule %s", ruleID) 518 519 if err := l7policies.DeleteRule(client, policyID, ruleID).ExtractErr(); err != nil { 520 if _, ok := err.(gophercloud.ErrDefault404); !ok { 521 t.Fatalf("Unable to delete l7 rule: %v", err) 522 } 523 } 524 525 if err := WaitForLoadBalancerState(client, lbID, "ACTIVE"); err != nil { 526 t.Fatalf("Timed out waiting for loadbalancer to become active: %s", err) 527 } 528 529 t.Logf("Successfully deleted l7 rule %s", ruleID) 530 } 531 532 // DeleteListener will delete a specified listener. A fatal error will occur if 533 // the listener could not be deleted. This works best when used as a deferred 534 // function. 535 func DeleteListener(t *testing.T, client *gophercloud.ServiceClient, lbID, listenerID string) { 536 t.Logf("Attempting to delete listener %s", listenerID) 537 538 if err := listeners.Delete(client, listenerID).ExtractErr(); err != nil { 539 if _, ok := err.(gophercloud.ErrDefault404); !ok { 540 t.Fatalf("Unable to delete listener: %v", err) 541 } 542 } 543 544 if err := WaitForLoadBalancerState(client, lbID, "ACTIVE"); err != nil { 545 t.Fatalf("Timed out waiting for loadbalancer to become active: %s", err) 546 } 547 548 t.Logf("Successfully deleted listener %s", listenerID) 549 } 550 551 // DeleteMember will delete a specified member. A fatal error will occur if the 552 // member could not be deleted. This works best when used as a deferred 553 // function. 554 func DeleteMember(t *testing.T, client *gophercloud.ServiceClient, lbID, poolID, memberID string) { 555 t.Logf("Attempting to delete member %s", memberID) 556 557 if err := pools.DeleteMember(client, poolID, memberID).ExtractErr(); err != nil { 558 if _, ok := err.(gophercloud.ErrDefault404); !ok { 559 t.Fatalf("Unable to delete member: %s", memberID) 560 } 561 } 562 563 if err := WaitForLoadBalancerState(client, lbID, "ACTIVE"); err != nil { 564 t.Fatalf("Timed out waiting for loadbalancer to become active: %s", err) 565 } 566 567 t.Logf("Successfully deleted member %s", memberID) 568 } 569 570 // DeleteLoadBalancer will delete a specified loadbalancer. A fatal error will 571 // occur if the loadbalancer could not be deleted. This works best when used 572 // as a deferred function. 573 func DeleteLoadBalancer(t *testing.T, client *gophercloud.ServiceClient, lbID string) { 574 t.Logf("Attempting to delete loadbalancer %s", lbID) 575 576 deleteOpts := loadbalancers.DeleteOpts{ 577 Cascade: false, 578 } 579 580 if err := loadbalancers.Delete(client, lbID, deleteOpts).ExtractErr(); err != nil { 581 if _, ok := err.(gophercloud.ErrDefault404); !ok { 582 t.Fatalf("Unable to delete loadbalancer: %v", err) 583 } 584 } 585 586 t.Logf("Waiting for loadbalancer %s to delete", lbID) 587 588 if err := WaitForLoadBalancerState(client, lbID, "DELETED"); err != nil { 589 t.Fatalf("Loadbalancer did not delete in time: %s", err) 590 } 591 592 t.Logf("Successfully deleted loadbalancer %s", lbID) 593 } 594 595 // CascadeDeleteLoadBalancer will perform a cascading delete on a loadbalancer. 596 // A fatal error will occur if the loadbalancer could not be deleted. This works 597 // best when used as a deferred function. 598 func CascadeDeleteLoadBalancer(t *testing.T, client *gophercloud.ServiceClient, lbID string) { 599 t.Logf("Attempting to cascade delete loadbalancer %s", lbID) 600 601 deleteOpts := loadbalancers.DeleteOpts{ 602 Cascade: true, 603 } 604 605 if err := loadbalancers.Delete(client, lbID, deleteOpts).ExtractErr(); err != nil { 606 t.Fatalf("Unable to cascade delete loadbalancer: %v", err) 607 } 608 609 t.Logf("Waiting for loadbalancer %s to cascade delete", lbID) 610 611 if err := WaitForLoadBalancerState(client, lbID, "DELETED"); err != nil { 612 t.Fatalf("Loadbalancer did not delete in time.") 613 } 614 615 t.Logf("Successfully deleted loadbalancer %s", lbID) 616 } 617 618 // DeleteMonitor will delete a specified monitor. A fatal error will occur if 619 // the monitor could not be deleted. This works best when used as a deferred 620 // function. 621 func DeleteMonitor(t *testing.T, client *gophercloud.ServiceClient, lbID, monitorID string) { 622 t.Logf("Attempting to delete monitor %s", monitorID) 623 624 if err := monitors.Delete(client, monitorID).ExtractErr(); err != nil { 625 if _, ok := err.(gophercloud.ErrDefault404); !ok { 626 t.Fatalf("Unable to delete monitor: %v", err) 627 } 628 } 629 630 if err := WaitForLoadBalancerState(client, lbID, "ACTIVE"); err != nil { 631 t.Fatalf("Timed out waiting for loadbalancer to become active: %s", err) 632 } 633 634 t.Logf("Successfully deleted monitor %s", monitorID) 635 } 636 637 // DeletePool will delete a specified pool. A fatal error will occur if the 638 // pool could not be deleted. This works best when used as a deferred function. 639 func DeletePool(t *testing.T, client *gophercloud.ServiceClient, lbID, poolID string) { 640 t.Logf("Attempting to delete pool %s", poolID) 641 642 if err := pools.Delete(client, poolID).ExtractErr(); err != nil { 643 if _, ok := err.(gophercloud.ErrDefault404); !ok { 644 t.Fatalf("Unable to delete pool: %v", err) 645 } 646 } 647 648 if err := WaitForLoadBalancerState(client, lbID, "ACTIVE"); err != nil { 649 t.Fatalf("Timed out waiting for loadbalancer to become active: %s", err) 650 } 651 652 t.Logf("Successfully deleted pool %s", poolID) 653 } 654 655 // WaitForLoadBalancerState will wait until a loadbalancer reaches a given state. 656 func WaitForLoadBalancerState(client *gophercloud.ServiceClient, lbID, status string) error { 657 return tools.WaitFor(func() (bool, error) { 658 current, err := loadbalancers.Get(client, lbID).Extract() 659 if err != nil { 660 if httpStatus, ok := err.(gophercloud.ErrDefault404); ok { 661 if httpStatus.Actual == 404 { 662 if status == "DELETED" { 663 return true, nil 664 } 665 } 666 } 667 return false, err 668 } 669 670 if current.ProvisioningStatus == status { 671 return true, nil 672 } 673 674 if current.ProvisioningStatus == "ERROR" { 675 return false, fmt.Errorf("Load balancer is in ERROR state") 676 } 677 678 return false, nil 679 }) 680 } 681 682 func CreateFlavorProfile(t *testing.T, client *gophercloud.ServiceClient) (*flavorprofiles.FlavorProfile, error) { 683 flavorProfileName := tools.RandomString("TESTACCT-", 8) 684 flavorProfileDriver := "amphora" 685 flavorProfileData := "{\"loadbalancer_topology\": \"SINGLE\"}" 686 687 createOpts := flavorprofiles.CreateOpts{ 688 Name: flavorProfileName, 689 ProviderName: flavorProfileDriver, 690 FlavorData: flavorProfileData, 691 } 692 693 flavorProfile, err := flavorprofiles.Create(client, createOpts).Extract() 694 if err != nil { 695 return flavorProfile, err 696 } 697 698 t.Logf("Successfully created flavorprofile %s", flavorProfileName) 699 700 th.AssertEquals(t, flavorProfileName, flavorProfile.Name) 701 th.AssertEquals(t, flavorProfileDriver, flavorProfile.ProviderName) 702 th.AssertEquals(t, flavorProfileData, flavorProfile.FlavorData) 703 704 return flavorProfile, nil 705 } 706 707 func DeleteFlavorProfile(t *testing.T, client *gophercloud.ServiceClient, flavorProfile *flavorprofiles.FlavorProfile) { 708 err := flavorprofiles.Delete(client, flavorProfile.ID).ExtractErr() 709 if err != nil { 710 t.Fatalf("Unable to delete flavorprofile: %v", err) 711 } 712 713 t.Logf("Successfully deleted flavorprofile %s", flavorProfile.Name) 714 } 715 716 func CreateFlavor(t *testing.T, client *gophercloud.ServiceClient, flavorProfile *flavorprofiles.FlavorProfile) (*flavors.Flavor, error) { 717 flavorName := tools.RandomString("TESTACCT-", 8) 718 description := tools.RandomString("TESTACCT-desc-", 32) 719 720 createOpts := flavors.CreateOpts{ 721 Name: flavorName, 722 Description: description, 723 FlavorProfileId: flavorProfile.ID, 724 Enabled: true, 725 } 726 727 flavor, err := flavors.Create(client, createOpts).Extract() 728 if err != nil { 729 return flavor, err 730 } 731 732 t.Logf("Successfully created flavor %s with flavorprofile %s", flavor.Name, flavorProfile.Name) 733 734 th.AssertEquals(t, flavorName, flavor.Name) 735 th.AssertEquals(t, description, flavor.Description) 736 th.AssertEquals(t, flavorProfile.ID, flavor.FlavorProfileId) 737 th.AssertEquals(t, true, flavor.Enabled) 738 739 return flavor, nil 740 } 741 742 func DeleteFlavor(t *testing.T, client *gophercloud.ServiceClient, flavor *flavors.Flavor) { 743 err := flavors.Delete(client, flavor.ID).ExtractErr() 744 if err != nil { 745 t.Fatalf("Unable to delete flavor: %v", err) 746 } 747 748 t.Logf("Successfully deleted flavor %s", flavor.Name) 749 }