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

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	"github.com/hashicorp/terraform/helper/diff"
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/terraform"
    11  	"github.com/mitchellh/goamz/ec2"
    12  )
    13  
    14  func resource_aws_subnet_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 so that we have all the proper attributes
    22  	s = s.MergeDiff(d)
    23  
    24  	// Create the Subnet
    25  	createOpts := &ec2.CreateSubnet{
    26  		AvailabilityZone: s.Attributes["availability_zone"],
    27  		CidrBlock:        s.Attributes["cidr_block"],
    28  		VpcId:            s.Attributes["vpc_id"],
    29  	}
    30  	log.Printf("[DEBUG] Subnet create config: %#v", createOpts)
    31  	resp, err := ec2conn.CreateSubnet(createOpts)
    32  	if err != nil {
    33  		return nil, fmt.Errorf("Error creating subnet: %s", err)
    34  	}
    35  
    36  	// Get the ID and store it
    37  	subnet := &resp.Subnet
    38  	s.ID = subnet.SubnetId
    39  	log.Printf("[INFO] Subnet ID: %s", s.ID)
    40  
    41  	// Wait for the Subnet to become available
    42  	log.Printf(
    43  		"[DEBUG] Waiting for subnet (%s) to become available",
    44  		s.ID)
    45  	stateConf := &resource.StateChangeConf{
    46  		Pending: []string{"pending"},
    47  		Target:  "available",
    48  		Refresh: SubnetStateRefreshFunc(ec2conn, s.ID),
    49  		Timeout: 10 * time.Minute,
    50  	}
    51  	subnetRaw, err := stateConf.WaitForState()
    52  	if err != nil {
    53  		return s, fmt.Errorf(
    54  			"Error waiting for subnet (%s) to become available: %s",
    55  			s.ID, err)
    56  	}
    57  
    58  	// Update our attributes and return
    59  	return resource_aws_subnet_update_state(s, subnetRaw.(*ec2.Subnet))
    60  }
    61  
    62  func resource_aws_subnet_update(
    63  	s *terraform.ResourceState,
    64  	d *terraform.ResourceDiff,
    65  	meta interface{}) (*terraform.ResourceState, error) {
    66  	// This should never be called because we have no update-able
    67  	// attributes
    68  	panic("Update for subnet is not supported")
    69  
    70  	return nil, nil
    71  }
    72  
    73  func resource_aws_subnet_destroy(
    74  	s *terraform.ResourceState,
    75  	meta interface{}) error {
    76  	p := meta.(*ResourceProvider)
    77  	ec2conn := p.ec2conn
    78  
    79  	log.Printf("[INFO] Deleting Subnet: %s", s.ID)
    80  	if _, err := ec2conn.DeleteSubnet(s.ID); err != nil {
    81  		ec2err, ok := err.(*ec2.Error)
    82  		if ok && ec2err.Code == "InvalidSubnetID.NotFound" {
    83  			return nil
    84  		}
    85  
    86  		return fmt.Errorf("Error deleting subnet: %s", err)
    87  	}
    88  
    89  	// Wait for the Subnet to actually delete
    90  	log.Printf("[DEBUG] Waiting for subnet (%s) to delete", s.ID)
    91  	stateConf := &resource.StateChangeConf{
    92  		Pending: []string{"available", "pending"},
    93  		Target:  "",
    94  		Refresh: SubnetStateRefreshFunc(ec2conn, s.ID),
    95  		Timeout: 10 * time.Minute,
    96  	}
    97  	if _, err := stateConf.WaitForState(); err != nil {
    98  		return fmt.Errorf(
    99  			"Error waiting for subnet (%s) to destroy",
   100  			s.ID, err)
   101  	}
   102  
   103  	return nil
   104  }
   105  
   106  func resource_aws_subnet_refresh(
   107  	s *terraform.ResourceState,
   108  	meta interface{}) (*terraform.ResourceState, error) {
   109  	p := meta.(*ResourceProvider)
   110  	ec2conn := p.ec2conn
   111  
   112  	subnetRaw, _, err := SubnetStateRefreshFunc(ec2conn, s.ID)()
   113  	if err != nil {
   114  		return s, err
   115  	}
   116  	if subnetRaw == nil {
   117  		return nil, nil
   118  	}
   119  
   120  	subnet := subnetRaw.(*ec2.Subnet)
   121  	return resource_aws_subnet_update_state(s, subnet)
   122  }
   123  
   124  func resource_aws_subnet_diff(
   125  	s *terraform.ResourceState,
   126  	c *terraform.ResourceConfig,
   127  	meta interface{}) (*terraform.ResourceDiff, error) {
   128  	b := &diff.ResourceBuilder{
   129  		Attrs: map[string]diff.AttrType{
   130  			"availability_zone": diff.AttrTypeCreate,
   131  			"cidr_block":        diff.AttrTypeCreate,
   132  			"vpc_id":            diff.AttrTypeCreate,
   133  		},
   134  
   135  		ComputedAttrs: []string{
   136  			"availability_zone",
   137  		},
   138  	}
   139  
   140  	return b.Diff(s, c)
   141  }
   142  
   143  func resource_aws_subnet_update_state(
   144  	s *terraform.ResourceState,
   145  	subnet *ec2.Subnet) (*terraform.ResourceState, error) {
   146  	s.Attributes["availability_zone"] = subnet.AvailabilityZone
   147  	s.Attributes["cidr_block"] = subnet.CidrBlock
   148  	s.Attributes["vpc_id"] = subnet.VpcId
   149  
   150  	// We belong to a VPC
   151  	s.Dependencies = []terraform.ResourceDependency{
   152  		terraform.ResourceDependency{ID: subnet.VpcId},
   153  	}
   154  
   155  	return s, nil
   156  }
   157  
   158  // SubnetStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
   159  // a Subnet.
   160  func SubnetStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
   161  	return func() (interface{}, string, error) {
   162  		resp, err := conn.DescribeSubnets([]string{id}, ec2.NewFilter())
   163  		if err != nil {
   164  			if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidSubnetID.NotFound" {
   165  				resp = nil
   166  			} else {
   167  				log.Printf("Error on SubnetStateRefresh: %s", err)
   168  				return nil, "", err
   169  			}
   170  		}
   171  
   172  		if resp == nil {
   173  			// Sometimes AWS just has consistency issues and doesn't see
   174  			// our instance yet. Return an empty state.
   175  			return nil, "", nil
   176  		}
   177  
   178  		subnet := &resp.Subnets[0]
   179  		return subnet, subnet.State, nil
   180  	}
   181  }