github.com/ezbercih/terraform@v0.1.1-0.20140729011846-3c33865e0839/builtin/providers/aws/resource_aws_eip.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform/helper/config"
     9  	"github.com/hashicorp/terraform/helper/diff"
    10  	"github.com/hashicorp/terraform/terraform"
    11  	"github.com/mitchellh/goamz/ec2"
    12  )
    13  
    14  func resource_aws_eip_create(
    15  	s *terraform.ResourceState,
    16  	d *terraform.ResourceDiff,
    17  	meta interface{}) (*terraform.ResourceState, error) {
    18  	p := meta.(*ResourceProvider)
    19  	ec2conn := p.ec2conn
    20  
    21  	// Merge the diff into the state so that we have all the attributes
    22  	// properly.
    23  	rs := s.MergeDiff(d)
    24  
    25  	// By default, we're not in a VPC
    26  	vpc := false
    27  	domainOpt := ""
    28  	if rs.Attributes["vpc"] == "true" {
    29  		vpc = true
    30  		domainOpt = "vpc"
    31  	}
    32  
    33  	allocOpts := ec2.AllocateAddress{
    34  		Domain: domainOpt,
    35  	}
    36  
    37  	log.Printf("[DEBUG] EIP create configuration: %#v", allocOpts)
    38  	allocResp, err := ec2conn.AllocateAddress(&allocOpts)
    39  	if err != nil {
    40  		return nil, fmt.Errorf("Error creating EIP: %s", err)
    41  	}
    42  
    43  	// Assign the eips (unique) allocation id for use later
    44  	// the EIP api has a conditional unique ID (really), so
    45  	// if we're in a VPC we need to save the ID as such, otherwise
    46  	// it defaults to using the public IP
    47  	log.Printf("[DEBUG] EIP Allocate: %#v", allocResp)
    48  	if allocResp.AllocationId != "" {
    49  		rs.ID = allocResp.AllocationId
    50  		rs.Attributes["vpc"] = "true"
    51  
    52  	} else {
    53  		rs.ID = allocResp.PublicIp
    54  	}
    55  
    56  	log.Printf("[INFO] EIP ID: %s (vpc: %v)", rs.ID, vpc)
    57  
    58  	return resource_aws_eip_update(rs, d, meta)
    59  }
    60  
    61  func resource_aws_eip_update(
    62  	s *terraform.ResourceState,
    63  	d *terraform.ResourceDiff,
    64  	meta interface{}) (*terraform.ResourceState, error) {
    65  	p := meta.(*ResourceProvider)
    66  	ec2conn := p.ec2conn
    67  
    68  	// Merge the diff into the state so that we have all the attributes
    69  	// properly.
    70  	rs := s.MergeDiff(d)
    71  
    72  	vpc := strings.Contains(rs.ID, "eipalloc")
    73  
    74  	// If we have an instance to register, do it
    75  	instanceId := rs.Attributes["instance"]
    76  
    77  	// Only register with an instance if we have one
    78  	if instanceId != "" {
    79  		assocOpts := ec2.AssociateAddress{
    80  			InstanceId: instanceId,
    81  			PublicIp:   rs.ID,
    82  		}
    83  
    84  		// more unique ID conditionals
    85  		if vpc {
    86  			assocOpts = ec2.AssociateAddress{
    87  				InstanceId:   instanceId,
    88  				AllocationId: rs.ID,
    89  				PublicIp:     "",
    90  			}
    91  		}
    92  
    93  		log.Printf("[DEBUG] EIP associate configuration: %#v (vpc: %v)", assocOpts, vpc)
    94  		_, err := ec2conn.AssociateAddress(&assocOpts)
    95  		if err != nil {
    96  			return rs, fmt.Errorf("Failure associating instances: %s", err)
    97  		}
    98  	}
    99  
   100  	address, err := resource_aws_eip_retrieve_address(rs.ID, vpc, ec2conn)
   101  	if err != nil {
   102  		return rs, err
   103  	}
   104  
   105  	return resource_aws_eip_update_state(rs, address)
   106  }
   107  
   108  func resource_aws_eip_destroy(
   109  	s *terraform.ResourceState,
   110  	meta interface{}) error {
   111  	p := meta.(*ResourceProvider)
   112  	ec2conn := p.ec2conn
   113  
   114  	var err error
   115  	if strings.Contains(s.ID, "eipalloc") {
   116  		log.Printf("[DEBUG] EIP release (destroy) address allocation: %v", s.ID)
   117  		_, err = ec2conn.ReleaseAddress(s.ID)
   118  		return err
   119  	} else {
   120  		log.Printf("[DEBUG] EIP release (destroy) address: %v", s.ID)
   121  		_, err = ec2conn.ReleasePublicAddress(s.ID)
   122  		return err
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  func resource_aws_eip_refresh(
   129  	s *terraform.ResourceState,
   130  	meta interface{}) (*terraform.ResourceState, error) {
   131  	p := meta.(*ResourceProvider)
   132  	ec2conn := p.ec2conn
   133  
   134  	vpc := false
   135  	if s.Attributes["vpc"] == "true" {
   136  		vpc = true
   137  	}
   138  
   139  	address, err := resource_aws_eip_retrieve_address(s.ID, vpc, ec2conn)
   140  
   141  	if err != nil {
   142  		return s, err
   143  	}
   144  
   145  	return resource_aws_eip_update_state(s, address)
   146  }
   147  
   148  func resource_aws_eip_diff(
   149  	s *terraform.ResourceState,
   150  	c *terraform.ResourceConfig,
   151  	meta interface{}) (*terraform.ResourceDiff, error) {
   152  
   153  	b := &diff.ResourceBuilder{
   154  		Attrs: map[string]diff.AttrType{
   155  			"vpc":      diff.AttrTypeCreate,
   156  			"instance": diff.AttrTypeUpdate,
   157  		},
   158  
   159  		ComputedAttrs: []string{
   160  			"public_ip",
   161  			"private_ip",
   162  		},
   163  	}
   164  
   165  	return b.Diff(s, c)
   166  }
   167  
   168  func resource_aws_eip_update_state(
   169  	s *terraform.ResourceState,
   170  	address *ec2.Address) (*terraform.ResourceState, error) {
   171  
   172  	s.Attributes["private_ip"] = address.PrivateIpAddress
   173  	s.Attributes["public_ip"] = address.PublicIp
   174  	s.Attributes["instance"] = address.InstanceId
   175  
   176  	return s, nil
   177  }
   178  
   179  // Returns a single address by it's ID
   180  func resource_aws_eip_retrieve_address(id string, vpc bool, ec2conn *ec2.EC2) (*ec2.Address, error) {
   181  	// Get the full address description for saving to state for
   182  	// use in other resources
   183  	assocIds := []string{}
   184  	publicIps := []string{}
   185  	if vpc {
   186  		assocIds = []string{id}
   187  	} else {
   188  		publicIps = []string{id}
   189  	}
   190  
   191  	log.Printf("[DEBUG] EIP describe configuration: %#v, %#v (vpc: %v)", assocIds, publicIps, vpc)
   192  
   193  	describeAddresses, err := ec2conn.Addresses(publicIps, assocIds, nil)
   194  
   195  	if err != nil {
   196  		return nil, fmt.Errorf("Error retrieving EIP: %s", err)
   197  	}
   198  
   199  	// Verify AWS returned our EIP
   200  	if len(describeAddresses.Addresses) != 1 ||
   201  		describeAddresses.Addresses[0].AllocationId != id ||
   202  		describeAddresses.Addresses[0].PublicIp != id {
   203  		if err != nil {
   204  			return nil, fmt.Errorf("Unable to find EIP: %#v", describeAddresses.Addresses)
   205  		}
   206  	}
   207  
   208  	address := describeAddresses.Addresses[0]
   209  
   210  	return &address, nil
   211  }
   212  
   213  func resource_aws_eip_validation() *config.Validator {
   214  	return &config.Validator{
   215  		Optional: []string{
   216  			"vpc",
   217  			"instance",
   218  		},
   219  	}
   220  }