github.com/bengesoff/terraform@v0.3.1-0.20141018223233-b25a53629922/builtin/providers/aws/resource_aws_vpc.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 resourceAwsVpc() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceAwsVpcCreate, 16 Read: resourceAwsVpcRead, 17 Update: resourceAwsVpcUpdate, 18 Delete: resourceAwsVpcDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "cidr_block": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 ForceNew: true, 25 }, 26 27 "enable_dns_hostnames": &schema.Schema{ 28 Type: schema.TypeBool, 29 Optional: true, 30 Computed: true, 31 }, 32 33 "enable_dns_support": &schema.Schema{ 34 Type: schema.TypeBool, 35 Optional: true, 36 Computed: true, 37 }, 38 39 "main_route_table_id": &schema.Schema{ 40 Type: schema.TypeString, 41 Computed: true, 42 }, 43 44 "tags": tagsSchema(), 45 }, 46 } 47 } 48 49 func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { 50 p := meta.(*ResourceProvider) 51 ec2conn := p.ec2conn 52 53 // Create the VPC 54 createOpts := &ec2.CreateVpc{ 55 CidrBlock: d.Get("cidr_block").(string), 56 } 57 log.Printf("[DEBUG] VPC create config: %#v", createOpts) 58 vpcResp, err := ec2conn.CreateVpc(createOpts) 59 if err != nil { 60 return fmt.Errorf("Error creating VPC: %s", err) 61 } 62 63 // Get the ID and store it 64 vpc := &vpcResp.VPC 65 log.Printf("[INFO] VPC ID: %s", vpc.VpcId) 66 d.SetId(vpc.VpcId) 67 68 // Set partial mode and say that we setup the cidr block 69 d.Partial(true) 70 d.SetPartial("cidr_block") 71 72 // Wait for the VPC to become available 73 log.Printf( 74 "[DEBUG] Waiting for VPC (%s) to become available", 75 d.Id()) 76 stateConf := &resource.StateChangeConf{ 77 Pending: []string{"pending"}, 78 Target: "available", 79 Refresh: VPCStateRefreshFunc(ec2conn, d.Id()), 80 Timeout: 10 * time.Minute, 81 } 82 if _, err := stateConf.WaitForState(); err != nil { 83 return fmt.Errorf( 84 "Error waiting for VPC (%s) to become available: %s", 85 d.Id(), err) 86 } 87 88 // Update our attributes and return 89 return resourceAwsVpcUpdate(d, meta) 90 } 91 92 func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { 93 p := meta.(*ResourceProvider) 94 ec2conn := p.ec2conn 95 96 // Turn on partial mode 97 d.Partial(true) 98 99 if d.HasChange("enable_dns_hostnames") { 100 options := new(ec2.ModifyVpcAttribute) 101 options.EnableDnsHostnames = d.Get("enable_dns_hostnames").(bool) 102 options.SetEnableDnsHostnames = true 103 104 log.Printf( 105 "[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v", 106 d.Id(), options) 107 if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil { 108 return err 109 } 110 111 d.SetPartial("enable_dns_hostnames") 112 } 113 114 if d.HasChange("enable_dns_support") { 115 options := new(ec2.ModifyVpcAttribute) 116 options.EnableDnsSupport = d.Get("enable_dns_support").(bool) 117 options.SetEnableDnsSupport = true 118 119 log.Printf( 120 "[INFO] Modifying enable_dns_support vpc attribute for %s: %#v", 121 d.Id(), options) 122 if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil { 123 return err 124 } 125 126 d.SetPartial("enable_dns_support") 127 } 128 129 if err := setTags(ec2conn, d); err != nil { 130 return err 131 } else { 132 d.SetPartial("tags") 133 } 134 135 d.Partial(false) 136 return resourceAwsVpcRead(d, meta) 137 } 138 139 func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { 140 p := meta.(*ResourceProvider) 141 ec2conn := p.ec2conn 142 143 log.Printf("[INFO] Deleting VPC: %s", d.Id()) 144 if _, err := ec2conn.DeleteVpc(d.Id()); err != nil { 145 ec2err, ok := err.(*ec2.Error) 146 if ok && ec2err.Code == "InvalidVpcID.NotFound" { 147 return nil 148 } 149 150 return fmt.Errorf("Error deleting VPC: %s", err) 151 } 152 153 return nil 154 } 155 156 func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { 157 p := meta.(*ResourceProvider) 158 ec2conn := p.ec2conn 159 160 // Refresh the VPC state 161 vpcRaw, _, err := VPCStateRefreshFunc(ec2conn, d.Id())() 162 if err != nil { 163 return err 164 } 165 if vpcRaw == nil { 166 return nil 167 } 168 169 // VPC stuff 170 vpc := vpcRaw.(*ec2.VPC) 171 d.Set("cidr_block", vpc.CidrBlock) 172 173 // Tags 174 d.Set("tags", tagsToMap(vpc.Tags)) 175 176 // Attributes 177 resp, err := ec2conn.VpcAttribute(d.Id(), "enableDnsSupport") 178 if err != nil { 179 return err 180 } 181 d.Set("enable_dns_support", resp.EnableDnsSupport) 182 183 resp, err = ec2conn.VpcAttribute(d.Id(), "enableDnsHostnames") 184 if err != nil { 185 return err 186 } 187 d.Set("enable_dns_hostnames", resp.EnableDnsHostnames) 188 189 // Get the main routing table for this VPC 190 filter := ec2.NewFilter() 191 filter.Add("association.main", "true") 192 filter.Add("vpc-id", d.Id()) 193 routeResp, err := ec2conn.DescribeRouteTables(nil, filter) 194 if err != nil { 195 return err 196 } 197 if v := routeResp.RouteTables; len(v) > 0 { 198 d.Set("main_route_table_id", v[0].RouteTableId) 199 } 200 201 return nil 202 } 203 204 // VPCStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch 205 // a VPC. 206 func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { 207 return func() (interface{}, string, error) { 208 resp, err := conn.DescribeVpcs([]string{id}, ec2.NewFilter()) 209 if err != nil { 210 if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidVpcID.NotFound" { 211 resp = nil 212 } else { 213 log.Printf("Error on VPCStateRefresh: %s", err) 214 return nil, "", err 215 } 216 } 217 218 if resp == nil { 219 // Sometimes AWS just has consistency issues and doesn't see 220 // our instance yet. Return an empty state. 221 return nil, "", nil 222 } 223 224 vpc := &resp.VPCs[0] 225 return vpc, vpc.State, nil 226 } 227 }