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 }