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