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