-
Notifications
You must be signed in to change notification settings - Fork 9.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CRUD, tests and Docs for managing a LoadBalancer, Listener, Pool, Member, and Monitor resources.
- Loading branch information
Showing
18 changed files
with
2,613 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
313 changes: 313 additions & 0 deletions
313
builtin/providers/openstack/resource_openstack_lb_listener_v2.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,313 @@ | ||
package openstack | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
|
||
"github.com/rackspace/gophercloud" | ||
"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas_v2/listeners" | ||
) | ||
|
||
func resourceListenerV2() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceListenerV2Create, | ||
Read: resourceListenerV2Read, | ||
Update: resourceListenerV2Update, | ||
Delete: resourceListenerV2Delete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"region": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), | ||
}, | ||
|
||
"protocol": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { | ||
value := v.(string) | ||
if value != "TCP" && value != "HTTP" && value != "HTTPS" { | ||
errors = append(errors, fmt.Errorf( | ||
"Only 'TCP', 'HTTP', and 'HTTPS' are supported values for 'protocol'")) | ||
} | ||
return | ||
}, | ||
}, | ||
|
||
"protocol_port": &schema.Schema{ | ||
Type: schema.TypeInt, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"tenant_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"loadbalancer_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
"default_pool_id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"description": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"connection_limit": &schema.Schema{ | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
}, | ||
|
||
"default_tls_container_ref": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"sni_container_refs": &schema.Schema{ | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
}, | ||
|
||
"admin_state_up": &schema.Schema{ | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
}, | ||
|
||
"id": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceListenerV2Create(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
networkingClient, err := config.networkingV2Client(d.Get("region").(string)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack networking client: %s", err) | ||
} | ||
|
||
adminStateUp := d.Get("admin_state_up").(bool) | ||
connLimit := d.Get("connection_limit").(int) | ||
var sniContainerRefs []string | ||
if raw, ok := d.GetOk("sni_container_refs"); ok { | ||
for _, v := range raw.([]interface{}) { | ||
sniContainerRefs = append(sniContainerRefs, v.(string)) | ||
} | ||
} | ||
createOpts := listeners.CreateOpts{ | ||
Protocol: listeners.Protocol(d.Get("protocol").(string)), | ||
ProtocolPort: d.Get("protocol_port").(int), | ||
TenantID: d.Get("tenant_id").(string), | ||
LoadbalancerID: d.Get("loadbalancer_id").(string), | ||
Name: d.Get("name").(string), | ||
DefaultPoolID: d.Get("default_pool_id").(string), | ||
Description: d.Get("description").(string), | ||
ConnLimit: &connLimit, | ||
DefaultTlsContainerRef: d.Get("default_tls_container_ref").(string), | ||
SniContainerRefs: sniContainerRefs, | ||
AdminStateUp: &adminStateUp, | ||
} | ||
|
||
log.Printf("[DEBUG] Create Options: %#v", createOpts) | ||
listener, err := listeners.Create(networkingClient, createOpts).Extract() | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack LBaaSV2 listener: %s", err) | ||
} | ||
log.Printf("[INFO] Listener ID: %s", listener.ID) | ||
|
||
log.Printf("[DEBUG] Waiting for Openstack LBaaSV2 listener (%s) to become available.", listener.ID) | ||
|
||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{"PENDING_CREATE"}, | ||
Target: []string{"ACTIVE"}, | ||
Refresh: waitForListenerActive(networkingClient, listener.ID), | ||
Timeout: 2 * time.Minute, | ||
Delay: 5 * time.Second, | ||
MinTimeout: 3 * time.Second, | ||
} | ||
|
||
_, err = stateConf.WaitForState() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId(listener.ID) | ||
|
||
return resourceListenerV2Read(d, meta) | ||
} | ||
|
||
func resourceListenerV2Read(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
networkingClient, err := config.networkingV2Client(d.Get("region").(string)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack networking client: %s", err) | ||
} | ||
|
||
listener, err := listeners.Get(networkingClient, d.Id()).Extract() | ||
if err != nil { | ||
return CheckDeleted(d, err, "LBV2 listener") | ||
} | ||
|
||
log.Printf("[DEBUG] Retreived OpenStack LBaaSV2 listener %s: %+v", d.Id(), listener) | ||
|
||
d.Set("id", listener.ID) | ||
d.Set("name", listener.Name) | ||
d.Set("protocol", listener.Protocol) | ||
d.Set("tenant_id", listener.TenantID) | ||
d.Set("description", listener.Description) | ||
d.Set("protocol_port", listener.ProtocolPort) | ||
d.Set("admin_state_up", listener.AdminStateUp) | ||
d.Set("default_pool_id", listener.DefaultPoolID) | ||
d.Set("connection_limit", listener.ConnLimit) | ||
d.Set("sni_container_refs", listener.SniContainerRefs) | ||
d.Set("default_tls_container_ref", listener.DefaultTlsContainerRef) | ||
|
||
return nil | ||
} | ||
|
||
func resourceListenerV2Update(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
networkingClient, err := config.networkingV2Client(d.Get("region").(string)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack networking client: %s", err) | ||
} | ||
|
||
var updateOpts listeners.UpdateOpts | ||
if d.HasChange("name") { | ||
updateOpts.Name = d.Get("name").(string) | ||
} | ||
if d.HasChange("description") { | ||
updateOpts.Description = d.Get("description").(string) | ||
} | ||
if d.HasChange("connection_limit") { | ||
connLimit := d.Get("connection_limit").(int) | ||
updateOpts.ConnLimit = &connLimit | ||
} | ||
if d.HasChange("default_tls_container_ref") { | ||
updateOpts.DefaultTlsContainerRef = d.Get("default_tls_container_ref").(string) | ||
} | ||
if d.HasChange("sni_container_refs") { | ||
var sniContainerRefs []string | ||
if raw, ok := d.GetOk("sni_container_refs"); ok { | ||
for _, v := range raw.([]interface{}) { | ||
sniContainerRefs = append(sniContainerRefs, v.(string)) | ||
} | ||
} | ||
updateOpts.SniContainerRefs = sniContainerRefs | ||
} | ||
if d.HasChange("admin_state_up") { | ||
asu := d.Get("admin_state_up").(bool) | ||
updateOpts.AdminStateUp = &asu | ||
} | ||
|
||
log.Printf("[DEBUG] Updating OpenStack LBaaSV2 Listener %s with options: %+v", d.Id(), updateOpts) | ||
|
||
_, err = listeners.Update(networkingClient, d.Id(), updateOpts).Extract() | ||
if err != nil { | ||
return fmt.Errorf("Error updating OpenStack LBaaSV2 Listener: %s", err) | ||
} | ||
|
||
return resourceListenerV2Read(d, meta) | ||
|
||
} | ||
|
||
func resourceListenerV2Delete(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
networkingClient, err := config.networkingV2Client(d.Get("region").(string)) | ||
if err != nil { | ||
return fmt.Errorf("Error creating OpenStack networking client: %s", err) | ||
} | ||
|
||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{"ACTIVE", "PENDING_DELETE"}, | ||
Target: []string{"DELETED"}, | ||
Refresh: waitForListenerDelete(networkingClient, d.Id()), | ||
Timeout: 2 * time.Minute, | ||
Delay: 5 * time.Second, | ||
MinTimeout: 3 * time.Second, | ||
} | ||
|
||
_, err = stateConf.WaitForState() | ||
if err != nil { | ||
return fmt.Errorf("Error deleting OpenStack LBaaSV2 listener: %s", err) | ||
} | ||
|
||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func waitForListenerActive(networkingClient *gophercloud.ServiceClient, listenerID string) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
listener, err := listeners.Get(networkingClient, listenerID).Extract() | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
// The listener resource has no Status attribute, so a successful Get is the best we can do | ||
log.Printf("[DEBUG] OpenStack LBaaSV2 listener: %+v", listener) | ||
return listener, "ACTIVE", nil | ||
} | ||
} | ||
|
||
func waitForListenerDelete(networkingClient *gophercloud.ServiceClient, listenerID string) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
log.Printf("[DEBUG] Attempting to delete OpenStack LBaaSV2 listener %s", listenerID) | ||
|
||
listener, err := listeners.Get(networkingClient, listenerID).Extract() | ||
if err != nil { | ||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) | ||
if !ok { | ||
return listener, "ACTIVE", err | ||
} | ||
if errCode.Actual == 404 { | ||
log.Printf("[DEBUG] Successfully deleted OpenStack LBaaSV2 listener %s", listenerID) | ||
return listener, "DELETED", nil | ||
} | ||
} | ||
|
||
log.Printf("[DEBUG] Openstack LBaaSV2 listener: %+v", listener) | ||
err = listeners.Delete(networkingClient, listenerID).ExtractErr() | ||
if err != nil { | ||
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) | ||
if !ok { | ||
return listener, "ACTIVE", err | ||
} | ||
if errCode.Actual == 404 { | ||
log.Printf("[DEBUG] Successfully deleted OpenStack LBaaSV2 listener %s", listenerID) | ||
return listener, "DELETED", nil | ||
} | ||
} | ||
|
||
log.Printf("[DEBUG] OpenStack LBaaSV2 listener %s still active.", listenerID) | ||
return listener, "ACTIVE", nil | ||
} | ||
} |
Oops, something went wrong.