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