github.com/erriapo/terraform@v0.6.12-0.20160203182612-0340ea72354f/builtin/providers/digitalocean/resource_digitalocean_floating_ip.go (about)

     1  package digitalocean
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	"github.com/digitalocean/godo"
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  )
    12  
    13  func resourceDigitalOceanFloatingIp() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourceDigitalOceanFloatingIpCreate,
    16  		Update: resourceDigitalOceanFloatingIpUpdate,
    17  		Read:   resourceDigitalOceanFloatingIpRead,
    18  		Delete: resourceDigitalOceanFloatingIpDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"ip_address": &schema.Schema{
    22  				Type:     schema.TypeString,
    23  				Optional: true,
    24  				Computed: true,
    25  			},
    26  
    27  			"region": &schema.Schema{
    28  				Type:     schema.TypeString,
    29  				Required: true,
    30  				ForceNew: true,
    31  			},
    32  
    33  			"droplet_id": &schema.Schema{
    34  				Type:     schema.TypeInt,
    35  				Optional: true,
    36  			},
    37  		},
    38  	}
    39  }
    40  
    41  func resourceDigitalOceanFloatingIpCreate(d *schema.ResourceData, meta interface{}) error {
    42  	client := meta.(*godo.Client)
    43  
    44  	log.Printf("[INFO] Create a FloatingIP In a Region")
    45  	regionOpts := &godo.FloatingIPCreateRequest{
    46  		Region: d.Get("region").(string),
    47  	}
    48  
    49  	log.Printf("[DEBUG] FloatingIP Create: %#v", regionOpts)
    50  	floatingIp, _, err := client.FloatingIPs.Create(regionOpts)
    51  	if err != nil {
    52  		return fmt.Errorf("Error creating FloatingIP: %s", err)
    53  	}
    54  
    55  	d.SetId(floatingIp.IP)
    56  
    57  	if v, ok := d.GetOk("droplet_id"); ok {
    58  
    59  		log.Printf("[INFO] Assigning the Floating IP to the Droplet %d", v.(int))
    60  		action, _, err := client.FloatingIPActions.Assign(d.Id(), v.(int))
    61  		if err != nil {
    62  			return fmt.Errorf(
    63  				"Error Assigning FloatingIP (%s) to the droplet: %s", d.Id(), err)
    64  		}
    65  
    66  		_, unassignedErr := waitForFloatingIPReady(d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID)
    67  		if unassignedErr != nil {
    68  			return fmt.Errorf(
    69  				"Error waiting for FloatingIP (%s) to be Assigned: %s", d.Id(), unassignedErr)
    70  		}
    71  	}
    72  
    73  	return resourceDigitalOceanFloatingIpRead(d, meta)
    74  }
    75  
    76  func resourceDigitalOceanFloatingIpUpdate(d *schema.ResourceData, meta interface{}) error {
    77  	client := meta.(*godo.Client)
    78  
    79  	if d.HasChange("droplet_id") {
    80  		if v, ok := d.GetOk("droplet_id"); ok {
    81  			log.Printf("[INFO] Assigning the Floating IP %s to the Droplet %d", d.Id(), v.(int))
    82  			action, _, err := client.FloatingIPActions.Assign(d.Id(), v.(int))
    83  			if err != nil {
    84  				return fmt.Errorf(
    85  					"Error Assigning FloatingIP (%s) to the droplet: %s", d.Id(), err)
    86  			}
    87  
    88  			_, unassignedErr := waitForFloatingIPReady(d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID)
    89  			if unassignedErr != nil {
    90  				return fmt.Errorf(
    91  					"Error waiting for FloatingIP (%s) to be Assigned: %s", d.Id(), unassignedErr)
    92  			}
    93  		} else {
    94  			log.Printf("[INFO] Unassigning the Floating IP %s", d.Id())
    95  			action, _, err := client.FloatingIPActions.Unassign(d.Id())
    96  			if err != nil {
    97  				return fmt.Errorf(
    98  					"Error Unassigning FloatingIP (%s): %s", d.Id(), err)
    99  			}
   100  
   101  			_, unassignedErr := waitForFloatingIPReady(d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID)
   102  			if unassignedErr != nil {
   103  				return fmt.Errorf(
   104  					"Error waiting for FloatingIP (%s) to be Unassigned: %s", d.Id(), unassignedErr)
   105  			}
   106  		}
   107  	}
   108  
   109  	return resourceDigitalOceanFloatingIpRead(d, meta)
   110  }
   111  
   112  func resourceDigitalOceanFloatingIpRead(d *schema.ResourceData, meta interface{}) error {
   113  	client := meta.(*godo.Client)
   114  
   115  	log.Printf("[INFO] Reading the details of the FloatingIP %s", d.Id())
   116  	floatingIp, _, err := client.FloatingIPs.Get(d.Id())
   117  	if err != nil {
   118  		return fmt.Errorf("Error retrieving FloatingIP: %s", err)
   119  	}
   120  
   121  	if floatingIp.Droplet != nil {
   122  		log.Printf("[INFO] A droplet was detected on the FloatingIP so setting the Region based on the Droplet")
   123  		log.Printf("[INFO] The region of the Droplet is %s", floatingIp.Droplet.Region.Slug)
   124  		d.Set("region", floatingIp.Droplet.Region.Slug)
   125  	} else {
   126  		d.Set("region", floatingIp.Region.Slug)
   127  	}
   128  
   129  	d.Set("ip_address", floatingIp.IP)
   130  
   131  	return nil
   132  }
   133  
   134  func resourceDigitalOceanFloatingIpDelete(d *schema.ResourceData, meta interface{}) error {
   135  	client := meta.(*godo.Client)
   136  
   137  	if _, ok := d.GetOk("droplet_id"); ok {
   138  		log.Printf("[INFO] Unassigning the Floating IP from the Droplet")
   139  		action, _, err := client.FloatingIPActions.Unassign(d.Id())
   140  		if err != nil {
   141  			return fmt.Errorf(
   142  				"Error Unassigning FloatingIP (%s) from the droplet: %s", d.Id(), err)
   143  		}
   144  
   145  		_, unassignedErr := waitForFloatingIPReady(d, "completed", []string{"new", "in-progress"}, "status", meta, action.ID)
   146  		if unassignedErr != nil {
   147  			return fmt.Errorf(
   148  				"Error waiting for FloatingIP (%s) to be unassigned: %s", d.Id(), unassignedErr)
   149  		}
   150  	}
   151  
   152  	log.Printf("[INFO] Deleting FloatingIP: %s", d.Id())
   153  	_, err := client.FloatingIPs.Delete(d.Id())
   154  	if err != nil {
   155  		return fmt.Errorf("Error deleting FloatingIP: %s", err)
   156  	}
   157  
   158  	d.SetId("")
   159  	return nil
   160  }
   161  
   162  func waitForFloatingIPReady(
   163  	d *schema.ResourceData, target string, pending []string, attribute string, meta interface{}, actionId int) (interface{}, error) {
   164  	log.Printf(
   165  		"[INFO] Waiting for FloatingIP (%s) to have %s of %s",
   166  		d.Id(), attribute, target)
   167  
   168  	stateConf := &resource.StateChangeConf{
   169  		Pending:    pending,
   170  		Target:     []string{target},
   171  		Refresh:    newFloatingIPStateRefreshFunc(d, attribute, meta, actionId),
   172  		Timeout:    60 * time.Minute,
   173  		Delay:      10 * time.Second,
   174  		MinTimeout: 3 * time.Second,
   175  
   176  		NotFoundChecks: 60,
   177  	}
   178  
   179  	return stateConf.WaitForState()
   180  }
   181  
   182  func newFloatingIPStateRefreshFunc(
   183  	d *schema.ResourceData, attribute string, meta interface{}, actionId int) resource.StateRefreshFunc {
   184  	client := meta.(*godo.Client)
   185  	return func() (interface{}, string, error) {
   186  
   187  		log.Printf("[INFO] Assigning the Floating IP to the Droplet")
   188  		action, _, err := client.FloatingIPActions.Get(d.Id(), actionId)
   189  		if err != nil {
   190  			return nil, "", fmt.Errorf("Error retrieving FloatingIP (%s) ActionId (%d): %s", d.Id(), actionId, err)
   191  		}
   192  
   193  		log.Printf("[INFO] The FloatingIP Action Status is %s", action.Status)
   194  		return &action, action.Status, nil
   195  	}
   196  }