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  }