From 38a8232e9a3234377a07a1360bc9e380ee393641 Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Wed, 25 Feb 2015 15:04:17 +0530 Subject: [PATCH 01/62] Added Connection to config --- builtin/providers/aws/config.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index 7a1896c14..9d324e495 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -14,6 +14,7 @@ import ( awsGo "github.com/awslabs/aws-sdk-go/aws" "github.com/awslabs/aws-sdk-go/gen/autoscaling" + awsEc2 "github.com/awslabs/aws-sdk-go/gen/ec2" "github.com/awslabs/aws-sdk-go/gen/route53" "github.com/awslabs/aws-sdk-go/gen/s3" ) @@ -32,6 +33,7 @@ type AWSClient struct { rdsconn *rds.Rds r53conn *route53.Route53 region string + awsEc2conn *awsEc2.EC2 } // Client configures and returns a fully initailized AWSClient @@ -76,6 +78,10 @@ func (c *Config) Client() (interface{}, error) { // See http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html log.Println("[INFO] Initializing Route53 connection") client.r53conn = route53.New(creds, "us-east-1", nil) + + //Check about using us-east-1 for all + log.Println("[INFO] Initializing AWS-GO EC2 Connection") + client.awsEc2conn = awsEc2.New(creds, "us-east-1", nil) } if len(errs) > 0 { From 1472f976d7dabf4702edef4a166253a48b033db9 Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Wed, 25 Feb 2015 16:17:55 +0530 Subject: [PATCH 02/62] First refactor --- builtin/providers/aws/resource_aws_vpc.go | 74 +++++++++++++++-------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index f4ac2162e..496096106 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -5,9 +5,10 @@ import ( "log" "time" + awsGo "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsVpc() *schema.Resource { @@ -57,29 +58,33 @@ func resourceAwsVpc() *schema.Resource { Computed: true, }, - "tags": tagsSchema(), + // "tags": tagsSchema(), }, } } func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn - + ec2conn := meta.(*AWSClient).awsEc2conn + cidr := d.Get("cidr_block").(string) + instance_tenancy := "default" + if v := d.Get("instance_tenancy"); v != nil { + instance_tenancy = v.(string) + } // Create the VPC - createOpts := &ec2.CreateVpc{ - CidrBlock: d.Get("cidr_block").(string), - InstanceTenancy: d.Get("instance_tenancy").(string), + createOpts := &ec2.CreateVPCRequest{ + CIDRBlock: &cidr, + InstanceTenancy: &instance_tenancy, } log.Printf("[DEBUG] VPC create config: %#v", createOpts) - vpcResp, err := ec2conn.CreateVpc(createOpts) + vpcResp, err := ec2conn.CreateVPC(createOpts) if err != nil { return fmt.Errorf("Error creating VPC: %s", err) } // Get the ID and store it - vpc := &vpcResp.VPC - log.Printf("[INFO] VPC ID: %s", vpc.VpcId) - d.SetId(vpc.VpcId) + vpc := vpcResp.VPC + d.SetId(*vpc.VPCID) + log.Printf("[INFO] VPC ID: %s", d.Id()) // Set partial mode and say that we setup the cidr block d.Partial(true) @@ -106,7 +111,7 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEc2conn // Refresh the VPC state vpcRaw, _, err := VPCStateRefreshFunc(ec2conn, d.Id())() @@ -120,34 +125,53 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { // VPC stuff vpc := vpcRaw.(*ec2.VPC) - d.Set("cidr_block", vpc.CidrBlock) + vpcid := d.Id() + d.Set("cidr_block", vpc.CIDRBlock) - // Tags - d.Set("tags", tagsToMap(vpc.Tags)) + // Tags - TBD rmenn + //d.Set("tags", tagsToMap(vpc.Tags)) // Attributes - resp, err := ec2conn.VpcAttribute(d.Id(), "enableDnsSupport") + attribute := "enableDnsSupport" + DescribeAttrOpts := &ec2.DescribeVPCAttributeRequest{ + Attribute: &attribute, + VPCID: &vpcid, + } + resp, err := ec2conn.DescribeVPCAttribute(DescribeAttrOpts) if err != nil { return err } - d.Set("enable_dns_support", resp.EnableDnsSupport) - - resp, err = ec2conn.VpcAttribute(d.Id(), "enableDnsHostnames") + d.Set("enable_dns_support", *resp.EnableDNSSupport) + attribute = "enableDnsHostnames" + DescribeAttrOpts = &ec2.DescribeVPCAttributeRequest{ + Attribute: &attribute, + VPCID: &vpcid, + } + resp, err = ec2conn.DescribeVPCAttribute(DescribeAttrOpts) if err != nil { return err } - d.Set("enable_dns_hostnames", resp.EnableDnsHostnames) + d.Set("enable_dns_hostnames", *resp.EnableDNSHostnames) // Get the main routing table for this VPC - filter := ec2.NewFilter() - filter.Add("association.main", "true") - filter.Add("vpc-id", d.Id()) - routeResp, err := ec2conn.DescribeRouteTables(nil, filter) + // Really Ugly need to make this better - rmenn + filter1 := &ec2.Filter{ + Name: awsGo.String("association.main"), + Values: []string{("true")}, + } + filter2 := &ec2.Filter{ + Name: awsGo.String("VPCID"), + Values: []string{(d.Id())}, + } + DescribeRouteOpts := &ec2.DescribeRouteTablesRequest{ + Filters: []ec2.Filter{*filter1, *filter2}, + } + routeResp, err := ec2conn.DescribeRouteTables(DescribeRouteOpts) if err != nil { return err } if v := routeResp.RouteTables; len(v) > 0 { - d.Set("main_route_table_id", v[0].RouteTableId) + d.Set("main_route_table_id", *v[0].RouteTableID) } resourceAwsVpcSetDefaultNetworkAcl(ec2conn, d) From 06b2d0bbf61c5a0810747e14aad99e45fd744466 Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Wed, 25 Feb 2015 17:34:27 +0530 Subject: [PATCH 03/62] VPC Refactor --- builtin/providers/aws/resource_aws_vpc.go | 101 ++++++++++++++-------- 1 file changed, 64 insertions(+), 37 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 496096106..153eda29a 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -181,20 +181,24 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEc2conn // Turn on partial mode d.Partial(true) - + vpcid := d.Id() + modifyOpts := &ec2.ModifyVPCAttributeRequest{ + VPCID: &vpcid, + } if d.HasChange("enable_dns_hostnames") { - options := new(ec2.ModifyVpcAttribute) - options.EnableDnsHostnames = d.Get("enable_dns_hostnames").(bool) - options.SetEnableDnsHostnames = true + val := d.Get("enable_dns_hostnames").(bool) + modifyOpts.EnableDNSHostnames = &ec2.AttributeBooleanValue{ + Value: &val, + } log.Printf( "[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v", - d.Id(), options) - if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil { + d.Id(), modifyOpts) + if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil { return err } @@ -202,36 +206,40 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { } if d.HasChange("enable_dns_support") { - options := new(ec2.ModifyVpcAttribute) - options.EnableDnsSupport = d.Get("enable_dns_support").(bool) - options.SetEnableDnsSupport = true + val := d.Get("enable_dns_hostnames").(bool) + modifyOpts.EnableDNSSupport = &ec2.AttributeBooleanValue{ + Value: &val, + } log.Printf( "[INFO] Modifying enable_dns_support vpc attribute for %s: %#v", - d.Id(), options) - if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil { + d.Id(), modifyOpts) + if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil { return err } d.SetPartial("enable_dns_support") } - - if err := setTags(ec2conn, d); err != nil { - return err - } else { - d.SetPartial("tags") - } + //Tagging Support need to be worked on - rmenn + // if err := setTags(ec2conn, d); err != nil { + // return err + // } else { + // d.SetPartial("tags") + // } d.Partial(false) return resourceAwsVpcRead(d, meta) } func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn - + ec2conn := meta.(*AWSClient).awsEc2conn + vpcID := d.Id() + DeleteVpcOpts := &ec2.DeleteVPCRequest{ + VPCID: &vpcID, + } log.Printf("[INFO] Deleting VPC: %s", d.Id()) - if _, err := ec2conn.DeleteVpc(d.Id()); err != nil { - ec2err, ok := err.(*ec2.Error) + if err := ec2conn.DeleteVPC(DeleteVpcOpts); err != nil { + ec2err, ok := err.(*awsGo.APIError) if ok && ec2err.Code == "InvalidVpcID.NotFound" { return nil } @@ -246,9 +254,12 @@ func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { // a VPC. func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := conn.DescribeVpcs([]string{id}, ec2.NewFilter()) + DescribeVpcOpts := &ec2.DescribeVPCsRequest{ + VPCIDs: []string{id}, + } + resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err != nil { - if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidVpcID.NotFound" { + if ec2err, ok := err.(*awsGo.APIError); ok && ec2err.Code == "InvalidVpcID.NotFound" { resp = nil } else { log.Printf("Error on VPCStateRefresh: %s", err) @@ -263,37 +274,53 @@ func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { } vpc := &resp.VPCs[0] - return vpc, vpc.State, nil + return vpc, *vpc.State, nil } } func resourceAwsVpcSetDefaultNetworkAcl(conn *ec2.EC2, d *schema.ResourceData) error { - filter := ec2.NewFilter() - filter.Add("default", "true") - filter.Add("vpc-id", d.Id()) - networkAclResp, err := conn.NetworkAcls(nil, filter) + filter1 := &ec2.Filter{ + Name: awsGo.String("default"), + Values: []string{("true")}, + } + filter2 := &ec2.Filter{ + Name: awsGo.String("vpc-id"), + Values: []string{(d.Id())}, + } + DescribeNetworkACLOpts := &ec2.DescribeNetworkACLsRequest{ + Filters: []ec2.Filter{*filter1, *filter2}, + } + networkAclResp, err := conn.DescribeNetworkACLs(DescribeNetworkACLOpts) if err != nil { return err } - if v := networkAclResp.NetworkAcls; len(v) > 0 { - d.Set("default_network_acl_id", v[0].NetworkAclId) + if v := networkAclResp.NetworkACLs; len(v) > 0 { + d.Set("default_network_acl_id", v[0].NetworkACLID) } return nil } func resourceAwsVpcSetDefaultSecurityGroup(conn *ec2.EC2, d *schema.ResourceData) error { - filter := ec2.NewFilter() - filter.Add("group-name", "default") - filter.Add("vpc-id", d.Id()) - securityGroupResp, err := conn.SecurityGroups(nil, filter) + filter1 := &ec2.Filter{ + Name: awsGo.String("group-name"), + Values: []string{("default")}, + } + filter2 := &ec2.Filter{ + Name: awsGo.String("vpc-id"), + Values: []string{(d.Id())}, + } + DescribeSgOpts := &ec2.DescribeSecurityGroupsRequest{ + Filters: []ec2.Filter{*filter1, *filter2}, + } + securityGroupResp, err := conn.DescribeSecurityGroups(DescribeSgOpts) if err != nil { return err } - if v := securityGroupResp.Groups; len(v) > 0 { - d.Set("default_security_group_id", v[0].Id) + if v := securityGroupResp.SecurityGroups; len(v) > 0 { + d.Set("default_security_group_id", v[0].GroupID) } return nil From ac58a450bac27147d9df7bc15da4ec135978bf11 Mon Sep 17 00:00:00 2001 From: Pablo Lalloni Date: Wed, 25 Feb 2015 08:38:23 -0300 Subject: [PATCH 04/62] Add DigitalOcean SSH Key resource --- builtin/providers/digitalocean/provider.go | 1 + .../resource_digitalocean_ssh_key.go | 114 ++++++++++++++++++ .../resource_digitalocean_ssh_key_test.go | 99 +++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 builtin/providers/digitalocean/resource_digitalocean_ssh_key.go create mode 100644 builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go diff --git a/builtin/providers/digitalocean/provider.go b/builtin/providers/digitalocean/provider.go index ecc7d67b8..080716e2e 100644 --- a/builtin/providers/digitalocean/provider.go +++ b/builtin/providers/digitalocean/provider.go @@ -21,6 +21,7 @@ func Provider() terraform.ResourceProvider { "digitalocean_domain": resourceDigitalOceanDomain(), "digitalocean_droplet": resourceDigitalOceanDroplet(), "digitalocean_record": resourceDigitalOceanRecord(), + "digitalocean_ssh_key": resourceDigitalOceanSSHKey(), }, ConfigureFunc: providerConfigure, diff --git a/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go b/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go new file mode 100644 index 000000000..c509d4725 --- /dev/null +++ b/builtin/providers/digitalocean/resource_digitalocean_ssh_key.go @@ -0,0 +1,114 @@ +package digitalocean + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/pearkes/digitalocean" +) + +func resourceDigitalOceanSSHKey() *schema.Resource { + return &schema.Resource{ + Create: resourceDigitalOceanSSHKeyCreate, + Read: resourceDigitalOceanSSHKeyRead, + Update: resourceDigitalOceanSSHKeyUpdate, + Delete: resourceDigitalOceanSSHKeyDelete, + + Schema: map[string]*schema.Schema{ + "id": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "public_key": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "fingerprint": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceDigitalOceanSSHKeyCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + // Build up our creation options + opts := &digitalocean.CreateSSHKey{ + Name: d.Get("name").(string), + PublicKey: d.Get("public_key").(string), + } + + log.Printf("[DEBUG] SSH Key create configuration: %#v", opts) + id, err := client.CreateSSHKey(opts) + if err != nil { + return fmt.Errorf("Error creating SSH Key: %s", err) + } + + d.SetId(id) + log.Printf("[INFO] SSH Key: %s", id) + + return resourceDigitalOceanSSHKeyRead(d, meta) +} + +func resourceDigitalOceanSSHKeyRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + key, err := client.RetrieveSSHKey(d.Id()) + if err != nil { + // If the key is somehow already destroyed, mark as + // succesfully gone + if strings.Contains(err.Error(), "404 Not Found") { + d.SetId("") + return nil + } + + return fmt.Errorf("Error retrieving SSH key: %s", err) + } + + d.Set("name", key.Name) + d.Set("fingerprint", key.Fingerprint) + + return nil +} + +func resourceDigitalOceanSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + var newName string + if v, ok := d.GetOk("name"); ok { + newName = v.(string) + } + + log.Printf("[DEBUG] SSH key update name: %#v", newName) + err := client.RenameSSHKey(d.Id(), newName) + if err != nil { + return fmt.Errorf("Failed to update SSH key: %s", err) + } + + return resourceDigitalOceanSSHKeyRead(d, meta) +} + +func resourceDigitalOceanSSHKeyDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*digitalocean.Client) + + log.Printf("[INFO] Deleting SSH key: %s", d.Id()) + err := client.DestroySSHKey(d.Id()) + if err != nil { + return fmt.Errorf("Error deleting SSH key: %s", err) + } + + d.SetId("") + return nil +} diff --git a/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go b/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go new file mode 100644 index 000000000..d5c50e6f8 --- /dev/null +++ b/builtin/providers/digitalocean/resource_digitalocean_ssh_key_test.go @@ -0,0 +1,99 @@ +package digitalocean + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/pearkes/digitalocean" +) + +func TestAccDigitalOceanSSHKey_Basic(t *testing.T) { + var key digitalocean.SSHKey + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckDigitalOceanSSHKeyDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckDigitalOceanSSHKeyConfig_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckDigitalOceanSSHKeyExists("digitalocean_ssh_key.foobar", &key), + testAccCheckDigitalOceanSSHKeyAttributes(&key), + resource.TestCheckResourceAttr( + "digitalocean_ssh_key.foobar", "name", "foobar"), + resource.TestCheckResourceAttr( + "digitalocean_ssh_key.foobar", "public_key", "abcdef"), + ), + }, + }, + }) +} + +func testAccCheckDigitalOceanSSHKeyDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*digitalocean.Client) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "digitalocean_ssh_key" { + continue + } + + // Try to find the key + _, err := client.RetrieveSSHKey(rs.Primary.ID) + + if err == nil { + fmt.Errorf("SSH key still exists") + } + } + + return nil +} + +func testAccCheckDigitalOceanSSHKeyAttributes(key *digitalocean.SSHKey) resource.TestCheckFunc { + return func(s *terraform.State) error { + + if key.Name != "foobar" { + return fmt.Errorf("Bad name: %s", key.Name) + } + + return nil + } +} + +func testAccCheckDigitalOceanSSHKeyExists(n string, key *digitalocean.SSHKey) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No Record ID is set") + } + + client := testAccProvider.Meta().(*digitalocean.Client) + + foundKey, err := client.RetrieveSSHKey(rs.Primary.ID) + + if err != nil { + return err + } + + if foundKey.Name != rs.Primary.ID { + return fmt.Errorf("Record not found") + } + + *key = foundKey + + return nil + } +} + +const testAccCheckDigitalOceanSSHKeyConfig_basic = ` +resource "digitalocean_ssh_key" "foobar" { + name = "foobar" + public_key = "abcdef" +}` From 89d01b49aba8a48b0b9f58559a02ff4eb1a287fc Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Mon, 2 Mar 2015 14:21:13 +0530 Subject: [PATCH 05/62] Refactor with Acceptance Tests --- builtin/providers/aws/config.go | 2 +- builtin/providers/aws/resource_aws_vpc.go | 8 +- .../providers/aws/resource_aws_vpc_test.go | 87 ++++++++++--------- 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index 9d324e495..c4d9a09f0 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -81,7 +81,7 @@ func (c *Config) Client() (interface{}, error) { //Check about using us-east-1 for all log.Println("[INFO] Initializing AWS-GO EC2 Connection") - client.awsEc2conn = awsEc2.New(creds, "us-east-1", nil) + client.awsEc2conn = awsEc2.New(creds, c.Region, nil) } if len(errs) > 0 { diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 153eda29a..d3207dfa7 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -67,7 +67,7 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { ec2conn := meta.(*AWSClient).awsEc2conn cidr := d.Get("cidr_block").(string) instance_tenancy := "default" - if v := d.Get("instance_tenancy"); v != nil { + if v, ok := d.GetOk("instance_tenancy"); ok { instance_tenancy = v.(string) } // Create the VPC @@ -75,10 +75,10 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { CIDRBlock: &cidr, InstanceTenancy: &instance_tenancy, } - log.Printf("[DEBUG] VPC create config: %#v", createOpts) + log.Printf("[DEBUG] VPC create config: %#v", *createOpts) vpcResp, err := ec2conn.CreateVPC(createOpts) if err != nil { - return fmt.Errorf("Error creating VPC: %s", err) + return fmt.Errorf("Error creating VPC: %s : %s", err) } // Get the ID and store it @@ -160,7 +160,7 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { Values: []string{("true")}, } filter2 := &ec2.Filter{ - Name: awsGo.String("VPCID"), + Name: awsGo.String("vpc-id"), Values: []string{(d.Id())}, } DescribeRouteOpts := &ec2.DescribeRouteTablesRequest{ diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index b555e0875..f91d2ac76 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -2,11 +2,11 @@ package aws import ( "fmt" - "testing" - + awsGo "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" + "testing" ) func TestAccVpc_basic(t *testing.T) { @@ -50,36 +50,36 @@ func TestAccVpc_dedicatedTenancy(t *testing.T) { }) } -func TestAccVpc_tags(t *testing.T) { - var vpc ec2.VPC - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccVpcConfigTags, - Check: resource.ComposeTestCheckFunc( - testAccCheckVpcExists("aws_vpc.foo", &vpc), - testAccCheckVpcCidr(&vpc, "10.1.0.0/16"), - resource.TestCheckResourceAttr( - "aws_vpc.foo", "cidr_block", "10.1.0.0/16"), - testAccCheckTags(&vpc.Tags, "foo", "bar"), - ), - }, - - resource.TestStep{ - Config: testAccVpcConfigTagsUpdate, - Check: resource.ComposeTestCheckFunc( - testAccCheckVpcExists("aws_vpc.foo", &vpc), - testAccCheckTags(&vpc.Tags, "foo", ""), - testAccCheckTags(&vpc.Tags, "bar", "baz"), - ), - }, - }, - }) -} +//func TestAccVpc_tags(t *testing.T) { +// var vpc ec2.VPC +// +// resource.Test(t, resource.TestCase{ +// PreCheck: func() { testAccPreCheck(t) }, +// Providers: testAccProviders, +// CheckDestroy: testAccCheckVpcDestroy, +// Steps: []resource.TestStep{ +// resource.TestStep{ +// Config: testAccVpcConfigTags, +// Check: resource.ComposeTestCheckFunc( +// testAccCheckVpcExists("aws_vpc.foo", &vpc), +// testAccCheckVpcCidr(&vpc, "10.1.0.0/16"), +// resource.TestCheckResourceAttr( +// "aws_vpc.foo", "cidr_block", "10.1.0.0/16"), +// testAccCheckTags(&vpc.Tags, "foo", "bar"), +// ), +// }, +// +// resource.TestStep{ +// Config: testAccVpcConfigTagsUpdate, +// Check: resource.ComposeTestCheckFunc( +// testAccCheckVpcExists("aws_vpc.foo", &vpc), +// testAccCheckTags(&vpc.Tags, "foo", ""), +// testAccCheckTags(&vpc.Tags, "bar", "baz"), +// ), +// }, +// }, +// }) +//} func TestAccVpcUpdate(t *testing.T) { var vpc ec2.VPC @@ -111,7 +111,7 @@ func TestAccVpcUpdate(t *testing.T) { } func testAccCheckVpcDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEc2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_vpc" { @@ -119,7 +119,10 @@ func testAccCheckVpcDestroy(s *terraform.State) error { } // Try to find the VPC - resp, err := conn.DescribeVpcs([]string{rs.Primary.ID}, ec2.NewFilter()) + DescribeVpcOpts := &ec2.DescribeVPCsRequest{ + VPCIDs: []string{rs.Primary.ID}, + } + resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err == nil { if len(resp.VPCs) > 0 { return fmt.Errorf("VPCs still exist.") @@ -129,7 +132,7 @@ func testAccCheckVpcDestroy(s *terraform.State) error { } // Verify the error is what we want - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(*awsGo.APIError) if !ok { return err } @@ -143,8 +146,9 @@ func testAccCheckVpcDestroy(s *terraform.State) error { func testAccCheckVpcCidr(vpc *ec2.VPC, expected string) resource.TestCheckFunc { return func(s *terraform.State) error { - if vpc.CidrBlock != expected { - return fmt.Errorf("Bad cidr: %s", vpc.CidrBlock) + CIDRBlock := vpc.CIDRBlock + if *CIDRBlock != expected { + return fmt.Errorf("Bad cidr: %s", *vpc.CIDRBlock) } return nil @@ -162,8 +166,11 @@ func testAccCheckVpcExists(n string, vpc *ec2.VPC) resource.TestCheckFunc { return fmt.Errorf("No VPC ID is set") } - conn := testAccProvider.Meta().(*AWSClient).ec2conn - resp, err := conn.DescribeVpcs([]string{rs.Primary.ID}, ec2.NewFilter()) + conn := testAccProvider.Meta().(*AWSClient).awsEc2conn + DescribeVpcOpts := &ec2.DescribeVPCsRequest{ + VPCIDs: []string{rs.Primary.ID}, + } + resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err != nil { return err } From d77df312a36fefd10ee667e355d327146078d2fe Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Tue, 3 Mar 2015 10:45:15 +0530 Subject: [PATCH 06/62] Changed things around as suggested by @catsby --- builtin/providers/aws/resource_aws_vpc.go | 21 +++++++++---------- .../providers/aws/resource_aws_vpc_test.go | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index d3207dfa7..6e2ddc95b 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -5,7 +5,7 @@ import ( "log" "time" - awsGo "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/aws" "github.com/awslabs/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" @@ -65,14 +65,13 @@ func resourceAwsVpc() *schema.Resource { func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { ec2conn := meta.(*AWSClient).awsEc2conn - cidr := d.Get("cidr_block").(string) instance_tenancy := "default" if v, ok := d.GetOk("instance_tenancy"); ok { instance_tenancy = v.(string) } // Create the VPC createOpts := &ec2.CreateVPCRequest{ - CIDRBlock: &cidr, + CIDRBlock: aws.String(d.Get("cidr_block").(string)), InstanceTenancy: &instance_tenancy, } log.Printf("[DEBUG] VPC create config: %#v", *createOpts) @@ -156,11 +155,11 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { // Get the main routing table for this VPC // Really Ugly need to make this better - rmenn filter1 := &ec2.Filter{ - Name: awsGo.String("association.main"), + Name: aws.String("association.main"), Values: []string{("true")}, } filter2 := &ec2.Filter{ - Name: awsGo.String("vpc-id"), + Name: aws.String("vpc-id"), Values: []string{(d.Id())}, } DescribeRouteOpts := &ec2.DescribeRouteTablesRequest{ @@ -239,7 +238,7 @@ func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { } log.Printf("[INFO] Deleting VPC: %s", d.Id()) if err := ec2conn.DeleteVPC(DeleteVpcOpts); err != nil { - ec2err, ok := err.(*awsGo.APIError) + ec2err, ok := err.(*aws.APIError) if ok && ec2err.Code == "InvalidVpcID.NotFound" { return nil } @@ -259,7 +258,7 @@ func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { } resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err != nil { - if ec2err, ok := err.(*awsGo.APIError); ok && ec2err.Code == "InvalidVpcID.NotFound" { + if ec2err, ok := err.(*aws.APIError); ok && ec2err.Code == "InvalidVpcID.NotFound" { resp = nil } else { log.Printf("Error on VPCStateRefresh: %s", err) @@ -280,11 +279,11 @@ func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { func resourceAwsVpcSetDefaultNetworkAcl(conn *ec2.EC2, d *schema.ResourceData) error { filter1 := &ec2.Filter{ - Name: awsGo.String("default"), + Name: aws.String("default"), Values: []string{("true")}, } filter2 := &ec2.Filter{ - Name: awsGo.String("vpc-id"), + Name: aws.String("vpc-id"), Values: []string{(d.Id())}, } DescribeNetworkACLOpts := &ec2.DescribeNetworkACLsRequest{ @@ -304,11 +303,11 @@ func resourceAwsVpcSetDefaultNetworkAcl(conn *ec2.EC2, d *schema.ResourceData) e func resourceAwsVpcSetDefaultSecurityGroup(conn *ec2.EC2, d *schema.ResourceData) error { filter1 := &ec2.Filter{ - Name: awsGo.String("group-name"), + Name: aws.String("group-name"), Values: []string{("default")}, } filter2 := &ec2.Filter{ - Name: awsGo.String("vpc-id"), + Name: aws.String("vpc-id"), Values: []string{(d.Id())}, } DescribeSgOpts := &ec2.DescribeSecurityGroupsRequest{ diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index f91d2ac76..dee441af8 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -2,7 +2,7 @@ package aws import ( "fmt" - awsGo "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/aws" "github.com/awslabs/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -132,7 +132,7 @@ func testAccCheckVpcDestroy(s *terraform.State) error { } // Verify the error is what we want - ec2err, ok := err.(*awsGo.APIError) + ec2err, ok := err.(*aws.APIError) if !ok { return err } From c5efe1e5ce4779c39b566b987b72ad84413f204a Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Tue, 3 Mar 2015 10:49:21 +0530 Subject: [PATCH 07/62] Using hashicorp/aws-sdk-go --- builtin/providers/aws/config.go | 10 +++++----- builtin/providers/aws/resource_aws_vpc.go | 4 ++-- builtin/providers/aws/resource_aws_vpc_test.go | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index c4d9a09f0..f603598f3 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -12,11 +12,11 @@ import ( "github.com/mitchellh/goamz/elb" "github.com/mitchellh/goamz/rds" - awsGo "github.com/awslabs/aws-sdk-go/aws" - "github.com/awslabs/aws-sdk-go/gen/autoscaling" - awsEc2 "github.com/awslabs/aws-sdk-go/gen/ec2" - "github.com/awslabs/aws-sdk-go/gen/route53" - "github.com/awslabs/aws-sdk-go/gen/s3" + awsGo "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/autoscaling" + awsEc2 "github.com/hashicorp/aws-sdk-go/gen/ec2" + "github.com/hashicorp/aws-sdk-go/gen/route53" + "github.com/hashicorp/aws-sdk-go/gen/s3" ) type Config struct { diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 6e2ddc95b..4d1d871ba 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -5,8 +5,8 @@ import ( "log" "time" - "github.com/awslabs/aws-sdk-go/aws" - "github.com/awslabs/aws-sdk-go/gen/ec2" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" ) diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index dee441af8..7570a1873 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -2,8 +2,8 @@ package aws import ( "fmt" - "github.com/awslabs/aws-sdk-go/aws" - "github.com/awslabs/aws-sdk-go/gen/ec2" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" "testing" From d56c683602ace8799ff6f58f3d13da43a56d657a Mon Sep 17 00:00:00 2001 From: rmenn Date: Tue, 3 Mar 2015 20:57:30 +0530 Subject: [PATCH 08/62] Removed additional variable for print, added for debugging --- builtin/providers/aws/resource_aws_vpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 4d1d871ba..00c8f6983 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -77,7 +77,7 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { log.Printf("[DEBUG] VPC create config: %#v", *createOpts) vpcResp, err := ec2conn.CreateVPC(createOpts) if err != nil { - return fmt.Errorf("Error creating VPC: %s : %s", err) + return fmt.Errorf("Error creating VPC: %s", err) } // Get the ID and store it From 1cecb37ab95302713d3303a1dcc6b254070e7463 Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Wed, 25 Feb 2015 15:04:17 +0530 Subject: [PATCH 09/62] Added vpc refactor in aws sdk go --- builtin/providers/aws/resource_aws_vpc.go | 180 +++++++++++------- .../providers/aws/resource_aws_vpc_test.go | 87 +++++---- 2 files changed, 162 insertions(+), 105 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index f4ac2162e..4d1d871ba 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -5,9 +5,10 @@ import ( "log" "time" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsVpc() *schema.Resource { @@ -57,29 +58,32 @@ func resourceAwsVpc() *schema.Resource { Computed: true, }, - "tags": tagsSchema(), + // "tags": tagsSchema(), }, } } func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn - - // Create the VPC - createOpts := &ec2.CreateVpc{ - CidrBlock: d.Get("cidr_block").(string), - InstanceTenancy: d.Get("instance_tenancy").(string), + ec2conn := meta.(*AWSClient).awsEc2conn + instance_tenancy := "default" + if v, ok := d.GetOk("instance_tenancy"); ok { + instance_tenancy = v.(string) } - log.Printf("[DEBUG] VPC create config: %#v", createOpts) - vpcResp, err := ec2conn.CreateVpc(createOpts) + // Create the VPC + createOpts := &ec2.CreateVPCRequest{ + CIDRBlock: aws.String(d.Get("cidr_block").(string)), + InstanceTenancy: &instance_tenancy, + } + log.Printf("[DEBUG] VPC create config: %#v", *createOpts) + vpcResp, err := ec2conn.CreateVPC(createOpts) if err != nil { - return fmt.Errorf("Error creating VPC: %s", err) + return fmt.Errorf("Error creating VPC: %s : %s", err) } // Get the ID and store it - vpc := &vpcResp.VPC - log.Printf("[INFO] VPC ID: %s", vpc.VpcId) - d.SetId(vpc.VpcId) + vpc := vpcResp.VPC + d.SetId(*vpc.VPCID) + log.Printf("[INFO] VPC ID: %s", d.Id()) // Set partial mode and say that we setup the cidr block d.Partial(true) @@ -106,7 +110,7 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEc2conn // Refresh the VPC state vpcRaw, _, err := VPCStateRefreshFunc(ec2conn, d.Id())() @@ -120,34 +124,53 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { // VPC stuff vpc := vpcRaw.(*ec2.VPC) - d.Set("cidr_block", vpc.CidrBlock) + vpcid := d.Id() + d.Set("cidr_block", vpc.CIDRBlock) - // Tags - d.Set("tags", tagsToMap(vpc.Tags)) + // Tags - TBD rmenn + //d.Set("tags", tagsToMap(vpc.Tags)) // Attributes - resp, err := ec2conn.VpcAttribute(d.Id(), "enableDnsSupport") + attribute := "enableDnsSupport" + DescribeAttrOpts := &ec2.DescribeVPCAttributeRequest{ + Attribute: &attribute, + VPCID: &vpcid, + } + resp, err := ec2conn.DescribeVPCAttribute(DescribeAttrOpts) if err != nil { return err } - d.Set("enable_dns_support", resp.EnableDnsSupport) - - resp, err = ec2conn.VpcAttribute(d.Id(), "enableDnsHostnames") + d.Set("enable_dns_support", *resp.EnableDNSSupport) + attribute = "enableDnsHostnames" + DescribeAttrOpts = &ec2.DescribeVPCAttributeRequest{ + Attribute: &attribute, + VPCID: &vpcid, + } + resp, err = ec2conn.DescribeVPCAttribute(DescribeAttrOpts) if err != nil { return err } - d.Set("enable_dns_hostnames", resp.EnableDnsHostnames) + d.Set("enable_dns_hostnames", *resp.EnableDNSHostnames) // Get the main routing table for this VPC - filter := ec2.NewFilter() - filter.Add("association.main", "true") - filter.Add("vpc-id", d.Id()) - routeResp, err := ec2conn.DescribeRouteTables(nil, filter) + // Really Ugly need to make this better - rmenn + filter1 := &ec2.Filter{ + Name: aws.String("association.main"), + Values: []string{("true")}, + } + filter2 := &ec2.Filter{ + Name: aws.String("vpc-id"), + Values: []string{(d.Id())}, + } + DescribeRouteOpts := &ec2.DescribeRouteTablesRequest{ + Filters: []ec2.Filter{*filter1, *filter2}, + } + routeResp, err := ec2conn.DescribeRouteTables(DescribeRouteOpts) if err != nil { return err } if v := routeResp.RouteTables; len(v) > 0 { - d.Set("main_route_table_id", v[0].RouteTableId) + d.Set("main_route_table_id", *v[0].RouteTableID) } resourceAwsVpcSetDefaultNetworkAcl(ec2conn, d) @@ -157,20 +180,24 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEc2conn // Turn on partial mode d.Partial(true) - + vpcid := d.Id() + modifyOpts := &ec2.ModifyVPCAttributeRequest{ + VPCID: &vpcid, + } if d.HasChange("enable_dns_hostnames") { - options := new(ec2.ModifyVpcAttribute) - options.EnableDnsHostnames = d.Get("enable_dns_hostnames").(bool) - options.SetEnableDnsHostnames = true + val := d.Get("enable_dns_hostnames").(bool) + modifyOpts.EnableDNSHostnames = &ec2.AttributeBooleanValue{ + Value: &val, + } log.Printf( "[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v", - d.Id(), options) - if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil { + d.Id(), modifyOpts) + if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil { return err } @@ -178,36 +205,40 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { } if d.HasChange("enable_dns_support") { - options := new(ec2.ModifyVpcAttribute) - options.EnableDnsSupport = d.Get("enable_dns_support").(bool) - options.SetEnableDnsSupport = true + val := d.Get("enable_dns_hostnames").(bool) + modifyOpts.EnableDNSSupport = &ec2.AttributeBooleanValue{ + Value: &val, + } log.Printf( "[INFO] Modifying enable_dns_support vpc attribute for %s: %#v", - d.Id(), options) - if _, err := ec2conn.ModifyVpcAttribute(d.Id(), options); err != nil { + d.Id(), modifyOpts) + if err := ec2conn.ModifyVPCAttribute(modifyOpts); err != nil { return err } d.SetPartial("enable_dns_support") } - - if err := setTags(ec2conn, d); err != nil { - return err - } else { - d.SetPartial("tags") - } + //Tagging Support need to be worked on - rmenn + // if err := setTags(ec2conn, d); err != nil { + // return err + // } else { + // d.SetPartial("tags") + // } d.Partial(false) return resourceAwsVpcRead(d, meta) } func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn - + ec2conn := meta.(*AWSClient).awsEc2conn + vpcID := d.Id() + DeleteVpcOpts := &ec2.DeleteVPCRequest{ + VPCID: &vpcID, + } log.Printf("[INFO] Deleting VPC: %s", d.Id()) - if _, err := ec2conn.DeleteVpc(d.Id()); err != nil { - ec2err, ok := err.(*ec2.Error) + if err := ec2conn.DeleteVPC(DeleteVpcOpts); err != nil { + ec2err, ok := err.(*aws.APIError) if ok && ec2err.Code == "InvalidVpcID.NotFound" { return nil } @@ -222,9 +253,12 @@ func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { // a VPC. func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := conn.DescribeVpcs([]string{id}, ec2.NewFilter()) + DescribeVpcOpts := &ec2.DescribeVPCsRequest{ + VPCIDs: []string{id}, + } + resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err != nil { - if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidVpcID.NotFound" { + if ec2err, ok := err.(*aws.APIError); ok && ec2err.Code == "InvalidVpcID.NotFound" { resp = nil } else { log.Printf("Error on VPCStateRefresh: %s", err) @@ -239,37 +273,53 @@ func VPCStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { } vpc := &resp.VPCs[0] - return vpc, vpc.State, nil + return vpc, *vpc.State, nil } } func resourceAwsVpcSetDefaultNetworkAcl(conn *ec2.EC2, d *schema.ResourceData) error { - filter := ec2.NewFilter() - filter.Add("default", "true") - filter.Add("vpc-id", d.Id()) - networkAclResp, err := conn.NetworkAcls(nil, filter) + filter1 := &ec2.Filter{ + Name: aws.String("default"), + Values: []string{("true")}, + } + filter2 := &ec2.Filter{ + Name: aws.String("vpc-id"), + Values: []string{(d.Id())}, + } + DescribeNetworkACLOpts := &ec2.DescribeNetworkACLsRequest{ + Filters: []ec2.Filter{*filter1, *filter2}, + } + networkAclResp, err := conn.DescribeNetworkACLs(DescribeNetworkACLOpts) if err != nil { return err } - if v := networkAclResp.NetworkAcls; len(v) > 0 { - d.Set("default_network_acl_id", v[0].NetworkAclId) + if v := networkAclResp.NetworkACLs; len(v) > 0 { + d.Set("default_network_acl_id", v[0].NetworkACLID) } return nil } func resourceAwsVpcSetDefaultSecurityGroup(conn *ec2.EC2, d *schema.ResourceData) error { - filter := ec2.NewFilter() - filter.Add("group-name", "default") - filter.Add("vpc-id", d.Id()) - securityGroupResp, err := conn.SecurityGroups(nil, filter) + filter1 := &ec2.Filter{ + Name: aws.String("group-name"), + Values: []string{("default")}, + } + filter2 := &ec2.Filter{ + Name: aws.String("vpc-id"), + Values: []string{(d.Id())}, + } + DescribeSgOpts := &ec2.DescribeSecurityGroupsRequest{ + Filters: []ec2.Filter{*filter1, *filter2}, + } + securityGroupResp, err := conn.DescribeSecurityGroups(DescribeSgOpts) if err != nil { return err } - if v := securityGroupResp.Groups; len(v) > 0 { - d.Set("default_security_group_id", v[0].Id) + if v := securityGroupResp.SecurityGroups; len(v) > 0 { + d.Set("default_security_group_id", v[0].GroupID) } return nil diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index b555e0875..7570a1873 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -2,11 +2,11 @@ package aws import ( "fmt" - "testing" - + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" + "testing" ) func TestAccVpc_basic(t *testing.T) { @@ -50,36 +50,36 @@ func TestAccVpc_dedicatedTenancy(t *testing.T) { }) } -func TestAccVpc_tags(t *testing.T) { - var vpc ec2.VPC - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckVpcDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccVpcConfigTags, - Check: resource.ComposeTestCheckFunc( - testAccCheckVpcExists("aws_vpc.foo", &vpc), - testAccCheckVpcCidr(&vpc, "10.1.0.0/16"), - resource.TestCheckResourceAttr( - "aws_vpc.foo", "cidr_block", "10.1.0.0/16"), - testAccCheckTags(&vpc.Tags, "foo", "bar"), - ), - }, - - resource.TestStep{ - Config: testAccVpcConfigTagsUpdate, - Check: resource.ComposeTestCheckFunc( - testAccCheckVpcExists("aws_vpc.foo", &vpc), - testAccCheckTags(&vpc.Tags, "foo", ""), - testAccCheckTags(&vpc.Tags, "bar", "baz"), - ), - }, - }, - }) -} +//func TestAccVpc_tags(t *testing.T) { +// var vpc ec2.VPC +// +// resource.Test(t, resource.TestCase{ +// PreCheck: func() { testAccPreCheck(t) }, +// Providers: testAccProviders, +// CheckDestroy: testAccCheckVpcDestroy, +// Steps: []resource.TestStep{ +// resource.TestStep{ +// Config: testAccVpcConfigTags, +// Check: resource.ComposeTestCheckFunc( +// testAccCheckVpcExists("aws_vpc.foo", &vpc), +// testAccCheckVpcCidr(&vpc, "10.1.0.0/16"), +// resource.TestCheckResourceAttr( +// "aws_vpc.foo", "cidr_block", "10.1.0.0/16"), +// testAccCheckTags(&vpc.Tags, "foo", "bar"), +// ), +// }, +// +// resource.TestStep{ +// Config: testAccVpcConfigTagsUpdate, +// Check: resource.ComposeTestCheckFunc( +// testAccCheckVpcExists("aws_vpc.foo", &vpc), +// testAccCheckTags(&vpc.Tags, "foo", ""), +// testAccCheckTags(&vpc.Tags, "bar", "baz"), +// ), +// }, +// }, +// }) +//} func TestAccVpcUpdate(t *testing.T) { var vpc ec2.VPC @@ -111,7 +111,7 @@ func TestAccVpcUpdate(t *testing.T) { } func testAccCheckVpcDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEc2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_vpc" { @@ -119,7 +119,10 @@ func testAccCheckVpcDestroy(s *terraform.State) error { } // Try to find the VPC - resp, err := conn.DescribeVpcs([]string{rs.Primary.ID}, ec2.NewFilter()) + DescribeVpcOpts := &ec2.DescribeVPCsRequest{ + VPCIDs: []string{rs.Primary.ID}, + } + resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err == nil { if len(resp.VPCs) > 0 { return fmt.Errorf("VPCs still exist.") @@ -129,7 +132,7 @@ func testAccCheckVpcDestroy(s *terraform.State) error { } // Verify the error is what we want - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(*aws.APIError) if !ok { return err } @@ -143,8 +146,9 @@ func testAccCheckVpcDestroy(s *terraform.State) error { func testAccCheckVpcCidr(vpc *ec2.VPC, expected string) resource.TestCheckFunc { return func(s *terraform.State) error { - if vpc.CidrBlock != expected { - return fmt.Errorf("Bad cidr: %s", vpc.CidrBlock) + CIDRBlock := vpc.CIDRBlock + if *CIDRBlock != expected { + return fmt.Errorf("Bad cidr: %s", *vpc.CIDRBlock) } return nil @@ -162,8 +166,11 @@ func testAccCheckVpcExists(n string, vpc *ec2.VPC) resource.TestCheckFunc { return fmt.Errorf("No VPC ID is set") } - conn := testAccProvider.Meta().(*AWSClient).ec2conn - resp, err := conn.DescribeVpcs([]string{rs.Primary.ID}, ec2.NewFilter()) + conn := testAccProvider.Meta().(*AWSClient).awsEc2conn + DescribeVpcOpts := &ec2.DescribeVPCsRequest{ + VPCIDs: []string{rs.Primary.ID}, + } + resp, err := conn.DescribeVPCs(DescribeVpcOpts) if err != nil { return err } From 840e6f4826afd12e0fa7ad41ee6c9cedd1f0726f Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Wed, 4 Mar 2015 18:37:30 +0530 Subject: [PATCH 10/62] Added Tagging --- builtin/providers/aws/resource_aws_vpc.go | 26 ++++---- .../providers/aws/resource_aws_vpc_test.go | 64 +++++++++---------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 4d1d871ba..d1234e637 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -58,13 +58,13 @@ func resourceAwsVpc() *schema.Resource { Computed: true, }, - // "tags": tagsSchema(), + "tags": tagsSchema(), }, } } func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEc2conn + ec2conn := meta.(*AWSClient).awsEC2conn instance_tenancy := "default" if v, ok := d.GetOk("instance_tenancy"); ok { instance_tenancy = v.(string) @@ -110,7 +110,7 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEc2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Refresh the VPC state vpcRaw, _, err := VPCStateRefreshFunc(ec2conn, d.Id())() @@ -127,8 +127,8 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { vpcid := d.Id() d.Set("cidr_block", vpc.CIDRBlock) - // Tags - TBD rmenn - //d.Set("tags", tagsToMap(vpc.Tags)) + // Tags + d.Set("tags", tagsToMapSDK(vpc.Tags)) // Attributes attribute := "enableDnsSupport" @@ -180,7 +180,7 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEc2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Turn on partial mode d.Partial(true) @@ -219,19 +219,19 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { d.SetPartial("enable_dns_support") } - //Tagging Support need to be worked on - rmenn - // if err := setTags(ec2conn, d); err != nil { - // return err - // } else { - // d.SetPartial("tags") - // } + + if err := setTagsSDK(ec2conn, d); err != nil { + return err + } else { + d.SetPartial("tags") + } d.Partial(false) return resourceAwsVpcRead(d, meta) } func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEc2conn + ec2conn := meta.(*AWSClient).awsEC2conn vpcID := d.Id() DeleteVpcOpts := &ec2.DeleteVPCRequest{ VPCID: &vpcID, diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index 7570a1873..7e324a5d9 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -50,36 +50,36 @@ func TestAccVpc_dedicatedTenancy(t *testing.T) { }) } -//func TestAccVpc_tags(t *testing.T) { -// var vpc ec2.VPC -// -// resource.Test(t, resource.TestCase{ -// PreCheck: func() { testAccPreCheck(t) }, -// Providers: testAccProviders, -// CheckDestroy: testAccCheckVpcDestroy, -// Steps: []resource.TestStep{ -// resource.TestStep{ -// Config: testAccVpcConfigTags, -// Check: resource.ComposeTestCheckFunc( -// testAccCheckVpcExists("aws_vpc.foo", &vpc), -// testAccCheckVpcCidr(&vpc, "10.1.0.0/16"), -// resource.TestCheckResourceAttr( -// "aws_vpc.foo", "cidr_block", "10.1.0.0/16"), -// testAccCheckTags(&vpc.Tags, "foo", "bar"), -// ), -// }, -// -// resource.TestStep{ -// Config: testAccVpcConfigTagsUpdate, -// Check: resource.ComposeTestCheckFunc( -// testAccCheckVpcExists("aws_vpc.foo", &vpc), -// testAccCheckTags(&vpc.Tags, "foo", ""), -// testAccCheckTags(&vpc.Tags, "bar", "baz"), -// ), -// }, -// }, -// }) -//} +func TestAccVpc_tags(t *testing.T) { + var vpc ec2.VPC + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpcDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccVpcConfigTags, + Check: resource.ComposeTestCheckFunc( + testAccCheckVpcExists("aws_vpc.foo", &vpc), + testAccCheckVpcCidr(&vpc, "10.1.0.0/16"), + resource.TestCheckResourceAttr( + "aws_vpc.foo", "cidr_block", "10.1.0.0/16"), + testAccCheckTagsSDK(&vpc.Tags, "foo", "bar"), + ), + }, + + resource.TestStep{ + Config: testAccVpcConfigTagsUpdate, + Check: resource.ComposeTestCheckFunc( + testAccCheckVpcExists("aws_vpc.foo", &vpc), + testAccCheckTagsSDK(&vpc.Tags, "foo", ""), + testAccCheckTagsSDK(&vpc.Tags, "bar", "baz"), + ), + }, + }, + }) +} func TestAccVpcUpdate(t *testing.T) { var vpc ec2.VPC @@ -111,7 +111,7 @@ func TestAccVpcUpdate(t *testing.T) { } func testAccCheckVpcDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEc2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_vpc" { @@ -166,7 +166,7 @@ func testAccCheckVpcExists(n string, vpc *ec2.VPC) resource.TestCheckFunc { return fmt.Errorf("No VPC ID is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEc2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn DescribeVpcOpts := &ec2.DescribeVPCsRequest{ VPCIDs: []string{rs.Primary.ID}, } From b6f89d3e328ef56a4cdf507909d5c85389a56663 Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Wed, 4 Mar 2015 18:51:07 +0100 Subject: [PATCH 11/62] Adding a few new resources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests and docs will be added tomorrow so we can merge the new resources… --- builtin/providers/cloudstack/provider.go | 25 ++- .../resource_cloudstack_vpn_connection.go | 95 +++++++++ ...esource_cloudstack_vpn_customer_gateway.go | 193 ++++++++++++++++++ .../resource_cloudstack_vpn_gateway.go | 97 +++++++++ 4 files changed, 399 insertions(+), 11 deletions(-) create mode 100644 builtin/providers/cloudstack/resource_cloudstack_vpn_connection.go create mode 100644 builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway.go create mode 100644 builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go diff --git a/builtin/providers/cloudstack/provider.go b/builtin/providers/cloudstack/provider.go index a9913f6e8..f7ce62725 100644 --- a/builtin/providers/cloudstack/provider.go +++ b/builtin/providers/cloudstack/provider.go @@ -35,17 +35,20 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "cloudstack_disk": resourceCloudStackDisk(), - "cloudstack_egress_firewall": resourceCloudStackEgressFirewall(), - "cloudstack_firewall": resourceCloudStackFirewall(), - "cloudstack_instance": resourceCloudStackInstance(), - "cloudstack_ipaddress": resourceCloudStackIPAddress(), - "cloudstack_network": resourceCloudStackNetwork(), - "cloudstack_network_acl": resourceCloudStackNetworkACL(), - "cloudstack_network_acl_rule": resourceCloudStackNetworkACLRule(), - "cloudstack_nic": resourceCloudStackNIC(), - "cloudstack_port_forward": resourceCloudStackPortForward(), - "cloudstack_vpc": resourceCloudStackVPC(), + "cloudstack_disk": resourceCloudStackDisk(), + "cloudstack_egress_firewall": resourceCloudStackEgressFirewall(), + "cloudstack_firewall": resourceCloudStackFirewall(), + "cloudstack_instance": resourceCloudStackInstance(), + "cloudstack_ipaddress": resourceCloudStackIPAddress(), + "cloudstack_network": resourceCloudStackNetwork(), + "cloudstack_network_acl": resourceCloudStackNetworkACL(), + "cloudstack_network_acl_rule": resourceCloudStackNetworkACLRule(), + "cloudstack_nic": resourceCloudStackNIC(), + "cloudstack_port_forward": resourceCloudStackPortForward(), + "cloudstack_vpc": resourceCloudStackVPC(), + "cloudstack_vpn_connection": resourceCloudStackVPNConnection(), + "cloudstack_vpn_customer_gateway": resourceCloudStackVPNCustomerGateway(), + "cloudstack_vpn_gateway": resourceCloudStackVPNGateway(), }, ConfigureFunc: providerConfigure, diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_connection.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_connection.go new file mode 100644 index 000000000..b036890a5 --- /dev/null +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_connection.go @@ -0,0 +1,95 @@ +package cloudstack + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +func resourceCloudStackVPNConnection() *schema.Resource { + return &schema.Resource{ + Create: resourceCloudStackVPNConnectionCreate, + Read: resourceCloudStackVPNConnectionRead, + Delete: resourceCloudStackVPNConnectionDelete, + + Schema: map[string]*schema.Schema{ + "customergatewayid": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "vpngatewayid": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func resourceCloudStackVPNConnectionCreate(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Create a new parameter struct + p := cs.VPN.NewCreateVpnConnectionParams( + d.Get("customergatewayid").(string), + d.Get("vpngatewayid").(string), + ) + + // Create the new VPN Connection + v, err := cs.VPN.CreateVpnConnection(p) + if err != nil { + return fmt.Errorf("Error creating VPN Connection: %s", err) + } + + d.SetId(v.Id) + + return resourceCloudStackVPNConnectionRead(d, meta) +} + +func resourceCloudStackVPNConnectionRead(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Get the VPN Connection details + v, count, err := cs.VPN.GetVpnConnectionByID(d.Id()) + if err != nil { + if count == 0 { + log.Printf("[DEBUG] VPN Connection does no longer exist") + d.SetId("") + return nil + } + + return err + } + + d.Set("customergatewayid", v.S2scustomergatewayid) + d.Set("vpngatewayid", v.S2svpngatewayid) + + return nil +} + +func resourceCloudStackVPNConnectionDelete(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Create a new parameter struct + p := cs.VPN.NewDeleteVpnConnectionParams(d.Id()) + + // Delete the VPN Connection + _, err := cs.VPN.DeleteVpnConnection(p) + if err != nil { + // This is a very poor way to be told the UUID does no longer exist :( + if strings.Contains(err.Error(), fmt.Sprintf( + "Invalid parameter id value=%s due to incorrect long value format, "+ + "or entity does not exist", d.Id())) { + return nil + } + + return fmt.Errorf("Error deleting VPN Connection: %s", err) + } + + return nil +} diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway.go new file mode 100644 index 000000000..90a03aeb0 --- /dev/null +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway.go @@ -0,0 +1,193 @@ +package cloudstack + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +func resourceCloudStackVPNCustomerGateway() *schema.Resource { + return &schema.Resource{ + Create: resourceCloudStackVPNCustomerGatewayCreate, + Read: resourceCloudStackVPNCustomerGatewayRead, + Update: resourceCloudStackVPNCustomerGatewayUpdate, + Delete: resourceCloudStackVPNCustomerGatewayDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "cidr": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "esp_policy": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "gateway": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "ike_policy": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "ipsec_psk": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + + "dpd": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + + "esp_lifetime": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + + "ike_lifetime": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + }, + } +} + +func resourceCloudStackVPNCustomerGatewayCreate(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Create a new parameter struct + p := cs.VPN.NewCreateVpnCustomerGatewayParams( + d.Get("cidr").(string), + d.Get("esp_policy").(string), + d.Get("gateway").(string), + d.Get("ike_policy").(string), + d.Get("ipsec_psk").(string), + ) + + p.SetName(d.Get("name").(string)) + + if dpd, ok := d.GetOk("dpd"); ok { + p.SetDpd(dpd.(bool)) + } + + if esplifetime, ok := d.GetOk("esp_lifetime"); ok { + p.SetEsplifetime(esplifetime.(int)) + } + + if ikelifetime, ok := d.GetOk("ike_lifetime"); ok { + p.SetIkelifetime(ikelifetime.(int)) + } + + // Create the new VPN Customer Gateway + v, err := cs.VPN.CreateVpnCustomerGateway(p) + if err != nil { + return fmt.Errorf("Error creating VPN Customer Gateway %s: %s", d.Get("name").(string), err) + } + + d.SetId(v.Id) + + return resourceCloudStackVPNCustomerGatewayRead(d, meta) +} + +func resourceCloudStackVPNCustomerGatewayRead(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Get the VPN Customer Gateway details + v, count, err := cs.VPN.GetVpnCustomerGatewayByID(d.Id()) + if err != nil { + if count == 0 { + log.Printf( + "[DEBUG] VPN Customer Gateway %s does no longer exist", d.Get("name").(string)) + d.SetId("") + return nil + } + + return err + } + + d.Set("name", v.Name) + d.Set("cidr", v.Cidrlist) + d.Set("esp_policy", v.Esppolicy) + d.Set("gateway", v.Gateway) + d.Set("ike_policy", v.Ikepolicy) + d.Set("ipsec_psk", v.Ipsecpsk) + d.Set("dpd", v.Dpd) + d.Set("esp_lifetime", v.Esplifetime) + d.Set("ike_lifetime", v.Ikelifetime) + + return nil +} + +func resourceCloudStackVPNCustomerGatewayUpdate(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Create a new parameter struct + p := cs.VPN.NewUpdateVpnCustomerGatewayParams( + d.Get("cidr").(string), + d.Get("esp_policy").(string), + d.Get("gateway").(string), + d.Id(), + d.Get("ike_policy").(string), + d.Get("ipsec_psk").(string), + ) + + p.SetName(d.Get("name").(string)) + + if dpd, ok := d.GetOk("dpd"); ok { + p.SetDpd(dpd.(bool)) + } + + if esplifetime, ok := d.GetOk("esp_lifetime"); ok { + p.SetEsplifetime(esplifetime.(int)) + } + + if ikelifetime, ok := d.GetOk("ike_lifetime"); ok { + p.SetIkelifetime(ikelifetime.(int)) + } + + // Update the VPN Customer Gateway + _, err := cs.VPN.UpdateVpnCustomerGateway(p) + if err != nil { + return fmt.Errorf("Error updating VPN Customer Gateway %s: %s", d.Get("name").(string), err) + } + + return resourceCloudStackVPNCustomerGatewayRead(d, meta) +} + +func resourceCloudStackVPNCustomerGatewayDelete(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Create a new parameter struct + p := cs.VPN.NewDeleteVpnCustomerGatewayParams(d.Id()) + + // Delete the VPN Customer Gateway + _, err := cs.VPN.DeleteVpnCustomerGateway(p) + if err != nil { + // This is a very poor way to be told the UUID does no longer exist :( + if strings.Contains(err.Error(), fmt.Sprintf( + "Invalid parameter id value=%s due to incorrect long value format, "+ + "or entity does not exist", d.Id())) { + return nil + } + + return fmt.Errorf("Error deleting VPN Customer Gateway %s: %s", d.Get("name").(string), err) + } + + return nil +} diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go new file mode 100644 index 000000000..650df6530 --- /dev/null +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go @@ -0,0 +1,97 @@ +package cloudstack + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +func resourceCloudStackVPNGateway() *schema.Resource { + return &schema.Resource{ + Create: resourceCloudStackVPNGatewayCreate, + Read: resourceCloudStackVPNGatewayRead, + Delete: resourceCloudStackVPNGatewayDelete, + + Schema: map[string]*schema.Schema{ + "vpc": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "publicip": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceCloudStackVPNGatewayCreate(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Retrieve the VPC UUID + vpcid, e := retrieveUUID(cs, "vpc", d.Get("vpc").(string)) + if e != nil { + return e.Error() + } + + // Create a new parameter struct + p := cs.VPN.NewCreateVpnGatewayParams(vpcid) + + // Create the new VPN Gateway + v, err := cs.VPN.CreateVpnGateway(p) + if err != nil { + return fmt.Errorf("Error creating VPN Gateway for VPC %s: %s", d.Get("vpc").(string), err) + } + + d.SetId(v.Id) + + return resourceCloudStackVPNGatewayRead(d, meta) +} + +func resourceCloudStackVPNGatewayRead(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Get the VPN Gateway details + v, count, err := cs.VPN.GetVpnGatewayByID(d.Id()) + if err != nil { + if count == 0 { + log.Printf( + "[DEBUG] VPN Gateway for VPC %s does no longer exist", d.Get("vpc").(string)) + d.SetId("") + return nil + } + + return err + } + + d.Set("publicip", v.Publicip) + + return nil +} + +func resourceCloudStackVPNGatewayDelete(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Create a new parameter struct + p := cs.VPN.NewDeleteVpnGatewayParams(d.Id()) + + // Delete the VPN Gateway + _, err := cs.VPN.DeleteVpnGateway(p) + if err != nil { + // This is a very poor way to be told the UUID does no longer exist :( + if strings.Contains(err.Error(), fmt.Sprintf( + "Invalid parameter id value=%s due to incorrect long value format, "+ + "or entity does not exist", d.Id())) { + return nil + } + + return fmt.Errorf("Error deleting VPN Gateway for VPC %s: %s", d.Get("vpc").(string), err) + } + + return nil +} From bc1baa871219dcfb244d529b6bb22f055d45c7a5 Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Thu, 5 Mar 2015 19:04:52 -0600 Subject: [PATCH 12/62] providers/aws: final_snapshot_id isn't ForceNew Removing `ForceNew` from `final_snapshot_identifier` - it's a parameter that's _only_ passed during the DeleteDBInstance API call, so it's perfectly valid to change the attribute for an existing DB Instance. fixes #1138 --- builtin/providers/aws/resource_aws_db_instance.go | 1 - 1 file changed, 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_db_instance.go b/builtin/providers/aws/resource_aws_db_instance.go index b57dc13f3..e99744a0f 100644 --- a/builtin/providers/aws/resource_aws_db_instance.go +++ b/builtin/providers/aws/resource_aws_db_instance.go @@ -156,7 +156,6 @@ func resourceAwsDbInstance() *schema.Resource { "final_snapshot_identifier": &schema.Schema{ Type: schema.TypeString, Optional: true, - ForceNew: true, }, "db_subnet_group_name": &schema.Schema{ From c87ac6df04684f3737a4192c50b8669e6d521bdd Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Fri, 6 Mar 2015 13:06:57 +0000 Subject: [PATCH 13/62] Replace git:// with https:// in middleman source --- website/Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/Gemfile b/website/Gemfile index 936305b5e..850fc4b6c 100644 --- a/website/Gemfile +++ b/website/Gemfile @@ -1,3 +1,3 @@ source 'https://rubygems.org' -gem 'middleman-hashicorp', github: 'hashicorp/middleman-hashicorp' +gem 'middleman-hashicorp', git: 'https://github.com/hashicorp/middleman-hashicorp' From 30707dbd0514e9a2d9d0c85a1fb7ad3d6602acef Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Fri, 6 Mar 2015 13:07:59 +0000 Subject: [PATCH 14/62] Locked dependencies updated to latest versions --- website/Gemfile.lock | 50 ++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/website/Gemfile.lock b/website/Gemfile.lock index e956a6aa6..a55579e6d 100644 --- a/website/Gemfile.lock +++ b/website/Gemfile.lock @@ -1,19 +1,19 @@ GIT - remote: git://github.com/hashicorp/middleman-hashicorp.git - revision: 30c15f93fb501041cff97c490b60ddc96c8314c9 + remote: https://github.com/hashicorp/middleman-hashicorp + revision: 783fe9517dd02badb85e5ddfeda4d8e35bbd05a8 specs: middleman-hashicorp (0.1.0) - bootstrap-sass (~> 3.2) + bootstrap-sass (~> 3.3) builder (~> 3.2) less (~> 2.6) middleman (~> 3.3) - middleman-livereload (~> 3.3) + middleman-livereload (~> 3.4) middleman-minify-html (~> 3.4) middleman-syntax (~> 2.0) - rack-contrib (~> 1.1) + rack-contrib (~> 1.2) rack-rewrite (~> 1.5) rack-ssl-enforcer (~> 0.2) - redcarpet (~> 3.1) + redcarpet (~> 3.2) therubyracer (~> 0.12) thin (~> 1.6) @@ -26,7 +26,7 @@ GEM minitest (~> 5.1) thread_safe (~> 0.1) tzinfo (~> 1.1) - autoprefixer-rails (5.0.0.2) + autoprefixer-rails (5.1.7) execjs json bootstrap-sass (3.3.3) @@ -35,11 +35,11 @@ GEM builder (3.2.2) celluloid (0.16.0) timers (~> 4.0.0) - chunky_png (1.3.3) + chunky_png (1.3.4) coffee-script (2.3.0) coffee-script-source execjs - coffee-script-source (1.8.0) + coffee-script-source (1.9.1) commonjs (0.2.7) compass (1.0.3) chunky_png (~> 1.2) @@ -58,8 +58,8 @@ GEM eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) erubis (2.7.0) - eventmachine (1.0.4) - execjs (2.2.2) + eventmachine (1.0.7) + execjs (2.4.0) ffi (1.9.6) haml (4.0.6) tilt @@ -69,9 +69,9 @@ GEM uber (~> 0.0.4) htmlcompressor (0.1.2) http_parser.rb (0.6.0) - i18n (0.6.11) + i18n (0.7.0) json (1.8.2) - kramdown (1.5.0) + kramdown (1.6.0) less (2.6.0) commonjs (~> 0.2.7) libv8 (3.16.14.7) @@ -79,23 +79,23 @@ GEM celluloid (>= 0.15.2) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) - middleman (3.3.7) + middleman (3.3.10) coffee-script (~> 2.2) compass (>= 1.0.0, < 2.0.0) compass-import-once (= 1.0.5) execjs (~> 2.0) haml (>= 4.0.5) kramdown (~> 1.2) - middleman-core (= 3.3.7) + middleman-core (= 3.3.10) middleman-sprockets (>= 3.1.2) sass (>= 3.4.0, < 4.0) uglifier (~> 2.5) - middleman-core (3.3.7) + middleman-core (3.3.10) activesupport (~> 4.1.0) bundler (~> 1.1) erubis hooks (~> 0.3) - i18n (~> 0.6.9) + i18n (~> 0.7.0) listen (>= 2.7.9, < 3.0) padrino-helpers (~> 0.12.3) rack (>= 1.4.5, < 2.0) @@ -109,7 +109,7 @@ GEM middleman-minify-html (3.4.0) htmlcompressor (~> 0.1.0) middleman-core (>= 3.2) - middleman-sprockets (3.4.1) + middleman-sprockets (3.4.2) middleman-core (>= 3.3) sprockets (~> 2.12.1) sprockets-helpers (~> 1.1.0) @@ -118,12 +118,12 @@ GEM middleman-core (~> 3.2) rouge (~> 1.0) minitest (5.5.1) - multi_json (1.10.1) - padrino-helpers (0.12.4) + multi_json (1.11.0) + padrino-helpers (0.12.5) i18n (~> 0.6, >= 0.6.7) - padrino-support (= 0.12.4) + padrino-support (= 0.12.5) tilt (~> 1.4.1) - padrino-support (0.12.4) + padrino-support (0.12.5) activesupport (>= 3.1) rack (1.6.0) rack-contrib (1.2.0) @@ -139,8 +139,8 @@ GEM ffi (>= 0.5.0) redcarpet (3.2.2) ref (1.0.5) - rouge (1.7.7) - sass (3.4.10) + rouge (1.8.0) + sass (3.4.13) sprockets (2.12.3) hike (~> 1.2) multi_json (~> 1.0) @@ -166,7 +166,7 @@ GEM tzinfo (1.2.2) thread_safe (~> 0.1) uber (0.0.13) - uglifier (2.7.0) + uglifier (2.7.1) execjs (>= 0.3.0) json (>= 1.8.0) From 996e7ff3e447503e0f7cb929a65bb93a5608a8d4 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Fri, 6 Mar 2015 17:05:00 +0000 Subject: [PATCH 15/62] Add quickdev option; skips getting dependencies to make repeated builds a bit faster and less network-heavy --- Makefile | 3 +++ scripts/build.sh | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index fdb9ab3d6..21a54a8f8 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,9 @@ bin: generate dev: generate @TF_DEV=1 sh -c "'$(CURDIR)/scripts/build.sh'" +quickdev: generate + @TF_QUICKDEV=1 TF_DEV=1 sh -c "'$(CURDIR)/scripts/build.sh'" + # test runs the unit tests and vets the code test: generate TF_ACC= go test $(TEST) $(TESTARGS) -timeout=30s -parallel=4 diff --git a/scripts/build.sh b/scripts/build.sh index bf6074068..4433d8f9b 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -19,9 +19,11 @@ GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true) XC_ARCH=${XC_ARCH:-"386 amd64 arm"} XC_OS=${XC_OS:-linux darwin windows freebsd openbsd} -# Install dependencies -echo "==> Getting dependencies..." -go get ./... +# Install dependencies unless running in quick mode +if [ "${TF_QUICKDEV}x" == "x" ]; then + echo "==> Getting dependencies..." + go get ./... +fi # Delete the old dir echo "==> Removing old directory..." From 26cc99bf3ff8230bed20e1f4ea46a7164c4f42f9 Mon Sep 17 00:00:00 2001 From: Jack Pearkes Date: Fri, 6 Mar 2015 10:00:41 -0800 Subject: [PATCH 16/62] website: add digitalocean ssh_key documentation cc/ @plalloni --- .../docs/providers/do/r/ssh_key.html.markdown | 41 +++++++++++++++++++ website/source/layouts/digitalocean.erb | 4 ++ 2 files changed, 45 insertions(+) create mode 100644 website/source/docs/providers/do/r/ssh_key.html.markdown diff --git a/website/source/docs/providers/do/r/ssh_key.html.markdown b/website/source/docs/providers/do/r/ssh_key.html.markdown new file mode 100644 index 000000000..7a8033519 --- /dev/null +++ b/website/source/docs/providers/do/r/ssh_key.html.markdown @@ -0,0 +1,41 @@ +--- +layout: "digitalocean" +page_title: "DigitalOcean: digitalocean_ssh_key" +sidebar_current: "docs-do-resource-ssh-key" +description: |- + Provides a DigitalOcean SSH key resource. +--- + +# digitalocean\_ssh_key + +Provides a DigitalOcean SSH key resource to allow you manage SSH +keys for Droplet access. Keys created with this resource +can be referenced in your droplet configuration via their ID or +fingerprint. + +## Example Usage + +``` +# Create a new SSH key +resource "digitalocean_ssh_key" "default" { + name = "Terraform Example" + public_key = "${file("/Users/terraform/.ssh/id_rsa.pub")}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the SSH key for identification +* `public_key` - (Required) The public key. If this is a file, it +can be read using the file interpolation function + +## Attributes Reference + +The following attributes are exported: + +* `id` - The unique ID of the key +* `name` - The name of the SSH key +* `public_key` - The text of the public key +* `fingerprint` - The fingerprint of the SSH key diff --git a/website/source/layouts/digitalocean.erb b/website/source/layouts/digitalocean.erb index cfffcd85f..c67d6395b 100644 --- a/website/source/layouts/digitalocean.erb +++ b/website/source/layouts/digitalocean.erb @@ -23,6 +23,10 @@ > digitalocean_record + + + > + digitalocean_ssh_key From 09bf26e84414939e409369999c33b181979bab34 Mon Sep 17 00:00:00 2001 From: Jack Pearkes Date: Fri, 6 Mar 2015 10:02:09 -0800 Subject: [PATCH 17/62] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cc6c6e60..679369ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,7 @@ IMPROVEMENTS: * **New resource: `aws_main_route_table_association`** - Manage the main routing table of a VPC. [GH-918] * **New resource: `aws_vpc_peering_connection`** [GH-963] + * **New resource: `digitalocean_ssh_key`** [GH-1074] * core: Formalized the syntax of interpolations and documented it very heavily. * core: Strings in interpolations can now contain further interpolations, From a090aac755791b49d1196fc85cd17b5bc58d9a5e Mon Sep 17 00:00:00 2001 From: Jack Pearkes Date: Fri, 6 Mar 2015 10:03:30 -0800 Subject: [PATCH 18/62] update changelog (fix previous) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 679369ea7..e5000e028 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ IMPROVEMENTS: info. [GH-1029] * **New config function: `split`** - Split a value based on a delimiter. This is useful for faking lists as parameters to modules. + * **New resource: `digitalocean_ssh_key`** [GH-1074] * core: The serial of the state is only updated if there is an actual change. This will lower the amount of state changing on things like refresh. @@ -68,7 +69,6 @@ IMPROVEMENTS: * **New resource: `aws_main_route_table_association`** - Manage the main routing table of a VPC. [GH-918] * **New resource: `aws_vpc_peering_connection`** [GH-963] - * **New resource: `digitalocean_ssh_key`** [GH-1074] * core: Formalized the syntax of interpolations and documented it very heavily. * core: Strings in interpolations can now contain further interpolations, From 94d30aa70ad53021e9d270ad46e0a7c29f132f32 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 5 Mar 2015 09:45:39 -0600 Subject: [PATCH 19/62] provider/aws: Convert aws instance test to aws-sdk convert AWS Instance and Test file to use aws-sdk-go --- .../providers/aws/resource_aws_instance.go | 253 +++++++++++------- .../aws/resource_aws_instance_test.go | 57 ++-- 2 files changed, 191 insertions(+), 119 deletions(-) diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index ee62d305e..54584402f 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -6,14 +6,14 @@ import ( "encoding/hex" "fmt" "log" - "strconv" "strings" "time" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsInstance() *schema.Resource { @@ -253,7 +253,7 @@ func resourceAwsInstance() *schema.Resource { } func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Figure out user data userData := "" @@ -261,38 +261,87 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { userData = v.(string) } + placement := &ec2.Placement{ + AvailabilityZone: aws.String(d.Get("availability_zone").(string)), + Tenancy: aws.String(d.Get("tenancy").(string)), + } + + iam := &ec2.IAMInstanceProfileSpecification{ + Name: aws.String(d.Get("iam_instance_profile").(string)), + } + + // Build the creation struct + runOpts := &ec2.RunInstancesRequest{ + ImageID: aws.String(d.Get("ami").(string)), + Placement: placement, + InstanceType: aws.String(d.Get("instance_type").(string)), + MaxCount: aws.Integer(1), + MinCount: aws.Integer(1), + UserData: aws.String(userData), + EBSOptimized: aws.Boolean(d.Get("ebs_optimized").(bool)), + IAMInstanceProfile: iam, + } + associatePublicIPAddress := false if v := d.Get("associate_public_ip_address"); v != nil { associatePublicIPAddress = v.(bool) } - // Build the creation struct - runOpts := &ec2.RunInstances{ - ImageId: d.Get("ami").(string), - AvailZone: d.Get("availability_zone").(string), - InstanceType: d.Get("instance_type").(string), - KeyName: d.Get("key_name").(string), - SubnetId: d.Get("subnet_id").(string), - PrivateIPAddress: d.Get("private_ip").(string), - AssociatePublicIpAddress: associatePublicIPAddress, - UserData: []byte(userData), - EbsOptimized: d.Get("ebs_optimized").(bool), - IamInstanceProfile: d.Get("iam_instance_profile").(string), - Tenancy: d.Get("tenancy").(string), + // check for non-default Subnet + subnet := false + var subnetID string + if v, ok := d.GetOk("subnet_id"); ok { + subnet = true + subnetID = v.(string) + } + + if subnet && associatePublicIPAddress { + // If we have a non-default VPC / Subnet specified, we can flag + // AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided. + // You cannot specify both SubnetId and the NetworkInterface.0.* parameters though, otherwise + // you get: Network interfaces and an instance-level subnet ID may not be specified on the same request + // You also need to attach Security Groups to the NetworkInterface instead of the instance, + // to avoid: Network interfaces and an instance-level security groups may not be specified on + // the same request + ni := ec2.InstanceNetworkInterfaceSpecification{ + AssociatePublicIPAddress: aws.Boolean(associatePublicIPAddress), + DeviceIndex: aws.Integer(0), + SubnetID: aws.String(subnetID), + } + + if v, ok := d.GetOk("private_ip"); ok { + ni.PrivateIPAddress = aws.String(v.(string)) + } + + runOpts.NetworkInterfaces = []ec2.InstanceNetworkInterfaceSpecification{ni} + } else { + if subnetID != "" { + runOpts.SubnetID = aws.String(subnetID) + } + + if v, ok := d.GetOk("private_ip"); ok { + runOpts.PrivateIPAddress = aws.String(v.(string)) + } + } + + if v, ok := d.GetOk("key_name"); ok { + runOpts.KeyName = aws.String(v.(string)) } if v := d.Get("security_groups"); v != nil { + // Security group names. + // For a nondefault VPC, you must use security group IDs instead. + // See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html + var groups []string for _, v := range v.(*schema.Set).List() { str := v.(string) - - var g ec2.SecurityGroup - if runOpts.SubnetId != "" { - g.Id = str - } else { - g.Name = str - } - - runOpts.SecurityGroups = append(runOpts.SecurityGroups, g) + groups = append(groups, str) + } + if runOpts.SubnetID != nil && + *runOpts.SubnetID != "" { + runOpts.SecurityGroupIDs = groups + } else { + runOpts.SecurityGroups = groups } } @@ -311,24 +360,27 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { } if len(blockDevices) > 0 { - runOpts.BlockDevices = make([]ec2.BlockDeviceMapping, len(blockDevices)) + runOpts.BlockDeviceMappings = make([]ec2.BlockDeviceMapping, len(blockDevices)) for i, v := range blockDevices { bd := v.(map[string]interface{}) - runOpts.BlockDevices[i].DeviceName = bd["device_name"].(string) - runOpts.BlockDevices[i].VolumeType = bd["volume_type"].(string) - runOpts.BlockDevices[i].VolumeSize = int64(bd["volume_size"].(int)) - runOpts.BlockDevices[i].DeleteOnTermination = bd["delete_on_termination"].(bool) - if v, ok := bd["virtual_name"].(string); ok { - runOpts.BlockDevices[i].VirtualName = v + runOpts.BlockDeviceMappings[i].DeviceName = aws.String(bd["device_name"].(string)) + runOpts.BlockDeviceMappings[i].EBS = &ec2.EBSBlockDevice{ + VolumeType: aws.String(bd["volume_type"].(string)), + VolumeSize: aws.Integer(bd["volume_size"].(int)), + DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)), } - if v, ok := bd["snapshot_id"].(string); ok { - runOpts.BlockDevices[i].SnapshotId = v + + if v, ok := bd["virtual_name"].(string); ok { + runOpts.BlockDeviceMappings[i].VirtualName = aws.String(v) + } + if v, ok := bd["snapshot_id"].(string); ok && v != "" { + runOpts.BlockDeviceMappings[i].EBS.SnapshotID = aws.String(v) } if v, ok := bd["encrypted"].(bool); ok { - runOpts.BlockDevices[i].Encrypted = v + runOpts.BlockDeviceMappings[i].EBS.Encrypted = aws.Boolean(v) } - if v, ok := bd["iops"].(int); ok { - runOpts.BlockDevices[i].IOPS = int64(v) + if v, ok := bd["iops"].(int); ok && v > 0 { + runOpts.BlockDeviceMappings[i].EBS.IOPS = aws.Integer(v) } } } @@ -341,21 +393,21 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { } instance := &runResp.Instances[0] - log.Printf("[INFO] Instance ID: %s", instance.InstanceId) + log.Printf("[INFO] Instance ID: %s", *instance.InstanceID) // Store the resulting ID so we can look this up later - d.SetId(instance.InstanceId) + d.SetId(*instance.InstanceID) // Wait for the instance to become running so we can get some attributes // that aren't available until later. log.Printf( "[DEBUG] Waiting for instance (%s) to become running", - instance.InstanceId) + *instance.InstanceID) stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, Target: "running", - Refresh: InstanceStateRefreshFunc(ec2conn, instance.InstanceId), + Refresh: InstanceStateRefreshFunc(ec2conn, *instance.InstanceID), Timeout: 10 * time.Minute, Delay: 10 * time.Second, MinTimeout: 3 * time.Second, @@ -365,16 +417,18 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { if err != nil { return fmt.Errorf( "Error waiting for instance (%s) to become ready: %s", - instance.InstanceId, err) + *instance.InstanceID, err) } instance = instanceRaw.(*ec2.Instance) // Initialize the connection info - d.SetConnInfo(map[string]string{ - "type": "ssh", - "host": instance.PublicIpAddress, - }) + if instance.PublicIPAddress != nil { + d.SetConnInfo(map[string]string{ + "type": "ssh", + "host": *instance.PublicIPAddress, + }) + } // Set our attributes if err := resourceAwsInstanceRead(d, meta); err != nil { @@ -386,13 +440,15 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn - resp, err := ec2conn.Instances([]string{d.Id()}, ec2.NewFilter()) + resp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesRequest{ + InstanceIDs: []string{d.Id()}, + }) if err != nil { // If the instance was not found, return nil so that we can show // that the instance is gone. - if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" { + if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidInstanceID.NotFound" { d.SetId("") return nil } @@ -410,28 +466,33 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { instance := &resp.Reservations[0].Instances[0] // If the instance is terminated, then it is gone - if instance.State.Name == "terminated" { + if *instance.State.Name == "terminated" { d.SetId("") return nil } - d.Set("availability_zone", instance.AvailZone) + d.Set("availability_zone", instance.Placement.AvailabilityZone) d.Set("key_name", instance.KeyName) - d.Set("public_dns", instance.DNSName) - d.Set("public_ip", instance.PublicIpAddress) + d.Set("public_dns", instance.PublicDNSName) + d.Set("public_ip", instance.PublicIPAddress) d.Set("private_dns", instance.PrivateDNSName) - d.Set("private_ip", instance.PrivateIpAddress) - d.Set("subnet_id", instance.SubnetId) - d.Set("ebs_optimized", instance.EbsOptimized) - d.Set("tags", tagsToMap(instance.Tags)) - d.Set("tenancy", instance.Tenancy) + d.Set("private_ip", instance.PrivateIPAddress) + d.Set("subnet_id", instance.SubnetID) + if len(instance.NetworkInterfaces) > 0 { + d.Set("subnet_id", instance.NetworkInterfaces[0].SubnetID) + } else { + d.Set("subnet_id", instance.SubnetID) + } + d.Set("ebs_optimized", instance.EBSOptimized) + d.Set("tags", tagsToMapSDK(instance.Tags)) + d.Set("tenancy", instance.Placement.Tenancy) // Determine whether we're referring to security groups with // IDs or names. We use a heuristic to figure this out. By default, // we use IDs if we're in a VPC. However, if we previously had an // all-name list of security groups, we use names. Or, if we had any // IDs, we use IDs. - useID := instance.SubnetId != "" + useID := *instance.SubnetID != "" if v := d.Get("security_groups"); v != nil { match := false for _, v := range v.(*schema.Set).List() { @@ -448,24 +509,26 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { sgs := make([]string, len(instance.SecurityGroups)) for i, sg := range instance.SecurityGroups { if useID { - sgs[i] = sg.Id + sgs[i] = *sg.GroupID } else { - sgs[i] = sg.Name + sgs[i] = *sg.GroupName } } d.Set("security_groups", sgs) - blockDevices := make(map[string]ec2.BlockDevice) - for _, bd := range instance.BlockDevices { - blockDevices[bd.VolumeId] = bd + blockDevices := make(map[string]ec2.InstanceBlockDeviceMapping) + for _, bd := range instance.BlockDeviceMappings { + blockDevices[*bd.EBS.VolumeID] = bd } volIDs := make([]string, 0, len(blockDevices)) - for volID := range blockDevices { - volIDs = append(volIDs, volID) + for _, vol := range blockDevices { + volIDs = append(volIDs, *vol.EBS.VolumeID) } - volResp, err := ec2conn.Volumes(volIDs, ec2.NewFilter()) + volResp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesRequest{ + VolumeIDs: volIDs, + }) if err != nil { return err } @@ -473,28 +536,25 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { nonRootBlockDevices := make([]map[string]interface{}, 0) rootBlockDevice := make([]interface{}, 0, 1) for _, vol := range volResp.Volumes { - volSize, err := strconv.Atoi(vol.Size) - if err != nil { - return err - } - blockDevice := make(map[string]interface{}) - blockDevice["device_name"] = blockDevices[vol.VolumeId].DeviceName - blockDevice["volume_type"] = vol.VolumeType - blockDevice["volume_size"] = volSize + blockDevice["device_name"] = *blockDevices[*vol.VolumeID].DeviceName + blockDevice["volume_type"] = *vol.VolumeType + blockDevice["volume_size"] = *vol.Size blockDevice["delete_on_termination"] = - blockDevices[vol.VolumeId].DeleteOnTermination + *blockDevices[*vol.VolumeID].EBS.DeleteOnTermination // If this is the root device, save it. We stop here since we // can't put invalid keys into this map. - if blockDevice["device_name"] == instance.RootDeviceName { + if blockDevice["device_name"] == *instance.RootDeviceName { rootBlockDevice = []interface{}{blockDevice} continue } - blockDevice["snapshot_id"] = vol.SnapshotId - blockDevice["encrypted"] = vol.Encrypted - blockDevice["iops"] = vol.IOPS + blockDevice["snapshot_id"] = *vol.SnapshotID + blockDevice["encrypted"] = *vol.Encrypted + if vol.IOPS != nil { + blockDevice["iops"] = *vol.IOPS + } nonRootBlockDevices = append(nonRootBlockDevices, blockDevice) } d.Set("block_device", nonRootBlockDevices) @@ -504,21 +564,25 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn - opts := new(ec2.ModifyInstance) - - opts.SetSourceDestCheck = true - opts.SourceDestCheck = d.Get("source_dest_check").(bool) + ec2conn := meta.(*AWSClient).awsEC2conn + opts := new(ec2.ModifyInstanceAttributeRequest) log.Printf("[INFO] Modifying instance %s: %#v", d.Id(), opts) - if _, err := ec2conn.ModifyInstance(d.Id(), opts); err != nil { + err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeRequest{ + InstanceID: aws.String(d.Id()), + SourceDestCheck: &ec2.AttributeBooleanValue{ + Value: aws.Boolean(d.Get("source_dest_check").(bool)), + }, + }) + + if err != nil { return err } // TODO(mitchellh): wait for the attributes we modified to // persist the change... - if err := setTags(ec2conn, d); err != nil { + if err := setTagsSDK(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") @@ -528,10 +592,13 @@ func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsInstanceDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn log.Printf("[INFO] Terminating instance: %s", d.Id()) - if _, err := ec2conn.TerminateInstances([]string{d.Id()}); err != nil { + req := &ec2.TerminateInstancesRequest{ + InstanceIDs: []string{d.Id()}, + } + if _, err := ec2conn.TerminateInstances(req); err != nil { return fmt.Errorf("Error terminating instance: %s", err) } @@ -563,9 +630,11 @@ func resourceAwsInstanceDelete(d *schema.ResourceData, meta interface{}) error { // an EC2 instance. func InstanceStateRefreshFunc(conn *ec2.EC2, instanceID string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := conn.Instances([]string{instanceID}, ec2.NewFilter()) + resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{ + InstanceIDs: []string{instanceID}, + }) if err != nil { - if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" { + if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidInstanceID.NotFound" { // Set this to nil as if we didn't find anything. resp = nil } else { @@ -581,7 +650,7 @@ func InstanceStateRefreshFunc(conn *ec2.EC2, instanceID string) resource.StateRe } i := &resp.Reservations[0].Instances[0] - return i, i.State.Name, nil + return i, *i.State.Name, nil } } diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index e25d23542..3a9c16588 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -5,24 +5,25 @@ import ( "reflect" "testing" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" ) func TestAccAWSInstance_normal(t *testing.T) { var v ec2.Instance testCheck := func(*terraform.State) error { - if v.AvailZone != "us-west-2a" { - return fmt.Errorf("bad availability zone: %#v", v.AvailZone) + if *v.Placement.AvailabilityZone != "us-west-2a" { + return fmt.Errorf("bad availability zone: %#v", *v.Placement.AvailabilityZone) } if len(v.SecurityGroups) == 0 { return fmt.Errorf("no security groups: %#v", v.SecurityGroups) } - if v.SecurityGroups[0].Name != "tf_test_foo" { + if *v.SecurityGroups[0].GroupName != "tf_test_foo" { return fmt.Errorf("no security groups: %#v", v.SecurityGroups) } @@ -73,9 +74,9 @@ func TestAccAWSInstance_blockDevices(t *testing.T) { return func(*terraform.State) error { // Map out the block devices by name, which should be unique. - blockDevices := make(map[string]ec2.BlockDevice) - for _, blockDevice := range v.BlockDevices { - blockDevices[blockDevice.DeviceName] = blockDevice + blockDevices := make(map[string]ec2.InstanceBlockDeviceMapping) + for _, blockDevice := range v.BlockDeviceMappings { + blockDevices[*blockDevice.DeviceName] = blockDevice } // Check if the root block device exists. @@ -147,8 +148,8 @@ func TestAccAWSInstance_sourceDestCheck(t *testing.T) { testCheck := func(enabled bool) resource.TestCheckFunc { return func(*terraform.State) error { - if v.SourceDestCheck != enabled { - return fmt.Errorf("bad source_dest_check: %#v", v.SourceDestCheck) + if *v.SourceDestCheck != enabled { + return fmt.Errorf("bad source_dest_check: %#v", *v.SourceDestCheck) } return nil @@ -206,7 +207,7 @@ func TestAccAWSInstance_vpc(t *testing.T) { }) } -func TestAccInstance_tags(t *testing.T) { +func TestAccAWSInstance_tags(t *testing.T) { var v ec2.Instance resource.Test(t, resource.TestCase{ @@ -218,9 +219,9 @@ func TestAccInstance_tags(t *testing.T) { Config: testAccCheckInstanceConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckInstanceExists("aws_instance.foo", &v), - testAccCheckTags(&v.Tags, "foo", "bar"), + testAccCheckTagsSDK(&v.Tags, "foo", "bar"), // Guard against regression of https://github.com/hashicorp/terraform/issues/914 - testAccCheckTags(&v.Tags, "#", ""), + testAccCheckTagsSDK(&v.Tags, "#", ""), ), }, @@ -228,21 +229,21 @@ func TestAccInstance_tags(t *testing.T) { Config: testAccCheckInstanceConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckInstanceExists("aws_instance.foo", &v), - testAccCheckTags(&v.Tags, "foo", ""), - testAccCheckTags(&v.Tags, "bar", "baz"), + testAccCheckTagsSDK(&v.Tags, "foo", ""), + testAccCheckTagsSDK(&v.Tags, "bar", "baz"), ), }, }, }) } -func TestAccInstance_privateIP(t *testing.T) { +func TestAccAWSInstance_privateIP(t *testing.T) { var v ec2.Instance testCheckPrivateIP := func() resource.TestCheckFunc { return func(*terraform.State) error { - if v.PrivateIpAddress != "10.1.1.42" { - return fmt.Errorf("bad private IP: %s", v.PrivateIpAddress) + if *v.PrivateIPAddress != "10.1.1.42" { + return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress) } return nil @@ -265,13 +266,13 @@ func TestAccInstance_privateIP(t *testing.T) { }) } -func TestAccInstance_associatePublicIPAndPrivateIP(t *testing.T) { +func TestAccAWSInstance_associatePublicIPAndPrivateIP(t *testing.T) { var v ec2.Instance testCheckPrivateIP := func() resource.TestCheckFunc { return func(*terraform.State) error { - if v.PrivateIpAddress != "10.1.1.42" { - return fmt.Errorf("bad private IP: %s", v.PrivateIpAddress) + if *v.PrivateIPAddress != "10.1.1.42" { + return fmt.Errorf("bad private IP: %s", *v.PrivateIPAddress) } return nil @@ -295,7 +296,7 @@ func TestAccInstance_associatePublicIPAndPrivateIP(t *testing.T) { } func testAccCheckInstanceDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_instance" { @@ -303,8 +304,9 @@ func testAccCheckInstanceDestroy(s *terraform.State) error { } // Try to find the resource - resp, err := conn.Instances( - []string{rs.Primary.ID}, ec2.NewFilter()) + resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{ + InstanceIDs: []string{rs.Primary.ID}, + }) if err == nil { if len(resp.Reservations) > 0 { return fmt.Errorf("still exist.") @@ -314,7 +316,7 @@ func testAccCheckInstanceDestroy(s *terraform.State) error { } // Verify the error is what we want - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(aws.APIError) if !ok { return err } @@ -337,9 +339,10 @@ func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFun return fmt.Errorf("No ID is set") } - conn := testAccProvider.Meta().(*AWSClient).ec2conn - resp, err := conn.Instances( - []string{rs.Primary.ID}, ec2.NewFilter()) + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{ + InstanceIDs: []string{rs.Primary.ID}, + }) if err != nil { return err } From 3d4b55e557894fdeefd4ecbe577b3194df37b125 Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Thu, 5 Mar 2015 19:04:04 -0600 Subject: [PATCH 20/62] helper/schema: schema versioning & migration Providers get a per-resource SchemaVersion integer that they can bump when a resource's schema changes format. Each InstanceState with an older recorded SchemaVersion than the cureent one is yielded to a `MigrateSchema` function to be transformed such that it can be addressed by the current version of the resource's Schema. --- helper/schema/resource.go | 52 ++++++++ helper/schema/resource_test.go | 216 +++++++++++++++++++++++++++++++++ terraform/state.go | 5 + 3 files changed, 273 insertions(+) diff --git a/helper/schema/resource.go b/helper/schema/resource.go index f0e0515cd..a19912eed 100644 --- a/helper/schema/resource.go +++ b/helper/schema/resource.go @@ -3,6 +3,7 @@ package schema import ( "errors" "fmt" + "strconv" "github.com/hashicorp/terraform/terraform" ) @@ -24,6 +25,31 @@ type Resource struct { // resource. Schema map[string]*Schema + // SchemaVersion is the version number for this resource's Schema + // definition. The current SchemaVersion stored in the state for each + // resource. Provider authors can increment this version number + // when Schema semantics change. If the State's SchemaVersion is less than + // the current SchemaVersion, the InstanceState is yielded to the + // MigrateState callback, where the provider can make whatever changes it + // needs to update the state to be compatible to the latest version of the + // Schema. + // + // When unset, SchemaVersion defaults to 0, so provider authors can start + // their Versioning at any integer >= 1 + SchemaVersion int + + // MigrateState is responsible for updating an InstanceState with an old + // version to the format expected by the current version of the Schema. + // + // It is called during Refresh if the State's stored SchemaVersion is less + // than the current SchemaVersion of the Resource. + // + // The function is yielded the state's stored SchemaVersion and a pointer to + // the InstanceState that needs updating, as well as the configured + // provider's configured meta interface{}, in case the migration process + // needs to make any remote API calls. + MigrateState StateMigrateFunc + // The functions below are the CRUD operations for this resource. // // The only optional operation is Update. If Update is not implemented, @@ -69,6 +95,10 @@ type DeleteFunc func(*ResourceData, interface{}) error // See Resource documentation. type ExistsFunc func(*ResourceData, interface{}) (bool, error) +// See Resource documentation. +type StateMigrateFunc func( + int, *terraform.InstanceState, interface{}) (*terraform.InstanceState, error) + // Apply creates, updates, and/or deletes a resource. func (r *Resource) Apply( s *terraform.InstanceState, @@ -158,6 +188,14 @@ func (r *Resource) Refresh( } } + needsMigration, stateSchemaVersion := r.checkSchemaVersion(s) + if needsMigration && r.MigrateState != nil { + s, err := r.MigrateState(stateSchemaVersion, s, meta) + if err != nil { + return s, err + } + } + data, err := schemaMap(r.Schema).Data(s, nil) if err != nil { return s, err @@ -169,6 +207,13 @@ func (r *Resource) Refresh( state = nil } + if state != nil && r.SchemaVersion > 0 { + if state.Meta == nil { + state.Meta = make(map[string]string) + } + state.Meta["schema_version"] = strconv.Itoa(r.SchemaVersion) + } + return state, err } @@ -189,3 +234,10 @@ func (r *Resource) InternalValidate() error { return schemaMap(r.Schema).InternalValidate() } + +// Determines if a given InstanceState needs to be migrated by checking the +// stored version number with the current SchemaVersion +func (r *Resource) checkSchemaVersion(is *terraform.InstanceState) (bool, int) { + stateSchemaVersion, _ := strconv.Atoi(is.Meta["schema_version"]) + return stateSchemaVersion < r.SchemaVersion, stateSchemaVersion +} diff --git a/helper/schema/resource_test.go b/helper/schema/resource_test.go index 0c71abddf..b1c42721f 100644 --- a/helper/schema/resource_test.go +++ b/helper/schema/resource_test.go @@ -3,6 +3,7 @@ package schema import ( "fmt" "reflect" + "strconv" "testing" "github.com/hashicorp/terraform/terraform" @@ -478,3 +479,218 @@ func TestResourceRefresh_noExists(t *testing.T) { t.Fatalf("should have no state") } } + +func TestResourceRefresh_needsMigration(t *testing.T) { + // Schema v2 it deals only in newfoo, which tracks foo as an int + r := &Resource{ + SchemaVersion: 2, + Schema: map[string]*Schema{ + "newfoo": &Schema{ + Type: TypeInt, + Optional: true, + }, + }, + } + + r.Read = func(d *ResourceData, m interface{}) error { + return d.Set("newfoo", d.Get("newfoo").(int)+1) + } + + r.MigrateState = func( + v int, + s *terraform.InstanceState, + meta interface{}) (*terraform.InstanceState, error) { + // Real state migration functions will probably switch on this value, + // but we'll just assert on it for now. + if v != 1 { + t.Fatalf("Expected StateSchemaVersion to be 1, got %d", v) + } + + if meta != 42 { + t.Fatal("Expected meta to be passed through to the migration function") + } + + oldfoo, err := strconv.ParseFloat(s.Attributes["oldfoo"], 64) + if err != nil { + t.Fatalf("err: %#v", err) + } + s.Attributes["newfoo"] = strconv.Itoa((int(oldfoo * 10))) + delete(s.Attributes, "oldfoo") + + return s, nil + } + + // State is v1 and deals in oldfoo, which tracked foo as a float at 1/10th + // the scale of newfoo + s := &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "oldfoo": "1.2", + }, + Meta: map[string]string{ + "schema_version": "1", + }, + } + + actual, err := r.Refresh(s, 42) + if err != nil { + t.Fatalf("err: %s", err) + } + + expected := &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "id": "bar", + "newfoo": "13", + }, + Meta: map[string]string{ + "schema_version": "2", + }, + } + + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad:\n\nexpected: %#v\ngot: %#v", expected, actual) + } +} + +func TestResourceRefresh_noMigrationNeeded(t *testing.T) { + r := &Resource{ + SchemaVersion: 2, + Schema: map[string]*Schema{ + "newfoo": &Schema{ + Type: TypeInt, + Optional: true, + }, + }, + } + + r.Read = func(d *ResourceData, m interface{}) error { + return d.Set("newfoo", d.Get("newfoo").(int)+1) + } + + r.MigrateState = func( + v int, + s *terraform.InstanceState, + meta interface{}) (*terraform.InstanceState, error) { + t.Fatal("Migrate function shouldn't be called!") + return nil, nil + } + + s := &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "newfoo": "12", + }, + Meta: map[string]string{ + "schema_version": "2", + }, + } + + actual, err := r.Refresh(s, nil) + if err != nil { + t.Fatalf("err: %s", err) + } + + expected := &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "id": "bar", + "newfoo": "13", + }, + Meta: map[string]string{ + "schema_version": "2", + }, + } + + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad:\n\nexpected: %#v\ngot: %#v", expected, actual) + } +} + +func TestResourceRefresh_stateSchemaVersionUnset(t *testing.T) { + r := &Resource{ + // Version 1 > Version 0 + SchemaVersion: 1, + Schema: map[string]*Schema{ + "newfoo": &Schema{ + Type: TypeInt, + Optional: true, + }, + }, + } + + r.Read = func(d *ResourceData, m interface{}) error { + return d.Set("newfoo", d.Get("newfoo").(int)+1) + } + + r.MigrateState = func( + v int, + s *terraform.InstanceState, + meta interface{}) (*terraform.InstanceState, error) { + s.Attributes["newfoo"] = s.Attributes["oldfoo"] + return s, nil + } + + s := &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "oldfoo": "12", + }, + } + + actual, err := r.Refresh(s, nil) + if err != nil { + t.Fatalf("err: %s", err) + } + + expected := &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "id": "bar", + "newfoo": "13", + }, + Meta: map[string]string{ + "schema_version": "1", + }, + } + + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad:\n\nexpected: %#v\ngot: %#v", expected, actual) + } +} + +func TestResourceRefresh_migrateStateErr(t *testing.T) { + r := &Resource{ + SchemaVersion: 2, + Schema: map[string]*Schema{ + "newfoo": &Schema{ + Type: TypeInt, + Optional: true, + }, + }, + } + + r.Read = func(d *ResourceData, m interface{}) error { + t.Fatal("Read should never be called!") + return nil + } + + r.MigrateState = func( + v int, + s *terraform.InstanceState, + meta interface{}) (*terraform.InstanceState, error) { + return s, fmt.Errorf("triggering an error") + } + + s := &terraform.InstanceState{ + ID: "bar", + Attributes: map[string]string{ + "oldfoo": "12", + }, + } + + _, err := r.Refresh(s, nil) + if err == nil { + t.Fatal("expected error, but got none!") + } +} diff --git a/terraform/state.go b/terraform/state.go index ddf57cd7d..3dbad7ae6 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -832,6 +832,11 @@ type InstanceState struct { // that is necessary for the Terraform run to complete, but is not // persisted to a state file. Ephemeral EphemeralState `json:"-"` + + // Meta is a simple K/V map that is persisted to the State but otherwise + // ignored by Terraform core. It's meant to be used for accounting by + // external client code. + Meta map[string]string `json:"meta,omitempty"` } func (i *InstanceState) init() { From a34800dff270e9eb0484db0435b26aa5ab7f4289 Mon Sep 17 00:00:00 2001 From: Rahul Menon Date: Mon, 9 Mar 2015 14:39:06 +0530 Subject: [PATCH 21/62] Tags Schema --- builtin/providers/aws/resource_aws_vpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 840c0b1b3..d1234e637 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -58,7 +58,7 @@ func resourceAwsVpc() *schema.Resource { Computed: true, }, - // "tags": tagsSchema(), + "tags": tagsSchema(), }, } } From bb7ef8db67d5e663b11713aa9fb8a4d2cce59e4f Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Mon, 9 Mar 2015 14:00:29 +0100 Subject: [PATCH 22/62] Adding tests and docs for the new VPN resources And did some (very) minor refactoring in the existing docs --- builtin/providers/cloudstack/provider_test.go | 3 +- .../resource_cloudstack_ipaddress_test.go | 2 +- ...source_cloudstack_network_acl_rule_test.go | 4 +- .../resource_cloudstack_network_acl_test.go | 2 +- .../resource_cloudstack_network_test.go | 2 +- .../resource_cloudstack_vpc_test.go | 6 +- ...resource_cloudstack_vpn_connection_test.go | 142 +++++++++++ ...ce_cloudstack_vpn_customer_gateway_test.go | 225 ++++++++++++++++++ .../resource_cloudstack_vpn_gateway.go | 4 +- .../resource_cloudstack_vpn_gateway_test.go | 101 ++++++++ .../r/egress_firewall.html.markdown | 2 +- .../cloudstack/r/firewall.html.markdown | 2 +- .../r/network_acl_rule.html.markdown | 2 +- .../cloudstack/r/vpn_connection.html.markdown | 38 +++ .../r/vpn_customer_gateway.html.markdown | 59 +++++ .../cloudstack/r/vpn_gateway.html.markdown | 35 +++ website/source/layouts/cloudstack.erb | 116 +++++---- 17 files changed, 679 insertions(+), 66 deletions(-) create mode 100644 builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go create mode 100644 builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go create mode 100644 builtin/providers/cloudstack/resource_cloudstack_vpn_gateway_test.go create mode 100644 website/source/docs/providers/cloudstack/r/vpn_connection.html.markdown create mode 100644 website/source/docs/providers/cloudstack/r/vpn_customer_gateway.html.markdown create mode 100644 website/source/docs/providers/cloudstack/r/vpn_gateway.html.markdown diff --git a/builtin/providers/cloudstack/provider_test.go b/builtin/providers/cloudstack/provider_test.go index a13839177..537a2664f 100644 --- a/builtin/providers/cloudstack/provider_test.go +++ b/builtin/providers/cloudstack/provider_test.go @@ -51,7 +51,8 @@ var CLOUDSTACK_NETWORK_1_OFFERING = "" var CLOUDSTACK_NETWORK_1_IPADDRESS = "" var CLOUDSTACK_NETWORK_2 = "" var CLOUDSTACK_NETWORK_2_IPADDRESS = "" -var CLOUDSTACK_VPC_CIDR = "" +var CLOUDSTACK_VPC_CIDR_1 = "" +var CLOUDSTACK_VPC_CIDR_2 = "" var CLOUDSTACK_VPC_OFFERING = "" var CLOUDSTACK_VPC_NETWORK_CIDR = "" var CLOUDSTACK_VPC_NETWORK_OFFERING = "" diff --git a/builtin/providers/cloudstack/resource_cloudstack_ipaddress_test.go b/builtin/providers/cloudstack/resource_cloudstack_ipaddress_test.go index 5b1fc9a31..dfdeba209 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_ipaddress_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_ipaddress_test.go @@ -132,6 +132,6 @@ resource "cloudstack_vpc" "foobar" { resource "cloudstack_ipaddress" "foo" { vpc = "${cloudstack_vpc.foobar.name}" }`, - CLOUDSTACK_VPC_CIDR, + CLOUDSTACK_VPC_CIDR_1, CLOUDSTACK_VPC_OFFERING, CLOUDSTACK_ZONE) diff --git a/builtin/providers/cloudstack/resource_cloudstack_network_acl_rule_test.go b/builtin/providers/cloudstack/resource_cloudstack_network_acl_rule_test.go index 037b9d10b..dbceb8d8d 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_network_acl_rule_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_network_acl_rule_test.go @@ -196,7 +196,7 @@ resource "cloudstack_network_acl_rule" "foo" { traffic_type = "ingress" } }`, - CLOUDSTACK_VPC_CIDR, + CLOUDSTACK_VPC_CIDR_1, CLOUDSTACK_VPC_OFFERING, CLOUDSTACK_ZONE) @@ -233,6 +233,6 @@ resource "cloudstack_network_acl_rule" "foo" { traffic_type = "egress" } }`, - CLOUDSTACK_VPC_CIDR, + CLOUDSTACK_VPC_CIDR_1, CLOUDSTACK_VPC_OFFERING, CLOUDSTACK_ZONE) diff --git a/builtin/providers/cloudstack/resource_cloudstack_network_acl_test.go b/builtin/providers/cloudstack/resource_cloudstack_network_acl_test.go index e625d4c2d..9bf0bb0cf 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_network_acl_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_network_acl_test.go @@ -112,6 +112,6 @@ resource "cloudstack_network_acl" "foo" { description = "terraform-acl-text" vpc = "${cloudstack_vpc.foobar.name}" }`, - CLOUDSTACK_VPC_CIDR, + CLOUDSTACK_VPC_CIDR_1, CLOUDSTACK_VPC_OFFERING, CLOUDSTACK_ZONE) diff --git a/builtin/providers/cloudstack/resource_cloudstack_network_test.go b/builtin/providers/cloudstack/resource_cloudstack_network_test.go index 750761f02..d936f8cb0 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_network_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_network_test.go @@ -186,7 +186,7 @@ resource "cloudstack_network" "foo" { aclid = "${cloudstack_network_acl.foo.id}" zone = "${cloudstack_vpc.foobar.zone}" }`, - CLOUDSTACK_VPC_CIDR, + CLOUDSTACK_VPC_CIDR_1, CLOUDSTACK_VPC_OFFERING, CLOUDSTACK_ZONE, CLOUDSTACK_VPC_NETWORK_CIDR, diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go b/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go index bf4e8f448..07861a091 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_vpc_test.go @@ -72,8 +72,8 @@ func testAccCheckCloudStackVPCAttributes( return fmt.Errorf("Bad display text: %s", vpc.Displaytext) } - if vpc.Cidr != CLOUDSTACK_VPC_CIDR { - return fmt.Errorf("Bad VPC offering: %s", vpc.Cidr) + if vpc.Cidr != CLOUDSTACK_VPC_CIDR_1 { + return fmt.Errorf("Bad VPC CIDR: %s", vpc.Cidr) } return nil @@ -113,6 +113,6 @@ resource "cloudstack_vpc" "foo" { vpc_offering = "%s" zone = "%s" }`, - CLOUDSTACK_VPC_CIDR, + CLOUDSTACK_VPC_CIDR_1, CLOUDSTACK_VPC_OFFERING, CLOUDSTACK_ZONE) diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go new file mode 100644 index 000000000..ff7a46fd3 --- /dev/null +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go @@ -0,0 +1,142 @@ +package cloudstack + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +func TestAccCloudStackVPNConnection_basic(t *testing.T) { + var vpnConnection cloudstack.VpnConnection + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCloudStackVPNConnectionDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCloudStackVPNConnection_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudStackVPNConnectionExists( + "cloudstack_vpn_connection.foo", &vpnConnection), + ), + }, + }, + }) +} + +func testAccCheckCloudStackVPNConnectionExists( + n string, vpnConnection *cloudstack.VpnConnection) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No VPN Connection ID is set") + } + + cs := testAccProvider.Meta().(*cloudstack.CloudStackClient) + v, _, err := cs.VPN.GetVpnConnectionByID(rs.Primary.ID) + + if err != nil { + return err + } + + if v.Id != rs.Primary.ID { + return fmt.Errorf("VPN Connection not found") + } + + *vpnConnection = *v + + return nil + } +} + +func testAccCheckCloudStackVPNConnectionDestroy(s *terraform.State) error { + cs := testAccProvider.Meta().(*cloudstack.CloudStackClient) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "cloudstack_vpn_connection" { + continue + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No VPN Connection ID is set") + } + + p := cs.VPN.NewDeleteVpnConnectionParams(rs.Primary.ID) + _, err := cs.VPN.DeleteVpnConnection(p) + + if err != nil { + return fmt.Errorf( + "Error deleting VPN Connection (%s): %s", + rs.Primary.ID, err) + } + } + + return nil +} + +var testAccCloudStackVPNConnection_basic = fmt.Sprintf(` +resource "cloudstack_vpc" "foo" { + name = "terraform-vpc" + display_text = "terraform-vpc-text" + cidr = "%s" + vpc_offering = "%s" + zone = "%s" +} + +resource "cloudstack_vpc" "bar" { + name = "terraform-vpc" + display_text = "terraform-vpc-text" + cidr = "%s" + vpc_offering = "%s" + zone = "%s" +} + +resource "cloudstack_vpn_gateway" "foo" { + vpc = "${cloudstack_vpc.foo.name}" +} + +resource "cloudstack_vpn_gateway" "bar" { + vpc = "${cloudstack_vpc.bar.name}" +} + +resource "cloudstack_vpn_customer_gateway" "foo" { + name = "terraform-foo" + cidr = "${cloudstack_vpc.foo.cidr}" + esp_policy = "aes256-sha1" + gateway = "${cloudstack_vpn_gateway.foo.publicip}" + ike_policy = "aes256-sha1" + ipsec_psk = "terraform" +} + +resource "cloudstack_vpn_customer_gateway" "bar" { + name = "terraform-bar" + cidr = "${cloudstack_vpc.bar.cidr}" + esp_policy = "aes256-sha1" + gateway = "${cloudstack_vpn_gateway.bar.publicip}" + ike_policy = "aes256-sha1" + ipsec_psk = "terraform" +} + +resource "cloudstack_vpn_connection" "foo-bar" { + customergatewayid = "${cloudstack_vpn_customer_gateway.foo.id}" + vpngatewayid = "${cloudstack_vpn_gateway.bar.id}" +} + +resource "cloudstack_vpn_connection" "bar-foo" { + customergatewayid = "${cloudstack_vpn_customer_gateway.bar.id}" + vpngatewayid = "${cloudstack_vpn_gateway.foo.id}" +}`, + CLOUDSTACK_VPC_CIDR_1, + CLOUDSTACK_VPC_OFFERING, + CLOUDSTACK_ZONE, + CLOUDSTACK_VPC_CIDR_2, + CLOUDSTACK_VPC_OFFERING, + CLOUDSTACK_ZONE) diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go new file mode 100644 index 000000000..9475e31a3 --- /dev/null +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go @@ -0,0 +1,225 @@ +package cloudstack + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +func TestAccCloudStackVPNCustomerGateway_basic(t *testing.T) { + var vpnCustomerGateway cloudstack.VpnCustomerGateway + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCloudStackVPNCustomerGatewayDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCloudStackVPNCustomerGateway_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudStackVPNCustomerGatewayExists( + "cloudstack_vpn_connection.foo", &vpnCustomerGateway), + testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.foo", "name", "terraform-foo"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.bar", "name", "terraform-bar"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.foo", "ike_policy", "aes256-sha1"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.bar", "esp_policy", "aes256-sha1"), + ), + }, + }, + }) +} + +func TestAccCloudStackVPNCustomerGateway_update(t *testing.T) { + var nic cloudstack.Nic + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCloudStackNICDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: TestAccCloudStackVPNCustomerGateway_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudStackVPNCustomerGatewayExists( + "cloudstack_vpn_connection.foo", &vpnCustomerGateway), + testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.foo", "name", "terraform-foo"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.bar", "name", "terraform-bar"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.foo", "ike_policy", "aes256-sha1"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.bar", "esp_policy", "aes256-sha1"), + ), + }, + + resource.TestStep{ + Config: TestAccCloudStackVPNCustomerGateway_update, + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudStackVPNCustomerGatewayExists( + "cloudstack_vpn_connection.foo", &vpnCustomerGateway), + testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.foo", "name", "terraform-foo-bar"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.bar", "name", "terraform-bar-foo"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.foo", "ike_policy", "3des-md5"), + resource.TestCheckResourceAttr( + "cloudstack_vpn_connection.bar", "esp_policy", "3des-md5"), + ), + }, + }, + }) +} + +func testAccCheckCloudStackVPNCustomerGatewayExists( + n string, vpnCustomerGateway *cloudstack.VpnCustomerGateway) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No VPN CustomerGateway ID is set") + } + + cs := testAccProvider.Meta().(*cloudstack.CloudStackClient) + v, _, err := cs.VPN.GetVpnCustomerGatewayByID(rs.Primary.ID) + + if err != nil { + return err + } + + if v.Id != rs.Primary.ID { + return fmt.Errorf("VPN CustomerGateway not found") + } + + *vpnCustomerGateway = *v + + return nil + } +} + +func testAccCheckCloudStackVPNCustomerGatewayAttributes( + vpnCustomerGateway *cloudstack.VpnCustomerGateway) resource.TestCheckFunc { + return func(s *terraform.State) error { + + if vpnCustomerGateway.Esppolicy != "aes256-sha1" { + return fmt.Errorf("Bad ESP policy: %s", vpnCustomerGateway.Esppolicy) + } + + if vpnCustomerGateway.Ikepolicy != "aes256-sha1" { + return fmt.Errorf("Bad IKE policy: %s", vpnCustomerGateway.Ikepolicy) + } + + if vpnCustomerGateway.Ipsecpsk != "terraform" { + return fmt.Errorf("Bad IPSEC pre-shared key: %s", vpnCustomerGateway.Ipsecpsk) + } + + return nil + } +} + +func testAccCheckCloudStackVPNCustomerGatewayDestroy(s *terraform.State) error { + cs := testAccProvider.Meta().(*cloudstack.CloudStackClient) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "cloudstack_vpn_connection" { + continue + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No VPN Customer Gateway ID is set") + } + + p := cs.VPN.NewDeleteVpnCustomerGatewayParams(rs.Primary.ID) + _, err := cs.VPN.DeleteVpnCustomerGateway(p) + + if err != nil { + return fmt.Errorf( + "Error deleting VPN Customer Gateway (%s): %s", + rs.Primary.ID, err) + } + } + + return nil +} + +var testAccCloudStackVPNCustomerGateway_basic = fmt.Sprintf(` +resource "cloudstack_vpc" "foo" { + name = "terraform-vpc" + display_text = "terraform-vpc-text" + cidr = "%s" + vpc_offering = "%s" + zone = "%s" +} + +resource "cloudstack_vpc" "bar" { + name = "terraform-vpc" + display_text = "terraform-vpc-text" + cidr = "%s" + vpc_offering = "%s" + zone = "%s" +} + +resource "cloudstack_vpn_gateway" "foo" { + vpc = "${cloudstack_vpc.foo.name}" +} + +resource "cloudstack_vpn_gateway" "bar" { + vpc = "${cloudstack_vpc.bar.name}" +} + +resource "cloudstack_vpn_customer_gateway" "foo" { + name = "terraform-foo" + cidr = "${cloudstack_vpc.foo.cidr}" + esp_policy = "aes256-sha1" + gateway = "${cloudstack_vpn_gateway.foo.publicip}" + ike_policy = "aes256-sha1" + ipsec_psk = "terraform" +} + +resource "cloudstack_vpn_customer_gateway" "bar" { + name = "terraform-bar" + cidr = "${cloudstack_vpc.bar.cidr}" + esp_policy = "aes256-sha1" + gateway = "${cloudstack_vpn_gateway.bar.publicip}" + ike_policy = "aes256-sha1" + ipsec_psk = "terraform" +}`, + CLOUDSTACK_VPC_CIDR_1, + CLOUDSTACK_VPC_OFFERING, + CLOUDSTACK_ZONE, + CLOUDSTACK_VPC_CIDR_2, + CLOUDSTACK_VPC_OFFERING, + CLOUDSTACK_ZONE) + +var testAccCloudStackVPNCustomerGateway_update = fmt.Sprintf(` +resource "cloudstack_vpn_customer_gateway" "foo" { + name = "terraform-foo-bar" + cidr = "${cloudstack_vpc.foo.cidr}" + esp_policy = "3des-md5" + gateway = "${cloudstack_vpn_gateway.foo.publicip}" + ike_policy = "3des-md5" + ipsec_psk = "terraform" +} + +resource "cloudstack_vpn_customer_gateway" "bar" { + name = "terraform-bar-foo" + cidr = "${cloudstack_vpc.bar.cidr}" + esp_policy = "3des-md5" + gateway = "${cloudstack_vpn_gateway.bar.publicip}" + ike_policy = "3des-md5" + ipsec_psk = "terraform" +}`) diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go index 650df6530..063c31777 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway.go @@ -22,7 +22,7 @@ func resourceCloudStackVPNGateway() *schema.Resource { ForceNew: true, }, - "publicip": &schema.Schema{ + "public_ip": &schema.Schema{ Type: schema.TypeString, Computed: true, }, @@ -69,7 +69,7 @@ func resourceCloudStackVPNGatewayRead(d *schema.ResourceData, meta interface{}) return err } - d.Set("publicip", v.Publicip) + d.Set("public_ip", v.Publicip) return nil } diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway_test.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway_test.go new file mode 100644 index 000000000..db6c0085a --- /dev/null +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_gateway_test.go @@ -0,0 +1,101 @@ +package cloudstack + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +func TestAccCloudStackVPNGateway_basic(t *testing.T) { + var vpnGateway cloudstack.VpnGateway + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCloudStackVPNGatewayDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCloudStackVPNGateway_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckCloudStackVPNGatewayExists( + "cloudstack_vpn_gateway.foo", &vpnGateway), + resource.TestCheckResourceAttr( + "cloudstack_vpn_gateway.foo", "vpc", "terraform-vpc"), + ), + }, + }, + }) +} + +func testAccCheckCloudStackVPNGatewayExists( + n string, vpnGateway *cloudstack.VpnGateway) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No VPN Gateway ID is set") + } + + cs := testAccProvider.Meta().(*cloudstack.CloudStackClient) + v, _, err := cs.VPN.GetVpnGatewayByID(rs.Primary.ID) + + if err != nil { + return err + } + + if v.Id != rs.Primary.ID { + return fmt.Errorf("VPN Gateway not found") + } + + *vpnGateway = *v + + return nil + } +} + +func testAccCheckCloudStackVPNGatewayDestroy(s *terraform.State) error { + cs := testAccProvider.Meta().(*cloudstack.CloudStackClient) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "cloudstack_vpn_gateway" { + continue + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No VPN Gateway ID is set") + } + + p := cs.VPN.NewDeleteVpnGatewayParams(rs.Primary.ID) + _, err := cs.VPN.DeleteVpnGateway(p) + + if err != nil { + return fmt.Errorf( + "Error deleting VPN Gateway (%s): %s", + rs.Primary.ID, err) + } + } + + return nil +} + +var testAccCloudStackVPNGateway_basic = fmt.Sprintf(` +resource "cloudstack_vpc" "foo" { + name = "terraform-vpc" + display_text = "terraform-vpc-text" + cidr = "%s" + vpc_offering = "%s" + zone = "%s" +} + +resource "cloudstack_vpn_gateway" "foo" { + vpc = "${cloudstack_vpc.foo.name}" +}`, + CLOUDSTACK_VPC_CIDR_1, + CLOUDSTACK_VPC_OFFERING, + CLOUDSTACK_ZONE) diff --git a/website/source/docs/providers/cloudstack/r/egress_firewall.html.markdown b/website/source/docs/providers/cloudstack/r/egress_firewall.html.markdown index 17fa20927..b905bc0e9 100644 --- a/website/source/docs/providers/cloudstack/r/egress_firewall.html.markdown +++ b/website/source/docs/providers/cloudstack/r/egress_firewall.html.markdown @@ -58,4 +58,4 @@ The `rule` block supports: The following attributes are exported: -* `ID` - The network ID for which the egress firewall rules are created. +* `id` - The network ID for which the egress firewall rules are created. diff --git a/website/source/docs/providers/cloudstack/r/firewall.html.markdown b/website/source/docs/providers/cloudstack/r/firewall.html.markdown index 1c659e6bf..8b8aa0089 100644 --- a/website/source/docs/providers/cloudstack/r/firewall.html.markdown +++ b/website/source/docs/providers/cloudstack/r/firewall.html.markdown @@ -58,4 +58,4 @@ The `rule` block supports: The following attributes are exported: -* `ID` - The IP address ID for which the firewall rules are created. +* `id` - The IP address ID for which the firewall rules are created. diff --git a/website/source/docs/providers/cloudstack/r/network_acl_rule.html.markdown b/website/source/docs/providers/cloudstack/r/network_acl_rule.html.markdown index fb6b0891f..f82b8f446 100644 --- a/website/source/docs/providers/cloudstack/r/network_acl_rule.html.markdown +++ b/website/source/docs/providers/cloudstack/r/network_acl_rule.html.markdown @@ -66,4 +66,4 @@ The `rule` block supports: The following attributes are exported: -* `ID` - The ACL ID for which the rules are created. +* `id` - The ACL ID for which the rules are created. diff --git a/website/source/docs/providers/cloudstack/r/vpn_connection.html.markdown b/website/source/docs/providers/cloudstack/r/vpn_connection.html.markdown new file mode 100644 index 000000000..3ecf17cbc --- /dev/null +++ b/website/source/docs/providers/cloudstack/r/vpn_connection.html.markdown @@ -0,0 +1,38 @@ +--- +layout: "cloudstack" +page_title: "CloudStack: cloudstack_vpn_connection" +sidebar_current: "docs-cloudstack-resource-vpn-connection" +description: |- + Creates a site to site VPN connection. +--- + +# cloudstack\_vpn\_connection + +Creates a site to site VPN connection. + +## Example Usage + +Basic usage: + +``` +resource "cloudstack_vpn_connection" "default" { + customergatewayid = "xxx" + vpngatewayid = "xxx" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `customergatewayid` - (Required) The Customer Gateway ID to connect. + Changing this forces a new resource to be created. + +* `vpngatewayid` - (Required) The VPN Gateway ID to connect. + Changing this forces a new resource to be created. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the VPN Connection. diff --git a/website/source/docs/providers/cloudstack/r/vpn_customer_gateway.html.markdown b/website/source/docs/providers/cloudstack/r/vpn_customer_gateway.html.markdown new file mode 100644 index 000000000..84183b8d6 --- /dev/null +++ b/website/source/docs/providers/cloudstack/r/vpn_customer_gateway.html.markdown @@ -0,0 +1,59 @@ +--- +layout: "cloudstack" +page_title: "CloudStack: cloudstack_vpn_customer_gateway" +sidebar_current: "docs-cloudstack-resource-vpn-customer-gateway" +description: |- + Creates a site to site VPN local customer gateway. +--- + +# cloudstack\_vpn\_customer\_gateway + +Creates a site to site VPN local customer gateway. + +## Example Usage + +Basic usage: + +``` +resource "cloudstack_vpn_customer_gateway" "default" { + name = "test-vpc" + cidr = "10.0.0.0/8" + esp_policy = "aes256-sha1" + gateway = "192.168.0.1" + ike_policy = "aes256-sha1" + ipsec_psk = "terraform" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the VPN Customer Gateway. + +* `cidr` - (Required) The CIDR block that needs to be routed through this gateway. + +* `esp_policy` - (Required) The ESP policy to use for this VPN Customer Gateway. + +* `gateway` - (Required) The public IP address of the related VPN Gateway. + +* `ike_policy` - (Required) The IKE policy to use for this VPN Customer Gateway. + +* `ipsec_psk` - (Required) The IPSEC pre-shared key used for this gateway. + +* `dpd` - (Optional) If DPD is enabled for the related VPN connection (defaults false) + +* `esp_lifetime` - (Optional) The ESP lifetime of phase 2 VPN connection to this + VPN Customer Gateway in seconds (defaults 86400) + +* `ike_lifetime` - (Optional) The IKE lifetime of phase 2 VPN connection to this + VPN Customer Gateway in seconds (defaults 86400) + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the VPN Customer Gateway. +* `dpd` - Enable or disable DPD is enabled for the related VPN connection. +* `esp_lifetime` - The ESP lifetime of phase 2 VPN connection to this VPN Customer Gateway. +* `ike_lifetime` - The IKE lifetime of phase 2 VPN connection to this VPN Customer Gateway. diff --git a/website/source/docs/providers/cloudstack/r/vpn_gateway.html.markdown b/website/source/docs/providers/cloudstack/r/vpn_gateway.html.markdown new file mode 100644 index 000000000..10aabd796 --- /dev/null +++ b/website/source/docs/providers/cloudstack/r/vpn_gateway.html.markdown @@ -0,0 +1,35 @@ +--- +layout: "cloudstack" +page_title: "CloudStack: cloudstack_vpn_gateway" +sidebar_current: "docs-cloudstack-resource-vpn-gateway" +description: |- + Creates a site to site VPN local gateway. +--- + +# cloudstack\_vpn\_gateway + +Creates a site to site VPN local gateway. + +## Example Usage + +Basic usage: + +``` +resource "cloudstack_vpn_gateway" "default" { + vpc = "test-vpc" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `vpc` - (Required) The name of the VPC for which to create the VPN Gateway. + Changing this forces a new resource to be created. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the VPN Gateway. +* `public_ip` - The public IP address associated with the VPN Gateway. diff --git a/website/source/layouts/cloudstack.erb b/website/source/layouts/cloudstack.erb index a0e137aae..ee1ae6587 100644 --- a/website/source/layouts/cloudstack.erb +++ b/website/source/layouts/cloudstack.erb @@ -1,66 +1,78 @@ <% wrap_layout :inner do %> - <% content_for :sidebar do %> - + <% end %> + + <%= yield %> +<% end %> From bb88adb5a326f24e40add8b469825de6e6044888 Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Mon, 9 Mar 2015 14:02:18 +0100 Subject: [PATCH 23/62] Fixing a corner case while retrieving a template UUID Added some logic to the go-cloudstack package to support a more customised call to GetTemplateID in order to get the correct/expected UUID. --- .../cloudstack/resource_cloudstack_instance.go | 12 ++++++------ builtin/providers/cloudstack/resources.go | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/builtin/providers/cloudstack/resource_cloudstack_instance.go b/builtin/providers/cloudstack/resource_cloudstack_instance.go index 600001a27..f0e52b588 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_instance.go +++ b/builtin/providers/cloudstack/resource_cloudstack_instance.go @@ -95,18 +95,18 @@ func resourceCloudStackInstanceCreate(d *schema.ResourceData, meta interface{}) return e.Error() } - // Retrieve the template UUID - templateid, e := retrieveUUID(cs, "template", d.Get("template").(string)) - if e != nil { - return e.Error() - } - // Retrieve the zone object zone, _, err := cs.Zone.GetZoneByName(d.Get("zone").(string)) if err != nil { return err } + // Retrieve the template UUID + templateid, e := retrieveTemplateUUID(cs, zone.Id, d.Get("template").(string)) + if e != nil { + return e.Error() + } + // Create a new parameter struct p := cs.VirtualMachine.NewDeployVirtualMachineParams(serviceofferingid, templateid, zone.Id) diff --git a/builtin/providers/cloudstack/resources.go b/builtin/providers/cloudstack/resources.go index acef7b3da..76d38eb7c 100644 --- a/builtin/providers/cloudstack/resources.go +++ b/builtin/providers/cloudstack/resources.go @@ -40,8 +40,6 @@ func retrieveUUID(cs *cloudstack.CloudStackClient, name, value string) (uuid str uuid, err = cs.VPC.GetVPCOfferingID(value) case "vpc": uuid, err = cs.VPC.GetVPCID(value) - case "template": - uuid, err = cs.Template.GetTemplateID(value, "executable") case "network": uuid, err = cs.Network.GetNetworkID(value) case "zone": @@ -71,6 +69,22 @@ func retrieveUUID(cs *cloudstack.CloudStackClient, name, value string) (uuid str return uuid, nil } +func retrieveTemplateUUID(cs *cloudstack.CloudStackClient, zoneid, value string) (uuid string, e *retrieveError) { + // If the supplied value isn't a UUID, try to retrieve the UUID ourselves + if isUUID(value) { + return value, nil + } + + log.Printf("[DEBUG] Retrieving UUID of template: %s", value) + + uuid, err := cs.Template.GetTemplateID(value, "executable", zoneid) + if err != nil { + return uuid, &retrieveError{name: "template", value: value, err: err} + } + + return uuid, nil +} + func isUUID(s string) bool { re := regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`) return re.MatchString(s) From 94608fc4bc318604b3ba47125660d6373ea76cfa Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Mon, 9 Mar 2015 17:44:09 +0100 Subject: [PATCH 24/62] Fixing up the tests to make them pass correctly --- builtin/providers/cloudstack/provider.go | 2 +- ...resource_cloudstack_vpn_connection_test.go | 14 ++--- ...ce_cloudstack_vpn_customer_gateway_test.go | 54 +++++++++---------- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/builtin/providers/cloudstack/provider.go b/builtin/providers/cloudstack/provider.go index f7ce62725..8bea67ef5 100644 --- a/builtin/providers/cloudstack/provider.go +++ b/builtin/providers/cloudstack/provider.go @@ -30,7 +30,7 @@ func Provider() terraform.ResourceProvider { "timeout": &schema.Schema{ Type: schema.TypeInt, Required: true, - DefaultFunc: schema.EnvDefaultFunc("CLOUDSTACK_TIMEOUT", 180), + DefaultFunc: schema.EnvDefaultFunc("CLOUDSTACK_TIMEOUT", 300), }, }, diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go index ff7a46fd3..1b9d9920a 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_connection_test.go @@ -21,7 +21,9 @@ func TestAccCloudStackVPNConnection_basic(t *testing.T) { Config: testAccCloudStackVPNConnection_basic, Check: resource.ComposeTestCheckFunc( testAccCheckCloudStackVPNConnectionExists( - "cloudstack_vpn_connection.foo", &vpnConnection), + "cloudstack_vpn_connection.foo-bar", &vpnConnection), + testAccCheckCloudStackVPNConnectionExists( + "cloudstack_vpn_connection.bar-foo", &vpnConnection), ), }, }, @@ -84,16 +86,14 @@ func testAccCheckCloudStackVPNConnectionDestroy(s *terraform.State) error { var testAccCloudStackVPNConnection_basic = fmt.Sprintf(` resource "cloudstack_vpc" "foo" { - name = "terraform-vpc" - display_text = "terraform-vpc-text" + name = "terraform-vpc-foo" cidr = "%s" vpc_offering = "%s" zone = "%s" } resource "cloudstack_vpc" "bar" { - name = "terraform-vpc" - display_text = "terraform-vpc-text" + name = "terraform-vpc-bar" cidr = "%s" vpc_offering = "%s" zone = "%s" @@ -111,7 +111,7 @@ resource "cloudstack_vpn_customer_gateway" "foo" { name = "terraform-foo" cidr = "${cloudstack_vpc.foo.cidr}" esp_policy = "aes256-sha1" - gateway = "${cloudstack_vpn_gateway.foo.publicip}" + gateway = "${cloudstack_vpn_gateway.foo.public_ip}" ike_policy = "aes256-sha1" ipsec_psk = "terraform" } @@ -120,7 +120,7 @@ resource "cloudstack_vpn_customer_gateway" "bar" { name = "terraform-bar" cidr = "${cloudstack_vpc.bar.cidr}" esp_policy = "aes256-sha1" - gateway = "${cloudstack_vpn_gateway.bar.publicip}" + gateway = "${cloudstack_vpn_gateway.bar.public_ip}" ike_policy = "aes256-sha1" ipsec_psk = "terraform" } diff --git a/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go b/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go index 9475e31a3..b468c76fe 100644 --- a/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go +++ b/builtin/providers/cloudstack/resource_cloudstack_vpn_customer_gateway_test.go @@ -21,16 +21,16 @@ func TestAccCloudStackVPNCustomerGateway_basic(t *testing.T) { Config: testAccCloudStackVPNCustomerGateway_basic, Check: resource.ComposeTestCheckFunc( testAccCheckCloudStackVPNCustomerGatewayExists( - "cloudstack_vpn_connection.foo", &vpnCustomerGateway), + "cloudstack_vpn_customer_gateway.foo", &vpnCustomerGateway), testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.foo", "name", "terraform-foo"), + "cloudstack_vpn_customer_gateway.foo", "name", "terraform-foo"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.bar", "name", "terraform-bar"), + "cloudstack_vpn_customer_gateway.bar", "name", "terraform-bar"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.foo", "ike_policy", "aes256-sha1"), + "cloudstack_vpn_customer_gateway.foo", "ike_policy", "aes256-sha1"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.bar", "esp_policy", "aes256-sha1"), + "cloudstack_vpn_customer_gateway.bar", "esp_policy", "aes256-sha1"), ), }, }, @@ -38,44 +38,44 @@ func TestAccCloudStackVPNCustomerGateway_basic(t *testing.T) { } func TestAccCloudStackVPNCustomerGateway_update(t *testing.T) { - var nic cloudstack.Nic + var vpnCustomerGateway cloudstack.VpnCustomerGateway resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, - CheckDestroy: testAccCheckCloudStackNICDestroy, + CheckDestroy: testAccCheckCloudStackVPNCustomerGatewayDestroy, Steps: []resource.TestStep{ resource.TestStep{ - Config: TestAccCloudStackVPNCustomerGateway_basic, + Config: testAccCloudStackVPNCustomerGateway_basic, Check: resource.ComposeTestCheckFunc( testAccCheckCloudStackVPNCustomerGatewayExists( - "cloudstack_vpn_connection.foo", &vpnCustomerGateway), + "cloudstack_vpn_customer_gateway.foo", &vpnCustomerGateway), testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.foo", "name", "terraform-foo"), + "cloudstack_vpn_customer_gateway.foo", "name", "terraform-foo"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.bar", "name", "terraform-bar"), + "cloudstack_vpn_customer_gateway.bar", "name", "terraform-bar"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.foo", "ike_policy", "aes256-sha1"), + "cloudstack_vpn_customer_gateway.foo", "ike_policy", "aes256-sha1"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.bar", "esp_policy", "aes256-sha1"), + "cloudstack_vpn_customer_gateway.bar", "esp_policy", "aes256-sha1"), ), }, resource.TestStep{ - Config: TestAccCloudStackVPNCustomerGateway_update, + Config: testAccCloudStackVPNCustomerGateway_update, Check: resource.ComposeTestCheckFunc( testAccCheckCloudStackVPNCustomerGatewayExists( - "cloudstack_vpn_connection.foo", &vpnCustomerGateway), + "cloudstack_vpn_customer_gateway.foo", &vpnCustomerGateway), testAccCheckCloudStackVPNCustomerGatewayAttributes(&vpnCustomerGateway), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.foo", "name", "terraform-foo-bar"), + "cloudstack_vpn_customer_gateway.foo", "name", "terraform-foo-bar"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.bar", "name", "terraform-bar-foo"), + "cloudstack_vpn_customer_gateway.bar", "name", "terraform-bar-foo"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.foo", "ike_policy", "3des-md5"), + "cloudstack_vpn_customer_gateway.foo", "ike_policy", "3des-md5"), resource.TestCheckResourceAttr( - "cloudstack_vpn_connection.bar", "esp_policy", "3des-md5"), + "cloudstack_vpn_customer_gateway.bar", "esp_policy", "3des-md5"), ), }, }, @@ -135,7 +135,7 @@ func testAccCheckCloudStackVPNCustomerGatewayDestroy(s *terraform.State) error { cs := testAccProvider.Meta().(*cloudstack.CloudStackClient) for _, rs := range s.RootModule().Resources { - if rs.Type != "cloudstack_vpn_connection" { + if rs.Type != "cloudstack_vpn_customer_gateway" { continue } @@ -158,16 +158,14 @@ func testAccCheckCloudStackVPNCustomerGatewayDestroy(s *terraform.State) error { var testAccCloudStackVPNCustomerGateway_basic = fmt.Sprintf(` resource "cloudstack_vpc" "foo" { - name = "terraform-vpc" - display_text = "terraform-vpc-text" + name = "terraform-vpc-foo" cidr = "%s" vpc_offering = "%s" zone = "%s" } resource "cloudstack_vpc" "bar" { - name = "terraform-vpc" - display_text = "terraform-vpc-text" + name = "terraform-vpc-bar" cidr = "%s" vpc_offering = "%s" zone = "%s" @@ -185,7 +183,7 @@ resource "cloudstack_vpn_customer_gateway" "foo" { name = "terraform-foo" cidr = "${cloudstack_vpc.foo.cidr}" esp_policy = "aes256-sha1" - gateway = "${cloudstack_vpn_gateway.foo.publicip}" + gateway = "${cloudstack_vpn_gateway.foo.public_ip}" ike_policy = "aes256-sha1" ipsec_psk = "terraform" } @@ -194,7 +192,7 @@ resource "cloudstack_vpn_customer_gateway" "bar" { name = "terraform-bar" cidr = "${cloudstack_vpc.bar.cidr}" esp_policy = "aes256-sha1" - gateway = "${cloudstack_vpn_gateway.bar.publicip}" + gateway = "${cloudstack_vpn_gateway.bar.public_ip}" ike_policy = "aes256-sha1" ipsec_psk = "terraform" }`, @@ -210,7 +208,7 @@ resource "cloudstack_vpn_customer_gateway" "foo" { name = "terraform-foo-bar" cidr = "${cloudstack_vpc.foo.cidr}" esp_policy = "3des-md5" - gateway = "${cloudstack_vpn_gateway.foo.publicip}" + gateway = "${cloudstack_vpn_gateway.foo.public_ip}" ike_policy = "3des-md5" ipsec_psk = "terraform" } @@ -219,7 +217,7 @@ resource "cloudstack_vpn_customer_gateway" "bar" { name = "terraform-bar-foo" cidr = "${cloudstack_vpc.bar.cidr}" esp_policy = "3des-md5" - gateway = "${cloudstack_vpn_gateway.bar.publicip}" + gateway = "${cloudstack_vpn_gateway.bar.public_ip}" ike_policy = "3des-md5" ipsec_psk = "terraform" }`) From 20b02cacd454c2318c60132e9ba1b7dc5f75ebca Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Mon, 9 Mar 2015 10:02:27 -0500 Subject: [PATCH 25/62] provider/aws: Convert AWS Security Group to aws-sdk-go Convert security group test too --- .../aws/resource_aws_security_group.go | 150 +++++++++++------- .../aws/resource_aws_security_group_test.go | 134 ++++++++-------- builtin/providers/aws/structure.go | 62 ++++++++ 3 files changed, 223 insertions(+), 123 deletions(-) diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index 451f1816f..a0b09a55a 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -7,10 +7,11 @@ import ( "sort" "time" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsSecurityGroup() *schema.Resource { @@ -141,18 +142,18 @@ func resourceAwsSecurityGroup() *schema.Resource { } func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn - securityGroupOpts := ec2.SecurityGroup{ - Name: d.Get("name").(string), + securityGroupOpts := &ec2.CreateSecurityGroupRequest{ + GroupName: aws.String(d.Get("name").(string)), } if v := d.Get("vpc_id"); v != nil { - securityGroupOpts.VpcId = v.(string) + securityGroupOpts.VPCID = aws.String(v.(string)) } if v := d.Get("description"); v != nil { - securityGroupOpts.Description = v.(string) + securityGroupOpts.Description = aws.String(v.(string)) } log.Printf( @@ -162,7 +163,7 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er return fmt.Errorf("Error creating Security Group: %s", err) } - d.SetId(createResp.Id) + d.SetId(*createResp.GroupID) log.Printf("[INFO] Security Group ID: %s", d.Id()) @@ -186,7 +187,7 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er } func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())() if err != nil { @@ -197,24 +198,23 @@ func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) erro return nil } - sg := sgRaw.(*ec2.SecurityGroupInfo) + sg := sgRaw.(ec2.SecurityGroup) - ingressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPerms) - egressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermsEgress) + ingressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermissions) + egressRules := resourceAwsSecurityGroupIPPermGather(d, sg.IPPermissionsEgress) d.Set("description", sg.Description) - d.Set("name", sg.Name) - d.Set("vpc_id", sg.VpcId) - d.Set("owner_id", sg.OwnerId) + d.Set("name", sg.GroupName) + d.Set("vpc_id", sg.VPCID) + d.Set("owner_id", sg.OwnerID) d.Set("ingress", ingressRules) d.Set("egress", egressRules) - d.Set("tags", tagsToMap(sg.Tags)) - + d.Set("tags", tagsToMapSDK(sg.Tags)) return nil } func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())() if err != nil { @@ -224,7 +224,8 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er d.SetId("") return nil } - group := sgRaw.(*ec2.SecurityGroupInfo).SecurityGroup + + group := sgRaw.(ec2.SecurityGroup) err = resourceAwsSecurityGroupUpdateRules(d, "ingress", meta, group) if err != nil { @@ -238,7 +239,7 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er } } - if err := setTags(ec2conn, d); err != nil { + if err := setTagsSDK(ec2conn, d); err != nil { return err } @@ -248,14 +249,16 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er } func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn log.Printf("[DEBUG] Security Group destroy: %v", d.Id()) return resource.Retry(5*time.Minute, func() error { - _, err := ec2conn.DeleteSecurityGroup(ec2.SecurityGroup{Id: d.Id()}) + err := ec2conn.DeleteSecurityGroup(&ec2.DeleteSecurityGroupRequest{ + GroupID: aws.String(d.Id()), + }) if err != nil { - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(aws.APIError) if !ok { return err } @@ -313,34 +316,49 @@ func resourceAwsSecurityGroupRuleHash(v interface{}) int { return hashcode.String(buf.String()) } -func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []ec2.IPPerm) []map[string]interface{} { +func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions []ec2.IPPermission) []map[string]interface{} { ruleMap := make(map[string]map[string]interface{}) for _, perm := range permissions { - k := fmt.Sprintf("%s-%d-%d", perm.Protocol, perm.FromPort, perm.ToPort) + var fromPort, toPort int + if perm.FromPort == nil { + fromPort = 0 + } else { + fromPort = *perm.FromPort + } + if perm.ToPort == nil { + toPort = 0 + } else { + toPort = *perm.ToPort + } + + k := fmt.Sprintf("%s-%d-%d", *perm.IPProtocol, fromPort, toPort) m, ok := ruleMap[k] if !ok { m = make(map[string]interface{}) ruleMap[k] = m } - m["from_port"] = perm.FromPort - m["to_port"] = perm.ToPort - m["protocol"] = perm.Protocol + m["from_port"] = fromPort + m["to_port"] = toPort + m["protocol"] = *perm.IPProtocol - if len(perm.SourceIPs) > 0 { + if len(perm.IPRanges) > 0 { raw, ok := m["cidr_blocks"] if !ok { - raw = make([]string, 0, len(perm.SourceIPs)) + raw = make([]string, 0, len(perm.IPRanges)) } list := raw.([]string) - list = append(list, perm.SourceIPs...) + for _, ip := range perm.IPRanges { + list = append(list, *ip.CIDRIP) + } + m["cidr_blocks"] = list } var groups []string - if len(perm.SourceGroups) > 0 { - groups = flattenSecurityGroups(perm.SourceGroups) + if len(perm.UserIDGroupPairs) > 0 { + groups = flattenSecurityGroupsSDK(perm.UserIDGroupPairs) } for i, id := range groups { if id == d.Id() { @@ -364,7 +382,6 @@ func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions [] for _, m := range ruleMap { rules = append(rules, m) } - return rules } @@ -383,8 +400,9 @@ func resourceAwsSecurityGroupUpdateRules( os := o.(*schema.Set) ns := n.(*schema.Set) - remove := expandIPPerms(d.Id(), os.Difference(ns).List()) - add := expandIPPerms(d.Id(), ns.Difference(os).List()) + // TODO: re-munge this when test is updated + remove := expandIPPermsSDK(d.Id(), os.Difference(ns).List()) + add := expandIPPermsSDK(d.Id(), ns.Difference(os).List()) // TODO: We need to handle partial state better in the in-between // in this update. @@ -396,34 +414,53 @@ func resourceAwsSecurityGroupUpdateRules( // not have service issues. if len(remove) > 0 || len(add) > 0 { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn + var err error if len(remove) > 0 { - // Revoke the old rules - revoke := ec2conn.RevokeSecurityGroup - if ruleset == "egress" { - revoke = ec2conn.RevokeSecurityGroupEgress - } - log.Printf("[DEBUG] Revoking security group %s %s rule: %#v", group, ruleset, remove) - if _, err := revoke(group, remove); err != nil { + + if ruleset == "egress" { + req := &ec2.RevokeSecurityGroupEgressRequest{ + GroupID: group.GroupID, + IPPermissions: remove, + } + err = ec2conn.RevokeSecurityGroupEgress(req) + } else { + req := &ec2.RevokeSecurityGroupIngressRequest{ + GroupID: group.GroupID, + IPPermissions: remove, + } + err = ec2conn.RevokeSecurityGroupIngress(req) + } + + if err != nil { return fmt.Errorf( - "Error revoking security group %s rules: %s", + "Error authorizing security group %s rules: %s", ruleset, err) } } if len(add) > 0 { - // Authorize the new rules - authorize := ec2conn.AuthorizeSecurityGroup - if ruleset == "egress" { - authorize = ec2conn.AuthorizeSecurityGroupEgress - } - log.Printf("[DEBUG] Authorizing security group %s %s rule: %#v", group, ruleset, add) - if _, err := authorize(group, add); err != nil { + // Authorize the new rules + if ruleset == "egress" { + req := &ec2.AuthorizeSecurityGroupEgressRequest{ + GroupID: group.GroupID, + IPPermissions: add, + } + err = ec2conn.AuthorizeSecurityGroupEgress(req) + } else { + req := &ec2.AuthorizeSecurityGroupIngressRequest{ + GroupID: group.GroupID, + IPPermissions: add, + } + err = ec2conn.AuthorizeSecurityGroupIngress(req) + } + + if err != nil { return fmt.Errorf( "Error authorizing security group %s rules: %s", ruleset, err) @@ -431,7 +468,6 @@ func resourceAwsSecurityGroupUpdateRules( } } } - return nil } @@ -439,10 +475,12 @@ func resourceAwsSecurityGroupUpdateRules( // a security group. func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - sgs := []ec2.SecurityGroup{ec2.SecurityGroup{Id: id}} - resp, err := conn.SecurityGroups(sgs, nil) + req := &ec2.DescribeSecurityGroupsRequest{ + GroupIDs: []string{id}, + } + resp, err := conn.DescribeSecurityGroups(req) if err != nil { - if ec2err, ok := err.(*ec2.Error); ok { + if ec2err, ok := err.(aws.APIError); ok { if ec2err.Code == "InvalidSecurityGroupID.NotFound" || ec2err.Code == "InvalidGroup.NotFound" { resp = nil @@ -460,7 +498,7 @@ func SGStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return nil, "", nil } - group := &resp.Groups[0] + group := resp.SecurityGroups[0] return group, "exists", nil } } diff --git a/builtin/providers/aws/resource_aws_security_group_test.go b/builtin/providers/aws/resource_aws_security_group_test.go index d31f9754b..c8c08c733 100644 --- a/builtin/providers/aws/resource_aws_security_group_test.go +++ b/builtin/providers/aws/resource_aws_security_group_test.go @@ -2,16 +2,18 @@ package aws import ( "fmt" + "log" "reflect" "testing" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" ) func TestAccAWSSecurityGroup_normal(t *testing.T) { - var group ec2.SecurityGroupInfo + var group ec2.SecurityGroup resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -44,16 +46,18 @@ func TestAccAWSSecurityGroup_normal(t *testing.T) { } func TestAccAWSSecurityGroup_self(t *testing.T) { - var group ec2.SecurityGroupInfo + var group ec2.SecurityGroup checkSelf := func(s *terraform.State) (err error) { defer func() { if e := recover(); e != nil { + log.Printf("\n\nbad here!!") err = fmt.Errorf("bad: %#v", group) } }() - if group.IPPerms[0].SourceGroups[0].Id != group.Id { + if *group.IPPermissions[0].UserIDGroupPairs[0].GroupID != *group.GroupID { + log.Printf("\n\n---- bad here ----\n") return fmt.Errorf("bad: %#v", group) } @@ -89,10 +93,10 @@ func TestAccAWSSecurityGroup_self(t *testing.T) { } func TestAccAWSSecurityGroup_vpc(t *testing.T) { - var group ec2.SecurityGroupInfo + var group ec2.SecurityGroup testCheck := func(*terraform.State) error { - if group.VpcId == "" { + if *group.VPCID == "" { return fmt.Errorf("should have vpc ID") } @@ -141,7 +145,7 @@ func TestAccAWSSecurityGroup_vpc(t *testing.T) { } func TestAccAWSSecurityGroup_MultiIngress(t *testing.T) { - var group ec2.SecurityGroupInfo + var group ec2.SecurityGroup resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -159,7 +163,7 @@ func TestAccAWSSecurityGroup_MultiIngress(t *testing.T) { } func TestAccAWSSecurityGroup_Change(t *testing.T) { - var group ec2.SecurityGroupInfo + var group ec2.SecurityGroup resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -184,30 +188,27 @@ func TestAccAWSSecurityGroup_Change(t *testing.T) { } func testAccCheckAWSSecurityGroupDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_security_group" { continue } - sgs := []ec2.SecurityGroup{ - ec2.SecurityGroup{ - Id: rs.Primary.ID, - }, - } - // Retrieve our group - resp, err := conn.SecurityGroups(sgs, nil) + req := &ec2.DescribeSecurityGroupsRequest{ + GroupIDs: []string{rs.Primary.ID}, + } + resp, err := conn.DescribeSecurityGroups(req) if err == nil { - if len(resp.Groups) > 0 && resp.Groups[0].Id == rs.Primary.ID { + if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupID == rs.Primary.ID { return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID) } return nil } - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(aws.APIError) if !ok { return err } @@ -220,7 +221,7 @@ func testAccCheckAWSSecurityGroupDestroy(s *terraform.State) error { return nil } -func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroupInfo) resource.TestCheckFunc { +func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -231,20 +232,19 @@ func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroupInfo) return fmt.Errorf("No Security Group is set") } - conn := testAccProvider.Meta().(*AWSClient).ec2conn - sgs := []ec2.SecurityGroup{ - ec2.SecurityGroup{ - Id: rs.Primary.ID, - }, + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + req := &ec2.DescribeSecurityGroupsRequest{ + GroupIDs: []string{rs.Primary.ID}, } - resp, err := conn.SecurityGroups(sgs, nil) + resp, err := conn.DescribeSecurityGroups(req) if err != nil { return err } - if len(resp.Groups) > 0 && resp.Groups[0].Id == rs.Primary.ID { + if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupID == rs.Primary.ID { - *group = resp.Groups[0] + log.Printf("\n==\n===\nfound group\n===\n==\n") + *group = resp.SecurityGroups[0] return nil } @@ -253,32 +253,32 @@ func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroupInfo) } } -func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroupInfo) resource.TestCheckFunc { +func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroup) resource.TestCheckFunc { return func(s *terraform.State) error { - p := ec2.IPPerm{ - FromPort: 80, - ToPort: 8000, - Protocol: "tcp", - SourceIPs: []string{"10.0.0.0/8"}, + p := ec2.IPPermission{ + FromPort: aws.Integer(80), + ToPort: aws.Integer(8000), + IPProtocol: aws.String("tcp"), + IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("10.0.0.0/8")}}, } - if group.Name != "terraform_acceptance_test_example" { - return fmt.Errorf("Bad name: %s", group.Name) + if *group.GroupName != "terraform_acceptance_test_example" { + return fmt.Errorf("Bad name: %s", *group.GroupName) } - if group.Description != "Used in the terraform acceptance tests" { - return fmt.Errorf("Bad description: %s", group.Description) + if *group.Description != "Used in the terraform acceptance tests" { + return fmt.Errorf("Bad description: %s", *group.Description) } - if len(group.IPPerms) == 0 { + if len(group.IPPermissions) == 0 { return fmt.Errorf("No IPPerms") } // Compare our ingress - if !reflect.DeepEqual(group.IPPerms[0], p) { + if !reflect.DeepEqual(group.IPPermissions[0], p) { return fmt.Errorf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", - group.IPPerms[0], + group.IPPermissions[0], p) } @@ -287,7 +287,7 @@ func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroupInfo) resour } func TestAccAWSSecurityGroup_tags(t *testing.T) { - var group ec2.SecurityGroupInfo + var group ec2.SecurityGroup resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -298,7 +298,7 @@ func TestAccAWSSecurityGroup_tags(t *testing.T) { Config: testAccAWSSecurityGroupConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group), - testAccCheckTags(&group.Tags, "foo", "bar"), + testAccCheckTagsSDK(&group.Tags, "foo", "bar"), ), }, @@ -306,56 +306,56 @@ func TestAccAWSSecurityGroup_tags(t *testing.T) { Config: testAccAWSSecurityGroupConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group), - testAccCheckTags(&group.Tags, "foo", ""), - testAccCheckTags(&group.Tags, "bar", "baz"), + testAccCheckTagsSDK(&group.Tags, "foo", ""), + testAccCheckTagsSDK(&group.Tags, "bar", "baz"), ), }, }, }) } -func testAccCheckAWSSecurityGroupAttributesChanged(group *ec2.SecurityGroupInfo) resource.TestCheckFunc { +func testAccCheckAWSSecurityGroupAttributesChanged(group *ec2.SecurityGroup) resource.TestCheckFunc { return func(s *terraform.State) error { - p := []ec2.IPPerm{ - ec2.IPPerm{ - FromPort: 80, - ToPort: 9000, - Protocol: "tcp", - SourceIPs: []string{"10.0.0.0/8"}, + p := []ec2.IPPermission{ + ec2.IPPermission{ + FromPort: aws.Integer(80), + ToPort: aws.Integer(9000), + IPProtocol: aws.String("tcp"), + IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("10.0.0.0/8")}}, }, - ec2.IPPerm{ - FromPort: 80, - ToPort: 8000, - Protocol: "tcp", - SourceIPs: []string{"0.0.0.0/0", "10.0.0.0/8"}, + ec2.IPPermission{ + FromPort: aws.Integer(80), + ToPort: aws.Integer(8000), + IPProtocol: aws.String("tcp"), + IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("0.0.0.0/0")}, ec2.IPRange{aws.String("10.0.0.0/8")}}, }, } - if group.Name != "terraform_acceptance_test_example" { - return fmt.Errorf("Bad name: %s", group.Name) + if *group.GroupName != "terraform_acceptance_test_example" { + return fmt.Errorf("Bad name: %s", *group.GroupName) } - if group.Description != "Used in the terraform acceptance tests" { - return fmt.Errorf("Bad description: %s", group.Description) + if *group.Description != "Used in the terraform acceptance tests" { + return fmt.Errorf("Bad description: %s", *group.Description) } // Compare our ingress - if len(group.IPPerms) != 2 { + if len(group.IPPermissions) != 2 { return fmt.Errorf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", - group.IPPerms, + group.IPPermissions, p) } - if group.IPPerms[0].ToPort == 8000 { - group.IPPerms[1], group.IPPerms[0] = - group.IPPerms[0], group.IPPerms[1] + if *group.IPPermissions[0].ToPort == 8000 { + group.IPPermissions[1], group.IPPermissions[0] = + group.IPPermissions[0], group.IPPermissions[1] } - if !reflect.DeepEqual(group.IPPerms, p) { + if !reflect.DeepEqual(group.IPPermissions, p) { return fmt.Errorf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", - group.IPPerms, + group.IPPermissions, p) } diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index 7d4793d3d..49f6cfc4d 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/hashicorp/aws-sdk-go/aws" + awsEC2 "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/aws-sdk-go/gen/elb" "github.com/hashicorp/aws-sdk-go/gen/rds" "github.com/hashicorp/terraform/helper/schema" @@ -89,6 +90,58 @@ func expandIPPerms(id string, configured []interface{}) []ec2.IPPerm { return perms } +// Takes the result of flatmap.Expand for an array of ingress/egress +// security group rules and returns EC2 API compatible objects +func expandIPPermsSDK(id string, configured []interface{}) []awsEC2.IPPermission { + perms := make([]awsEC2.IPPermission, len(configured)) + for i, mRaw := range configured { + var perm awsEC2.IPPermission + m := mRaw.(map[string]interface{}) + + perm.FromPort = aws.Integer(m["from_port"].(int)) + perm.ToPort = aws.Integer(m["to_port"].(int)) + perm.IPProtocol = aws.String(m["protocol"].(string)) + + var groups []string + if raw, ok := m["security_groups"]; ok { + list := raw.(*schema.Set).List() + for _, v := range list { + groups = append(groups, v.(string)) + } + } + if v, ok := m["self"]; ok && v.(bool) { + groups = append(groups, id) + } + + if len(groups) > 0 { + perm.UserIDGroupPairs = make([]awsEC2.UserIDGroupPair, len(groups)) + for i, name := range groups { + ownerId, id := "", name + if items := strings.Split(id, "/"); len(items) > 1 { + ownerId, id = items[0], items[1] + } + + perm.UserIDGroupPairs[i] = awsEC2.UserIDGroupPair{ + GroupID: aws.String(id), + UserID: aws.String(ownerId), + } + } + } + + if raw, ok := m["cidr_blocks"]; ok { + list := raw.([]interface{}) + perm.IPRanges = make([]awsEC2.IPRange, len(list)) + for i, v := range list { + perm.IPRanges[i] = awsEC2.IPRange{aws.String(v.(string))} + } + } + + perms[i] = perm + } + + return perms +} + // Takes the result of flatmap.Expand for an array of parameters and // returns Parameter API compatible objects func expandParameters(configured []interface{}) ([]rds.Parameter, error) { @@ -162,6 +215,15 @@ func flattenSecurityGroups(list []ec2.UserSecurityGroup) []string { return result } +// Flattens an array of UserSecurityGroups into a []string +func flattenSecurityGroupsSDK(list []awsEC2.UserIDGroupPair) []string { + result := make([]string, 0, len(list)) + for _, g := range list { + result = append(result, *g.GroupID) + } + return result +} + // Flattens an array of Instances into a []string func flattenInstances(list []elb.Instance) []string { result := make([]string, 0, len(list)) From bc44fdc1a7443c2c94ac5d982791ae03beb1b77c Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Mon, 9 Mar 2015 19:06:27 +0000 Subject: [PATCH 26/62] aws/Route53 record creation timeout 10->30 mins --- builtin/providers/aws/resource_aws_route53_record.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_route53_record.go b/builtin/providers/aws/resource_aws_route53_record.go index 96c7608fe..fcd781c61 100644 --- a/builtin/providers/aws/resource_aws_route53_record.go +++ b/builtin/providers/aws/resource_aws_route53_record.go @@ -138,7 +138,7 @@ func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) er Delay: 30 * time.Second, Pending: []string{"PENDING"}, Target: "INSYNC", - Timeout: 10 * time.Minute, + Timeout: 30 * time.Minute, MinTimeout: 5 * time.Second, Refresh: func() (result interface{}, state string, err error) { changeRequest := &route53.GetChangeRequest{ From 5a13ac9bc9a856e47646ed14ce99cb6ece20bd55 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Mon, 9 Mar 2015 16:15:25 -0500 Subject: [PATCH 27/62] provider/aws: Convert Main Route Table assoc. to aws-sdk-go --- ...source_aws_main_route_table_association.go | 56 ++++++++++++------- ...e_aws_main_route_table_association_test.go | 6 +- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/builtin/providers/aws/resource_aws_main_route_table_association.go b/builtin/providers/aws/resource_aws_main_route_table_association.go index f656f3760..a489b9a50 100644 --- a/builtin/providers/aws/resource_aws_main_route_table_association.go +++ b/builtin/providers/aws/resource_aws_main_route_table_association.go @@ -4,8 +4,9 @@ import ( "fmt" "log" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsMainRouteTableAssociation() *schema.Resource { @@ -39,7 +40,7 @@ func resourceAwsMainRouteTableAssociation() *schema.Resource { } func resourceAwsMainRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn vpcId := d.Get("vpc_id").(string) routeTableId := d.Get("route_table_id").(string) @@ -50,23 +51,23 @@ func resourceAwsMainRouteTableAssociationCreate(d *schema.ResourceData, meta int return err } - resp, err := ec2conn.ReassociateRouteTable( - mainAssociation.AssociationId, - routeTableId, - ) + resp, err := ec2conn.ReplaceRouteTableAssociation(&ec2.ReplaceRouteTableAssociationRequest{ + AssociationID: mainAssociation.RouteTableAssociationID, + RouteTableID: aws.String(routeTableId), + }) if err != nil { return err } - d.Set("original_route_table_id", mainAssociation.RouteTableId) - d.SetId(resp.AssociationId) + d.Set("original_route_table_id", mainAssociation.RouteTableID) + d.SetId(*resp.NewAssociationID) log.Printf("[INFO] New main route table association ID: %s", d.Id()) return nil } func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn mainAssociation, err := findMainRouteTableAssociation( ec2conn, @@ -75,7 +76,7 @@ func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta inter return err } - if mainAssociation.AssociationId != d.Id() { + if *mainAssociation.RouteTableAssociationID != d.Id() { // It seems it doesn't exist anymore, so clear the ID d.SetId("") } @@ -87,25 +88,28 @@ func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta inter // original_route_table_id - this needs to stay recorded as the AWS-created // table from VPC creation. func resourceAwsMainRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn vpcId := d.Get("vpc_id").(string) routeTableId := d.Get("route_table_id").(string) log.Printf("[INFO] Updating main route table association: %s => %s", vpcId, routeTableId) - resp, err := ec2conn.ReassociateRouteTable(d.Id(), routeTableId) + resp, err := ec2conn.ReplaceRouteTableAssociation(&ec2.ReplaceRouteTableAssociationRequest{ + AssociationID: aws.String(d.Id()), + RouteTableID: aws.String(routeTableId), + }) if err != nil { return err } - d.SetId(resp.AssociationId) + d.SetId(*resp.NewAssociationID) log.Printf("[INFO] New main route table association ID: %s", d.Id()) return nil } func resourceAwsMainRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn vpcId := d.Get("vpc_id").(string) originalRouteTableId := d.Get("original_route_table_id").(string) @@ -113,12 +117,15 @@ func resourceAwsMainRouteTableAssociationDelete(d *schema.ResourceData, meta int vpcId, originalRouteTableId) - resp, err := ec2conn.ReassociateRouteTable(d.Id(), originalRouteTableId) + resp, err := ec2conn.ReplaceRouteTableAssociation(&ec2.ReplaceRouteTableAssociationRequest{ + AssociationID: aws.String(d.Id()), + RouteTableID: aws.String(originalRouteTableId), + }) if err != nil { return err } - log.Printf("[INFO] Resulting Association ID: %s", resp.AssociationId) + log.Printf("[INFO] Resulting Association ID: %s", *resp.NewAssociationID) return nil } @@ -130,7 +137,7 @@ func findMainRouteTableAssociation(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTa } for _, a := range mainRouteTable.Associations { - if a.Main { + if *a.Main { return &a, nil } } @@ -138,10 +145,17 @@ func findMainRouteTableAssociation(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTa } func findMainRouteTable(ec2conn *ec2.EC2, vpcId string) (*ec2.RouteTable, error) { - filter := ec2.NewFilter() - filter.Add("association.main", "true") - filter.Add("vpc-id", vpcId) - routeResp, err := ec2conn.DescribeRouteTables(nil, filter) + mainFilter := ec2.Filter{ + aws.String("association.main"), + []string{"true"}, + } + vpcFilter := ec2.Filter{ + aws.String("vpc-id"), + []string{vpcId}, + } + routeResp, err := ec2conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ + Filters: []ec2.Filter{mainFilter, vpcFilter}, + }) if err != nil { return nil, err } else if len(routeResp.RouteTables) != 1 { diff --git a/builtin/providers/aws/resource_aws_main_route_table_association_test.go b/builtin/providers/aws/resource_aws_main_route_table_association_test.go index 937014cae..76e3e4d72 100644 --- a/builtin/providers/aws/resource_aws_main_route_table_association_test.go +++ b/builtin/providers/aws/resource_aws_main_route_table_association_test.go @@ -65,15 +65,15 @@ func testAccCheckMainRouteTableAssociation( return fmt.Errorf("Not found: %s", vpcResource) } - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn mainAssociation, err := findMainRouteTableAssociation(conn, vpc.Primary.ID) if err != nil { return err } - if mainAssociation.AssociationId != rs.Primary.ID { + if *mainAssociation.RouteTableAssociationID != rs.Primary.ID { return fmt.Errorf("Found wrong main association: %s", - mainAssociation.AssociationId) + *mainAssociation.RouteTableAssociationID) } return nil From 795970d5a267c665d3ff9720d39473e7b448ddb6 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Mon, 9 Mar 2015 17:11:30 -0500 Subject: [PATCH 28/62] Give route table assoc it's own copy of this method for now --- .../resource_aws_route_table_association.go | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/builtin/providers/aws/resource_aws_route_table_association.go b/builtin/providers/aws/resource_aws_route_table_association.go index 846836008..4b39a79b7 100644 --- a/builtin/providers/aws/resource_aws_route_table_association.go +++ b/builtin/providers/aws/resource_aws_route_table_association.go @@ -4,6 +4,7 @@ import ( "fmt" "log" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/mitchellh/goamz/ec2" ) @@ -129,3 +130,29 @@ func resourceAwsRouteTableAssociationDelete(d *schema.ResourceData, meta interfa return nil } + +// TODO: remove this method when converting to aws-sdk-go +// resourceAwsRouteTableStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch +// a RouteTable. +func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + resp, err := conn.DescribeRouteTables([]string{id}, ec2.NewFilter()) + if err != nil { + if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidRouteTableID.NotFound" { + resp = nil + } else { + log.Printf("Error on RouteTableStateRefresh: %s", err) + return nil, "", err + } + } + + if resp == nil { + // Sometimes AWS just has consistency issues and doesn't see + // our instance yet. Return an empty state. + return nil, "", nil + } + + rt := &resp.RouteTables[0] + return rt, "ready", nil + } +} From 30941dfdc4e6d04d8e999f700286fbd24955f5f2 Mon Sep 17 00:00:00 2001 From: Suguru Namura Date: Tue, 10 Mar 2015 19:45:56 +0900 Subject: [PATCH 29/62] providers/aws: iops in root device skipped when output state --- builtin/providers/aws/resource_aws_instance.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index ee62d305e..d0c6a3bb7 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -482,6 +482,7 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { blockDevice["device_name"] = blockDevices[vol.VolumeId].DeviceName blockDevice["volume_type"] = vol.VolumeType blockDevice["volume_size"] = volSize + blockDevice["iops"] = vol.IOPS blockDevice["delete_on_termination"] = blockDevices[vol.VolumeId].DeleteOnTermination @@ -494,7 +495,6 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { blockDevice["snapshot_id"] = vol.SnapshotId blockDevice["encrypted"] = vol.Encrypted - blockDevice["iops"] = vol.IOPS nonRootBlockDevices = append(nonRootBlockDevices, blockDevice) } d.Set("block_device", nonRootBlockDevices) From 30f401eab7bf285cdd8b0f48819881d362dec24e Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 10:23:14 -0500 Subject: [PATCH 30/62] provider/aws: Convert AWS Route Table to aws-sdk-go --- .../providers/aws/resource_aws_route_table.go | 98 +++++++++++-------- .../aws/resource_aws_route_table_test.go | 10 +- 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/builtin/providers/aws/resource_aws_route_table.go b/builtin/providers/aws/resource_aws_route_table.go index 9d01218b0..76bcd17a2 100644 --- a/builtin/providers/aws/resource_aws_route_table.go +++ b/builtin/providers/aws/resource_aws_route_table.go @@ -6,10 +6,11 @@ import ( "log" "time" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsRouteTable() *schema.Resource { @@ -61,11 +62,11 @@ func resourceAwsRouteTable() *schema.Resource { } func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Create the routing table - createOpts := &ec2.CreateRouteTable{ - VpcId: d.Get("vpc_id").(string), + createOpts := &ec2.CreateRouteTableRequest{ + VPCID: aws.String(d.Get("vpc_id").(string)), } log.Printf("[DEBUG] RouteTable create config: %#v", createOpts) @@ -75,8 +76,8 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error } // Get the ID and store it - rt := &resp.RouteTable - d.SetId(rt.RouteTableId) + rt := resp.RouteTable + d.SetId(*rt.RouteTableID) log.Printf("[INFO] Route Table ID: %s", d.Id()) // Wait for the route table to become available @@ -86,7 +87,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, Target: "ready", - Refresh: resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id()), + Refresh: resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id()), Timeout: 1 * time.Minute, } if _, err := stateConf.WaitForState(); err != nil { @@ -99,9 +100,9 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error } func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id())() + rtRaw, _, err := resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id())() if err != nil { return err } @@ -110,40 +111,48 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { } rt := rtRaw.(*ec2.RouteTable) - d.Set("vpc_id", rt.VpcId) + d.Set("vpc_id", rt.VPCID) // Create an empty schema.Set to hold all routes route := &schema.Set{F: resourceAwsRouteTableHash} // Loop through the routes and add them to the set for _, r := range rt.Routes { - if r.GatewayId == "local" { + if r.GatewayID != nil && *r.GatewayID == "local" { continue } - if r.Origin == "EnableVgwRoutePropagation" { + if r.Origin != nil && *r.Origin == "EnableVgwRoutePropagation" { continue } m := make(map[string]interface{}) - m["cidr_block"] = r.DestinationCidrBlock - m["gateway_id"] = r.GatewayId - m["instance_id"] = r.InstanceId - m["vpc_peering_connection_id"] = r.VpcPeeringConnectionId + if r.DestinationCIDRBlock != nil { + m["cidr_block"] = *r.DestinationCIDRBlock + } + if r.GatewayID != nil { + m["gateway_id"] = *r.GatewayID + } + if r.InstanceID != nil { + m["instance_id"] = *r.InstanceID + } + if r.VPCPeeringConnectionID != nil { + m["vpc_peering_connection_id"] = *r.VPCPeeringConnectionID + } route.Add(m) } d.Set("route", route) // Tags - d.Set("tags", tagsToMap(rt.Tags)) + d.Set("tags", tagsToMapSDK(rt.Tags)) return nil } func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Check if the route set as a whole has changed if d.HasChange("route") { @@ -159,8 +168,10 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error log.Printf( "[INFO] Deleting route from %s: %s", d.Id(), m["cidr_block"].(string)) - _, err := ec2conn.DeleteRoute( - d.Id(), m["cidr_block"].(string)) + err := ec2conn.DeleteRoute(&ec2.DeleteRouteRequest{ + RouteTableID: aws.String(d.Id()), + DestinationCIDRBlock: aws.String(m["cidr_block"].(string)), + }) if err != nil { return err } @@ -174,17 +185,16 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error for _, route := range nrs.List() { m := route.(map[string]interface{}) - opts := ec2.CreateRoute{ - RouteTableId: d.Id(), - DestinationCidrBlock: m["cidr_block"].(string), - GatewayId: m["gateway_id"].(string), - InstanceId: m["instance_id"].(string), - VpcPeeringConnectionId: m["vpc_peering_connection_id"].(string), + opts := ec2.CreateRouteRequest{ + RouteTableID: aws.String(d.Id()), + DestinationCIDRBlock: aws.String(m["cidr_block"].(string)), + GatewayID: aws.String(m["gateway_id"].(string)), + InstanceID: aws.String(m["instance_id"].(string)), + VPCPeeringConnectionID: aws.String(m["vpc_peering_connection_id"].(string)), } log.Printf("[INFO] Creating route for %s: %#v", d.Id(), opts) - _, err := ec2conn.CreateRoute(&opts) - if err != nil { + if err := ec2conn.CreateRoute(&opts); err != nil { return err } @@ -193,7 +203,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error } } - if err := setTags(ec2conn, d); err != nil { + if err := setTagsSDK(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") @@ -203,11 +213,11 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error } func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn // First request the routing table since we'll have to disassociate // all the subnets first. - rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id())() + rtRaw, _, err := resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id())() if err != nil { return err } @@ -218,16 +228,22 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error // Do all the disassociations for _, a := range rt.Associations { - log.Printf("[INFO] Disassociating association: %s", a.AssociationId) - if _, err := ec2conn.DisassociateRouteTable(a.AssociationId); err != nil { + log.Printf("[INFO] Disassociating association: %s", *a.RouteTableAssociationID) + err := ec2conn.DisassociateRouteTable(&ec2.DisassociateRouteTableRequest{ + AssociationID: a.RouteTableAssociationID, + }) + if err != nil { return err } } // Delete the route table log.Printf("[INFO] Deleting Route Table: %s", d.Id()) - if _, err := ec2conn.DeleteRouteTable(d.Id()); err != nil { - ec2err, ok := err.(*ec2.Error) + err = ec2conn.DeleteRouteTable(&ec2.DeleteRouteTableRequest{ + RouteTableID: aws.String(d.Id()), + }) + if err != nil { + ec2err, ok := err.(aws.APIError) if ok && ec2err.Code == "InvalidRouteTableID.NotFound" { return nil } @@ -243,7 +259,7 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error stateConf := &resource.StateChangeConf{ Pending: []string{"ready"}, Target: "", - Refresh: resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id()), + Refresh: resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id()), Timeout: 1 * time.Minute, } if _, err := stateConf.WaitForState(); err != nil { @@ -275,13 +291,15 @@ func resourceAwsRouteTableHash(v interface{}) int { return hashcode.String(buf.String()) } -// resourceAwsRouteTableStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch +// resourceAwsRouteTableStateRefreshFuncSDK returns a resource.StateRefreshFunc that is used to watch // a RouteTable. -func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { +func resourceAwsRouteTableStateRefreshFuncSDK(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := conn.DescribeRouteTables([]string{id}, ec2.NewFilter()) + resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ + RouteTableIDs: []string{id}, + }) if err != nil { - if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidRouteTableID.NotFound" { + if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidRouteTableID.NotFound" { resp = nil } else { log.Printf("Error on RouteTableStateRefresh: %s", err) diff --git a/builtin/providers/aws/resource_aws_route_table_test.go b/builtin/providers/aws/resource_aws_route_table_test.go index 2f4dfab2e..944f0c570 100644 --- a/builtin/providers/aws/resource_aws_route_table_test.go +++ b/builtin/providers/aws/resource_aws_route_table_test.go @@ -208,7 +208,10 @@ func testAccCheckRouteTableExists(n string, v *ec2.RouteTable) resource.TestChec } } -func TestAccAWSRouteTable_vpcPeering(t *testing.T) { +// TODO: re-enable this test. +// VPC Peering connections are prefixed with pcx +// Right now there is no VPC Peering resource +func _TestAccAWSRouteTable_vpcPeering(t *testing.T) { var v ec2.RouteTable testCheck := func(*terraform.State) error { @@ -345,6 +348,9 @@ resource "aws_route_table" "foo" { } ` +// TODO: re-enable this test. +// VPC Peering connections are prefixed with pcx +// Right now there is no VPC Peering resource const testAccRouteTableVpcPeeringConfig = ` resource "aws_vpc" "foo" { cidr_block = "10.1.0.0/16" @@ -359,7 +365,7 @@ resource "aws_route_table" "foo" { route { cidr_block = "10.2.0.0/16" - vpc_peering_connection_id = "vpc-12345" + vpc_peering_connection_id = "pcx-12345" } } ` From e7b3f3cf17605970515d4554b10c4b0f55ae1a4b Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 10:30:01 -0500 Subject: [PATCH 31/62] convert route table tests to aws-sdk-go --- .../aws/resource_aws_route_table_test.go | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/builtin/providers/aws/resource_aws_route_table_test.go b/builtin/providers/aws/resource_aws_route_table_test.go index 944f0c570..5e6f90026 100644 --- a/builtin/providers/aws/resource_aws_route_table_test.go +++ b/builtin/providers/aws/resource_aws_route_table_test.go @@ -4,9 +4,10 @@ import ( "fmt" "testing" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" ) func TestAccAWSRouteTable_normal(t *testing.T) { @@ -19,7 +20,7 @@ func TestAccAWSRouteTable_normal(t *testing.T) { routes := make(map[string]ec2.Route) for _, r := range v.Routes { - routes[r.DestinationCidrBlock] = r + routes[*r.DestinationCIDRBlock] = r } if _, ok := routes["10.1.0.0/16"]; !ok { @@ -39,7 +40,7 @@ func TestAccAWSRouteTable_normal(t *testing.T) { routes := make(map[string]ec2.Route) for _, r := range v.Routes { - routes[r.DestinationCidrBlock] = r + routes[*r.DestinationCIDRBlock] = r } if _, ok := routes["10.1.0.0/16"]; !ok { @@ -91,7 +92,7 @@ func TestAccAWSRouteTable_instance(t *testing.T) { routes := make(map[string]ec2.Route) for _, r := range v.Routes { - routes[r.DestinationCidrBlock] = r + routes[*r.DestinationCIDRBlock] = r } if _, ok := routes["10.1.0.0/16"]; !ok { @@ -133,7 +134,7 @@ func TestAccAWSRouteTable_tags(t *testing.T) { Config: testAccRouteTableConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists("aws_route_table.foo", &route_table), - testAccCheckTags(&route_table.Tags, "foo", "bar"), + testAccCheckTagsSDK(&route_table.Tags, "foo", "bar"), ), }, @@ -141,8 +142,8 @@ func TestAccAWSRouteTable_tags(t *testing.T) { Config: testAccRouteTableConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists("aws_route_table.foo", &route_table), - testAccCheckTags(&route_table.Tags, "foo", ""), - testAccCheckTags(&route_table.Tags, "bar", "baz"), + testAccCheckTagsSDK(&route_table.Tags, "foo", ""), + testAccCheckTagsSDK(&route_table.Tags, "bar", "baz"), ), }, }, @@ -150,7 +151,7 @@ func TestAccAWSRouteTable_tags(t *testing.T) { } func testAccCheckRouteTableDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_route_table" { @@ -158,8 +159,9 @@ func testAccCheckRouteTableDestroy(s *terraform.State) error { } // Try to find the resource - resp, err := conn.DescribeRouteTables( - []string{rs.Primary.ID}, ec2.NewFilter()) + resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ + RouteTableIDs: []string{rs.Primary.ID}, + }) if err == nil { if len(resp.RouteTables) > 0 { return fmt.Errorf("still exist.") @@ -169,7 +171,7 @@ func testAccCheckRouteTableDestroy(s *terraform.State) error { } // Verify the error is what we want - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(aws.APIError) if !ok { return err } @@ -192,9 +194,10 @@ func testAccCheckRouteTableExists(n string, v *ec2.RouteTable) resource.TestChec return fmt.Errorf("No ID is set") } - conn := testAccProvider.Meta().(*AWSClient).ec2conn - resp, err := conn.DescribeRouteTables( - []string{rs.Primary.ID}, ec2.NewFilter()) + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ + RouteTableIDs: []string{rs.Primary.ID}, + }) if err != nil { return err } @@ -221,7 +224,7 @@ func _TestAccAWSRouteTable_vpcPeering(t *testing.T) { routes := make(map[string]ec2.Route) for _, r := range v.Routes { - routes[r.DestinationCidrBlock] = r + routes[*r.DestinationCIDRBlock] = r } if _, ok := routes["10.1.0.0/16"]; !ok { From fe293f909e161664464ee3819444c37d3bb0cc1e Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 14:44:07 -0500 Subject: [PATCH 32/62] provider/aws: Add env default for AWS_ACCOUNT_ID in VPC Peering connection --- .../providers/aws/resource_aws_vpc_peering_connection.go | 7 ++++--- .../aws/resource_aws_vpc_peering_connection_test.go | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection.go b/builtin/providers/aws/resource_aws_vpc_peering_connection.go index a8316c114..b3cb1d2d8 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection.go @@ -19,9 +19,10 @@ func resourceAwsVpcPeeringConnection() *schema.Resource { Schema: map[string]*schema.Schema{ "peer_owner_id": &schema.Schema{ - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + DefaultFunc: schema.EnvDefaultFunc("AWS_ACCOUNT_ID", nil), }, "peer_vpc_id": &schema.Schema{ Type: schema.TypeString, diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go index 2b4b71e33..569bf96d0 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go @@ -68,11 +68,10 @@ resource "aws_vpc" "foo" { } resource "aws_vpc" "bar" { - cidr_block = "10.0.1.0/16" + cidr_block = "10.1.0.0/16" } resource "aws_vpc_peering_connection" "foo" { - peer_owner_id = "12345" vpc_id = "${aws_vpc.foo.id}" peer_vpc_id = "${aws_vpc.bar.id}" } From 30125e3a5f2dd082616f08bb9b95275932b3f49b Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 15:18:30 -0500 Subject: [PATCH 33/62] providers/aws: Convert AWS VPC Peering to aws-sdk-go --- .../resource_aws_vpc_peering_connection.go | 50 +++++++++++-------- ...esource_aws_vpc_peering_connection_test.go | 11 ++-- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection.go b/builtin/providers/aws/resource_aws_vpc_peering_connection.go index b3cb1d2d8..06f50f01c 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection.go @@ -5,9 +5,10 @@ import ( "log" "time" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsVpcPeeringConnection() *schema.Resource { @@ -40,23 +41,23 @@ func resourceAwsVpcPeeringConnection() *schema.Resource { } func resourceAwsVpcPeeringCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Create the vpc peering connection - createOpts := &ec2.CreateVpcPeeringConnection{ - PeerOwnerId: d.Get("peer_owner_id").(string), - PeerVpcId: d.Get("peer_vpc_id").(string), - VpcId: d.Get("vpc_id").(string), + createOpts := &ec2.CreateVPCPeeringConnectionRequest{ + PeerOwnerID: aws.String(d.Get("peer_owner_id").(string)), + PeerVPCID: aws.String(d.Get("peer_vpc_id").(string)), + VPCID: aws.String(d.Get("vpc_id").(string)), } log.Printf("[DEBUG] VpcPeeringCreate create config: %#v", createOpts) - resp, err := ec2conn.CreateVpcPeeringConnection(createOpts) + resp, err := ec2conn.CreateVPCPeeringConnection(createOpts) if err != nil { return fmt.Errorf("Error creating vpc peering connection: %s", err) } // Get the ID and store it - rt := &resp.VpcPeeringConnection - d.SetId(rt.VpcPeeringConnectionId) + rt := resp.VPCPeeringConnection + d.SetId(*rt.VPCPeeringConnectionID) log.Printf("[INFO] Vpc Peering Connection ID: %s", d.Id()) // Wait for the vpc peering connection to become available @@ -79,7 +80,7 @@ func resourceAwsVpcPeeringCreate(d *schema.ResourceData, meta interface{}) error } func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn pcRaw, _, err := resourceAwsVpcPeeringConnectionStateRefreshFunc(ec2conn, d.Id())() if err != nil { return err @@ -89,20 +90,20 @@ func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error { return nil } - pc := pcRaw.(*ec2.VpcPeeringConnection) + pc := pcRaw.(*ec2.VPCPeeringConnection) - d.Set("peer_owner_id", pc.AccepterVpcInfo.OwnerId) - d.Set("peer_vpc_id", pc.AccepterVpcInfo.VpcId) - d.Set("vpc_id", pc.RequesterVpcInfo.VpcId) - d.Set("tags", tagsToMap(pc.Tags)) + d.Set("peer_owner_id", pc.AccepterVPCInfo.OwnerID) + d.Set("peer_vpc_id", pc.AccepterVPCInfo.VPCID) + d.Set("vpc_id", pc.RequesterVPCInfo.VPCID) + d.Set("tags", tagsToMapSDK(pc.Tags)) return nil } func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn - if err := setTags(ec2conn, d); err != nil { + if err := setTagsSDK(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") @@ -112,9 +113,12 @@ func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error } func resourceAwsVpcPeeringDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn - _, err := ec2conn.DeleteVpcPeeringConnection(d.Id()) + _, err := ec2conn.DeleteVPCPeeringConnection( + &ec2.DeleteVPCPeeringConnectionRequest{ + VPCPeeringConnectionID: aws.String(d.Id()), + }) return err } @@ -123,9 +127,11 @@ func resourceAwsVpcPeeringDelete(d *schema.ResourceData, meta interface{}) error func resourceAwsVpcPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - resp, err := conn.DescribeVpcPeeringConnection([]string{id}, ec2.NewFilter()) + resp, err := conn.DescribeVPCPeeringConnections(&ec2.DescribeVPCPeeringConnectionsRequest{ + VPCPeeringConnectionIDs: []string{id}, + }) if err != nil { - if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidVpcPeeringConnectionID.NotFound" { + if ec2err, ok := err.(aws.APIError); ok && ec2err.Code == "InvalidVpcPeeringConnectionID.NotFound" { resp = nil } else { log.Printf("Error on VpcPeeringConnectionStateRefresh: %s", err) @@ -139,7 +145,7 @@ func resourceAwsVpcPeeringConnectionStateRefreshFunc(conn *ec2.EC2, id string) r return nil, "", nil } - pc := &resp.VpcPeeringConnections[0] + pc := &resp.VPCPeeringConnections[0] return pc, "ready", nil } diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go index 569bf96d0..307dcb7d9 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go @@ -4,9 +4,9 @@ import ( "fmt" "testing" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" ) func TestAccAWSVPCPeeringConnection_normal(t *testing.T) { @@ -28,17 +28,20 @@ func TestAccAWSVPCPeeringConnection_normal(t *testing.T) { } func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_vpc_peering_connection" { continue } - describe, err := conn.DescribeVpcPeeringConnection([]string{rs.Primary.ID}, ec2.NewFilter()) + describe, err := conn.DescribeVPCPeeringConnections( + &ec2.DescribeVPCPeeringConnectionsRequest{ + VPCPeeringConnectionIDs: []string{rs.Primary.ID}, + }) if err == nil { - if len(describe.VpcPeeringConnections) != 0 { + if len(describe.VPCPeeringConnections) != 0 { return fmt.Errorf("vpc peering connection still exists") } } From a22c23ad42d9977de39bf331e40615495c2a6eb3 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 15:55:49 -0500 Subject: [PATCH 34/62] clean up debug output to make go vet happy --- builtin/providers/aws/resource_aws_security_group.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index a0b09a55a..4283332d9 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -418,7 +418,7 @@ func resourceAwsSecurityGroupUpdateRules( var err error if len(remove) > 0 { - log.Printf("[DEBUG] Revoking security group %s %s rule: %#v", + log.Printf("[DEBUG] Revoking security group %#v %s rule: %#v", group, ruleset, remove) if ruleset == "egress" { @@ -443,7 +443,7 @@ func resourceAwsSecurityGroupUpdateRules( } if len(add) > 0 { - log.Printf("[DEBUG] Authorizing security group %s %s rule: %#v", + log.Printf("[DEBUG] Authorizing security group %#v %s rule: %#v", group, ruleset, add) // Authorize the new rules if ruleset == "egress" { From 3977256c17d72a036980600522158415620bbdf1 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 16:33:15 -0500 Subject: [PATCH 35/62] Cleansup: Restore expandIPPerms, remove flattenIPPerms --- .../aws/resource_aws_security_group.go | 4 +- .../aws/resource_aws_security_group_test.go | 2 - builtin/providers/aws/structure.go | 79 +--------- builtin/providers/aws/structure_test.go | 139 +++++------------- 4 files changed, 43 insertions(+), 181 deletions(-) diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index 4283332d9..4a7153cc7 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -401,8 +401,8 @@ func resourceAwsSecurityGroupUpdateRules( ns := n.(*schema.Set) // TODO: re-munge this when test is updated - remove := expandIPPermsSDK(d.Id(), os.Difference(ns).List()) - add := expandIPPermsSDK(d.Id(), ns.Difference(os).List()) + remove := expandIPPerms(d.Id(), os.Difference(ns).List()) + add := expandIPPerms(d.Id(), ns.Difference(os).List()) // TODO: We need to handle partial state better in the in-between // in this update. diff --git a/builtin/providers/aws/resource_aws_security_group_test.go b/builtin/providers/aws/resource_aws_security_group_test.go index c8c08c733..c292c80d6 100644 --- a/builtin/providers/aws/resource_aws_security_group_test.go +++ b/builtin/providers/aws/resource_aws_security_group_test.go @@ -51,13 +51,11 @@ func TestAccAWSSecurityGroup_self(t *testing.T) { checkSelf := func(s *terraform.State) (err error) { defer func() { if e := recover(); e != nil { - log.Printf("\n\nbad here!!") err = fmt.Errorf("bad: %#v", group) } }() if *group.IPPermissions[0].UserIDGroupPairs[0].GroupID != *group.GroupID { - log.Printf("\n\n---- bad here ----\n") return fmt.Errorf("bad: %#v", group) } diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index 49f6cfc4d..910f748e6 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -40,59 +40,7 @@ func expandListeners(configured []interface{}) ([]elb.Listener, error) { // Takes the result of flatmap.Expand for an array of ingress/egress // security group rules and returns EC2 API compatible objects -func expandIPPerms(id string, configured []interface{}) []ec2.IPPerm { - perms := make([]ec2.IPPerm, len(configured)) - for i, mRaw := range configured { - var perm ec2.IPPerm - m := mRaw.(map[string]interface{}) - - perm.FromPort = m["from_port"].(int) - perm.ToPort = m["to_port"].(int) - perm.Protocol = m["protocol"].(string) - - var groups []string - if raw, ok := m["security_groups"]; ok { - list := raw.(*schema.Set).List() - for _, v := range list { - groups = append(groups, v.(string)) - } - } - if v, ok := m["self"]; ok && v.(bool) { - groups = append(groups, id) - } - - if len(groups) > 0 { - perm.SourceGroups = make([]ec2.UserSecurityGroup, len(groups)) - for i, name := range groups { - ownerId, id := "", name - if items := strings.Split(id, "/"); len(items) > 1 { - ownerId, id = items[0], items[1] - } - - perm.SourceGroups[i] = ec2.UserSecurityGroup{ - Id: id, - OwnerId: ownerId, - } - } - } - - if raw, ok := m["cidr_blocks"]; ok { - list := raw.([]interface{}) - perm.SourceIPs = make([]string, len(list)) - for i, v := range list { - perm.SourceIPs[i] = v.(string) - } - } - - perms[i] = perm - } - - return perms -} - -// Takes the result of flatmap.Expand for an array of ingress/egress -// security group rules and returns EC2 API compatible objects -func expandIPPermsSDK(id string, configured []interface{}) []awsEC2.IPPermission { +func expandIPPerms(id string, configured []interface{}) []awsEC2.IPPermission { perms := make([]awsEC2.IPPermission, len(configured)) for i, mRaw := range configured { var perm awsEC2.IPPermission @@ -164,31 +112,6 @@ func expandParameters(configured []interface{}) ([]rds.Parameter, error) { return parameters, nil } -// Flattens an array of ipPerms into a list of primitives that -// flatmap.Flatten() can handle -func flattenIPPerms(list []ec2.IPPerm) []map[string]interface{} { - result := make([]map[string]interface{}, 0, len(list)) - - for _, perm := range list { - n := make(map[string]interface{}) - n["from_port"] = perm.FromPort - n["protocol"] = perm.Protocol - n["to_port"] = perm.ToPort - - if len(perm.SourceIPs) > 0 { - n["cidr_blocks"] = perm.SourceIPs - } - - if v := flattenSecurityGroups(perm.SourceGroups); len(v) > 0 { - n["security_groups"] = v - } - - result = append(result, n) - } - - return result -} - // Flattens a health check into something that flatmap.Flatten() // can handle func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} { diff --git a/builtin/providers/aws/structure_test.go b/builtin/providers/aws/structure_test.go index f3a8bcc72..fdee02585 100644 --- a/builtin/providers/aws/structure_test.go +++ b/builtin/providers/aws/structure_test.go @@ -1,16 +1,17 @@ package aws import ( + "log" "reflect" "testing" "github.com/hashicorp/aws-sdk-go/aws" + awsEC2 "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/aws-sdk-go/gen/elb" "github.com/hashicorp/aws-sdk-go/gen/rds" "github.com/hashicorp/terraform/flatmap" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) // Returns test configuration @@ -61,120 +62,60 @@ func TestExpandIPPerms(t *testing.T) { } perms := expandIPPerms("foo", expanded) - expected := []ec2.IPPerm{ - ec2.IPPerm{ - Protocol: "icmp", - FromPort: 1, - ToPort: -1, - SourceIPs: []string{"0.0.0.0/0"}, - SourceGroups: []ec2.UserSecurityGroup{ - ec2.UserSecurityGroup{ - OwnerId: "foo", - Id: "sg-22222", + log.Printf("wtf is perms:\n%#v", perms) + + expected := []awsEC2.IPPermission{ + awsEC2.IPPermission{ + IPProtocol: aws.String("icmp"), + FromPort: aws.Integer(1), + ToPort: aws.Integer(-1), + IPRanges: []awsEC2.IPRange{awsEC2.IPRange{aws.String("0.0.0.0/0")}}, + UserIDGroupPairs: []awsEC2.UserIDGroupPair{ + awsEC2.UserIDGroupPair{ + UserID: aws.String("foo"), + GroupID: aws.String("sg-22222"), }, - ec2.UserSecurityGroup{ - Id: "sg-11111", + awsEC2.UserIDGroupPair{ + GroupID: aws.String("sg-22222"), }, }, }, - ec2.IPPerm{ - Protocol: "icmp", - FromPort: 1, - ToPort: -1, - SourceGroups: []ec2.UserSecurityGroup{ - ec2.UserSecurityGroup{ - Id: "foo", + awsEC2.IPPermission{ + IPProtocol: aws.String("icmp"), + FromPort: aws.Integer(1), + ToPort: aws.Integer(-1), + UserIDGroupPairs: []awsEC2.UserIDGroupPair{ + awsEC2.UserIDGroupPair{ + UserID: aws.String("foo"), }, }, }, } - if !reflect.DeepEqual(perms, expected) { + exp := expected[0] + perm := perms[0] + + if *exp.FromPort != *perm.FromPort { t.Fatalf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", - perms[0], - expected) + *perm.FromPort, + *exp.FromPort) } -} - -func TestFlattenIPPerms(t *testing.T) { - cases := []struct { - Input []ec2.IPPerm - Output []map[string]interface{} - }{ - { - Input: []ec2.IPPerm{ - ec2.IPPerm{ - Protocol: "icmp", - FromPort: 1, - ToPort: -1, - SourceIPs: []string{"0.0.0.0/0"}, - SourceGroups: []ec2.UserSecurityGroup{ - ec2.UserSecurityGroup{ - Id: "sg-11111", - }, - }, - }, - }, - - Output: []map[string]interface{}{ - map[string]interface{}{ - "protocol": "icmp", - "from_port": 1, - "to_port": -1, - "cidr_blocks": []string{"0.0.0.0/0"}, - "security_groups": []string{"sg-11111"}, - }, - }, - }, - - { - Input: []ec2.IPPerm{ - ec2.IPPerm{ - Protocol: "icmp", - FromPort: 1, - ToPort: -1, - SourceIPs: []string{"0.0.0.0/0"}, - SourceGroups: nil, - }, - }, - - Output: []map[string]interface{}{ - map[string]interface{}{ - "protocol": "icmp", - "from_port": 1, - "to_port": -1, - "cidr_blocks": []string{"0.0.0.0/0"}, - }, - }, - }, - { - Input: []ec2.IPPerm{ - ec2.IPPerm{ - Protocol: "icmp", - FromPort: 1, - ToPort: -1, - SourceIPs: nil, - }, - }, - - Output: []map[string]interface{}{ - map[string]interface{}{ - "protocol": "icmp", - "from_port": 1, - "to_port": -1, - }, - }, - }, + if *exp.IPRanges[0].CIDRIP != *perm.IPRanges[0].CIDRIP { + t.Fatalf( + "Got:\n\n%#v\n\nExpected:\n\n%#v\n", + *perm.IPRanges[0].CIDRIP, + *exp.IPRanges[0].CIDRIP) } - for _, tc := range cases { - output := flattenIPPerms(tc.Input) - if !reflect.DeepEqual(output, tc.Output) { - t.Fatalf("Input:\n\n%#v\n\nOutput:\n\n%#v", tc.Input, output) - } + if *exp.UserIDGroupPairs[0].UserID != *perm.UserIDGroupPairs[0].UserID { + t.Fatalf( + "Got:\n\n%#v\n\nExpected:\n\n%#v\n", + *perm.UserIDGroupPairs[0].UserID, + *exp.UserIDGroupPairs[0].UserID) } + } func TestExpandListeners(t *testing.T) { From b038e5f720e4f740a53af29d6ca1c17b61ec3cb8 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Mon, 9 Mar 2015 17:11:30 -0500 Subject: [PATCH 36/62] provider/aws: Convert AWS Route Table Association to aws-sdk-go --- .../resource_aws_route_table_association.go | 43 +++++++++++-------- ...source_aws_route_table_association_test.go | 21 +++++---- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/builtin/providers/aws/resource_aws_route_table_association.go b/builtin/providers/aws/resource_aws_route_table_association.go index 4b39a79b7..3a566a56b 100644 --- a/builtin/providers/aws/resource_aws_route_table_association.go +++ b/builtin/providers/aws/resource_aws_route_table_association.go @@ -4,9 +4,10 @@ import ( "fmt" "log" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsRouteTableAssociation() *schema.Resource { @@ -32,30 +33,31 @@ func resourceAwsRouteTableAssociation() *schema.Resource { } func resourceAwsRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn log.Printf( "[INFO] Creating route table association: %s => %s", d.Get("subnet_id").(string), d.Get("route_table_id").(string)) - resp, err := ec2conn.AssociateRouteTable( - d.Get("route_table_id").(string), - d.Get("subnet_id").(string)) + resp, err := ec2conn.AssociateRouteTable(&ec2.AssociateRouteTableRequest{ + RouteTableID: aws.String(d.Get("route_table_id").(string)), + SubnetID: aws.String(d.Get("subnet_id").(string)), + }) if err != nil { return err } // Set the ID and return - d.SetId(resp.AssociationId) + d.SetId(*resp.AssociationID) log.Printf("[INFO] Association ID: %s", d.Id()) return nil } func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Get the routing table that this association belongs to rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc( @@ -71,9 +73,9 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface // Inspect that the association exists found := false for _, a := range rt.Associations { - if a.AssociationId == d.Id() { + if *a.RouteTableAssociationID == d.Id() { found = true - d.Set("subnet_id", a.SubnetId) + d.Set("subnet_id", *a.SubnetID) break } } @@ -87,19 +89,21 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface } func resourceAwsRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn log.Printf( "[INFO] Creating route table association: %s => %s", d.Get("subnet_id").(string), d.Get("route_table_id").(string)) - resp, err := ec2conn.ReassociateRouteTable( - d.Id(), - d.Get("route_table_id").(string)) + req := &ec2.ReplaceRouteTableAssociationRequest{ + AssociationID: aws.String(d.Id()), + RouteTableID: aws.String(d.Get("route_table_id").(string)), + } + resp, err := ec2conn.ReplaceRouteTableAssociation(req) if err != nil { - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(aws.APIError) if ok && ec2err.Code == "InvalidAssociationID.NotFound" { // Not found, so just create a new one return resourceAwsRouteTableAssociationCreate(d, meta) @@ -109,18 +113,21 @@ func resourceAwsRouteTableAssociationUpdate(d *schema.ResourceData, meta interfa } // Update the ID - d.SetId(resp.AssociationId) + d.SetId(*resp.NewAssociationID) log.Printf("[INFO] Association ID: %s", d.Id()) return nil } func resourceAwsRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn log.Printf("[INFO] Deleting route table association: %s", d.Id()) - if _, err := ec2conn.DisassociateRouteTable(d.Id()); err != nil { - ec2err, ok := err.(*ec2.Error) + err := ec2conn.DisassociateRouteTable(&ec2.DisassociateRouteTableRequest{ + AssociationID: aws.String(d.Id()), + }) + if err != nil { + ec2err, ok := err.(aws.APIError) if ok && ec2err.Code == "InvalidAssociationID.NotFound" { return nil } diff --git a/builtin/providers/aws/resource_aws_route_table_association_test.go b/builtin/providers/aws/resource_aws_route_table_association_test.go index 079fb41f8..e0a591be4 100644 --- a/builtin/providers/aws/resource_aws_route_table_association_test.go +++ b/builtin/providers/aws/resource_aws_route_table_association_test.go @@ -4,9 +4,10 @@ import ( "fmt" "testing" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" ) func TestAccAWSRouteTableAssociation(t *testing.T) { @@ -37,7 +38,7 @@ func TestAccAWSRouteTableAssociation(t *testing.T) { } func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_route_table_association" { @@ -45,11 +46,12 @@ func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error { } // Try to find the resource - resp, err := conn.DescribeRouteTables( - []string{rs.Primary.Attributes["route_table_Id"]}, ec2.NewFilter()) + resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ + RouteTableIDs: []string{rs.Primary.Attributes["route_table_id"]}, + }) if err != nil { // Verify the error is what we want - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(aws.APIError) if !ok { return err } @@ -62,7 +64,7 @@ func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error { rt := resp.RouteTables[0] if len(rt.Associations) > 0 { return fmt.Errorf( - "route table %s has associations", rt.RouteTableId) + "route table %s has associations", rt.RouteTableID) } } @@ -81,9 +83,10 @@ func testAccCheckRouteTableAssociationExists(n string, v *ec2.RouteTable) resour return fmt.Errorf("No ID is set") } - conn := testAccProvider.Meta().(*AWSClient).ec2conn - resp, err := conn.DescribeRouteTables( - []string{rs.Primary.Attributes["route_table_id"]}, ec2.NewFilter()) + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ + RouteTableIDs: []string{rs.Primary.Attributes["route_table_id"]}, + }) if err != nil { return err } From 3c3b7d51a27d742b4e1ffe0f3bc44a8f98c0ec90 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 16:52:09 -0500 Subject: [PATCH 37/62] remove duplicated function --- .../providers/aws/resource_aws_route_table.go | 12 ++++----- .../resource_aws_route_table_association.go | 27 ------------------- 2 files changed, 6 insertions(+), 33 deletions(-) diff --git a/builtin/providers/aws/resource_aws_route_table.go b/builtin/providers/aws/resource_aws_route_table.go index 76bcd17a2..0290d053f 100644 --- a/builtin/providers/aws/resource_aws_route_table.go +++ b/builtin/providers/aws/resource_aws_route_table.go @@ -87,7 +87,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, Target: "ready", - Refresh: resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id()), + Refresh: resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id()), Timeout: 1 * time.Minute, } if _, err := stateConf.WaitForState(); err != nil { @@ -102,7 +102,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { ec2conn := meta.(*AWSClient).awsEC2conn - rtRaw, _, err := resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id())() + rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id())() if err != nil { return err } @@ -217,7 +217,7 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error // First request the routing table since we'll have to disassociate // all the subnets first. - rtRaw, _, err := resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id())() + rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id())() if err != nil { return err } @@ -259,7 +259,7 @@ func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error stateConf := &resource.StateChangeConf{ Pending: []string{"ready"}, Target: "", - Refresh: resourceAwsRouteTableStateRefreshFuncSDK(ec2conn, d.Id()), + Refresh: resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id()), Timeout: 1 * time.Minute, } if _, err := stateConf.WaitForState(); err != nil { @@ -291,9 +291,9 @@ func resourceAwsRouteTableHash(v interface{}) int { return hashcode.String(buf.String()) } -// resourceAwsRouteTableStateRefreshFuncSDK returns a resource.StateRefreshFunc that is used to watch +// resourceAwsRouteTableStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a RouteTable. -func resourceAwsRouteTableStateRefreshFuncSDK(conn *ec2.EC2, id string) resource.StateRefreshFunc { +func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ RouteTableIDs: []string{id}, diff --git a/builtin/providers/aws/resource_aws_route_table_association.go b/builtin/providers/aws/resource_aws_route_table_association.go index 3a566a56b..a9a614f7f 100644 --- a/builtin/providers/aws/resource_aws_route_table_association.go +++ b/builtin/providers/aws/resource_aws_route_table_association.go @@ -6,7 +6,6 @@ import ( "github.com/hashicorp/aws-sdk-go/aws" "github.com/hashicorp/aws-sdk-go/gen/ec2" - "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" ) @@ -137,29 +136,3 @@ func resourceAwsRouteTableAssociationDelete(d *schema.ResourceData, meta interfa return nil } - -// TODO: remove this method when converting to aws-sdk-go -// resourceAwsRouteTableStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch -// a RouteTable. -func resourceAwsRouteTableStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - resp, err := conn.DescribeRouteTables([]string{id}, ec2.NewFilter()) - if err != nil { - if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidRouteTableID.NotFound" { - resp = nil - } else { - log.Printf("Error on RouteTableStateRefresh: %s", err) - return nil, "", err - } - } - - if resp == nil { - // Sometimes AWS just has consistency issues and doesn't see - // our instance yet. Return an empty state. - return nil, "", nil - } - - rt := &resp.RouteTables[0] - return rt, "ready", nil - } -} From 314453abe5dd68fdd2b4e6324345bdbcd9e1faa0 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Tue, 10 Mar 2015 16:57:43 -0500 Subject: [PATCH 38/62] fix nit-pick from go vet --- .../providers/aws/resource_aws_route_table_association_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_route_table_association_test.go b/builtin/providers/aws/resource_aws_route_table_association_test.go index e0a591be4..8c4246aba 100644 --- a/builtin/providers/aws/resource_aws_route_table_association_test.go +++ b/builtin/providers/aws/resource_aws_route_table_association_test.go @@ -64,7 +64,7 @@ func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error { rt := resp.RouteTables[0] if len(rt.Associations) > 0 { return fmt.Errorf( - "route table %s has associations", rt.RouteTableID) + "route table %s has associations", *rt.RouteTableID) } } From c7ccf4f74d4db5fd16336252202ac7a3726fb189 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Tue, 10 Mar 2015 23:01:05 +0000 Subject: [PATCH 39/62] Bugfix: Add tags on AWS IG creation, not just on update --- builtin/providers/aws/resource_aws_internet_gateway.go | 5 +++++ builtin/providers/aws/resource_aws_internet_gateway_test.go | 1 + 2 files changed, 6 insertions(+) diff --git a/builtin/providers/aws/resource_aws_internet_gateway.go b/builtin/providers/aws/resource_aws_internet_gateway.go index 08f77a5c6..499a20ed3 100644 --- a/builtin/providers/aws/resource_aws_internet_gateway.go +++ b/builtin/providers/aws/resource_aws_internet_gateway.go @@ -43,6 +43,11 @@ func resourceAwsInternetGatewayCreate(d *schema.ResourceData, meta interface{}) d.SetId(*ig.InternetGatewayID) log.Printf("[INFO] InternetGateway ID: %s", d.Id()) + err = setTagsSDK(ec2conn, d) + if err != nil { + return err + } + // Attach the new gateway to the correct vpc return resourceAwsInternetGatewayAttach(d, meta) } diff --git a/builtin/providers/aws/resource_aws_internet_gateway_test.go b/builtin/providers/aws/resource_aws_internet_gateway_test.go index a990342f9..26929f466 100644 --- a/builtin/providers/aws/resource_aws_internet_gateway_test.go +++ b/builtin/providers/aws/resource_aws_internet_gateway_test.go @@ -98,6 +98,7 @@ func TestAccInternetGateway_tags(t *testing.T) { Config: testAccCheckInternetGatewayConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckInternetGatewayExists("aws_internet_gateway.foo", &v), + testAccCheckTagsSDK(&v.Tags, "foo", "bar"), ), }, From f5b4f3fe09da5620eadd1abc06d9f8856013b990 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 11 Mar 2015 08:31:58 +0100 Subject: [PATCH 40/62] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5000e028..8470f90b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,7 +49,8 @@ BUG FIXES: "resource.0" would ignore the latter completely. [GH-1086] * providers/aws: manually deleted VPC removes it from the state * providers/aws: `source_dest_check` regression fixed (now works). [GH-1020] - * providers/aws: Longer wait times for DB instances + * providers/aws: Longer wait times for DB instances. + * providers/aws: Longer wait times for route53 records (30 mins). [GH-1164] * providers/digitalocean: Waits until droplet is ready to be destroyed [GH-1057] * providers/digitalocean: More lenient about 404's while waiting [GH-1062] * providers/google: Network data in state was not being stored. [GH-1095] From 902ca25f36032dd08e8b73b95499e00b63a372a6 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 08:30:43 -0500 Subject: [PATCH 41/62] Code cleanup --- builtin/providers/aws/resource_aws_security_group.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index 4a7153cc7..b7addd9aa 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -320,15 +320,11 @@ func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions [] ruleMap := make(map[string]map[string]interface{}) for _, perm := range permissions { var fromPort, toPort int - if perm.FromPort == nil { - fromPort = 0 - } else { - fromPort = *perm.FromPort + if v := perm.FromPort; v != nil { + fromPort = *v } - if perm.ToPort == nil { - toPort = 0 - } else { - toPort = *perm.ToPort + if v := perm.ToPort; v != nil { + toPort = *v } k := fmt.Sprintf("%s-%d-%d", *perm.IPProtocol, fromPort, toPort) From 9d6f05e529f9cffbefa4302bc62a7a38eded1a8f Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 09:24:59 -0500 Subject: [PATCH 42/62] restore IOPS positioning --- builtin/providers/aws/resource_aws_instance.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index 54584402f..b732f8e8c 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -540,6 +540,9 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { blockDevice["device_name"] = *blockDevices[*vol.VolumeID].DeviceName blockDevice["volume_type"] = *vol.VolumeType blockDevice["volume_size"] = *vol.Size + if vol.IOPS != nil { + blockDevice["iops"] = *vol.IOPS + } blockDevice["delete_on_termination"] = *blockDevices[*vol.VolumeID].EBS.DeleteOnTermination @@ -552,9 +555,6 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { blockDevice["snapshot_id"] = *vol.SnapshotID blockDevice["encrypted"] = *vol.Encrypted - if vol.IOPS != nil { - blockDevice["iops"] = *vol.IOPS - } nonRootBlockDevices = append(nonRootBlockDevices, blockDevice) } d.Set("block_device", nonRootBlockDevices) From 751140351b3747d5652479f2632b4c9b5e9b7175 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 09:55:32 -0500 Subject: [PATCH 43/62] code cleanup on subnet check --- builtin/providers/aws/resource_aws_instance.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index b732f8e8c..5475e7454 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -287,15 +287,12 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { associatePublicIPAddress = v.(bool) } - // check for non-default Subnet - subnet := false - var subnetID string - if v, ok := d.GetOk("subnet_id"); ok { - subnet = true - subnetID = v.(string) - } + // check for non-default Subnet, and cast it to a String + var hasSubnet bool + subnet, hasSubnet := d.GetOk("subnet_id") + subnetID := subnet.(string) - if subnet && associatePublicIPAddress { + if hasSubnet && associatePublicIPAddress { // If we have a non-default VPC / Subnet specified, we can flag // AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided. // You cannot specify both SubnetId and the NetworkInterface.0.* parameters though, otherwise From 8a5c3b85252f543c8205349300088e6f5e1dcac8 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 10:40:32 -0500 Subject: [PATCH 44/62] provider/aws update Network ACL tests --- .../aws/resource_aws_network_acl_test.go | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index 939e8633e..9c1ef9114 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -24,29 +24,29 @@ func TestAccAWSNetworkAclsWithEgressAndIngressRules(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.bar", &networkAcl), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.580214135.protocol", "tcp"), + "aws_network_acl.bar", "ingress.3409203205.protocol", "tcp"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.580214135.rule_no", "1"), + "aws_network_acl.bar", "ingress.3409203205.rule_no", "1"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.580214135.from_port", "80"), + "aws_network_acl.bar", "ingress.3409203205.from_port", "80"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.580214135.to_port", "80"), + "aws_network_acl.bar", "ingress.3409203205.to_port", "80"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.580214135.action", "allow"), + "aws_network_acl.bar", "ingress.3409203205.action", "allow"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.580214135.cidr_block", "10.3.10.3/18"), + "aws_network_acl.bar", "ingress.3409203205.cidr_block", "10.3.10.3/18"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.1730430240.protocol", "tcp"), + "aws_network_acl.bar", "egress.2579689292.protocol", "tcp"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.1730430240.rule_no", "2"), + "aws_network_acl.bar", "egress.2579689292.rule_no", "2"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.1730430240.from_port", "443"), + "aws_network_acl.bar", "egress.2579689292.from_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.1730430240.to_port", "443"), + "aws_network_acl.bar", "egress.2579689292.to_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.1730430240.cidr_block", "10.3.2.3/18"), + "aws_network_acl.bar", "egress.2579689292.cidr_block", "10.3.2.3/18"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.1730430240.action", "allow"), + "aws_network_acl.bar", "egress.2579689292.action", "allow"), ), }, }, @@ -157,7 +157,7 @@ func TestAccAWSNetworkAclsOnlyEgressRules(t *testing.T) { }) } -func TestAccNetworkAcl_SubnetChange(t *testing.T) { +func TestAccAWSNetworkAcl_SubnetChange(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, From 70a989a23ed3cb9eaef8beda8d905e2d4cf6300a Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 11:19:08 -0500 Subject: [PATCH 45/62] more test updates --- .../aws/resource_aws_network_acl_test.go | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index 9c1ef9114..53e26abf3 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -67,17 +67,17 @@ func TestAccAWSNetworkAclsOnlyIngressRules(t *testing.T) { testAccCheckAWSNetworkAclExists("aws_network_acl.foos", &networkAcl), // testAccCheckSubnetAssociation("aws_network_acl.foos", "aws_subnet.blob"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.protocol", "tcp"), + "aws_network_acl.foos", "ingress.2750166237.protocol", "tcp"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.rule_no", "1"), + "aws_network_acl.foos", "ingress.2750166237.rule_no", "1"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.from_port", "0"), + "aws_network_acl.foos", "ingress.2750166237.from_port", "0"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.to_port", "22"), + "aws_network_acl.foos", "ingress.2750166237.to_port", "22"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.action", "deny"), + "aws_network_acl.foos", "ingress.2750166237.action", "deny"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.cidr_block", "10.2.2.3/18"), + "aws_network_acl.foos", "ingress.2750166237.cidr_block", "10.2.2.3/18"), ), }, }, @@ -98,21 +98,21 @@ func TestAccAWSNetworkAclsOnlyIngressRulesChange(t *testing.T) { testAccCheckAWSNetworkAclExists("aws_network_acl.foos", &networkAcl), testIngressRuleLength(&networkAcl, 2), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.protocol", "tcp"), + "aws_network_acl.foos", "ingress.37211640.protocol", "tcp"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.rule_no", "1"), + "aws_network_acl.foos", "ingress.37211640.rule_no", "1"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.from_port", "0"), + "aws_network_acl.foos", "ingress.37211640.from_port", "0"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.to_port", "22"), + "aws_network_acl.foos", "ingress.37211640.to_port", "22"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.action", "deny"), + "aws_network_acl.foos", "ingress.37211640.action", "deny"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.cidr_block", "10.2.2.3/18"), + "aws_network_acl.foos", "ingress.37211640.cidr_block", "10.2.2.3/18"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2438803013.from_port", "443"), + "aws_network_acl.foos", "ingress.2750166237.from_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2438803013.rule_no", "2"), + "aws_network_acl.foos", "ingress.2750166237.rule_no", "2"), ), }, resource.TestStep{ @@ -121,17 +121,17 @@ func TestAccAWSNetworkAclsOnlyIngressRulesChange(t *testing.T) { testAccCheckAWSNetworkAclExists("aws_network_acl.foos", &networkAcl), testIngressRuleLength(&networkAcl, 1), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.protocol", "tcp"), + "aws_network_acl.foos", "ingress.37211640.protocol", "tcp"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.rule_no", "1"), + "aws_network_acl.foos", "ingress.37211640.rule_no", "1"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.from_port", "0"), + "aws_network_acl.foos", "ingress.37211640.from_port", "0"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.to_port", "22"), + "aws_network_acl.foos", "ingress.37211640.to_port", "22"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.action", "deny"), + "aws_network_acl.foos", "ingress.37211640.action", "deny"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.3697634361.cidr_block", "10.2.2.3/18"), + "aws_network_acl.foos", "ingress.37211640.cidr_block", "10.2.2.3/18"), ), }, }, @@ -183,6 +183,7 @@ func TestAccAWSNetworkAcl_SubnetChange(t *testing.T) { } func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { + // log.Printf("\n@@@\nEnter Destroy func\n@@@\n") conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { @@ -194,21 +195,26 @@ func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { resp, err := conn.NetworkAcls([]string{rs.Primary.ID}, ec2.NewFilter()) if err == nil { if len(resp.NetworkAcls) > 0 && resp.NetworkAcls[0].NetworkAclId == rs.Primary.ID { + // log.Printf("\n@@@\nDestroy func err: still exists\n@@@\n") return fmt.Errorf("Network Acl (%s) still exists.", rs.Primary.ID) } + // log.Printf("\n@@@\nDestroy func err: found something, but returning nil\n@@@\n") return nil } ec2err, ok := err.(*ec2.Error) if !ok { + // log.Printf("\n@@@\nDestroy func err: aws err:%#v\n@@@\n", err) return err } // Confirm error code is what we want if ec2err.Code != "InvalidNetworkAclID.NotFound" { + // log.Printf("\n@@@\nDestroy func err: not found aws err:%#v\n@@@\n", err) return err } } + // log.Printf("\n@@@\nDestroy func err: end return\n@@@\n") return nil } From 64f7e6a19c020704d184816b1002f94eb54eac63 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 13:37:56 -0500 Subject: [PATCH 46/62] Update website docs on AWS RDS encryption field --- website/source/docs/providers/aws/r/db_instance.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/source/docs/providers/aws/r/db_instance.html.markdown b/website/source/docs/providers/aws/r/db_instance.html.markdown index 7727b9dd6..4b2253115 100644 --- a/website/source/docs/providers/aws/r/db_instance.html.markdown +++ b/website/source/docs/providers/aws/r/db_instance.html.markdown @@ -61,6 +61,7 @@ The following arguments are supported: Only used for [DB Instances on the _EC2-Classic_ Platform](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.html#USER_VPC.FindDefaultVPC). * `db_subnet_group_name` - (Optional) Name of DB subnet group * `parameter_group_name` - (Optional) Name of the DB parameter group to associate. +* `storage_encrypted` - (Optional) Specifies whether the DB instance is encrypted. The Default is `false` if not specified. ## Attributes Reference @@ -82,4 +83,5 @@ The following attributes are exported: * `port` - The database port * `status` - The RDS instance status * `username` - The master username for the database +* `storage_encrypted` - Specifies whether the DB instance is encrypted From bd591877feccb18f2bbe752c2c91abdea0b45691 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 15:01:07 -0500 Subject: [PATCH 47/62] provider/aws: Convert AWS Network ACL to aws-sdk-go --- builtin/providers/aws/network_acl_entry.go | 41 +++--- .../providers/aws/network_acl_entry_test.go | 89 +++++++------ .../providers/aws/resource_aws_network_acl.go | 117 ++++++++++++------ .../aws/resource_aws_network_acl_test.go | 82 +++++++----- 4 files changed, 196 insertions(+), 133 deletions(-) diff --git a/builtin/providers/aws/network_acl_entry.go b/builtin/providers/aws/network_acl_entry.go index 8ce88d81a..09954083a 100644 --- a/builtin/providers/aws/network_acl_entry.go +++ b/builtin/providers/aws/network_acl_entry.go @@ -2,11 +2,14 @@ package aws import ( "fmt" - "github.com/mitchellh/goamz/ec2" + "strconv" + + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" ) -func expandNetworkAclEntries(configured []interface{}, entryType string) ([]ec2.NetworkAclEntry, error) { - entries := make([]ec2.NetworkAclEntry, 0, len(configured)) +func expandNetworkAclEntries(configured []interface{}, entryType string) ([]ec2.NetworkACLEntry, error) { + entries := make([]ec2.NetworkACLEntry, 0, len(configured)) for _, eRaw := range configured { data := eRaw.(map[string]interface{}) protocol := data["protocol"].(string) @@ -15,16 +18,16 @@ func expandNetworkAclEntries(configured []interface{}, entryType string) ([]ec2. return nil, fmt.Errorf("Invalid Protocol %s for rule %#v", protocol, data) } p := extractProtocolInteger(data["protocol"].(string)) - e := ec2.NetworkAclEntry{ - Protocol: p, - PortRange: ec2.PortRange{ - From: data["from_port"].(int), - To: data["to_port"].(int), + e := ec2.NetworkACLEntry{ + Protocol: aws.String(strconv.Itoa(p)), + PortRange: &ec2.PortRange{ + From: aws.Integer(data["from_port"].(int)), + To: aws.Integer(data["to_port"].(int)), }, - Egress: (entryType == "egress"), - RuleAction: data["action"].(string), - RuleNumber: data["rule_no"].(int), - CidrBlock: data["cidr_block"].(string), + Egress: aws.Boolean((entryType == "egress")), + RuleAction: aws.String(data["action"].(string)), + RuleNumber: aws.Integer(data["rule_no"].(int)), + CIDRBlock: aws.String(data["cidr_block"].(string)), } entries = append(entries, e) } @@ -33,17 +36,17 @@ func expandNetworkAclEntries(configured []interface{}, entryType string) ([]ec2. } -func flattenNetworkAclEntries(list []ec2.NetworkAclEntry) []map[string]interface{} { +func flattenNetworkAclEntries(list []ec2.NetworkACLEntry) []map[string]interface{} { entries := make([]map[string]interface{}, 0, len(list)) for _, entry := range list { entries = append(entries, map[string]interface{}{ - "from_port": entry.PortRange.From, - "to_port": entry.PortRange.To, - "action": entry.RuleAction, - "rule_no": entry.RuleNumber, - "protocol": extractProtocolString(entry.Protocol), - "cidr_block": entry.CidrBlock, + "from_port": *entry.PortRange.From, + "to_port": *entry.PortRange.To, + "action": *entry.RuleAction, + "rule_no": *entry.RuleNumber, + "protocol": *entry.Protocol, + "cidr_block": *entry.CIDRBlock, }) } return entries diff --git a/builtin/providers/aws/network_acl_entry_test.go b/builtin/providers/aws/network_acl_entry_test.go index a2d60abb8..dbbca1e87 100644 --- a/builtin/providers/aws/network_acl_entry_test.go +++ b/builtin/providers/aws/network_acl_entry_test.go @@ -4,10 +4,11 @@ import ( "reflect" "testing" - "github.com/mitchellh/goamz/ec2" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" ) -func Test_expandNetworkAclEntry(t *testing.T) { +func Test_expandNetworkACLEntry(t *testing.T) { input := []interface{}{ map[string]interface{}{ "protocol": "tcp", @@ -28,30 +29,36 @@ func Test_expandNetworkAclEntry(t *testing.T) { } expanded, _ := expandNetworkAclEntries(input, "egress") - expected := []ec2.NetworkAclEntry{ - ec2.NetworkAclEntry{ - Protocol: 6, - PortRange: ec2.PortRange{ - From: 22, - To: 22, + expected := []ec2.NetworkACLEntry{ + ec2.NetworkACLEntry{ + Protocol: aws.String("tcp"), + PortRange: &ec2.PortRange{ + From: aws.Integer(22), + To: aws.Integer(22), + }, + RuleAction: aws.String("deny"), + RuleNumber: aws.Integer(1), + CIDRBlock: aws.String("0.0.0.0/0"), + Egress: aws.Boolean(true), + ICMPTypeCode: &ec2.ICMPTypeCode{ + Code: aws.Integer(0), + Type: aws.Integer(0), }, - RuleAction: "deny", - RuleNumber: 1, - CidrBlock: "0.0.0.0/0", - Egress: true, - IcmpCode: ec2.IcmpCode{Code: 0, Type: 0}, }, - ec2.NetworkAclEntry{ - Protocol: 6, - PortRange: ec2.PortRange{ - From: 443, - To: 443, + ec2.NetworkACLEntry{ + Protocol: aws.String("tcp"), + PortRange: &ec2.PortRange{ + From: aws.Integer(443), + To: aws.Integer(443), + }, + RuleAction: aws.String("deny"), + RuleNumber: aws.Integer(2), + CIDRBlock: aws.String("0.0.0.0/0"), + Egress: aws.Boolean(true), + ICMPTypeCode: &ec2.ICMPTypeCode{ + Code: aws.Integer(0), + Type: aws.Integer(0), }, - RuleAction: "deny", - RuleNumber: 2, - CidrBlock: "0.0.0.0/0", - Egress: true, - IcmpCode: ec2.IcmpCode{Code: 0, Type: 0}, }, } @@ -64,28 +71,28 @@ func Test_expandNetworkAclEntry(t *testing.T) { } -func Test_flattenNetworkAclEntry(t *testing.T) { +func Test_flattenNetworkACLEntry(t *testing.T) { - apiInput := []ec2.NetworkAclEntry{ - ec2.NetworkAclEntry{ - Protocol: 6, - PortRange: ec2.PortRange{ - From: 22, - To: 22, + apiInput := []ec2.NetworkACLEntry{ + ec2.NetworkACLEntry{ + Protocol: aws.String("tcp"), + PortRange: &ec2.PortRange{ + From: aws.Integer(22), + To: aws.Integer(22), }, - RuleAction: "deny", - RuleNumber: 1, - CidrBlock: "0.0.0.0/0", + RuleAction: aws.String("deny"), + RuleNumber: aws.Integer(1), + CIDRBlock: aws.String("0.0.0.0/0"), }, - ec2.NetworkAclEntry{ - Protocol: 6, - PortRange: ec2.PortRange{ - From: 443, - To: 443, + ec2.NetworkACLEntry{ + Protocol: aws.String("tcp"), + PortRange: &ec2.PortRange{ + From: aws.Integer(443), + To: aws.Integer(443), }, - RuleAction: "deny", - RuleNumber: 2, - CidrBlock: "0.0.0.0/0", + RuleAction: aws.String("deny"), + RuleNumber: aws.Integer(2), + CIDRBlock: aws.String("0.0.0.0/0"), }, } flattened := flattenNetworkAclEntries(apiInput) diff --git a/builtin/providers/aws/resource_aws_network_acl.go b/builtin/providers/aws/resource_aws_network_acl.go index efafd7ffe..a8f654db7 100644 --- a/builtin/providers/aws/resource_aws_network_acl.go +++ b/builtin/providers/aws/resource_aws_network_acl.go @@ -6,10 +6,11 @@ import ( "log" "time" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) func resourceAwsNetworkAcl() *schema.Resource { @@ -108,32 +109,34 @@ func resourceAwsNetworkAcl() *schema.Resource { func resourceAwsNetworkAclCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn // Create the Network Acl - createOpts := &ec2.CreateNetworkAcl{ - VpcId: d.Get("vpc_id").(string), + createOpts := &ec2.CreateNetworkACLRequest{ + VPCID: aws.String(d.Get("vpc_id").(string)), } log.Printf("[DEBUG] Network Acl create config: %#v", createOpts) - resp, err := ec2conn.CreateNetworkAcl(createOpts) + resp, err := ec2conn.CreateNetworkACL(createOpts) if err != nil { return fmt.Errorf("Error creating network acl: %s", err) } // Get the ID and store it - networkAcl := &resp.NetworkAcl - d.SetId(networkAcl.NetworkAclId) - log.Printf("[INFO] Network Acl ID: %s", networkAcl.NetworkAclId) + networkAcl := resp.NetworkACL + d.SetId(*networkAcl.NetworkACLID) + log.Printf("[INFO] Network Acl ID: %s", *networkAcl.NetworkACLID) // Update rules and subnet association once acl is created return resourceAwsNetworkAclUpdate(d, meta) } func resourceAwsNetworkAclRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn - resp, err := ec2conn.NetworkAcls([]string{d.Id()}, ec2.NewFilter()) + resp, err := ec2conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ + NetworkACLIDs: []string{d.Id()}, + }) if err != nil { return err @@ -142,29 +145,29 @@ func resourceAwsNetworkAclRead(d *schema.ResourceData, meta interface{}) error { return nil } - networkAcl := &resp.NetworkAcls[0] - var ingressEntries []ec2.NetworkAclEntry - var egressEntries []ec2.NetworkAclEntry + networkAcl := &resp.NetworkACLs[0] + var ingressEntries []ec2.NetworkACLEntry + var egressEntries []ec2.NetworkACLEntry // separate the ingress and egress rules - for _, e := range networkAcl.EntrySet { - if e.Egress == true { + for _, e := range networkAcl.Entries { + if *e.Egress == true { egressEntries = append(egressEntries, e) } else { ingressEntries = append(ingressEntries, e) } } - d.Set("vpc_id", networkAcl.VpcId) + d.Set("vpc_id", networkAcl.VPCID) d.Set("ingress", ingressEntries) d.Set("egress", egressEntries) - d.Set("tags", tagsToMap(networkAcl.Tags)) + d.Set("tags", tagsToMapSDK(networkAcl.Tags)) return nil } func resourceAwsNetworkAclUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn d.Partial(true) if d.HasChange("ingress") { @@ -190,13 +193,16 @@ func resourceAwsNetworkAclUpdate(d *schema.ResourceData, meta interface{}) error if err != nil { return fmt.Errorf("Failed to update acl %s with subnet %s: %s", d.Id(), newSubnet, err) } - _, err = ec2conn.ReplaceNetworkAclAssociation(association.NetworkAclAssociationId, d.Id()) + _, err = ec2conn.ReplaceNetworkACLAssociation(&ec2.ReplaceNetworkACLAssociationRequest{ + AssociationID: association.NetworkACLAssociationID, + NetworkACLID: aws.String(d.Id()), + }) if err != nil { return err } } - if err := setTags(ec2conn, d); err != nil { + if err := setTagsSDK(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") @@ -226,7 +232,11 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, ec2conn * } for _, remove := range toBeDeleted { // Delete old Acl - _, err := ec2conn.DeleteNetworkAclEntry(d.Id(), remove.RuleNumber, remove.Egress) + err := ec2conn.DeleteNetworkACLEntry(&ec2.DeleteNetworkACLEntryRequest{ + NetworkACLID: aws.String(d.Id()), + RuleNumber: remove.RuleNumber, + Egress: remove.Egress, + }) if err != nil { return fmt.Errorf("Error deleting %s entry: %s", entryType, err) } @@ -238,7 +248,15 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, ec2conn * } for _, add := range toBeCreated { // Add new Acl entry - _, err := ec2conn.CreateNetworkAclEntry(d.Id(), &add) + err := ec2conn.CreateNetworkACLEntry(&ec2.CreateNetworkACLEntryRequest{ + NetworkACLID: aws.String(d.Id()), + CIDRBlock: add.CIDRBlock, + Egress: add.Egress, + PortRange: add.PortRange, + Protocol: add.Protocol, + RuleAction: add.RuleAction, + RuleNumber: add.RuleNumber, + }) if err != nil { return fmt.Errorf("Error creating %s entry: %s", entryType, err) } @@ -247,12 +265,15 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, ec2conn * } func resourceAwsNetworkAclDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).ec2conn + ec2conn := meta.(*AWSClient).awsEC2conn log.Printf("[INFO] Deleting Network Acl: %s", d.Id()) return resource.Retry(5*time.Minute, func() error { - if _, err := ec2conn.DeleteNetworkAcl(d.Id()); err != nil { - ec2err := err.(*ec2.Error) + err := ec2conn.DeleteNetworkACL(&ec2.DeleteNetworkACLRequest{ + NetworkACLID: aws.String(d.Id()), + }) + if err != nil { + ec2err := err.(aws.APIError) switch ec2err.Code { case "InvalidNetworkAclID.NotFound": return nil @@ -267,7 +288,10 @@ func resourceAwsNetworkAclDelete(d *schema.ResourceData, meta interface{}) error if err != nil { return fmt.Errorf("Dependency violation: Cannot delete acl %s: %s", d.Id(), err) } - _, err = ec2conn.ReplaceNetworkAclAssociation(association.NetworkAclAssociationId, defaultAcl.NetworkAclId) + _, err = ec2conn.ReplaceNetworkACLAssociation(&ec2.ReplaceNetworkACLAssociationRequest{ + AssociationID: association.NetworkACLAssociationID, + NetworkACLID: defaultAcl.NetworkACLID, + }) return resource.RetryError{Err: err} default: // Any other error, we want to quit the retry loop immediately @@ -296,30 +320,43 @@ func resourceAwsNetworkAclEntryHash(v interface{}) int { return hashcode.String(buf.String()) } -func getDefaultNetworkAcl(vpc_id string, ec2conn *ec2.EC2) (defaultAcl *ec2.NetworkAcl, err error) { - filter := ec2.NewFilter() - filter.Add("default", "true") - filter.Add("vpc-id", vpc_id) - - resp, err := ec2conn.NetworkAcls([]string{}, filter) +func getDefaultNetworkAcl(vpc_id string, ec2conn *ec2.EC2) (defaultAcl *ec2.NetworkACL, err error) { + resp, err := ec2conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ + NetworkACLIDs: []string{}, + Filters: []ec2.Filter{ + ec2.Filter{ + Name: aws.String("default"), + Values: []string{"true"}, + }, + ec2.Filter{ + Name: aws.String("vpc-id"), + Values: []string{vpc_id}, + }, + }, + }) if err != nil { return nil, err } - return &resp.NetworkAcls[0], nil + return &resp.NetworkACLs[0], nil } -func findNetworkAclAssociation(subnetId string, ec2conn *ec2.EC2) (networkAclAssociation *ec2.NetworkAclAssociation, err error) { - filter := ec2.NewFilter() - filter.Add("association.subnet-id", subnetId) - - resp, err := ec2conn.NetworkAcls([]string{}, filter) +func findNetworkAclAssociation(subnetId string, ec2conn *ec2.EC2) (networkAclAssociation *ec2.NetworkACLAssociation, err error) { + resp, err := ec2conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ + NetworkACLIDs: []string{}, + Filters: []ec2.Filter{ + ec2.Filter{ + Name: aws.String("association.subnet-id"), + Values: []string{subnetId}, + }, + }, + }) if err != nil { return nil, err } - for _, association := range resp.NetworkAcls[0].AssociationSet { - if association.SubnetId == subnetId { + for _, association := range resp.NetworkACLs[0].Associations { + if *association.SubnetID == subnetId { return &association, nil } } diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index 53e26abf3..493058946 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -4,15 +4,16 @@ import ( "fmt" "testing" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" // "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" // "github.com/hashicorp/terraform/helper/schema" ) func TestAccAWSNetworkAclsWithEgressAndIngressRules(t *testing.T) { - var networkAcl ec2.NetworkAcl + var networkAcl ec2.NetworkACL resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -54,7 +55,7 @@ func TestAccAWSNetworkAclsWithEgressAndIngressRules(t *testing.T) { } func TestAccAWSNetworkAclsOnlyIngressRules(t *testing.T) { - var networkAcl ec2.NetworkAcl + var networkAcl ec2.NetworkACL resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -85,7 +86,7 @@ func TestAccAWSNetworkAclsOnlyIngressRules(t *testing.T) { } func TestAccAWSNetworkAclsOnlyIngressRulesChange(t *testing.T) { - var networkAcl ec2.NetworkAcl + var networkAcl ec2.NetworkACL resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -139,7 +140,7 @@ func TestAccAWSNetworkAclsOnlyIngressRulesChange(t *testing.T) { } func TestAccAWSNetworkAclsOnlyEgressRules(t *testing.T) { - var networkAcl ec2.NetworkAcl + var networkAcl ec2.NetworkACL resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -150,7 +151,7 @@ func TestAccAWSNetworkAclsOnlyEgressRules(t *testing.T) { Config: testAccAWSNetworkAclEgressConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.bond", &networkAcl), - testAccCheckTags(&networkAcl.Tags, "foo", "bar"), + testAccCheckTagsSDK(&networkAcl.Tags, "foo", "bar"), ), }, }, @@ -184,7 +185,7 @@ func TestAccAWSNetworkAcl_SubnetChange(t *testing.T) { func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { // log.Printf("\n@@@\nEnter Destroy func\n@@@\n") - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_network" { @@ -192,9 +193,11 @@ func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { } // Retrieve the network acl - resp, err := conn.NetworkAcls([]string{rs.Primary.ID}, ec2.NewFilter()) + resp, err := conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ + NetworkACLIDs: []string{rs.Primary.ID}, + }) if err == nil { - if len(resp.NetworkAcls) > 0 && resp.NetworkAcls[0].NetworkAclId == rs.Primary.ID { + if len(resp.NetworkACLs) > 0 && *resp.NetworkACLs[0].NetworkACLID == rs.Primary.ID { // log.Printf("\n@@@\nDestroy func err: still exists\n@@@\n") return fmt.Errorf("Network Acl (%s) still exists.", rs.Primary.ID) } @@ -203,7 +206,7 @@ func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { return nil } - ec2err, ok := err.(*ec2.Error) + ec2err, ok := err.(aws.APIError) if !ok { // log.Printf("\n@@@\nDestroy func err: aws err:%#v\n@@@\n", err) return err @@ -219,7 +222,7 @@ func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { return nil } -func testAccCheckAWSNetworkAclExists(n string, networkAcl *ec2.NetworkAcl) resource.TestCheckFunc { +func testAccCheckAWSNetworkAclExists(n string, networkAcl *ec2.NetworkACL) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] if !ok { @@ -229,15 +232,17 @@ func testAccCheckAWSNetworkAclExists(n string, networkAcl *ec2.NetworkAcl) resou if rs.Primary.ID == "" { return fmt.Errorf("No Security Group is set") } - conn := testAccProvider.Meta().(*AWSClient).ec2conn + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn - resp, err := conn.NetworkAcls([]string{rs.Primary.ID}, nil) + resp, err := conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ + NetworkACLIDs: []string{rs.Primary.ID}, + }) if err != nil { return err } - if len(resp.NetworkAcls) > 0 && resp.NetworkAcls[0].NetworkAclId == rs.Primary.ID { - *networkAcl = resp.NetworkAcls[0] + if len(resp.NetworkACLs) > 0 && *resp.NetworkACLs[0].NetworkACLID == rs.Primary.ID { + *networkAcl = resp.NetworkACLs[0] return nil } @@ -245,11 +250,11 @@ func testAccCheckAWSNetworkAclExists(n string, networkAcl *ec2.NetworkAcl) resou } } -func testIngressRuleLength(networkAcl *ec2.NetworkAcl, length int) resource.TestCheckFunc { +func testIngressRuleLength(networkAcl *ec2.NetworkACL, length int) resource.TestCheckFunc { return func(s *terraform.State) error { - var ingressEntries []ec2.NetworkAclEntry - for _, e := range networkAcl.EntrySet { - if e.Egress == false { + var ingressEntries []ec2.NetworkACLEntry + for _, e := range networkAcl.Entries { + if *e.Egress == false { ingressEntries = append(ingressEntries, e) } } @@ -267,21 +272,26 @@ func testAccCheckSubnetIsAssociatedWithAcl(acl string, sub string) resource.Test networkAcl := s.RootModule().Resources[acl] subnet := s.RootModule().Resources[sub] - conn := testAccProvider.Meta().(*AWSClient).ec2conn - filter := ec2.NewFilter() - filter.Add("association.subnet-id", subnet.Primary.ID) - resp, err := conn.NetworkAcls([]string{networkAcl.Primary.ID}, filter) - + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + resp, err := conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ + NetworkACLIDs: []string{networkAcl.Primary.ID}, + Filters: []ec2.Filter{ + ec2.Filter{ + Name: aws.String("association.subnet-id"), + Values: []string{subnet.Primary.ID}, + }, + }, + }) if err != nil { return err } - if len(resp.NetworkAcls) > 0 { + if len(resp.NetworkACLs) > 0 { return nil } - r, _ := conn.NetworkAcls([]string{}, ec2.NewFilter()) - fmt.Printf("\n\nall acls\n %#v\n\n", r.NetworkAcls) - conn.NetworkAcls([]string{}, filter) + // r, _ := conn.NetworkACLs([]string{}, ec2.NewFilter()) + // fmt.Printf("\n\nall acls\n %#v\n\n", r.NetworkAcls) + // conn.NetworkAcls([]string{}, filter) return fmt.Errorf("Network Acl %s is not associated with subnet %s", acl, sub) } @@ -292,15 +302,21 @@ func testAccCheckSubnetIsNotAssociatedWithAcl(acl string, subnet string) resourc networkAcl := s.RootModule().Resources[acl] subnet := s.RootModule().Resources[subnet] - conn := testAccProvider.Meta().(*AWSClient).ec2conn - filter := ec2.NewFilter() - filter.Add("association.subnet-id", subnet.Primary.ID) - resp, err := conn.NetworkAcls([]string{networkAcl.Primary.ID}, filter) + conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + resp, err := conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ + NetworkACLIDs: []string{networkAcl.Primary.ID}, + Filters: []ec2.Filter{ + ec2.Filter{ + Name: aws.String("association.subnet-id"), + Values: []string{subnet.Primary.ID}, + }, + }, + }) if err != nil { return err } - if len(resp.NetworkAcls) > 0 { + if len(resp.NetworkACLs) > 0 { return fmt.Errorf("Network Acl %s is still associated with subnet %s", acl, subnet) } return nil From 8a5eadedd10e37465d07d800c29bcf4aa0b80e21 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 15:18:42 -0500 Subject: [PATCH 48/62] clean up --- builtin/providers/aws/resource_aws_network_acl_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index 493058946..a4183a1a1 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -184,7 +184,6 @@ func TestAccAWSNetworkAcl_SubnetChange(t *testing.T) { } func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { - // log.Printf("\n@@@\nEnter Destroy func\n@@@\n") conn := testAccProvider.Meta().(*AWSClient).awsEC2conn for _, rs := range s.RootModule().Resources { @@ -198,26 +197,21 @@ func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { }) if err == nil { if len(resp.NetworkACLs) > 0 && *resp.NetworkACLs[0].NetworkACLID == rs.Primary.ID { - // log.Printf("\n@@@\nDestroy func err: still exists\n@@@\n") return fmt.Errorf("Network Acl (%s) still exists.", rs.Primary.ID) } - // log.Printf("\n@@@\nDestroy func err: found something, but returning nil\n@@@\n") return nil } ec2err, ok := err.(aws.APIError) if !ok { - // log.Printf("\n@@@\nDestroy func err: aws err:%#v\n@@@\n", err) return err } // Confirm error code is what we want if ec2err.Code != "InvalidNetworkAclID.NotFound" { - // log.Printf("\n@@@\nDestroy func err: not found aws err:%#v\n@@@\n", err) return err } } - // log.Printf("\n@@@\nDestroy func err: end return\n@@@\n") return nil } From 85caf9d8d763a72823a45bf0a0e09ace10e9c507 Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Wed, 11 Mar 2015 15:48:47 -0500 Subject: [PATCH 49/62] helper/ssh: update import location go's ssh package now lives canonically at `golang.org/x/crypto/ssh` see https://godoc.org/golang.org/x/crypto/ssh closes #1179 --- helper/ssh/communicator.go | 2 +- helper/ssh/communicator_test.go | 2 +- helper/ssh/password.go | 2 +- helper/ssh/password_test.go | 2 +- helper/ssh/provisioner.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helper/ssh/communicator.go b/helper/ssh/communicator.go index 186fd4824..817f37368 100644 --- a/helper/ssh/communicator.go +++ b/helper/ssh/communicator.go @@ -14,7 +14,7 @@ import ( "sync" "time" - "code.google.com/p/go.crypto/ssh" + "golang.org/x/crypto/ssh" ) // RemoteCmd represents a remote command being prepared or run. diff --git a/helper/ssh/communicator_test.go b/helper/ssh/communicator_test.go index 2e16e1482..0e80c9415 100644 --- a/helper/ssh/communicator_test.go +++ b/helper/ssh/communicator_test.go @@ -4,7 +4,7 @@ package ssh import ( "bytes" - "code.google.com/p/go.crypto/ssh" + "golang.org/x/crypto/ssh" "fmt" "net" "testing" diff --git a/helper/ssh/password.go b/helper/ssh/password.go index 934bcd01f..8db6f82da 100644 --- a/helper/ssh/password.go +++ b/helper/ssh/password.go @@ -1,7 +1,7 @@ package ssh import ( - "code.google.com/p/go.crypto/ssh" + "golang.org/x/crypto/ssh" "log" ) diff --git a/helper/ssh/password_test.go b/helper/ssh/password_test.go index e74b46e06..6e3e0a257 100644 --- a/helper/ssh/password_test.go +++ b/helper/ssh/password_test.go @@ -1,7 +1,7 @@ package ssh import ( - "code.google.com/p/go.crypto/ssh" + "golang.org/x/crypto/ssh" "reflect" "testing" ) diff --git a/helper/ssh/provisioner.go b/helper/ssh/provisioner.go index baebbd9b6..2d60d8934 100644 --- a/helper/ssh/provisioner.go +++ b/helper/ssh/provisioner.go @@ -7,7 +7,7 @@ import ( "log" "time" - "code.google.com/p/go.crypto/ssh" + "golang.org/x/crypto/ssh" "github.com/hashicorp/terraform/terraform" "github.com/mitchellh/go-homedir" "github.com/mitchellh/mapstructure" From 670d53b1a1f783765329e2986080184966673e77 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Wed, 11 Mar 2015 16:21:22 -0500 Subject: [PATCH 50/62] upgrade tests and remove ICMPTypeCode for now --- builtin/providers/aws/network_acl_entry_test.go | 12 ++---------- builtin/providers/aws/structure_test.go | 3 --- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/builtin/providers/aws/network_acl_entry_test.go b/builtin/providers/aws/network_acl_entry_test.go index dbbca1e87..50f6fdc85 100644 --- a/builtin/providers/aws/network_acl_entry_test.go +++ b/builtin/providers/aws/network_acl_entry_test.go @@ -31,7 +31,7 @@ func Test_expandNetworkACLEntry(t *testing.T) { expected := []ec2.NetworkACLEntry{ ec2.NetworkACLEntry{ - Protocol: aws.String("tcp"), + Protocol: aws.String("6"), PortRange: &ec2.PortRange{ From: aws.Integer(22), To: aws.Integer(22), @@ -40,13 +40,9 @@ func Test_expandNetworkACLEntry(t *testing.T) { RuleNumber: aws.Integer(1), CIDRBlock: aws.String("0.0.0.0/0"), Egress: aws.Boolean(true), - ICMPTypeCode: &ec2.ICMPTypeCode{ - Code: aws.Integer(0), - Type: aws.Integer(0), - }, }, ec2.NetworkACLEntry{ - Protocol: aws.String("tcp"), + Protocol: aws.String("6"), PortRange: &ec2.PortRange{ From: aws.Integer(443), To: aws.Integer(443), @@ -55,10 +51,6 @@ func Test_expandNetworkACLEntry(t *testing.T) { RuleNumber: aws.Integer(2), CIDRBlock: aws.String("0.0.0.0/0"), Egress: aws.Boolean(true), - ICMPTypeCode: &ec2.ICMPTypeCode{ - Code: aws.Integer(0), - Type: aws.Integer(0), - }, }, } diff --git a/builtin/providers/aws/structure_test.go b/builtin/providers/aws/structure_test.go index fdee02585..d5e470341 100644 --- a/builtin/providers/aws/structure_test.go +++ b/builtin/providers/aws/structure_test.go @@ -1,7 +1,6 @@ package aws import ( - "log" "reflect" "testing" @@ -62,8 +61,6 @@ func TestExpandIPPerms(t *testing.T) { } perms := expandIPPerms("foo", expanded) - log.Printf("wtf is perms:\n%#v", perms) - expected := []awsEC2.IPPermission{ awsEC2.IPPermission{ IPProtocol: aws.String("icmp"), From 749db242f4716047fe271f770d1a119ec8989ef1 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 12 Mar 2015 11:04:31 -0500 Subject: [PATCH 51/62] Fix issue with Network interfaces and an instance-level security groups (#1188) --- .../providers/aws/resource_aws_instance.go | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index 5475e7454..28c7b79e7 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -292,6 +292,17 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { subnet, hasSubnet := d.GetOk("subnet_id") subnetID := subnet.(string) + var groups []string + if v := d.Get("security_groups"); v != nil { + // Security group names. + // For a nondefault VPC, you must use security group IDs instead. + // See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html + for _, v := range v.(*schema.Set).List() { + str := v.(string) + groups = append(groups, str) + } + } + if hasSubnet && associatePublicIPAddress { // If we have a non-default VPC / Subnet specified, we can flag // AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided. @@ -310,6 +321,10 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { ni.PrivateIPAddress = aws.String(v.(string)) } + if len(groups) > 0 { + ni.Groups = groups + } + runOpts.NetworkInterfaces = []ec2.InstanceNetworkInterfaceSpecification{ni} } else { if subnetID != "" { @@ -319,21 +334,6 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { if v, ok := d.GetOk("private_ip"); ok { runOpts.PrivateIPAddress = aws.String(v.(string)) } - } - - if v, ok := d.GetOk("key_name"); ok { - runOpts.KeyName = aws.String(v.(string)) - } - - if v := d.Get("security_groups"); v != nil { - // Security group names. - // For a nondefault VPC, you must use security group IDs instead. - // See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html - var groups []string - for _, v := range v.(*schema.Set).List() { - str := v.(string) - groups = append(groups, str) - } if runOpts.SubnetID != nil && *runOpts.SubnetID != "" { runOpts.SecurityGroupIDs = groups @@ -342,6 +342,10 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { } } + if v, ok := d.GetOk("key_name"); ok { + runOpts.KeyName = aws.String(v.(string)) + } + blockDevices := make([]interface{}, 0) if v := d.Get("block_device"); v != nil { From 3a5918d013739bc798d57ae0bc644047c2d00c09 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 12 Mar 2015 14:26:10 -0500 Subject: [PATCH 52/62] Add acceptance test for Network / Instance security group fix --- .../aws/resource_aws_instance_test.go | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index 3a9c16588..1076c49e0 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -207,6 +207,25 @@ func TestAccAWSInstance_vpc(t *testing.T) { }) } +func TestAccInstance_NetworkInstanceSecurityGroups(t *testing.T) { + var v ec2.Instance + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccInstanceNetworkInstanceSecurityGroups, + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceExists( + "aws_instance.foo_instance", &v), + ), + }, + }, + }) +} + func TestAccAWSInstance_tags(t *testing.T) { var v ec2.Instance @@ -533,3 +552,44 @@ resource "aws_instance" "foo" { private_ip = "10.1.1.42" } ` + +const testAccInstanceNetworkInstanceSecurityGroups = ` +resource "aws_internet_gateway" "gw" { + vpc_id = "${aws_vpc.foo.id}" +} + +resource "aws_vpc" "foo" { + cidr_block = "10.1.0.0/16" +} + +resource "aws_security_group" "tf_test_foo" { + name = "tf_test_foo" + description = "foo" + vpc_id="${aws_vpc.foo.id}" + + ingress { + protocol = "icmp" + from_port = -1 + to_port = -1 + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_subnet" "foo" { + cidr_block = "10.1.1.0/24" + vpc_id = "${aws_vpc.foo.id}" +} + +resource "aws_instance" "foo_instance" { + ami = "ami-21f78e11" + instance_type = "t1.micro" + security_groups = ["${aws_security_group.tf_test_foo.id}"] + subnet_id = "${aws_subnet.foo.id}" + associate_public_ip_address = true +} + +resource "aws_eip" "foo_eip" { + instance = "${aws_instance.foo_instance.id}" + vpc = true +} +` From 33fdc0c63f4202a145edf84cb8d0e96f1a3cd50f Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 12 Mar 2015 15:01:24 -0500 Subject: [PATCH 53/62] update the new test config --- builtin/providers/aws/resource_aws_instance_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index 1076c49e0..f85928cc5 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -556,10 +556,14 @@ resource "aws_instance" "foo" { const testAccInstanceNetworkInstanceSecurityGroups = ` resource "aws_internet_gateway" "gw" { vpc_id = "${aws_vpc.foo.id}" + depends_on = ["aws_eip.foo_eip"] } resource "aws_vpc" "foo" { cidr_block = "10.1.0.0/16" + tags { + Name = "tf-network-test" + } } resource "aws_security_group" "tf_test_foo" { From 0fbd701ccbfc5a31d59e375e784eb89382b9bfe4 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 12 Mar 2015 15:13:45 -0500 Subject: [PATCH 54/62] minor style cleanups --- builtin/providers/aws/resource_aws_vpc.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index d1234e637..df7feb5a0 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -72,12 +72,12 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { // Create the VPC createOpts := &ec2.CreateVPCRequest{ CIDRBlock: aws.String(d.Get("cidr_block").(string)), - InstanceTenancy: &instance_tenancy, + InstanceTenancy: aws.String(instance_tenancy), } log.Printf("[DEBUG] VPC create config: %#v", *createOpts) vpcResp, err := ec2conn.CreateVPC(createOpts) if err != nil { - return fmt.Errorf("Error creating VPC: %s : %s", err) + return fmt.Errorf("Error creating VPC: %s", err) } // Get the ID and store it @@ -133,8 +133,8 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { // Attributes attribute := "enableDnsSupport" DescribeAttrOpts := &ec2.DescribeVPCAttributeRequest{ - Attribute: &attribute, - VPCID: &vpcid, + Attribute: aws.String(attribute), + VPCID: aws.String(vpcid), } resp, err := ec2conn.DescribeVPCAttribute(DescribeAttrOpts) if err != nil { From 57556bba75737c93ac6064c9d1a6006df202654e Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 12 Mar 2015 16:43:08 -0500 Subject: [PATCH 55/62] Replace tags files with tags_sdk, rename, and update --- .../providers/aws/resource_aws_instance.go | 4 +- .../aws/resource_aws_instance_test.go | 8 +- .../aws/resource_aws_internet_gateway.go | 6 +- .../aws/resource_aws_internet_gateway_test.go | 6 +- .../providers/aws/resource_aws_network_acl.go | 4 +- .../aws/resource_aws_network_acl_test.go | 2 +- .../providers/aws/resource_aws_route_table.go | 4 +- .../aws/resource_aws_route_table_test.go | 6 +- .../aws/resource_aws_security_group.go | 4 +- .../aws/resource_aws_security_group_test.go | 6 +- builtin/providers/aws/resource_aws_subnet.go | 4 +- builtin/providers/aws/resource_aws_vpc.go | 4 +- .../resource_aws_vpc_peering_connection.go | 4 +- .../providers/aws/resource_aws_vpc_test.go | 6 +- builtin/providers/aws/tags.go | 28 +++-- builtin/providers/aws/tags_sdk.go | 106 ------------------ builtin/providers/aws/tags_sdk_test.go | 85 -------------- builtin/providers/aws/tags_test.go | 2 +- 18 files changed, 54 insertions(+), 235 deletions(-) delete mode 100644 builtin/providers/aws/tags_sdk.go delete mode 100644 builtin/providers/aws/tags_sdk_test.go diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index 5475e7454..5ecd86645 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -481,7 +481,7 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { d.Set("subnet_id", instance.SubnetID) } d.Set("ebs_optimized", instance.EBSOptimized) - d.Set("tags", tagsToMapSDK(instance.Tags)) + d.Set("tags", tagsToMap(instance.Tags)) d.Set("tenancy", instance.Placement.Tenancy) // Determine whether we're referring to security groups with @@ -579,7 +579,7 @@ func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error { // TODO(mitchellh): wait for the attributes we modified to // persist the change... - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index 3a9c16588..b0d2783ac 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -219,9 +219,9 @@ func TestAccAWSInstance_tags(t *testing.T) { Config: testAccCheckInstanceConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckInstanceExists("aws_instance.foo", &v), - testAccCheckTagsSDK(&v.Tags, "foo", "bar"), + testAccCheckTags(&v.Tags, "foo", "bar"), // Guard against regression of https://github.com/hashicorp/terraform/issues/914 - testAccCheckTagsSDK(&v.Tags, "#", ""), + testAccCheckTags(&v.Tags, "#", ""), ), }, @@ -229,8 +229,8 @@ func TestAccAWSInstance_tags(t *testing.T) { Config: testAccCheckInstanceConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckInstanceExists("aws_instance.foo", &v), - testAccCheckTagsSDK(&v.Tags, "foo", ""), - testAccCheckTagsSDK(&v.Tags, "bar", "baz"), + testAccCheckTags(&v.Tags, "foo", ""), + testAccCheckTags(&v.Tags, "bar", "baz"), ), }, }, diff --git a/builtin/providers/aws/resource_aws_internet_gateway.go b/builtin/providers/aws/resource_aws_internet_gateway.go index 499a20ed3..b43e4fd44 100644 --- a/builtin/providers/aws/resource_aws_internet_gateway.go +++ b/builtin/providers/aws/resource_aws_internet_gateway.go @@ -43,7 +43,7 @@ func resourceAwsInternetGatewayCreate(d *schema.ResourceData, meta interface{}) d.SetId(*ig.InternetGatewayID) log.Printf("[INFO] InternetGateway ID: %s", d.Id()) - err = setTagsSDK(ec2conn, d) + err = setTags(ec2conn, d) if err != nil { return err } @@ -73,7 +73,7 @@ func resourceAwsInternetGatewayRead(d *schema.ResourceData, meta interface{}) er d.Set("vpc_id", ig.Attachments[0].VPCID) } - d.Set("tags", tagsToMapSDK(ig.Tags)) + d.Set("tags", tagsToMap(ig.Tags)) return nil } @@ -93,7 +93,7 @@ func resourceAwsInternetGatewayUpdate(d *schema.ResourceData, meta interface{}) ec2conn := meta.(*AWSClient).awsEC2conn - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } diff --git a/builtin/providers/aws/resource_aws_internet_gateway_test.go b/builtin/providers/aws/resource_aws_internet_gateway_test.go index 26929f466..48f7de664 100644 --- a/builtin/providers/aws/resource_aws_internet_gateway_test.go +++ b/builtin/providers/aws/resource_aws_internet_gateway_test.go @@ -98,7 +98,7 @@ func TestAccInternetGateway_tags(t *testing.T) { Config: testAccCheckInternetGatewayConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckInternetGatewayExists("aws_internet_gateway.foo", &v), - testAccCheckTagsSDK(&v.Tags, "foo", "bar"), + testAccCheckTags(&v.Tags, "foo", "bar"), ), }, @@ -106,8 +106,8 @@ func TestAccInternetGateway_tags(t *testing.T) { Config: testAccCheckInternetGatewayConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckInternetGatewayExists("aws_internet_gateway.foo", &v), - testAccCheckTagsSDK(&v.Tags, "foo", ""), - testAccCheckTagsSDK(&v.Tags, "bar", "baz"), + testAccCheckTags(&v.Tags, "foo", ""), + testAccCheckTags(&v.Tags, "bar", "baz"), ), }, }, diff --git a/builtin/providers/aws/resource_aws_network_acl.go b/builtin/providers/aws/resource_aws_network_acl.go index a8f654db7..9afe8aee3 100644 --- a/builtin/providers/aws/resource_aws_network_acl.go +++ b/builtin/providers/aws/resource_aws_network_acl.go @@ -161,7 +161,7 @@ func resourceAwsNetworkAclRead(d *schema.ResourceData, meta interface{}) error { d.Set("vpc_id", networkAcl.VPCID) d.Set("ingress", ingressEntries) d.Set("egress", egressEntries) - d.Set("tags", tagsToMapSDK(networkAcl.Tags)) + d.Set("tags", tagsToMap(networkAcl.Tags)) return nil } @@ -202,7 +202,7 @@ func resourceAwsNetworkAclUpdate(d *schema.ResourceData, meta interface{}) error } } - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index a4183a1a1..e27e57d1a 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -151,7 +151,7 @@ func TestAccAWSNetworkAclsOnlyEgressRules(t *testing.T) { Config: testAccAWSNetworkAclEgressConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.bond", &networkAcl), - testAccCheckTagsSDK(&networkAcl.Tags, "foo", "bar"), + testAccCheckTags(&networkAcl.Tags, "foo", "bar"), ), }, }, diff --git a/builtin/providers/aws/resource_aws_route_table.go b/builtin/providers/aws/resource_aws_route_table.go index 0290d053f..e26c17ce1 100644 --- a/builtin/providers/aws/resource_aws_route_table.go +++ b/builtin/providers/aws/resource_aws_route_table.go @@ -146,7 +146,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { d.Set("route", route) // Tags - d.Set("tags", tagsToMapSDK(rt.Tags)) + d.Set("tags", tagsToMap(rt.Tags)) return nil } @@ -203,7 +203,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error } } - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") diff --git a/builtin/providers/aws/resource_aws_route_table_test.go b/builtin/providers/aws/resource_aws_route_table_test.go index 5e6f90026..da90d491d 100644 --- a/builtin/providers/aws/resource_aws_route_table_test.go +++ b/builtin/providers/aws/resource_aws_route_table_test.go @@ -134,7 +134,7 @@ func TestAccAWSRouteTable_tags(t *testing.T) { Config: testAccRouteTableConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists("aws_route_table.foo", &route_table), - testAccCheckTagsSDK(&route_table.Tags, "foo", "bar"), + testAccCheckTags(&route_table.Tags, "foo", "bar"), ), }, @@ -142,8 +142,8 @@ func TestAccAWSRouteTable_tags(t *testing.T) { Config: testAccRouteTableConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckRouteTableExists("aws_route_table.foo", &route_table), - testAccCheckTagsSDK(&route_table.Tags, "foo", ""), - testAccCheckTagsSDK(&route_table.Tags, "bar", "baz"), + testAccCheckTags(&route_table.Tags, "foo", ""), + testAccCheckTags(&route_table.Tags, "bar", "baz"), ), }, }, diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index b7addd9aa..588040830 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -209,7 +209,7 @@ func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) erro d.Set("owner_id", sg.OwnerID) d.Set("ingress", ingressRules) d.Set("egress", egressRules) - d.Set("tags", tagsToMapSDK(sg.Tags)) + d.Set("tags", tagsToMap(sg.Tags)) return nil } @@ -239,7 +239,7 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er } } - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } diff --git a/builtin/providers/aws/resource_aws_security_group_test.go b/builtin/providers/aws/resource_aws_security_group_test.go index c292c80d6..a0cd2c12f 100644 --- a/builtin/providers/aws/resource_aws_security_group_test.go +++ b/builtin/providers/aws/resource_aws_security_group_test.go @@ -296,7 +296,7 @@ func TestAccAWSSecurityGroup_tags(t *testing.T) { Config: testAccAWSSecurityGroupConfigTags, Check: resource.ComposeTestCheckFunc( testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group), - testAccCheckTagsSDK(&group.Tags, "foo", "bar"), + testAccCheckTags(&group.Tags, "foo", "bar"), ), }, @@ -304,8 +304,8 @@ func TestAccAWSSecurityGroup_tags(t *testing.T) { Config: testAccAWSSecurityGroupConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckAWSSecurityGroupExists("aws_security_group.foo", &group), - testAccCheckTagsSDK(&group.Tags, "foo", ""), - testAccCheckTagsSDK(&group.Tags, "bar", "baz"), + testAccCheckTags(&group.Tags, "foo", ""), + testAccCheckTags(&group.Tags, "bar", "baz"), ), }, }, diff --git a/builtin/providers/aws/resource_aws_subnet.go b/builtin/providers/aws/resource_aws_subnet.go index e09fb8bc4..07a3413f2 100644 --- a/builtin/providers/aws/resource_aws_subnet.go +++ b/builtin/providers/aws/resource_aws_subnet.go @@ -115,7 +115,7 @@ func resourceAwsSubnetRead(d *schema.ResourceData, meta interface{}) error { d.Set("availability_zone", subnet.AvailabilityZone) d.Set("cidr_block", subnet.CIDRBlock) d.Set("map_public_ip_on_launch", subnet.MapPublicIPOnLaunch) - d.Set("tags", tagsToMapSDK(subnet.Tags)) + d.Set("tags", tagsToMap(subnet.Tags)) return nil } @@ -125,7 +125,7 @@ func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error { d.Partial(true) - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index df7feb5a0..0e2485972 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -128,7 +128,7 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { d.Set("cidr_block", vpc.CIDRBlock) // Tags - d.Set("tags", tagsToMapSDK(vpc.Tags)) + d.Set("tags", tagsToMap(vpc.Tags)) // Attributes attribute := "enableDnsSupport" @@ -220,7 +220,7 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { d.SetPartial("enable_dns_support") } - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection.go b/builtin/providers/aws/resource_aws_vpc_peering_connection.go index 06f50f01c..548718f43 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection.go @@ -95,7 +95,7 @@ func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error { d.Set("peer_owner_id", pc.AccepterVPCInfo.OwnerID) d.Set("peer_vpc_id", pc.AccepterVPCInfo.VPCID) d.Set("vpc_id", pc.RequesterVPCInfo.VPCID) - d.Set("tags", tagsToMapSDK(pc.Tags)) + d.Set("tags", tagsToMap(pc.Tags)) return nil } @@ -103,7 +103,7 @@ func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error { func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error { ec2conn := meta.(*AWSClient).awsEC2conn - if err := setTagsSDK(ec2conn, d); err != nil { + if err := setTags(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index 7e324a5d9..4f3f02f0f 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -65,7 +65,7 @@ func TestAccVpc_tags(t *testing.T) { testAccCheckVpcCidr(&vpc, "10.1.0.0/16"), resource.TestCheckResourceAttr( "aws_vpc.foo", "cidr_block", "10.1.0.0/16"), - testAccCheckTagsSDK(&vpc.Tags, "foo", "bar"), + testAccCheckTags(&vpc.Tags, "foo", "bar"), ), }, @@ -73,8 +73,8 @@ func TestAccVpc_tags(t *testing.T) { Config: testAccVpcConfigTagsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckVpcExists("aws_vpc.foo", &vpc), - testAccCheckTagsSDK(&vpc.Tags, "foo", ""), - testAccCheckTagsSDK(&vpc.Tags, "bar", "baz"), + testAccCheckTags(&vpc.Tags, "foo", ""), + testAccCheckTags(&vpc.Tags, "bar", "baz"), ), }, }, diff --git a/builtin/providers/aws/tags.go b/builtin/providers/aws/tags.go index b45875c59..1c64b18b4 100644 --- a/builtin/providers/aws/tags.go +++ b/builtin/providers/aws/tags.go @@ -3,11 +3,13 @@ package aws import ( "log" + "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) // tagsSchema returns the schema to use for tags. +// func tagsSchema() *schema.Schema { return &schema.Schema{ Type: schema.TypeMap, @@ -27,13 +29,21 @@ func setTags(conn *ec2.EC2, d *schema.ResourceData) error { // Set tags if len(remove) > 0 { log.Printf("[DEBUG] Removing tags: %#v", remove) - if _, err := conn.DeleteTags([]string{d.Id()}, remove); err != nil { + err := conn.DeleteTags(&ec2.DeleteTagsRequest{ + Resources: []string{d.Id()}, + Tags: remove, + }) + if err != nil { return err } } if len(create) > 0 { log.Printf("[DEBUG] Creating tags: %#v", create) - if _, err := conn.CreateTags([]string{d.Id()}, create); err != nil { + err := conn.CreateTags(&ec2.CreateTagsRequest{ + Resources: []string{d.Id()}, + Tags: create, + }) + if err != nil { return err } } @@ -49,14 +59,14 @@ func diffTags(oldTags, newTags []ec2.Tag) ([]ec2.Tag, []ec2.Tag) { // First, we're creating everything we have create := make(map[string]interface{}) for _, t := range newTags { - create[t.Key] = t.Value + create[*t.Key] = *t.Value } // Build the list of what to remove var remove []ec2.Tag for _, t := range oldTags { - old, ok := create[t.Key] - if !ok || old != t.Value { + old, ok := create[*t.Key] + if !ok || old != *t.Value { // Delete it! remove = append(remove, t) } @@ -70,8 +80,8 @@ func tagsFromMap(m map[string]interface{}) []ec2.Tag { result := make([]ec2.Tag, 0, len(m)) for k, v := range m { result = append(result, ec2.Tag{ - Key: k, - Value: v.(string), + Key: aws.String(k), + Value: aws.String(v.(string)), }) } @@ -82,7 +92,7 @@ func tagsFromMap(m map[string]interface{}) []ec2.Tag { func tagsToMap(ts []ec2.Tag) map[string]string { result := make(map[string]string) for _, t := range ts { - result[t.Key] = t.Value + result[*t.Key] = *t.Value } return result diff --git a/builtin/providers/aws/tags_sdk.go b/builtin/providers/aws/tags_sdk.go deleted file mode 100644 index 7e9690b78..000000000 --- a/builtin/providers/aws/tags_sdk.go +++ /dev/null @@ -1,106 +0,0 @@ -package aws - -// TODO: Clint: consolidate tags and tags_sdk -// tags_sdk and tags_sdk_test are used only for transition to aws-sdk-go -// and will replace tags and tags_test when the transition to aws-sdk-go/ec2 is -// complete - -import ( - "log" - - "github.com/hashicorp/aws-sdk-go/aws" - "github.com/hashicorp/aws-sdk-go/gen/ec2" - "github.com/hashicorp/terraform/helper/schema" -) - -// tagsSchema returns the schema to use for tags. -// -// TODO: uncomment this when we replace the original tags.go -// -// func tagsSchema() *schema.Schema { -// return &schema.Schema{ -// Type: schema.TypeMap, -// Optional: true, -// } -// } - -// setTags is a helper to set the tags for a resource. It expects the -// tags field to be named "tags" -func setTagsSDK(conn *ec2.EC2, d *schema.ResourceData) error { - if d.HasChange("tags") { - oraw, nraw := d.GetChange("tags") - o := oraw.(map[string]interface{}) - n := nraw.(map[string]interface{}) - create, remove := diffTagsSDK(tagsFromMapSDK(o), tagsFromMapSDK(n)) - - // Set tags - if len(remove) > 0 { - log.Printf("[DEBUG] Removing tags: %#v", remove) - err := conn.DeleteTags(&ec2.DeleteTagsRequest{ - Resources: []string{d.Id()}, - Tags: remove, - }) - if err != nil { - return err - } - } - if len(create) > 0 { - log.Printf("[DEBUG] Creating tags: %#v", create) - err := conn.CreateTags(&ec2.CreateTagsRequest{ - Resources: []string{d.Id()}, - Tags: create, - }) - if err != nil { - return err - } - } - } - - return nil -} - -// diffTags takes our tags locally and the ones remotely and returns -// the set of tags that must be created, and the set of tags that must -// be destroyed. -func diffTagsSDK(oldTags, newTags []ec2.Tag) ([]ec2.Tag, []ec2.Tag) { - // First, we're creating everything we have - create := make(map[string]interface{}) - for _, t := range newTags { - create[*t.Key] = *t.Value - } - - // Build the list of what to remove - var remove []ec2.Tag - for _, t := range oldTags { - old, ok := create[*t.Key] - if !ok || old != *t.Value { - // Delete it! - remove = append(remove, t) - } - } - - return tagsFromMapSDK(create), remove -} - -// tagsFromMap returns the tags for the given map of data. -func tagsFromMapSDK(m map[string]interface{}) []ec2.Tag { - result := make([]ec2.Tag, 0, len(m)) - for k, v := range m { - result = append(result, ec2.Tag{ - Key: aws.String(k), - Value: aws.String(v.(string)), - }) - } - - return result -} - -// tagsToMap turns the list of tags into a map. -func tagsToMapSDK(ts []ec2.Tag) map[string]string { - result := make(map[string]string) - for _, t := range ts { - result[*t.Key] = *t.Value - } - - return result -} diff --git a/builtin/providers/aws/tags_sdk_test.go b/builtin/providers/aws/tags_sdk_test.go deleted file mode 100644 index 5a5b0e600..000000000 --- a/builtin/providers/aws/tags_sdk_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package aws - -import ( - "fmt" - "reflect" - "testing" - - "github.com/hashicorp/aws-sdk-go/gen/ec2" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" -) - -func TestDiffTagsSDK(t *testing.T) { - cases := []struct { - Old, New map[string]interface{} - Create, Remove map[string]string - }{ - // Basic add/remove - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "bar": "baz", - }, - Create: map[string]string{ - "bar": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - - // Modify - { - Old: map[string]interface{}{ - "foo": "bar", - }, - New: map[string]interface{}{ - "foo": "baz", - }, - Create: map[string]string{ - "foo": "baz", - }, - Remove: map[string]string{ - "foo": "bar", - }, - }, - } - - for i, tc := range cases { - c, r := diffTagsSDK(tagsFromMapSDK(tc.Old), tagsFromMapSDK(tc.New)) - cm := tagsToMapSDK(c) - rm := tagsToMapSDK(r) - if !reflect.DeepEqual(cm, tc.Create) { - t.Fatalf("%d: bad create: %#v", i, cm) - } - if !reflect.DeepEqual(rm, tc.Remove) { - t.Fatalf("%d: bad remove: %#v", i, rm) - } - } -} - -// testAccCheckTags can be used to check the tags on a resource. -func testAccCheckTagsSDK( - ts *[]ec2.Tag, key string, value string) resource.TestCheckFunc { - return func(s *terraform.State) error { - m := tagsToMapSDK(*ts) - v, ok := m[key] - if value != "" && !ok { - return fmt.Errorf("Missing tag: %s", key) - } else if value == "" && ok { - return fmt.Errorf("Extra tag: %s", key) - } - if value == "" { - return nil - } - - if v != value { - return fmt.Errorf("%s: bad value: %s", key, v) - } - - return nil - } -} diff --git a/builtin/providers/aws/tags_test.go b/builtin/providers/aws/tags_test.go index 6e89492ca..16578ac1b 100644 --- a/builtin/providers/aws/tags_test.go +++ b/builtin/providers/aws/tags_test.go @@ -5,9 +5,9 @@ import ( "reflect" "testing" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/ec2" ) func TestDiffTags(t *testing.T) { From 580b696e7f167b23b0b6e4fa8f76560b27a54a82 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 12 Mar 2015 16:49:38 -0500 Subject: [PATCH 56/62] Strike 'goamz' from the repo' --- builtin/providers/aws/config.go | 14 ++++------- .../aws/resource_aws_db_parameter_group.go | 2 +- builtin/providers/aws/resource_aws_elb.go | 2 +- builtin/providers/aws/structure.go | 23 +++++++++---------- .../providers/aws/r/vpc_peering.html.markdown | 2 +- 5 files changed, 18 insertions(+), 25 deletions(-) diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index 8bc9adab5..c318465b2 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -7,17 +7,14 @@ import ( "unicode" "github.com/hashicorp/terraform/helper/multierror" - "github.com/mitchellh/goamz/aws" - "github.com/mitchellh/goamz/ec2" - awsGo "github.com/hashicorp/aws-sdk-go/aws" + "github.com/hashicorp/aws-sdk-go/aws" "github.com/hashicorp/aws-sdk-go/gen/autoscaling" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/aws-sdk-go/gen/elb" "github.com/hashicorp/aws-sdk-go/gen/rds" "github.com/hashicorp/aws-sdk-go/gen/route53" "github.com/hashicorp/aws-sdk-go/gen/s3" - - awsEC2 "github.com/hashicorp/aws-sdk-go/gen/ec2" ) type Config struct { @@ -29,7 +26,6 @@ type Config struct { type AWSClient struct { ec2conn *ec2.EC2 - awsEC2conn *awsEC2.EC2 elbconn *elb.ELB autoscalingconn *autoscaling.AutoScaling s3conn *s3.S3 @@ -62,10 +58,8 @@ func (c *Config) Client() (interface{}, error) { // bucket storage in S3 client.region = c.Region - creds := awsGo.Creds(c.AccessKey, c.SecretKey, c.Token) + creds := aws.Creds(c.AccessKey, c.SecretKey, c.Token) - log.Println("[INFO] Initializing EC2 connection") - client.ec2conn = ec2.New(auth, region) log.Println("[INFO] Initializing ELB connection") client.elbconn = elb.New(creds, c.Region, nil) log.Println("[INFO] Initializing AutoScaling connection") @@ -80,7 +74,7 @@ func (c *Config) Client() (interface{}, error) { // See http://docs.aws.amazon.com/general/latest/gr/sigv4_changes.html log.Println("[INFO] Initializing Route53 connection") client.r53conn = route53.New(creds, "us-east-1", nil) - log.Println("[INFO] Initializing AWS-GO EC2 Connection") + log.Println("[INFO] Initializing EC2 Connection") client.awsEC2conn = awsEC2.New(creds, c.Region, nil) } diff --git a/builtin/providers/aws/resource_aws_db_parameter_group.go b/builtin/providers/aws/resource_aws_db_parameter_group.go index cf40d3b26..a5eda1a64 100644 --- a/builtin/providers/aws/resource_aws_db_parameter_group.go +++ b/builtin/providers/aws/resource_aws_db_parameter_group.go @@ -152,7 +152,7 @@ func resourceAwsDbParameterGroupUpdate(d *schema.ResourceData, meta interface{}) os := o.(*schema.Set) ns := n.(*schema.Set) - // Expand the "parameter" set to goamz compat []rds.Parameter + // Expand the "parameter" set to aws-sdk-go compat []rds.Parameter parameters, err := expandParameters(ns.Difference(os).List()) if err != nil { return err diff --git a/builtin/providers/aws/resource_aws_elb.go b/builtin/providers/aws/resource_aws_elb.go index e5ed9f3cf..7898f2120 100644 --- a/builtin/providers/aws/resource_aws_elb.go +++ b/builtin/providers/aws/resource_aws_elb.go @@ -161,7 +161,7 @@ func resourceAwsElb() *schema.Resource { func resourceAwsElbCreate(d *schema.ResourceData, meta interface{}) error { elbconn := meta.(*AWSClient).elbconn - // Expand the "listener" set to goamz compat []elb.Listener + // Expand the "listener" set to aws-sdk-go compat []elb.Listener listeners, err := expandListeners(d.Get("listener").(*schema.Set).List()) if err != nil { return err diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index 910f748e6..bdc04bcd2 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -4,11 +4,10 @@ import ( "strings" "github.com/hashicorp/aws-sdk-go/aws" - awsEC2 "github.com/hashicorp/aws-sdk-go/gen/ec2" + "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/aws-sdk-go/gen/elb" "github.com/hashicorp/aws-sdk-go/gen/rds" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/ec2" ) // Takes the result of flatmap.Expand for an array of listeners and @@ -17,7 +16,7 @@ func expandListeners(configured []interface{}) ([]elb.Listener, error) { listeners := make([]elb.Listener, 0, len(configured)) // Loop over our configured listeners and create - // an array of goamz compatabile objects + // an array of aws-sdk-go compatabile objects for _, lRaw := range configured { data := lRaw.(map[string]interface{}) @@ -40,10 +39,10 @@ func expandListeners(configured []interface{}) ([]elb.Listener, error) { // Takes the result of flatmap.Expand for an array of ingress/egress // security group rules and returns EC2 API compatible objects -func expandIPPerms(id string, configured []interface{}) []awsEC2.IPPermission { - perms := make([]awsEC2.IPPermission, len(configured)) +func expandIPPerms(id string, configured []interface{}) []ec2.IPPermission { + perms := make([]ec2.IPPermission, len(configured)) for i, mRaw := range configured { - var perm awsEC2.IPPermission + var perm ec2.IPPermission m := mRaw.(map[string]interface{}) perm.FromPort = aws.Integer(m["from_port"].(int)) @@ -62,14 +61,14 @@ func expandIPPerms(id string, configured []interface{}) []awsEC2.IPPermission { } if len(groups) > 0 { - perm.UserIDGroupPairs = make([]awsEC2.UserIDGroupPair, len(groups)) + perm.UserIDGroupPairs = make([]ec2.UserIDGroupPair, len(groups)) for i, name := range groups { ownerId, id := "", name if items := strings.Split(id, "/"); len(items) > 1 { ownerId, id = items[0], items[1] } - perm.UserIDGroupPairs[i] = awsEC2.UserIDGroupPair{ + perm.UserIDGroupPairs[i] = ec2.UserIDGroupPair{ GroupID: aws.String(id), UserID: aws.String(ownerId), } @@ -78,9 +77,9 @@ func expandIPPerms(id string, configured []interface{}) []awsEC2.IPPermission { if raw, ok := m["cidr_blocks"]; ok { list := raw.([]interface{}) - perm.IPRanges = make([]awsEC2.IPRange, len(list)) + perm.IPRanges = make([]ec2.IPRange, len(list)) for i, v := range list { - perm.IPRanges[i] = awsEC2.IPRange{aws.String(v.(string))} + perm.IPRanges[i] = ec2.IPRange{aws.String(v.(string))} } } @@ -96,7 +95,7 @@ func expandParameters(configured []interface{}) ([]rds.Parameter, error) { parameters := make([]rds.Parameter, 0, len(configured)) // Loop over our configured parameters and create - // an array of goamz compatabile objects + // an array of aws-sdk-go compatabile objects for _, pRaw := range configured { data := pRaw.(map[string]interface{}) @@ -139,7 +138,7 @@ func flattenSecurityGroups(list []ec2.UserSecurityGroup) []string { } // Flattens an array of UserSecurityGroups into a []string -func flattenSecurityGroupsSDK(list []awsEC2.UserIDGroupPair) []string { +func flattenSecurityGroupsSDK(list []ec2.UserIDGroupPair) []string { result := make([]string, 0, len(list)) for _, g := range list { result = append(result, *g.GroupID) diff --git a/website/source/docs/providers/aws/r/vpc_peering.html.markdown b/website/source/docs/providers/aws/r/vpc_peering.html.markdown index 59af3c0ca..1d396a584 100644 --- a/website/source/docs/providers/aws/r/vpc_peering.html.markdown +++ b/website/source/docs/providers/aws/r/vpc_peering.html.markdown @@ -56,4 +56,4 @@ The following attributes are exported: ## Notes -You still have to accept the peering with the aws console, aws-cli or goamz +You still have to accept the peering with the aws console, aws-cli or aws-sdk-go. From 28fbd971fc1b3890044b83fe10e26517420987d9 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Fri, 13 Mar 2015 09:42:50 -0500 Subject: [PATCH 57/62] Retire goamz --- builtin/providers/aws/config.go | 55 ++----------------- builtin/providers/aws/resource_aws_eip.go | 8 +-- .../providers/aws/resource_aws_eip_test.go | 4 +- .../providers/aws/resource_aws_instance.go | 8 +-- .../aws/resource_aws_instance_test.go | 4 +- .../aws/resource_aws_internet_gateway.go | 12 ++-- .../aws/resource_aws_internet_gateway_test.go | 4 +- .../providers/aws/resource_aws_key_pair.go | 6 +- .../aws/resource_aws_key_pair_test.go | 4 +- ...source_aws_main_route_table_association.go | 8 +-- ...e_aws_main_route_table_association_test.go | 2 +- .../providers/aws/resource_aws_network_acl.go | 8 +-- .../aws/resource_aws_network_acl_test.go | 8 +-- .../providers/aws/resource_aws_route_table.go | 8 +-- .../resource_aws_route_table_association.go | 8 +-- ...source_aws_route_table_association_test.go | 4 +- .../aws/resource_aws_route_table_test.go | 4 +- .../aws/resource_aws_security_group.go | 13 ++--- .../aws/resource_aws_security_group_test.go | 4 +- builtin/providers/aws/resource_aws_subnet.go | 8 +-- .../providers/aws/resource_aws_subnet_test.go | 4 +- builtin/providers/aws/resource_aws_vpc.go | 8 +-- .../resource_aws_vpc_peering_connection.go | 8 +-- ...esource_aws_vpc_peering_connection_test.go | 2 +- .../providers/aws/resource_aws_vpc_test.go | 4 +- builtin/providers/aws/structure.go | 11 +--- builtin/providers/aws/structure_test.go | 20 +++---- 27 files changed, 92 insertions(+), 145 deletions(-) diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index c318465b2..672af6f07 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -3,8 +3,6 @@ package aws import ( "fmt" "log" - "strings" - "unicode" "github.com/hashicorp/terraform/helper/multierror" @@ -41,14 +39,9 @@ func (c *Config) Client() (interface{}, error) { // Get the auth and region. This can fail if keys/regions were not // specified and we're attempting to use the environment. var errs []error - log.Println("[INFO] Building AWS auth structure") - auth, err := c.AWSAuth() - if err != nil { - errs = append(errs, err) - } log.Println("[INFO] Building AWS region structure") - region, err := c.AWSRegion() + err := c.ValidateRegion() if err != nil { errs = append(errs, err) } @@ -58,6 +51,7 @@ func (c *Config) Client() (interface{}, error) { // bucket storage in S3 client.region = c.Region + log.Println("[INFO] Building AWS auth structure") creds := aws.Creds(c.AccessKey, c.SecretKey, c.Token) log.Println("[INFO] Initializing ELB connection") @@ -75,7 +69,7 @@ func (c *Config) Client() (interface{}, error) { log.Println("[INFO] Initializing Route53 connection") client.r53conn = route53.New(creds, "us-east-1", nil) log.Println("[INFO] Initializing EC2 Connection") - client.awsEC2conn = awsEC2.New(creds, c.Region, nil) + client.ec2conn = ec2.New(creds, c.Region, nil) } if len(errs) > 0 { @@ -85,54 +79,17 @@ func (c *Config) Client() (interface{}, error) { return &client, nil } -// AWSAuth returns a valid aws.Auth object for access to AWS services, or -// an error if the authentication couldn't be resolved. -// -// TODO(mitchellh): Test in some way. -func (c *Config) AWSAuth() (aws.Auth, error) { - auth, err := aws.GetAuth(c.AccessKey, c.SecretKey) - if err == nil { - // Store the accesskey and secret that we got... - c.AccessKey = auth.AccessKey - c.SecretKey = auth.SecretKey - c.Token = auth.Token - } - - return auth, err -} - // IsValidRegion returns true if the configured region is a valid AWS // region and false if it's not -func (c *Config) IsValidRegion() bool { +func (c *Config) ValidateRegion() error { var regions = [11]string{"us-east-1", "us-west-2", "us-west-1", "eu-west-1", "eu-central-1", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1", "sa-east-1", "cn-north-1", "us-gov-west-1"} for _, valid := range regions { if c.Region == valid { - return true + return nil } } - return false -} - -// AWSRegion returns the configured region. -// -// TODO(mitchellh): Test in some way. -func (c *Config) AWSRegion() (aws.Region, error) { - if c.Region != "" { - if c.IsValidRegion() { - return aws.Regions[c.Region], nil - } else { - return aws.Region{}, fmt.Errorf("Not a valid region: %s", c.Region) - } - } - - md, err := aws.GetMetaData("placement/availability-zone") - if err != nil { - return aws.Region{}, err - } - - region := strings.TrimRightFunc(string(md), unicode.IsLetter) - return aws.Regions[region], nil + return fmt.Errorf("Not a valid region: %s", c.Region) } diff --git a/builtin/providers/aws/resource_aws_eip.go b/builtin/providers/aws/resource_aws_eip.go index 103f9bc5a..c78fec4c9 100644 --- a/builtin/providers/aws/resource_aws_eip.go +++ b/builtin/providers/aws/resource_aws_eip.go @@ -60,7 +60,7 @@ func resourceAwsEip() *schema.Resource { } func resourceAwsEipCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // By default, we're not in a VPC domainOpt := "" @@ -97,7 +97,7 @@ func resourceAwsEipCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsEipRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn domain := resourceAwsEipDomain(d) id := d.Id() @@ -148,7 +148,7 @@ func resourceAwsEipRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn domain := resourceAwsEipDomain(d) @@ -181,7 +181,7 @@ func resourceAwsEipUpdate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsEipDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn if err := resourceAwsEipRead(d, meta); err != nil { return err diff --git a/builtin/providers/aws/resource_aws_eip_test.go b/builtin/providers/aws/resource_aws_eip_test.go index 79e88b8f3..b9944366f 100644 --- a/builtin/providers/aws/resource_aws_eip_test.go +++ b/builtin/providers/aws/resource_aws_eip_test.go @@ -58,7 +58,7 @@ func TestAccAWSEIP_instance(t *testing.T) { } func testAccCheckAWSEIPDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_eip" { @@ -113,7 +113,7 @@ func testAccCheckAWSEIPExists(n string, res *ec2.Address) resource.TestCheckFunc return fmt.Errorf("No EIP ID is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn if strings.Contains(rs.Primary.ID, "eipalloc") { req := &ec2.DescribeAddressesRequest{ diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index 5ecd86645..0fb3d68c0 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -253,7 +253,7 @@ func resourceAwsInstance() *schema.Resource { } func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Figure out user data userData := "" @@ -437,7 +437,7 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn resp, err := ec2conn.DescribeInstances(&ec2.DescribeInstancesRequest{ InstanceIDs: []string{d.Id()}, @@ -561,7 +561,7 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn opts := new(ec2.ModifyInstanceAttributeRequest) log.Printf("[INFO] Modifying instance %s: %#v", d.Id(), opts) @@ -589,7 +589,7 @@ func resourceAwsInstanceUpdate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsInstanceDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn log.Printf("[INFO] Terminating instance: %s", d.Id()) req := &ec2.TerminateInstancesRequest{ diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index b0d2783ac..369c1b832 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -296,7 +296,7 @@ func TestAccAWSInstance_associatePublicIPAndPrivateIP(t *testing.T) { } func testAccCheckInstanceDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_instance" { @@ -339,7 +339,7 @@ func testAccCheckInstanceExists(n string, i *ec2.Instance) resource.TestCheckFun return fmt.Errorf("No ID is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := conn.DescribeInstances(&ec2.DescribeInstancesRequest{ InstanceIDs: []string{rs.Primary.ID}, }) diff --git a/builtin/providers/aws/resource_aws_internet_gateway.go b/builtin/providers/aws/resource_aws_internet_gateway.go index b43e4fd44..9546ffb5c 100644 --- a/builtin/providers/aws/resource_aws_internet_gateway.go +++ b/builtin/providers/aws/resource_aws_internet_gateway.go @@ -29,7 +29,7 @@ func resourceAwsInternetGateway() *schema.Resource { } func resourceAwsInternetGatewayCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Create the gateway log.Printf("[DEBUG] Creating internet gateway") @@ -53,7 +53,7 @@ func resourceAwsInternetGatewayCreate(d *schema.ResourceData, meta interface{}) } func resourceAwsInternetGatewayRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn igRaw, _, err := IGStateRefreshFunc(ec2conn, d.Id())() if err != nil { @@ -91,7 +91,7 @@ func resourceAwsInternetGatewayUpdate(d *schema.ResourceData, meta interface{}) } } - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn if err := setTags(ec2conn, d); err != nil { return err @@ -103,7 +103,7 @@ func resourceAwsInternetGatewayUpdate(d *schema.ResourceData, meta interface{}) } func resourceAwsInternetGatewayDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Detach if it is attached if err := resourceAwsInternetGatewayDetach(d, meta); err != nil { @@ -137,7 +137,7 @@ func resourceAwsInternetGatewayDelete(d *schema.ResourceData, meta interface{}) } func resourceAwsInternetGatewayAttach(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn if d.Get("vpc_id").(string) == "" { log.Printf( @@ -182,7 +182,7 @@ func resourceAwsInternetGatewayAttach(d *schema.ResourceData, meta interface{}) } func resourceAwsInternetGatewayDetach(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Get the old VPC ID to detach from vpcID, _ := d.GetChange("vpc_id") diff --git a/builtin/providers/aws/resource_aws_internet_gateway_test.go b/builtin/providers/aws/resource_aws_internet_gateway_test.go index 48f7de664..a07d1abff 100644 --- a/builtin/providers/aws/resource_aws_internet_gateway_test.go +++ b/builtin/providers/aws/resource_aws_internet_gateway_test.go @@ -115,7 +115,7 @@ func TestAccInternetGateway_tags(t *testing.T) { } func testAccCheckInternetGatewayDestroy(s *terraform.State) error { - ec2conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_internet_gateway" { @@ -158,7 +158,7 @@ func testAccCheckInternetGatewayExists(n string, ig *ec2.InternetGateway) resour return fmt.Errorf("No ID is set") } - ec2conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := ec2conn.DescribeInternetGateways(&ec2.DescribeInternetGatewaysRequest{ InternetGatewayIDs: []string{rs.Primary.ID}, }) diff --git a/builtin/providers/aws/resource_aws_key_pair.go b/builtin/providers/aws/resource_aws_key_pair.go index 573a93567..e96ecf620 100644 --- a/builtin/providers/aws/resource_aws_key_pair.go +++ b/builtin/providers/aws/resource_aws_key_pair.go @@ -37,7 +37,7 @@ func resourceAwsKeyPair() *schema.Resource { } func resourceAwsKeyPairCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn keyName := d.Get("key_name").(string) publicKey := d.Get("public_key").(string) @@ -55,7 +55,7 @@ func resourceAwsKeyPairCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsKeyPairRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn req := &ec2.DescribeKeyPairsRequest{ KeyNames: []string{d.Id()}, @@ -77,7 +77,7 @@ func resourceAwsKeyPairRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsKeyPairDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn err := ec2conn.DeleteKeyPair(&ec2.DeleteKeyPairRequest{ KeyName: aws.String(d.Id()), diff --git a/builtin/providers/aws/resource_aws_key_pair_test.go b/builtin/providers/aws/resource_aws_key_pair_test.go index b601d479a..695da661f 100644 --- a/builtin/providers/aws/resource_aws_key_pair_test.go +++ b/builtin/providers/aws/resource_aws_key_pair_test.go @@ -30,7 +30,7 @@ func TestAccAWSKeyPair_normal(t *testing.T) { } func testAccCheckAWSKeyPairDestroy(s *terraform.State) error { - ec2conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_key_pair" { @@ -81,7 +81,7 @@ func testAccCheckAWSKeyPairExists(n string, res *ec2.KeyPairInfo) resource.TestC return fmt.Errorf("No KeyPair name is set") } - ec2conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + ec2conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := ec2conn.DescribeKeyPairs(&ec2.DescribeKeyPairsRequest{ KeyNames: []string{rs.Primary.ID}, diff --git a/builtin/providers/aws/resource_aws_main_route_table_association.go b/builtin/providers/aws/resource_aws_main_route_table_association.go index a489b9a50..40303ab1e 100644 --- a/builtin/providers/aws/resource_aws_main_route_table_association.go +++ b/builtin/providers/aws/resource_aws_main_route_table_association.go @@ -40,7 +40,7 @@ func resourceAwsMainRouteTableAssociation() *schema.Resource { } func resourceAwsMainRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn vpcId := d.Get("vpc_id").(string) routeTableId := d.Get("route_table_id").(string) @@ -67,7 +67,7 @@ func resourceAwsMainRouteTableAssociationCreate(d *schema.ResourceData, meta int } func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn mainAssociation, err := findMainRouteTableAssociation( ec2conn, @@ -88,7 +88,7 @@ func resourceAwsMainRouteTableAssociationRead(d *schema.ResourceData, meta inter // original_route_table_id - this needs to stay recorded as the AWS-created // table from VPC creation. func resourceAwsMainRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn vpcId := d.Get("vpc_id").(string) routeTableId := d.Get("route_table_id").(string) @@ -109,7 +109,7 @@ func resourceAwsMainRouteTableAssociationUpdate(d *schema.ResourceData, meta int } func resourceAwsMainRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn vpcId := d.Get("vpc_id").(string) originalRouteTableId := d.Get("original_route_table_id").(string) diff --git a/builtin/providers/aws/resource_aws_main_route_table_association_test.go b/builtin/providers/aws/resource_aws_main_route_table_association_test.go index 76e3e4d72..81f87a901 100644 --- a/builtin/providers/aws/resource_aws_main_route_table_association_test.go +++ b/builtin/providers/aws/resource_aws_main_route_table_association_test.go @@ -65,7 +65,7 @@ func testAccCheckMainRouteTableAssociation( return fmt.Errorf("Not found: %s", vpcResource) } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn mainAssociation, err := findMainRouteTableAssociation(conn, vpc.Primary.ID) if err != nil { return err diff --git a/builtin/providers/aws/resource_aws_network_acl.go b/builtin/providers/aws/resource_aws_network_acl.go index 9afe8aee3..0d625ffe4 100644 --- a/builtin/providers/aws/resource_aws_network_acl.go +++ b/builtin/providers/aws/resource_aws_network_acl.go @@ -109,7 +109,7 @@ func resourceAwsNetworkAcl() *schema.Resource { func resourceAwsNetworkAclCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Create the Network Acl createOpts := &ec2.CreateNetworkACLRequest{ @@ -132,7 +132,7 @@ func resourceAwsNetworkAclCreate(d *schema.ResourceData, meta interface{}) error } func resourceAwsNetworkAclRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn resp, err := ec2conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ NetworkACLIDs: []string{d.Id()}, @@ -167,7 +167,7 @@ func resourceAwsNetworkAclRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsNetworkAclUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn d.Partial(true) if d.HasChange("ingress") { @@ -265,7 +265,7 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, ec2conn * } func resourceAwsNetworkAclDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn log.Printf("[INFO] Deleting Network Acl: %s", d.Id()) return resource.Retry(5*time.Minute, func() error { diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index e27e57d1a..23c60db44 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -184,7 +184,7 @@ func TestAccAWSNetworkAcl_SubnetChange(t *testing.T) { } func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_network" { @@ -226,7 +226,7 @@ func testAccCheckAWSNetworkAclExists(n string, networkAcl *ec2.NetworkACL) resou if rs.Primary.ID == "" { return fmt.Errorf("No Security Group is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ NetworkACLIDs: []string{rs.Primary.ID}, @@ -266,7 +266,7 @@ func testAccCheckSubnetIsAssociatedWithAcl(acl string, sub string) resource.Test networkAcl := s.RootModule().Resources[acl] subnet := s.RootModule().Resources[sub] - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ NetworkACLIDs: []string{networkAcl.Primary.ID}, Filters: []ec2.Filter{ @@ -296,7 +296,7 @@ func testAccCheckSubnetIsNotAssociatedWithAcl(acl string, subnet string) resourc networkAcl := s.RootModule().Resources[acl] subnet := s.RootModule().Resources[subnet] - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := conn.DescribeNetworkACLs(&ec2.DescribeNetworkACLsRequest{ NetworkACLIDs: []string{networkAcl.Primary.ID}, Filters: []ec2.Filter{ diff --git a/builtin/providers/aws/resource_aws_route_table.go b/builtin/providers/aws/resource_aws_route_table.go index e26c17ce1..6a4b1d3ca 100644 --- a/builtin/providers/aws/resource_aws_route_table.go +++ b/builtin/providers/aws/resource_aws_route_table.go @@ -62,7 +62,7 @@ func resourceAwsRouteTable() *schema.Resource { } func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Create the routing table createOpts := &ec2.CreateRouteTableRequest{ @@ -100,7 +100,7 @@ func resourceAwsRouteTableCreate(d *schema.ResourceData, meta interface{}) error } func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc(ec2conn, d.Id())() if err != nil { @@ -152,7 +152,7 @@ func resourceAwsRouteTableRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Check if the route set as a whole has changed if d.HasChange("route") { @@ -213,7 +213,7 @@ func resourceAwsRouteTableUpdate(d *schema.ResourceData, meta interface{}) error } func resourceAwsRouteTableDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // First request the routing table since we'll have to disassociate // all the subnets first. diff --git a/builtin/providers/aws/resource_aws_route_table_association.go b/builtin/providers/aws/resource_aws_route_table_association.go index a9a614f7f..8fd324035 100644 --- a/builtin/providers/aws/resource_aws_route_table_association.go +++ b/builtin/providers/aws/resource_aws_route_table_association.go @@ -32,7 +32,7 @@ func resourceAwsRouteTableAssociation() *schema.Resource { } func resourceAwsRouteTableAssociationCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn log.Printf( "[INFO] Creating route table association: %s => %s", @@ -56,7 +56,7 @@ func resourceAwsRouteTableAssociationCreate(d *schema.ResourceData, meta interfa } func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Get the routing table that this association belongs to rtRaw, _, err := resourceAwsRouteTableStateRefreshFunc( @@ -88,7 +88,7 @@ func resourceAwsRouteTableAssociationRead(d *schema.ResourceData, meta interface } func resourceAwsRouteTableAssociationUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn log.Printf( "[INFO] Creating route table association: %s => %s", @@ -119,7 +119,7 @@ func resourceAwsRouteTableAssociationUpdate(d *schema.ResourceData, meta interfa } func resourceAwsRouteTableAssociationDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn log.Printf("[INFO] Deleting route table association: %s", d.Id()) err := ec2conn.DisassociateRouteTable(&ec2.DisassociateRouteTableRequest{ diff --git a/builtin/providers/aws/resource_aws_route_table_association_test.go b/builtin/providers/aws/resource_aws_route_table_association_test.go index 8c4246aba..f5302258d 100644 --- a/builtin/providers/aws/resource_aws_route_table_association_test.go +++ b/builtin/providers/aws/resource_aws_route_table_association_test.go @@ -38,7 +38,7 @@ func TestAccAWSRouteTableAssociation(t *testing.T) { } func testAccCheckRouteTableAssociationDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_route_table_association" { @@ -83,7 +83,7 @@ func testAccCheckRouteTableAssociationExists(n string, v *ec2.RouteTable) resour return fmt.Errorf("No ID is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ RouteTableIDs: []string{rs.Primary.Attributes["route_table_id"]}, }) diff --git a/builtin/providers/aws/resource_aws_route_table_test.go b/builtin/providers/aws/resource_aws_route_table_test.go index da90d491d..b428b8786 100644 --- a/builtin/providers/aws/resource_aws_route_table_test.go +++ b/builtin/providers/aws/resource_aws_route_table_test.go @@ -151,7 +151,7 @@ func TestAccAWSRouteTable_tags(t *testing.T) { } func testAccCheckRouteTableDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_route_table" { @@ -194,7 +194,7 @@ func testAccCheckRouteTableExists(n string, v *ec2.RouteTable) resource.TestChec return fmt.Errorf("No ID is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := conn.DescribeRouteTables(&ec2.DescribeRouteTablesRequest{ RouteTableIDs: []string{rs.Primary.ID}, }) diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index 588040830..c8051813f 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -142,7 +142,7 @@ func resourceAwsSecurityGroup() *schema.Resource { } func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn securityGroupOpts := &ec2.CreateSecurityGroupRequest{ GroupName: aws.String(d.Get("name").(string)), @@ -187,7 +187,7 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er } func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())() if err != nil { @@ -214,7 +214,7 @@ func resourceAwsSecurityGroupRead(d *schema.ResourceData, meta interface{}) erro } func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn sgRaw, _, err := SGStateRefreshFunc(ec2conn, d.Id())() if err != nil { @@ -249,7 +249,7 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er } func resourceAwsSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn log.Printf("[DEBUG] Security Group destroy: %v", d.Id()) @@ -354,7 +354,7 @@ func resourceAwsSecurityGroupIPPermGather(d *schema.ResourceData, permissions [] var groups []string if len(perm.UserIDGroupPairs) > 0 { - groups = flattenSecurityGroupsSDK(perm.UserIDGroupPairs) + groups = flattenSecurityGroups(perm.UserIDGroupPairs) } for i, id := range groups { if id == d.Id() { @@ -396,7 +396,6 @@ func resourceAwsSecurityGroupUpdateRules( os := o.(*schema.Set) ns := n.(*schema.Set) - // TODO: re-munge this when test is updated remove := expandIPPerms(d.Id(), os.Difference(ns).List()) add := expandIPPerms(d.Id(), ns.Difference(os).List()) @@ -410,7 +409,7 @@ func resourceAwsSecurityGroupUpdateRules( // not have service issues. if len(remove) > 0 || len(add) > 0 { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn var err error if len(remove) > 0 { diff --git a/builtin/providers/aws/resource_aws_security_group_test.go b/builtin/providers/aws/resource_aws_security_group_test.go index a0cd2c12f..b1e4e8c82 100644 --- a/builtin/providers/aws/resource_aws_security_group_test.go +++ b/builtin/providers/aws/resource_aws_security_group_test.go @@ -186,7 +186,7 @@ func TestAccAWSSecurityGroup_Change(t *testing.T) { } func testAccCheckAWSSecurityGroupDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_security_group" { @@ -230,7 +230,7 @@ func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroup) reso return fmt.Errorf("No Security Group is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn req := &ec2.DescribeSecurityGroupsRequest{ GroupIDs: []string{rs.Primary.ID}, } diff --git a/builtin/providers/aws/resource_aws_subnet.go b/builtin/providers/aws/resource_aws_subnet.go index 07a3413f2..d1db5aed9 100644 --- a/builtin/providers/aws/resource_aws_subnet.go +++ b/builtin/providers/aws/resource_aws_subnet.go @@ -51,7 +51,7 @@ func resourceAwsSubnet() *schema.Resource { } func resourceAwsSubnetCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn createOpts := &ec2.CreateSubnetRequest{ AvailabilityZone: aws.String(d.Get("availability_zone").(string)), @@ -91,7 +91,7 @@ func resourceAwsSubnetCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsSubnetRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsRequest{ SubnetIDs: []string{d.Id()}, @@ -121,7 +121,7 @@ func resourceAwsSubnetRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn d.Partial(true) @@ -154,7 +154,7 @@ func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsSubnetDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn log.Printf("[INFO] Deleting subnet: %s", d.Id()) diff --git a/builtin/providers/aws/resource_aws_subnet_test.go b/builtin/providers/aws/resource_aws_subnet_test.go index 77dfeccf0..ae7b28dee 100644 --- a/builtin/providers/aws/resource_aws_subnet_test.go +++ b/builtin/providers/aws/resource_aws_subnet_test.go @@ -43,7 +43,7 @@ func TestAccAWSSubnet(t *testing.T) { } func testAccCheckSubnetDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_subnet" { @@ -86,7 +86,7 @@ func testAccCheckSubnetExists(n string, v *ec2.Subnet) resource.TestCheckFunc { return fmt.Errorf("No ID is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn resp, err := conn.DescribeSubnets(&ec2.DescribeSubnetsRequest{ SubnetIDs: []string{rs.Primary.ID}, }) diff --git a/builtin/providers/aws/resource_aws_vpc.go b/builtin/providers/aws/resource_aws_vpc.go index 0e2485972..0ef8aa570 100644 --- a/builtin/providers/aws/resource_aws_vpc.go +++ b/builtin/providers/aws/resource_aws_vpc.go @@ -64,7 +64,7 @@ func resourceAwsVpc() *schema.Resource { } func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn instance_tenancy := "default" if v, ok := d.GetOk("instance_tenancy"); ok { instance_tenancy = v.(string) @@ -110,7 +110,7 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Refresh the VPC state vpcRaw, _, err := VPCStateRefreshFunc(ec2conn, d.Id())() @@ -180,7 +180,7 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Turn on partial mode d.Partial(true) @@ -231,7 +231,7 @@ func resourceAwsVpcUpdate(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn vpcID := d.Id() DeleteVpcOpts := &ec2.DeleteVPCRequest{ VPCID: &vpcID, diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection.go b/builtin/providers/aws/resource_aws_vpc_peering_connection.go index 548718f43..0f8c6185b 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection.go @@ -41,7 +41,7 @@ func resourceAwsVpcPeeringConnection() *schema.Resource { } func resourceAwsVpcPeeringCreate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn // Create the vpc peering connection createOpts := &ec2.CreateVPCPeeringConnectionRequest{ @@ -80,7 +80,7 @@ func resourceAwsVpcPeeringCreate(d *schema.ResourceData, meta interface{}) error } func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn pcRaw, _, err := resourceAwsVpcPeeringConnectionStateRefreshFunc(ec2conn, d.Id())() if err != nil { return err @@ -101,7 +101,7 @@ func resourceAwsVpcPeeringRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn if err := setTags(ec2conn, d); err != nil { return err @@ -113,7 +113,7 @@ func resourceAwsVpcPeeringUpdate(d *schema.ResourceData, meta interface{}) error } func resourceAwsVpcPeeringDelete(d *schema.ResourceData, meta interface{}) error { - ec2conn := meta.(*AWSClient).awsEC2conn + ec2conn := meta.(*AWSClient).ec2conn _, err := ec2conn.DeleteVPCPeeringConnection( &ec2.DeleteVPCPeeringConnectionRequest{ diff --git a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go index 307dcb7d9..c374646b8 100644 --- a/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go +++ b/builtin/providers/aws/resource_aws_vpc_peering_connection_test.go @@ -28,7 +28,7 @@ func TestAccAWSVPCPeeringConnection_normal(t *testing.T) { } func testAccCheckAWSVpcPeeringConnectionDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_vpc_peering_connection" { diff --git a/builtin/providers/aws/resource_aws_vpc_test.go b/builtin/providers/aws/resource_aws_vpc_test.go index 4f3f02f0f..092f47806 100644 --- a/builtin/providers/aws/resource_aws_vpc_test.go +++ b/builtin/providers/aws/resource_aws_vpc_test.go @@ -111,7 +111,7 @@ func TestAccVpcUpdate(t *testing.T) { } func testAccCheckVpcDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_vpc" { @@ -166,7 +166,7 @@ func testAccCheckVpcExists(n string, vpc *ec2.VPC) resource.TestCheckFunc { return fmt.Errorf("No VPC ID is set") } - conn := testAccProvider.Meta().(*AWSClient).awsEC2conn + conn := testAccProvider.Meta().(*AWSClient).ec2conn DescribeVpcOpts := &ec2.DescribeVPCsRequest{ VPCIDs: []string{rs.Primary.ID}, } diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index bdc04bcd2..617c2bbf9 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -129,16 +129,7 @@ func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} { } // Flattens an array of UserSecurityGroups into a []string -func flattenSecurityGroups(list []ec2.UserSecurityGroup) []string { - result := make([]string, 0, len(list)) - for _, g := range list { - result = append(result, g.Id) - } - return result -} - -// Flattens an array of UserSecurityGroups into a []string -func flattenSecurityGroupsSDK(list []ec2.UserIDGroupPair) []string { +func flattenSecurityGroups(list []ec2.UserIDGroupPair) []string { result := make([]string, 0, len(list)) for _, g := range list { result = append(result, *g.GroupID) diff --git a/builtin/providers/aws/structure_test.go b/builtin/providers/aws/structure_test.go index d5e470341..b85adc51a 100644 --- a/builtin/providers/aws/structure_test.go +++ b/builtin/providers/aws/structure_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/hashicorp/aws-sdk-go/aws" - awsEC2 "github.com/hashicorp/aws-sdk-go/gen/ec2" + ec2 "github.com/hashicorp/aws-sdk-go/gen/ec2" "github.com/hashicorp/aws-sdk-go/gen/elb" "github.com/hashicorp/aws-sdk-go/gen/rds" "github.com/hashicorp/terraform/flatmap" @@ -61,28 +61,28 @@ func TestExpandIPPerms(t *testing.T) { } perms := expandIPPerms("foo", expanded) - expected := []awsEC2.IPPermission{ - awsEC2.IPPermission{ + expected := []ec2.IPPermission{ + ec2.IPPermission{ IPProtocol: aws.String("icmp"), FromPort: aws.Integer(1), ToPort: aws.Integer(-1), - IPRanges: []awsEC2.IPRange{awsEC2.IPRange{aws.String("0.0.0.0/0")}}, - UserIDGroupPairs: []awsEC2.UserIDGroupPair{ - awsEC2.UserIDGroupPair{ + IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("0.0.0.0/0")}}, + UserIDGroupPairs: []ec2.UserIDGroupPair{ + ec2.UserIDGroupPair{ UserID: aws.String("foo"), GroupID: aws.String("sg-22222"), }, - awsEC2.UserIDGroupPair{ + ec2.UserIDGroupPair{ GroupID: aws.String("sg-22222"), }, }, }, - awsEC2.IPPermission{ + ec2.IPPermission{ IPProtocol: aws.String("icmp"), FromPort: aws.Integer(1), ToPort: aws.Integer(-1), - UserIDGroupPairs: []awsEC2.UserIDGroupPair{ - awsEC2.UserIDGroupPair{ + UserIDGroupPairs: []ec2.UserIDGroupPair{ + ec2.UserIDGroupPair{ UserID: aws.String("foo"), }, }, From d5f23aec0a5c795635687386ebf9430f787c1b10 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Fri, 13 Mar 2015 10:54:00 -0500 Subject: [PATCH 58/62] provider/aws: Fix encoding bug with AWS Instance --- builtin/providers/aws/resource_aws_instance.go | 3 ++- builtin/providers/aws/resource_aws_instance_test.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index 5475e7454..6ffd6a983 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -3,6 +3,7 @@ package aws import ( "bytes" "crypto/sha1" + "encoding/base64" "encoding/hex" "fmt" "log" @@ -258,7 +259,7 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { // Figure out user data userData := "" if v := d.Get("user_data"); v != nil { - userData = v.(string) + userData = base64.StdEncoding.EncodeToString([]byte(v.(string))) } placement := &ec2.Placement{ diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index 3a9c16588..a9d439591 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -392,7 +392,7 @@ resource "aws_instance" "foo" { instance_type = "m1.small" security_groups = ["${aws_security_group.tf_test_foo.name}"] - user_data = "foo" + user_data = "foo:-with-character's" } ` From 670d22e18f1f7991475da33546b42bfdceffe0f1 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Fri, 13 Mar 2015 14:58:05 -0500 Subject: [PATCH 59/62] update acceptance test with the correct depends_on declarations --- builtin/providers/aws/resource_aws_instance_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index e5f460954..461a5e926 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -556,7 +556,6 @@ resource "aws_instance" "foo" { const testAccInstanceNetworkInstanceSecurityGroups = ` resource "aws_internet_gateway" "gw" { vpc_id = "${aws_vpc.foo.id}" - depends_on = ["aws_eip.foo_eip"] } resource "aws_vpc" "foo" { @@ -590,10 +589,12 @@ resource "aws_instance" "foo_instance" { security_groups = ["${aws_security_group.tf_test_foo.id}"] subnet_id = "${aws_subnet.foo.id}" associate_public_ip_address = true + depends_on = ["aws_internet_gateway.gw"] } resource "aws_eip" "foo_eip" { instance = "${aws_instance.foo_instance.id}" vpc = true + depends_on = ["aws_internet_gateway.gw"] } ` From 2d62e55b0edce36d07653cf09257a1835f9ea974 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Fri, 13 Mar 2015 15:39:17 -0500 Subject: [PATCH 60/62] Add note to Intergent Gateway resource on using depends_on --- .../docs/providers/aws/r/internet_gateway.html.markdown | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/website/source/docs/providers/aws/r/internet_gateway.html.markdown b/website/source/docs/providers/aws/r/internet_gateway.html.markdown index ec79f922a..40fedbb2a 100644 --- a/website/source/docs/providers/aws/r/internet_gateway.html.markdown +++ b/website/source/docs/providers/aws/r/internet_gateway.html.markdown @@ -29,6 +29,11 @@ The following arguments are supported: * `vpc_id` - (Required) The VPC ID to create in. * `tags` - (Optional) A mapping of tags to assign to the resource. +-> **Note:** When using Internet Gateways with AWS Instances or Elastic IPs, +it is recommended to denote that they depend on the Internet Gateway created, +via the `depends_on` attribute: +`depends_on = ["aws_internet_gateway.gw"]`. + ## Attributes Reference The following attributes are exported: From cd15c9aaf9bbca910a19b22d68a00c04ce2cbc8e Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Fri, 13 Mar 2015 16:04:27 -0500 Subject: [PATCH 61/62] clean up docs --- .../aws/r/internet_gateway.html.markdown | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/website/source/docs/providers/aws/r/internet_gateway.html.markdown b/website/source/docs/providers/aws/r/internet_gateway.html.markdown index 40fedbb2a..cefedc6ad 100644 --- a/website/source/docs/providers/aws/r/internet_gateway.html.markdown +++ b/website/source/docs/providers/aws/r/internet_gateway.html.markdown @@ -29,10 +29,17 @@ The following arguments are supported: * `vpc_id` - (Required) The VPC ID to create in. * `tags` - (Optional) A mapping of tags to assign to the resource. --> **Note:** When using Internet Gateways with AWS Instances or Elastic IPs, -it is recommended to denote that they depend on the Internet Gateway created, -via the `depends_on` attribute: -`depends_on = ["aws_internet_gateway.gw"]`. +-> **Note:** It's recommended to denote that the AWS Instance or Elastic IP depends on the Internet Gateway. For example: + + + resource "aws_internet_gateway" "gw" { + vpc_id = "${aws_vpc.main.id}" + } + + resource "aws_instance" "foo" { + depends_on = ["aws_internet_gateway.gw"] + } + ## Attributes Reference From 0d13cd1f54cf220d8f88f3d94f8c6574014bd14d Mon Sep 17 00:00:00 2001 From: Joshua Lund Date: Fri, 13 Mar 2015 17:37:05 -0600 Subject: [PATCH 62/62] Typo fix. --- website/source/docs/commands/remote.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/docs/commands/remote.html.markdown b/website/source/docs/commands/remote.html.markdown index 3bc96c802..22d341891 100644 --- a/website/source/docs/commands/remote.html.markdown +++ b/website/source/docs/commands/remote.html.markdown @@ -16,7 +16,7 @@ Terraform will automatically fetch the latest state from the remote server when necessary and if any updates are made, the newest state is persisted back to the remote server. In this mode, users do not need to durably store the state using version -control or shared storaged. +control or shared storage. ## Usage