From 94d30aa70ad53021e9d270ad46e0a7c29f132f32 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Thu, 5 Mar 2015 09:45:39 -0600 Subject: [PATCH 01/28] 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 02/28] 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 20b02cacd454c2318c60132e9ba1b7dc5f75ebca Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Mon, 9 Mar 2015 10:02:27 -0500 Subject: [PATCH 03/28] 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 04/28] 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 05/28] 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 06/28] 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 07/28] 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 08/28] 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 09/28] 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 10/28] 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 11/28] 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 12/28] 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 13/28] 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 14/28] 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 15/28] 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 16/28] 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 17/28] 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 18/28] 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 19/28] 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 20/28] 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 21/28] 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 22/28] 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 23/28] 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 24/28] 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 25/28] 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 26/28] 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 27/28] 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 28/28] 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"),