github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_nat_gateway.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 "time" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/service/ec2" 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 func resourceAwsNatGateway() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceAwsNatGatewayCreate, 19 Read: resourceAwsNatGatewayRead, 20 Delete: resourceAwsNatGatewayDelete, 21 Importer: &schema.ResourceImporter{ 22 State: schema.ImportStatePassthrough, 23 }, 24 25 Schema: map[string]*schema.Schema{ 26 "allocation_id": &schema.Schema{ 27 Type: schema.TypeString, 28 Required: true, 29 ForceNew: true, 30 }, 31 32 "subnet_id": &schema.Schema{ 33 Type: schema.TypeString, 34 Required: true, 35 ForceNew: true, 36 }, 37 38 "network_interface_id": &schema.Schema{ 39 Type: schema.TypeString, 40 Optional: true, 41 Computed: true, 42 }, 43 44 "private_ip": &schema.Schema{ 45 Type: schema.TypeString, 46 Optional: true, 47 Computed: true, 48 }, 49 50 "public_ip": &schema.Schema{ 51 Type: schema.TypeString, 52 Optional: true, 53 Computed: true, 54 }, 55 }, 56 } 57 } 58 59 func resourceAwsNatGatewayCreate(d *schema.ResourceData, meta interface{}) error { 60 conn := meta.(*AWSClient).ec2conn 61 62 // Create the NAT Gateway 63 createOpts := &ec2.CreateNatGatewayInput{ 64 AllocationId: aws.String(d.Get("allocation_id").(string)), 65 SubnetId: aws.String(d.Get("subnet_id").(string)), 66 } 67 68 log.Printf("[DEBUG] Create NAT Gateway: %s", *createOpts) 69 natResp, err := conn.CreateNatGateway(createOpts) 70 if err != nil { 71 return fmt.Errorf("Error creating NAT Gateway: %s", err) 72 } 73 74 // Get the ID and store it 75 ng := natResp.NatGateway 76 d.SetId(*ng.NatGatewayId) 77 log.Printf("[INFO] NAT Gateway ID: %s", d.Id()) 78 79 // Wait for the NAT Gateway to become available 80 log.Printf("[DEBUG] Waiting for NAT Gateway (%s) to become available", d.Id()) 81 stateConf := &resource.StateChangeConf{ 82 Pending: []string{"pending"}, 83 Target: []string{"available"}, 84 Refresh: NGStateRefreshFunc(conn, d.Id()), 85 Timeout: 10 * time.Minute, 86 } 87 88 if _, err := stateConf.WaitForState(); err != nil { 89 return fmt.Errorf("Error waiting for NAT Gateway (%s) to become available: %s", d.Id(), err) 90 } 91 92 // Update our attributes and return 93 return resourceAwsNatGatewayRead(d, meta) 94 } 95 96 func resourceAwsNatGatewayRead(d *schema.ResourceData, meta interface{}) error { 97 conn := meta.(*AWSClient).ec2conn 98 99 // Refresh the NAT Gateway state 100 ngRaw, state, err := NGStateRefreshFunc(conn, d.Id())() 101 if err != nil { 102 return err 103 } 104 105 status := map[string]bool{ 106 "deleted": true, 107 "deleting": true, 108 "failed": true, 109 } 110 111 if _, ok := status[strings.ToLower(state)]; ngRaw == nil || ok { 112 log.Printf("[INFO] Removing %s from Terraform state as it is not found or in the deleted state.", d.Id()) 113 d.SetId("") 114 return nil 115 } 116 117 // Set NAT Gateway attributes 118 ng := ngRaw.(*ec2.NatGateway) 119 d.Set("subnet_id", ng.SubnetId) 120 121 // Address 122 address := ng.NatGatewayAddresses[0] 123 d.Set("allocation_id", address.AllocationId) 124 d.Set("network_interface_id", address.NetworkInterfaceId) 125 d.Set("private_ip", address.PrivateIp) 126 d.Set("public_ip", address.PublicIp) 127 128 return nil 129 } 130 131 func resourceAwsNatGatewayDelete(d *schema.ResourceData, meta interface{}) error { 132 conn := meta.(*AWSClient).ec2conn 133 deleteOpts := &ec2.DeleteNatGatewayInput{ 134 NatGatewayId: aws.String(d.Id()), 135 } 136 log.Printf("[INFO] Deleting NAT Gateway: %s", d.Id()) 137 138 _, err := conn.DeleteNatGateway(deleteOpts) 139 if err != nil { 140 ec2err, ok := err.(awserr.Error) 141 if !ok { 142 return err 143 } 144 145 if ec2err.Code() == "NatGatewayNotFound" { 146 return nil 147 } 148 149 return err 150 } 151 152 stateConf := &resource.StateChangeConf{ 153 Pending: []string{"deleting"}, 154 Target: []string{"deleted"}, 155 Refresh: NGStateRefreshFunc(conn, d.Id()), 156 Timeout: 30 * time.Minute, 157 Delay: 10 * time.Second, 158 MinTimeout: 10 * time.Second, 159 } 160 161 _, stateErr := stateConf.WaitForState() 162 if stateErr != nil { 163 return fmt.Errorf("Error waiting for NAT Gateway (%s) to delete: %s", d.Id(), err) 164 } 165 166 return nil 167 } 168 169 // NGStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch 170 // a NAT Gateway. 171 func NGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { 172 return func() (interface{}, string, error) { 173 opts := &ec2.DescribeNatGatewaysInput{ 174 NatGatewayIds: []*string{aws.String(id)}, 175 } 176 resp, err := conn.DescribeNatGateways(opts) 177 if err != nil { 178 if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "NatGatewayNotFound" { 179 resp = nil 180 } else { 181 log.Printf("Error on NGStateRefresh: %s", err) 182 return nil, "", err 183 } 184 } 185 186 if resp == nil { 187 // Sometimes AWS just has consistency issues and doesn't see 188 // our instance yet. Return an empty state. 189 return nil, "", nil 190 } 191 192 ng := resp.NatGateways[0] 193 return ng, *ng.State, nil 194 } 195 }