From d79b0d7fd1bae570c8f4bc1d766a9c8876b47927 Mon Sep 17 00:00:00 2001 From: Clint Shryock Date: Mon, 23 Feb 2015 15:22:52 -0600 Subject: [PATCH] provider/aws: Convert AWS DB Instance over to awslabs/aws-sdk-go - Remove check on password for AWS RDS Instance - Update documentation on AWS RDS Instance regarding DB Security Groups - Change error handling to check error code from AWS API [ci skip] --- builtin/providers/aws/config.go | 4 + .../providers/aws/resource_aws_db_instance.go | 124 +++++++++--------- .../aws/resource_aws_db_instance_test.go | 45 ++----- .../providers/aws/r/db_instance.html.markdown | 4 +- 4 files changed, 83 insertions(+), 94 deletions(-) diff --git a/builtin/providers/aws/config.go b/builtin/providers/aws/config.go index 47e1c00fb..99367642b 100644 --- a/builtin/providers/aws/config.go +++ b/builtin/providers/aws/config.go @@ -15,6 +15,7 @@ import ( awsGo "github.com/awslabs/aws-sdk-go/aws" awsAutoScaling "github.com/awslabs/aws-sdk-go/gen/autoscaling" + awsRDS "github.com/awslabs/aws-sdk-go/gen/rds" "github.com/awslabs/aws-sdk-go/gen/route53" "github.com/awslabs/aws-sdk-go/gen/s3" ) @@ -34,6 +35,7 @@ type AWSClient struct { r53conn *route53.Route53 region string awsAutoScalingconn *awsAutoScaling.AutoScaling + awsRDSconn *awsRDS.RDS } // Client configures and returns a fully initailized AWSClient @@ -80,6 +82,8 @@ func (c *Config) Client() (interface{}, error) { client.r53conn = route53.New(creds, "us-east-1", nil) log.Println("[INFO] Initializing AWS Go AutoScaling connection") client.awsAutoScalingconn = awsAutoScaling.New(creds, c.Region, nil) + log.Println("[INFO] Initializing AWS Go RDS connection") + client.awsRDSconn = awsRDS.New(creds, c.Region, nil) } if len(errs) > 0 { diff --git a/builtin/providers/aws/resource_aws_db_instance.go b/builtin/providers/aws/resource_aws_db_instance.go index ff88a1e44..c95847a7b 100644 --- a/builtin/providers/aws/resource_aws_db_instance.go +++ b/builtin/providers/aws/resource_aws_db_instance.go @@ -3,13 +3,14 @@ package aws import ( "fmt" "log" - "strings" "time" + "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/gen/rds" + "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" - "github.com/mitchellh/goamz/rds" ) func resourceAwsDbInstance() *schema.Resource { @@ -184,64 +185,60 @@ func resourceAwsDbInstance() *schema.Resource { } func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).rdsconn - opts := rds.CreateDBInstance{ - AllocatedStorage: d.Get("allocated_storage").(int), - SetAllocatedStorage: true, - DBInstanceClass: d.Get("instance_class").(string), - DBInstanceIdentifier: d.Get("identifier").(string), - DBName: d.Get("name").(string), - MasterUsername: d.Get("username").(string), - MasterUserPassword: d.Get("password").(string), - Engine: d.Get("engine").(string), - EngineVersion: d.Get("engine_version").(string), + conn := meta.(*AWSClient).awsRDSconn + opts := rds.CreateDBInstanceMessage{ + AllocatedStorage: aws.Integer(d.Get("allocated_storage").(int)), + DBInstanceClass: aws.String(d.Get("instance_class").(string)), + DBInstanceIdentifier: aws.String(d.Get("identifier").(string)), + DBName: aws.String(d.Get("name").(string)), + MasterUsername: aws.String(d.Get("username").(string)), + MasterUserPassword: aws.String(d.Get("password").(string)), + Engine: aws.String(d.Get("engine").(string)), + EngineVersion: aws.String(d.Get("engine_version").(string)), } if attr, ok := d.GetOk("storage_type"); ok { - opts.StorageType = attr.(string) + opts.StorageType = aws.String(attr.(string)) } if attr, ok := d.GetOk("backup_retention_period"); ok { - opts.BackupRetentionPeriod = attr.(int) - opts.SetBackupRetentionPeriod = true + opts.BackupRetentionPeriod = aws.Integer(attr.(int)) } if attr, ok := d.GetOk("iops"); ok { - opts.Iops = attr.(int) - opts.SetIops = true + opts.IOPS = aws.Integer(attr.(int)) } if attr, ok := d.GetOk("port"); ok { - opts.Port = attr.(int) - opts.SetPort = true + opts.Port = aws.Integer(attr.(int)) } if attr, ok := d.GetOk("multi_az"); ok { - opts.MultiAZ = attr.(bool) + opts.MultiAZ = aws.Boolean(attr.(bool)) } if attr, ok := d.GetOk("availability_zone"); ok { - opts.AvailabilityZone = attr.(string) + opts.AvailabilityZone = aws.String(attr.(string)) } if attr, ok := d.GetOk("maintenance_window"); ok { - opts.PreferredMaintenanceWindow = attr.(string) + opts.PreferredMaintenanceWindow = aws.String(attr.(string)) } if attr, ok := d.GetOk("backup_window"); ok { - opts.PreferredBackupWindow = attr.(string) + opts.PreferredBackupWindow = aws.String(attr.(string)) } if attr, ok := d.GetOk("publicly_accessible"); ok { - opts.PubliclyAccessible = attr.(bool) + opts.PubliclyAccessible = aws.Boolean(attr.(bool)) } if attr, ok := d.GetOk("db_subnet_group_name"); ok { - opts.DBSubnetGroupName = attr.(string) + opts.DBSubnetGroupName = aws.String(attr.(string)) } if attr, ok := d.GetOk("parameter_group_name"); ok { - opts.DBParameterGroupName = attr.(string) + opts.DBParameterGroupName = aws.String(attr.(string)) } if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { @@ -249,7 +246,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error for _, v := range attr.List() { s = append(s, v.(string)) } - opts.VpcSecurityGroupIds = s + opts.VPCSecurityGroupIDs = s } if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 { @@ -257,7 +254,7 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error for _, v := range attr.List() { s = append(s, v.(string)) } - opts.DBSecurityGroupNames = s + opts.DBSecurityGroups = s } log.Printf("[DEBUG] DB Instance create configuration: %#v", opts) @@ -302,24 +299,28 @@ func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error { return nil } - d.Set("name", v.DBName) - d.Set("username", v.MasterUsername) - d.Set("engine", v.Engine) - d.Set("engine_version", v.EngineVersion) - d.Set("allocated_storage", v.AllocatedStorage) - d.Set("storage_type", v.StorageType) - d.Set("instance_class", v.DBInstanceClass) - d.Set("availability_zone", v.AvailabilityZone) - d.Set("backup_retention_period", v.BackupRetentionPeriod) - d.Set("backup_window", v.PreferredBackupWindow) - d.Set("maintenance_window", v.PreferredMaintenanceWindow) - d.Set("multi_az", v.MultiAZ) - d.Set("port", v.Port) - d.Set("db_subnet_group_name", v.DBSubnetGroup.Name) - d.Set("parameter_group_name", v.DBParameterGroupName) - d.Set("address", v.Address) - d.Set("endpoint", fmt.Sprintf("%s:%d", v.Address, v.Port)) - d.Set("status", v.DBInstanceStatus) + d.Set("name", *v.DBName) + d.Set("username", *v.MasterUsername) + d.Set("engine", *v.Engine) + d.Set("engine_version", *v.EngineVersion) + d.Set("allocated_storage", *v.AllocatedStorage) + d.Set("storage_type", *v.StorageType) + d.Set("instance_class", *v.DBInstanceClass) + d.Set("availability_zone", *v.AvailabilityZone) + d.Set("backup_retention_period", *v.BackupRetentionPeriod) + d.Set("backup_window", *v.PreferredBackupWindow) + d.Set("maintenance_window", *v.PreferredMaintenanceWindow) + d.Set("multi_az", *v.MultiAZ) + d.Set("port", *v.Endpoint.Port) + d.Set("db_subnet_group_name", *v.DBSubnetGroup.DBSubnetGroupName) + + if len(v.DBParameterGroups) > 0 { + d.Set("parameter_group_name", *v.DBParameterGroups[0].DBParameterGroupName) + } + + d.Set("address", *v.Endpoint.Port) + d.Set("endpoint", fmt.Sprintf("%s:%d", *v.Endpoint.Address, *v.Endpoint.Port)) + d.Set("status", *v.DBInstanceStatus) // Create an empty schema.Set to hold all vpc security group ids ids := &schema.Set{ @@ -327,8 +328,8 @@ func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error { return hashcode.String(v.(string)) }, } - for _, v := range v.VpcSecurityGroupIds { - ids.Add(v) + for _, v := range v.VPCSecurityGroups { + ids.Add(*v.VPCSecurityGroupID) } d.Set("vpc_security_group_ids", ids) @@ -338,8 +339,8 @@ func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error { return hashcode.String(v.(string)) }, } - for _, v := range v.DBSecurityGroupNames { - sgn.Add(v) + for _, v := range v.DBSecurityGroups { + sgn.Add(*v.DBSecurityGroupName) } d.Set("security_group_names", sgn) @@ -347,17 +348,17 @@ func resourceAwsDbInstanceRead(d *schema.ResourceData, meta interface{}) error { } func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*AWSClient).rdsconn + conn := meta.(*AWSClient).awsRDSconn log.Printf("[DEBUG] DB Instance destroy: %v", d.Id()) - opts := rds.DeleteDBInstance{DBInstanceIdentifier: d.Id()} + opts := rds.DeleteDBInstanceMessage{DBInstanceIdentifier: aws.String(d.Id())} finalSnapshot := d.Get("final_snapshot_identifier").(string) if finalSnapshot == "" { - opts.SkipFinalSnapshot = true + opts.SkipFinalSnapshot = aws.Boolean(true) } else { - opts.FinalDBSnapshotIdentifier = finalSnapshot + opts.FinalDBSnapshotIdentifier = aws.String(finalSnapshot) } log.Printf("[DEBUG] DB Instance destroy configuration: %v", opts) @@ -385,10 +386,10 @@ func resourceAwsDbInstanceDelete(d *schema.ResourceData, meta interface{}) error func resourceAwsBbInstanceRetrieve( d *schema.ResourceData, meta interface{}) (*rds.DBInstance, error) { - conn := meta.(*AWSClient).rdsconn + conn := meta.(*AWSClient).awsRDSconn - opts := rds.DescribeDBInstances{ - DBInstanceIdentifier: d.Id(), + opts := rds.DescribeDBInstancesMessage{ + DBInstanceIdentifier: aws.String(d.Id()), } log.Printf("[DEBUG] DB Instance describe configuration: %#v", opts) @@ -396,14 +397,15 @@ func resourceAwsBbInstanceRetrieve( resp, err := conn.DescribeDBInstances(&opts) if err != nil { - if strings.Contains(err.Error(), "DBInstanceNotFound") { + dbinstanceerr, ok := err.(aws.APIError) + if ok && dbinstanceerr.Code == "DBInstanceNotFound" { return nil, nil } return nil, fmt.Errorf("Error retrieving DB Instances: %s", err) } if len(resp.DBInstances) != 1 || - resp.DBInstances[0].DBInstanceIdentifier != d.Id() { + *resp.DBInstances[0].DBInstanceIdentifier != d.Id() { if err != nil { return nil, nil } @@ -428,6 +430,6 @@ func resourceAwsDbInstanceStateRefreshFunc( return nil, "", nil } - return v, v.DBInstanceStatus, nil + return v, *v.DBInstanceStatus, nil } } diff --git a/builtin/providers/aws/resource_aws_db_instance_test.go b/builtin/providers/aws/resource_aws_db_instance_test.go index 8af1b036d..f44b67ade 100644 --- a/builtin/providers/aws/resource_aws_db_instance_test.go +++ b/builtin/providers/aws/resource_aws_db_instance_test.go @@ -6,7 +6,9 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/mitchellh/goamz/rds" + + "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/gen/rds" ) func TestAccAWSDBInstance(t *testing.T) { @@ -34,13 +36,8 @@ func TestAccAWSDBInstance(t *testing.T) { "aws_db_instance.bar", "instance_class", "db.t1.micro"), resource.TestCheckResourceAttr( "aws_db_instance.bar", "name", "baz"), - resource.TestCheckResourceAttr( - // Shouldn't save password to state - "aws_db_instance.bar", "password", ""), resource.TestCheckResourceAttr( "aws_db_instance.bar", "username", "foo"), - resource.TestCheckResourceAttr( - "aws_db_instance.bar", "security_group_names.3322503515", "secfoobarbaz-test-terraform"), resource.TestCheckResourceAttr( "aws_db_instance.bar", "parameter_group_name", "default.mysql5.6"), ), @@ -50,7 +47,7 @@ func TestAccAWSDBInstance(t *testing.T) { } func testAccCheckAWSDBInstanceDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).rdsconn + conn := testAccProvider.Meta().(*AWSClient).awsRDSconn for _, rs := range s.RootModule().Resources { if rs.Type != "aws_db_instance" { @@ -59,19 +56,19 @@ func testAccCheckAWSDBInstanceDestroy(s *terraform.State) error { // Try to find the Group resp, err := conn.DescribeDBInstances( - &rds.DescribeDBInstances{ - DBInstanceIdentifier: rs.Primary.ID, + &rds.DescribeDBInstancesMessage{ + DBInstanceIdentifier: aws.String(rs.Primary.ID), }) if err == nil { if len(resp.DBInstances) != 0 && - resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID { + *resp.DBInstances[0].DBInstanceIdentifier == rs.Primary.ID { return fmt.Errorf("DB Instance still exists") } } // Verify the error - newerr, ok := err.(*rds.Error) + newerr, ok := err.(*aws.APIError) if !ok { return err } @@ -86,15 +83,11 @@ func testAccCheckAWSDBInstanceDestroy(s *terraform.State) error { func testAccCheckAWSDBInstanceAttributes(v *rds.DBInstance) resource.TestCheckFunc { return func(s *terraform.State) error { - if len(v.DBSecurityGroupNames) == 0 { - return fmt.Errorf("no sec names: %#v", v.DBSecurityGroupNames) - } - - if v.Engine != "mysql" { + if *v.Engine != "mysql" { return fmt.Errorf("bad engine: %#v", v.Engine) } - if v.EngineVersion != "5.6.21" { + if *v.EngineVersion != "5.6.21" { return fmt.Errorf("bad engine_version: %#v", v.EngineVersion) } @@ -113,10 +106,10 @@ func testAccCheckAWSDBInstanceExists(n string, v *rds.DBInstance) resource.TestC return fmt.Errorf("No DB Instance ID is set") } - conn := testAccProvider.Meta().(*AWSClient).rdsconn + conn := testAccProvider.Meta().(*AWSClient).awsRDSconn - opts := rds.DescribeDBInstances{ - DBInstanceIdentifier: rs.Primary.ID, + opts := rds.DescribeDBInstancesMessage{ + DBInstanceIdentifier: aws.String(rs.Primary.ID), } resp, err := conn.DescribeDBInstances(&opts) @@ -126,7 +119,7 @@ func testAccCheckAWSDBInstanceExists(n string, v *rds.DBInstance) resource.TestC } if len(resp.DBInstances) != 1 || - resp.DBInstances[0].DBInstanceIdentifier != rs.Primary.ID { + *resp.DBInstances[0].DBInstanceIdentifier != rs.Primary.ID { return fmt.Errorf("DB Instance not found") } @@ -137,15 +130,6 @@ func testAccCheckAWSDBInstanceExists(n string, v *rds.DBInstance) resource.TestC } const testAccAWSDBInstanceConfig = ` -resource "aws_db_security_group" "bar" { - name = "secfoobarbaz-test-terraform" - description = "just cuz" - - ingress { - cidr = "10.0.0.1/24" - } -} - resource "aws_db_instance" "bar" { identifier = "foobarbaz-test-terraform" @@ -157,7 +141,6 @@ resource "aws_db_instance" "bar" { password = "barbarbarbar" username = "foo" - security_group_names = ["${aws_db_security_group.bar.name}"] parameter_group_name = "default.mysql5.6" } ` 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 43616ba2d..7727b9dd6 100644 --- a/website/source/docs/providers/aws/r/db_instance.html.markdown +++ b/website/source/docs/providers/aws/r/db_instance.html.markdown @@ -22,7 +22,6 @@ resource "aws_db_instance" "default" { name = "mydb" username = "foo" password = "bar" - security_group_names = ["${aws_db_security_group.bar.name}"] db_subnet_group_name = "my_database_subnet_group" parameter_group_name = "default.mysql5.6" } @@ -58,7 +57,8 @@ The following arguments are supported: * `port` - (Optional) The port on which the DB accepts connections. * `publicly_accessible` - (Optional) Bool to control if instance is publicly accessible. * `vpc_security_group_ids` - (Optional) List of VPC security groups to associate. -* `security_group_names` - (Optional) List of DB Security Groups to associate. +* `security_group_names` - (Optional/Deprecated) List of DB Security Groups to associate. + 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.