github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/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/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 "github.com/mitchellh/goamz/ec2" 11 ) 12 13 func resourceAwsSubnet() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceAwsSubnetCreate, 16 Read: resourceAwsSubnetRead, 17 Update: resourceAwsSubnetUpdate, 18 Delete: resourceAwsSubnetDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "vpc_id": &schema.Schema{ 22 Type: schema.TypeString, 23 Optional: true, 24 ForceNew: true, 25 Computed: true, 26 }, 27 28 "cidr_block": &schema.Schema{ 29 Type: schema.TypeString, 30 Required: true, 31 ForceNew: true, 32 }, 33 34 "availability_zone": &schema.Schema{ 35 Type: schema.TypeString, 36 Optional: true, 37 Computed: true, 38 ForceNew: true, 39 }, 40 41 "map_public_ip_on_launch": &schema.Schema{ 42 Type: schema.TypeBool, 43 Optional: true, 44 Computed: true, 45 }, 46 47 "tags": tagsSchema(), 48 }, 49 } 50 } 51 52 func resourceAwsSubnetCreate(d *schema.ResourceData, meta interface{}) error { 53 ec2conn := meta.(*AWSClient).ec2conn 54 55 createOpts := &ec2.CreateSubnet{ 56 AvailabilityZone: d.Get("availability_zone").(string), 57 CidrBlock: d.Get("cidr_block").(string), 58 VpcId: d.Get("vpc_id").(string), 59 } 60 61 resp, err := ec2conn.CreateSubnet(createOpts) 62 63 if err != nil { 64 return fmt.Errorf("Error creating subnet: %s", err) 65 } 66 67 // Get the ID and store it 68 subnet := &resp.Subnet 69 d.SetId(subnet.SubnetId) 70 log.Printf("[INFO] Subnet ID: %s", subnet.SubnetId) 71 72 // Wait for the Subnet to become available 73 log.Printf("[DEBUG] Waiting for subnet (%s) to become available", subnet.SubnetId) 74 stateConf := &resource.StateChangeConf{ 75 Pending: []string{"pending"}, 76 Target: "available", 77 Refresh: SubnetStateRefreshFunc(ec2conn, subnet.SubnetId), 78 Timeout: 10 * time.Minute, 79 } 80 81 _, err = stateConf.WaitForState() 82 83 if err != nil { 84 return fmt.Errorf( 85 "Error waiting for subnet (%s) to become ready: %s", 86 d.Id(), err) 87 } 88 89 return resourceAwsSubnetUpdate(d, meta) 90 } 91 92 func resourceAwsSubnetRead(d *schema.ResourceData, meta interface{}) error { 93 ec2conn := meta.(*AWSClient).ec2conn 94 95 resp, err := ec2conn.DescribeSubnets([]string{d.Id()}, ec2.NewFilter()) 96 97 if err != nil { 98 if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidSubnetID.NotFound" { 99 // Update state to indicate the subnet no longer exists. 100 d.SetId("") 101 return nil 102 } 103 return err 104 } 105 if resp == nil { 106 return nil 107 } 108 109 subnet := &resp.Subnets[0] 110 111 d.Set("vpc_id", subnet.VpcId) 112 d.Set("availability_zone", subnet.AvailabilityZone) 113 d.Set("cidr_block", subnet.CidrBlock) 114 d.Set("map_public_ip_on_launch", subnet.MapPublicIpOnLaunch) 115 d.Set("tags", tagsToMap(subnet.Tags)) 116 117 return nil 118 } 119 120 func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error { 121 ec2conn := meta.(*AWSClient).ec2conn 122 123 d.Partial(true) 124 125 if err := setTags(ec2conn, d); err != nil { 126 return err 127 } else { 128 d.SetPartial("tags") 129 } 130 131 if d.HasChange("map_public_ip_on_launch") { 132 modifyOpts := &ec2.ModifySubnetAttribute{ 133 SubnetId: d.Id(), 134 MapPublicIpOnLaunch: true, 135 } 136 137 log.Printf("[DEBUG] Subnet modify attributes: %#v", modifyOpts) 138 139 _, err := ec2conn.ModifySubnetAttribute(modifyOpts) 140 141 if err != nil { 142 return err 143 } else { 144 d.SetPartial("map_public_ip_on_launch") 145 } 146 } 147 148 d.Partial(false) 149 150 return resourceAwsSubnetRead(d, meta) 151 } 152 153 func resourceAwsSubnetDelete(d *schema.ResourceData, meta interface{}) error { 154 ec2conn := meta.(*AWSClient).ec2conn 155 156 log.Printf("[INFO] Deleting subnet: %s", d.Id()) 157 if _, err := ec2conn.DeleteSubnet(d.Id()); err != nil { 158 ec2err, ok := err.(*ec2.Error) 159 if ok && ec2err.Code == "InvalidSubnetID.NotFound" { 160 return nil 161 } 162 163 return fmt.Errorf("Error deleting subnet: %s", err) 164 } 165 166 return nil 167 } 168 169 // SubnetStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch a Subnet. 170 func SubnetStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { 171 return func() (interface{}, string, error) { 172 resp, err := conn.DescribeSubnets([]string{id}, ec2.NewFilter()) 173 if err != nil { 174 if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidSubnetID.NotFound" { 175 resp = nil 176 } else { 177 log.Printf("Error on SubnetStateRefresh: %s", err) 178 return nil, "", err 179 } 180 } 181 182 if resp == nil { 183 // Sometimes AWS just has consistency issues and doesn't see 184 // our instance yet. Return an empty state. 185 return nil, "", nil 186 } 187 188 subnet := &resp.Subnets[0] 189 return subnet, subnet.State, nil 190 } 191 }