github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/openstack/resource_openstack_lb_monitor_v1.go (about)

     1  package openstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  
    12  	"github.com/rackspace/gophercloud"
    13  	"github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
    14  )
    15  
    16  func resourceLBMonitorV1() *schema.Resource {
    17  	return &schema.Resource{
    18  		Create: resourceLBMonitorV1Create,
    19  		Read:   resourceLBMonitorV1Read,
    20  		Update: resourceLBMonitorV1Update,
    21  		Delete: resourceLBMonitorV1Delete,
    22  
    23  		Schema: map[string]*schema.Schema{
    24  			"region": &schema.Schema{
    25  				Type:        schema.TypeString,
    26  				Required:    true,
    27  				ForceNew:    true,
    28  				DefaultFunc: envDefaultFuncAllowMissing("OS_REGION_NAME"),
    29  			},
    30  			"tenant_id": &schema.Schema{
    31  				Type:     schema.TypeString,
    32  				Optional: true,
    33  				ForceNew: true,
    34  				Computed: true,
    35  			},
    36  			"type": &schema.Schema{
    37  				Type:     schema.TypeString,
    38  				Required: true,
    39  				ForceNew: true,
    40  			},
    41  			"delay": &schema.Schema{
    42  				Type:     schema.TypeInt,
    43  				Required: true,
    44  				ForceNew: false,
    45  			},
    46  			"timeout": &schema.Schema{
    47  				Type:     schema.TypeInt,
    48  				Required: true,
    49  				ForceNew: false,
    50  			},
    51  			"max_retries": &schema.Schema{
    52  				Type:     schema.TypeInt,
    53  				Required: true,
    54  				ForceNew: false,
    55  			},
    56  			"url_path": &schema.Schema{
    57  				Type:     schema.TypeString,
    58  				Optional: true,
    59  				ForceNew: false,
    60  			},
    61  			"http_method": &schema.Schema{
    62  				Type:     schema.TypeString,
    63  				Optional: true,
    64  				ForceNew: false,
    65  			},
    66  			"expected_codes": &schema.Schema{
    67  				Type:     schema.TypeString,
    68  				Optional: true,
    69  				ForceNew: false,
    70  			},
    71  			"admin_state_up": &schema.Schema{
    72  				Type:     schema.TypeString,
    73  				Optional: true,
    74  				ForceNew: false,
    75  				Computed: true,
    76  			},
    77  		},
    78  	}
    79  }
    80  
    81  func resourceLBMonitorV1Create(d *schema.ResourceData, meta interface{}) error {
    82  	config := meta.(*Config)
    83  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
    84  	if err != nil {
    85  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
    86  	}
    87  
    88  	createOpts := monitors.CreateOpts{
    89  		TenantID:      d.Get("tenant_id").(string),
    90  		Type:          d.Get("type").(string),
    91  		Delay:         d.Get("delay").(int),
    92  		Timeout:       d.Get("timeout").(int),
    93  		MaxRetries:    d.Get("max_retries").(int),
    94  		URLPath:       d.Get("url_path").(string),
    95  		ExpectedCodes: d.Get("expected_codes").(string),
    96  		HTTPMethod:    d.Get("http_method").(string),
    97  	}
    98  
    99  	asuRaw := d.Get("admin_state_up").(string)
   100  	if asuRaw != "" {
   101  		asu, err := strconv.ParseBool(asuRaw)
   102  		if err != nil {
   103  			return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'")
   104  		}
   105  		createOpts.AdminStateUp = &asu
   106  	}
   107  
   108  	log.Printf("[DEBUG] Create Options: %#v", createOpts)
   109  	m, err := monitors.Create(networkingClient, createOpts).Extract()
   110  	if err != nil {
   111  		return fmt.Errorf("Error creating OpenStack LB Monitor: %s", err)
   112  	}
   113  	log.Printf("[INFO] LB Monitor ID: %s", m.ID)
   114  
   115  	log.Printf("[DEBUG] Waiting for OpenStack LB Monitor (%s) to become available.", m.ID)
   116  
   117  	stateConf := &resource.StateChangeConf{
   118  		Pending:    []string{"PENDING"},
   119  		Target:     "ACTIVE",
   120  		Refresh:    waitForLBMonitorActive(networkingClient, m.ID),
   121  		Timeout:    2 * time.Minute,
   122  		Delay:      5 * time.Second,
   123  		MinTimeout: 3 * time.Second,
   124  	}
   125  
   126  	_, err = stateConf.WaitForState()
   127  	if err != nil {
   128  		return err
   129  	}
   130  
   131  	d.SetId(m.ID)
   132  
   133  	return resourceLBMonitorV1Read(d, meta)
   134  }
   135  
   136  func resourceLBMonitorV1Read(d *schema.ResourceData, meta interface{}) error {
   137  	config := meta.(*Config)
   138  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   139  	if err != nil {
   140  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   141  	}
   142  
   143  	m, err := monitors.Get(networkingClient, d.Id()).Extract()
   144  	if err != nil {
   145  		return CheckDeleted(d, err, "LB monitor")
   146  	}
   147  
   148  	log.Printf("[DEBUG] Retreived OpenStack LB Monitor %s: %+v", d.Id(), m)
   149  
   150  	d.Set("type", m.Type)
   151  	d.Set("delay", m.Delay)
   152  	d.Set("timeout", m.Timeout)
   153  	d.Set("max_retries", m.MaxRetries)
   154  	d.Set("tenant_id", m.TenantID)
   155  	d.Set("url_path", m.URLPath)
   156  	d.Set("http_method", m.HTTPMethod)
   157  	d.Set("expected_codes", m.ExpectedCodes)
   158  	d.Set("admin_state_up", strconv.FormatBool(m.AdminStateUp))
   159  
   160  	return nil
   161  }
   162  
   163  func resourceLBMonitorV1Update(d *schema.ResourceData, meta interface{}) error {
   164  	config := meta.(*Config)
   165  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   166  	if err != nil {
   167  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   168  	}
   169  
   170  	updateOpts := monitors.UpdateOpts{
   171  		Delay:         d.Get("delay").(int),
   172  		Timeout:       d.Get("timeout").(int),
   173  		MaxRetries:    d.Get("max_retries").(int),
   174  		URLPath:       d.Get("url_path").(string),
   175  		HTTPMethod:    d.Get("http_method").(string),
   176  		ExpectedCodes: d.Get("expected_codes").(string),
   177  	}
   178  
   179  	if d.HasChange("admin_state_up") {
   180  		asuRaw := d.Get("admin_state_up").(string)
   181  		if asuRaw != "" {
   182  			asu, err := strconv.ParseBool(asuRaw)
   183  			if err != nil {
   184  				return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'")
   185  			}
   186  			updateOpts.AdminStateUp = &asu
   187  		}
   188  	}
   189  
   190  	log.Printf("[DEBUG] Updating OpenStack LB Monitor %s with options: %+v", d.Id(), updateOpts)
   191  
   192  	_, err = monitors.Update(networkingClient, d.Id(), updateOpts).Extract()
   193  	if err != nil {
   194  		return fmt.Errorf("Error updating OpenStack LB Monitor: %s", err)
   195  	}
   196  
   197  	return resourceLBMonitorV1Read(d, meta)
   198  }
   199  
   200  func resourceLBMonitorV1Delete(d *schema.ResourceData, meta interface{}) error {
   201  	config := meta.(*Config)
   202  	networkingClient, err := config.networkingV2Client(d.Get("region").(string))
   203  	if err != nil {
   204  		return fmt.Errorf("Error creating OpenStack networking client: %s", err)
   205  	}
   206  
   207  	stateConf := &resource.StateChangeConf{
   208  		Pending:    []string{"ACTIVE", "PENDING"},
   209  		Target:     "DELETED",
   210  		Refresh:    waitForLBMonitorDelete(networkingClient, d.Id()),
   211  		Timeout:    2 * time.Minute,
   212  		Delay:      5 * time.Second,
   213  		MinTimeout: 3 * time.Second,
   214  	}
   215  
   216  	_, err = stateConf.WaitForState()
   217  	if err != nil {
   218  		return fmt.Errorf("Error deleting OpenStack LB Monitor: %s", err)
   219  	}
   220  
   221  	d.SetId("")
   222  	return nil
   223  }
   224  
   225  func waitForLBMonitorActive(networkingClient *gophercloud.ServiceClient, monitorId string) resource.StateRefreshFunc {
   226  	return func() (interface{}, string, error) {
   227  		m, err := monitors.Get(networkingClient, monitorId).Extract()
   228  		if err != nil {
   229  			return nil, "", err
   230  		}
   231  
   232  		// The monitor resource has no Status attribute, so a successful Get is the best we can do
   233  		log.Printf("[DEBUG] OpenStack LB Monitor: %+v", m)
   234  		return m, "ACTIVE", nil
   235  	}
   236  }
   237  
   238  func waitForLBMonitorDelete(networkingClient *gophercloud.ServiceClient, monitorId string) resource.StateRefreshFunc {
   239  	return func() (interface{}, string, error) {
   240  		log.Printf("[DEBUG] Attempting to delete OpenStack LB Monitor %s", monitorId)
   241  
   242  		m, err := monitors.Get(networkingClient, monitorId).Extract()
   243  		if err != nil {
   244  			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
   245  			if !ok {
   246  				return m, "ACTIVE", err
   247  			}
   248  			if errCode.Actual == 404 {
   249  				log.Printf("[DEBUG] Successfully deleted OpenStack LB Monitor %s", monitorId)
   250  				return m, "DELETED", nil
   251  			}
   252  			if errCode.Actual == 409 {
   253  				log.Printf("[DEBUG] OpenStack LB Monitor (%s) is waiting for Pool to delete.", monitorId)
   254  				return m, "PENDING", nil
   255  			}
   256  		}
   257  
   258  		log.Printf("[DEBUG] OpenStack LB Monitor: %+v", m)
   259  		err = monitors.Delete(networkingClient, monitorId).ExtractErr()
   260  		if err != nil {
   261  			errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
   262  			if !ok {
   263  				return m, "ACTIVE", err
   264  			}
   265  			if errCode.Actual == 404 {
   266  				log.Printf("[DEBUG] Successfully deleted OpenStack LB Monitor %s", monitorId)
   267  				return m, "DELETED", nil
   268  			}
   269  			if errCode.Actual == 409 {
   270  				log.Printf("[DEBUG] OpenStack LB Monitor (%s) is waiting for Pool to delete.", monitorId)
   271  				return m, "PENDING", nil
   272  			}
   273  		}
   274  
   275  		log.Printf("[DEBUG] OpenStack LB Monitor %s still active.", monitorId)
   276  		return m, "ACTIVE", nil
   277  	}
   278  
   279  }