github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/openstack/resource_openstack_lb_member_v1.go (about)

     1  package openstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	"github.com/hashicorp/terraform/helper/resource"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  
    11  	"github.com/gophercloud/gophercloud"
    12  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members"
    13  )
    14  
    15  func resourceLBMemberV1() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceLBMemberV1Create,
    18  		Read:   resourceLBMemberV1Read,
    19  		Update: resourceLBMemberV1Update,
    20  		Delete: resourceLBMemberV1Delete,
    21  		Importer: &schema.ResourceImporter{
    22  			State: schema.ImportStatePassthrough,
    23  		},
    24  
    25  		Timeouts: &schema.ResourceTimeout{
    26  			Create: schema.DefaultTimeout(10 * time.Minute),
    27  			Delete: schema.DefaultTimeout(10 * time.Minute),
    28  		},
    29  
    30  		Schema: map[string]*schema.Schema{
    31  			"region": &schema.Schema{
    32  				Type:        schema.TypeString,
    33  				Required:    true,
    34  				ForceNew:    true,
    35  				DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
    36  			},
    37  			"tenant_id": &schema.Schema{
    38  				Type:     schema.TypeString,
    39  				Optional: true,
    40  				ForceNew: true,
    41  			},
    42  			"pool_id": &schema.Schema{
    43  				Type:     schema.TypeString,
    44  				Required: true,
    45  				ForceNew: true,
    46  			},
    47  			"address": &schema.Schema{
    48  				Type:     schema.TypeString,
    49  				Required: true,
    50  				ForceNew: true,
    51  			},
    52  			"port": &schema.Schema{
    53  				Type:     schema.TypeInt,
    54  				Required: true,
    55  				ForceNew: true,
    56  			},
    57  			"weight": &schema.Schema{
    58  				Type:     schema.TypeInt,
    59  				Optional: true,
    60  				Computed: true,
    61  			},
    62  			"admin_state_up": &schema.Schema{
    63  				Type:     schema.TypeBool,
    64  				Optional: true,
    65  				ForceNew: false,
    66  				Computed: true,
    67  			},
    68  		},
    69  	}
    70  }
    71  
    72  func resourceLBMemberV1Create(d *schema.ResourceData, meta interface{}) error {
    73  	config := meta.(*Config)
    74  	networkingClient, err := config.networkingV2Client(GetRegion(d))
    75  	if err != nil {
    76  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
    77  	}
    78  
    79  	createOpts := members.CreateOpts{
    80  		TenantID:     d.Get("tenant_id").(string),
    81  		PoolID:       d.Get("pool_id").(string),
    82  		Address:      d.Get("address").(string),
    83  		ProtocolPort: d.Get("port").(int),
    84  	}
    85  
    86  	log.Printf("[DEBUG] OpenStack LB Member Create Options: %#v", createOpts)
    87  	m, err := members.Create(networkingClient, createOpts).Extract()
    88  	if err != nil {
    89  		return fmt.Errorf("Error creating OpenStack LB member: %s", err)
    90  	}
    91  	log.Printf("[INFO] LB member ID: %s", m.ID)
    92  
    93  	log.Printf("[DEBUG] Waiting for OpenStack LB member (%s) to become available.", m.ID)
    94  
    95  	stateConf := &resource.StateChangeConf{
    96  		Pending:    []string{"PENDING_CREATE"},
    97  		Target:     []string{"ACTIVE", "INACTIVE", "CREATED", "DOWN"},
    98  		Refresh:    waitForLBMemberActive(networkingClient, m.ID),
    99  		Timeout:    d.Timeout(schema.TimeoutCreate),
   100  		Delay:      5 * time.Second,
   101  		MinTimeout: 3 * time.Second,
   102  	}
   103  
   104  	_, err = stateConf.WaitForState()
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	d.SetId(m.ID)
   110  
   111  	// Due to the way Gophercloud is currently set up, AdminStateUp must be set post-create
   112  	asu := d.Get("admin_state_up").(bool)
   113  	updateOpts := members.UpdateOpts{
   114  		AdminStateUp: &asu,
   115  	}
   116  
   117  	log.Printf("[DEBUG] OpenStack LB Member Update Options: %#v", createOpts)
   118  	m, err = members.Update(networkingClient, m.ID, updateOpts).Extract()
   119  	if err != nil {
   120  		return fmt.Errorf("Error updating OpenStack LB member: %s", err)
   121  	}
   122  
   123  	return resourceLBMemberV1Read(d, meta)
   124  }
   125  
   126  func resourceLBMemberV1Read(d *schema.ResourceData, meta interface{}) error {
   127  	config := meta.(*Config)
   128  	networkingClient, err := config.networkingV2Client(GetRegion(d))
   129  	if err != nil {
   130  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   131  	}
   132  
   133  	m, err := members.Get(networkingClient, d.Id()).Extract()
   134  	if err != nil {
   135  		return CheckDeleted(d, err, "LB member")
   136  	}
   137  
   138  	log.Printf("[DEBUG] Retrieved OpenStack LB member %s: %+v", d.Id(), m)
   139  
   140  	d.Set("address", m.Address)
   141  	d.Set("pool_id", m.PoolID)
   142  	d.Set("port", m.ProtocolPort)
   143  	d.Set("weight", m.Weight)
   144  	d.Set("admin_state_up", m.AdminStateUp)
   145  	d.Set("region", GetRegion(d))
   146  
   147  	return nil
   148  }
   149  
   150  func resourceLBMemberV1Update(d *schema.ResourceData, meta interface{}) error {
   151  	config := meta.(*Config)
   152  	networkingClient, err := config.networkingV2Client(GetRegion(d))
   153  	if err != nil {
   154  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   155  	}
   156  
   157  	var updateOpts members.UpdateOpts
   158  	if d.HasChange("admin_state_up") {
   159  		asu := d.Get("admin_state_up").(bool)
   160  		updateOpts.AdminStateUp = &asu
   161  	}
   162  
   163  	log.Printf("[DEBUG] Updating LB member %s with options: %+v", d.Id(), updateOpts)
   164  
   165  	_, err = members.Update(networkingClient, d.Id(), updateOpts).Extract()
   166  	if err != nil {
   167  		return fmt.Errorf("Error updating OpenStack LB member: %s", err)
   168  	}
   169  
   170  	return resourceLBMemberV1Read(d, meta)
   171  }
   172  
   173  func resourceLBMemberV1Delete(d *schema.ResourceData, meta interface{}) error {
   174  	config := meta.(*Config)
   175  	networkingClient, err := config.networkingV2Client(GetRegion(d))
   176  	if err != nil {
   177  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   178  	}
   179  
   180  	err = members.Delete(networkingClient, d.Id()).ExtractErr()
   181  	if err != nil {
   182  		CheckDeleted(d, err, "LB member")
   183  	}
   184  
   185  	stateConf := &resource.StateChangeConf{
   186  		Pending:    []string{"ACTIVE", "PENDING_DELETE"},
   187  		Target:     []string{"DELETED"},
   188  		Refresh:    waitForLBMemberDelete(networkingClient, d.Id()),
   189  		Timeout:    d.Timeout(schema.TimeoutDelete),
   190  		Delay:      5 * time.Second,
   191  		MinTimeout: 3 * time.Second,
   192  	}
   193  
   194  	_, err = stateConf.WaitForState()
   195  	if err != nil {
   196  		return fmt.Errorf("Error deleting OpenStack LB member: %s", err)
   197  	}
   198  
   199  	d.SetId("")
   200  	return nil
   201  }
   202  
   203  func waitForLBMemberActive(networkingClient *gophercloud.ServiceClient, memberId string) resource.StateRefreshFunc {
   204  	return func() (interface{}, string, error) {
   205  		m, err := members.Get(networkingClient, memberId).Extract()
   206  		if err != nil {
   207  			return nil, "", err
   208  		}
   209  
   210  		log.Printf("[DEBUG] OpenStack LB member: %+v", m)
   211  		if m.Status == "ACTIVE" {
   212  			return m, "ACTIVE", nil
   213  		}
   214  
   215  		return m, m.Status, nil
   216  	}
   217  }
   218  
   219  func waitForLBMemberDelete(networkingClient *gophercloud.ServiceClient, memberId string) resource.StateRefreshFunc {
   220  	return func() (interface{}, string, error) {
   221  		log.Printf("[DEBUG] Attempting to delete OpenStack LB member %s", memberId)
   222  
   223  		m, err := members.Get(networkingClient, memberId).Extract()
   224  		if err != nil {
   225  			if _, ok := err.(gophercloud.ErrDefault404); ok {
   226  				log.Printf("[DEBUG] Successfully deleted OpenStack LB member %s", memberId)
   227  				return m, "DELETED", nil
   228  			}
   229  			return m, "ACTIVE", err
   230  		}
   231  
   232  		log.Printf("[DEBUG] OpenStack LB member %s still active.", memberId)
   233  		return m, "ACTIVE", nil
   234  	}
   235  
   236  }