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 }