-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement aws_db_subnet_group resource
- Loading branch information
Alek Storm
committed
Aug 21, 2014
1 parent
cdc2a53
commit 0b9fd66
Showing
7 changed files
with
405 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"strings" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform/flatmap" | ||
"github.com/hashicorp/terraform/helper/config" | ||
"github.com/hashicorp/terraform/helper/diff" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
"github.com/mitchellh/goamz/rds" | ||
) | ||
|
||
func resource_aws_db_subnet_group_create( | ||
s *terraform.ResourceState, | ||
d *terraform.ResourceDiff, | ||
meta interface{}) (*terraform.ResourceState, error) { | ||
p := meta.(*ResourceProvider) | ||
conn := p.rdsconn | ||
|
||
// Merge the diff into the state so that we have all the attributes | ||
// properly. | ||
rs := s.MergeDiff(d) | ||
|
||
var err error | ||
|
||
opts := rds.CreateDBSubnetGroup{ | ||
DBSubnetGroupName: rs.Attributes["name"], | ||
DBSubnetGroupDescription: rs.Attributes["description"], | ||
SubnetIds: expandStringList(flatmap.Expand( | ||
rs.Attributes, "subnet_ids").([]interface{})), | ||
} | ||
|
||
log.Printf("[DEBUG] DB Subnet Group create configuration: %#v", opts) | ||
_, err = conn.CreateDBSubnetGroup(&opts) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error creating DB Subnet Group: %s", err) | ||
} | ||
|
||
rs.ID = rs.Attributes["name"] | ||
|
||
log.Printf("[INFO] DB Subnet Group ID: %s", rs.ID) | ||
|
||
log.Println( | ||
"[INFO] Waiting for DB Subnet Group creation to be complete") | ||
|
||
stateConf := &resource.StateChangeConf{ | ||
// TODO are there any other states? | ||
Pending: []string{}, | ||
Target: "Complete", | ||
Refresh: DBSubnetGroupStateRefreshFunc(rs.ID, conn), | ||
Timeout: 10 * time.Minute, | ||
} | ||
|
||
// Wait, catching any errors | ||
_, err = stateConf.WaitForState() | ||
if err != nil { | ||
return rs, err | ||
} | ||
|
||
v, err := resource_aws_db_subnet_group_retrieve(rs.ID, conn) | ||
if err != nil { | ||
return rs, err | ||
} | ||
|
||
return resource_aws_db_subnet_group_update_state(rs, v) | ||
} | ||
|
||
func resource_aws_db_subnet_group_update( | ||
s *terraform.ResourceState, | ||
d *terraform.ResourceDiff, | ||
meta interface{}) (*terraform.ResourceState, error) { | ||
|
||
panic("Cannot update DB Subnet Group") | ||
|
||
return nil, nil | ||
} | ||
|
||
func resource_aws_db_subnet_group_destroy( | ||
s *terraform.ResourceState, | ||
meta interface{}) error { | ||
p := meta.(*ResourceProvider) | ||
conn := p.rdsconn | ||
|
||
log.Printf("[DEBUG] DB Subnet Group destroy: %v", s.ID) | ||
|
||
opts := rds.DeleteDBSubnetGroup{DBSubnetGroupName: s.ID} | ||
|
||
log.Printf("[DEBUG] DB Subnet Group destroy configuration: %v", opts) | ||
_, err := conn.DeleteDBSubnetGroup(&opts) | ||
|
||
if err != nil { | ||
newerr, ok := err.(*rds.Error) | ||
if ok && newerr.Code == "DBSubnetGroupNotFoundFault" { | ||
return nil | ||
} | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resource_aws_db_subnet_group_refresh( | ||
s *terraform.ResourceState, | ||
meta interface{}) (*terraform.ResourceState, error) { | ||
p := meta.(*ResourceProvider) | ||
conn := p.rdsconn | ||
|
||
v, err := resource_aws_db_subnet_group_retrieve(s.ID, conn) | ||
|
||
if err != nil || v == nil { | ||
return s, err | ||
} | ||
|
||
return resource_aws_db_subnet_group_update_state(s, v) | ||
} | ||
|
||
func resource_aws_db_subnet_group_diff( | ||
s *terraform.ResourceState, | ||
c *terraform.ResourceConfig, | ||
meta interface{}) (*terraform.ResourceDiff, error) { | ||
|
||
b := &diff.ResourceBuilder{ | ||
Attrs: map[string]diff.AttrType{ | ||
"name": diff.AttrTypeCreate, | ||
"description": diff.AttrTypeCreate, | ||
"subnet_ids": diff.AttrTypeCreate, | ||
}, | ||
} | ||
|
||
return b.Diff(s, c) | ||
} | ||
|
||
func resource_aws_db_subnet_group_update_state( | ||
s *terraform.ResourceState, | ||
v *rds.DBSubnetGroup) (*terraform.ResourceState, error) { | ||
|
||
s.Attributes["name"] = v.Name | ||
s.Attributes["description"] = v.Description | ||
|
||
// Flatten our group values | ||
toFlatten := make(map[string]interface{}) | ||
|
||
if len(v.SubnetIds) > 0 && v.SubnetIds[0] != "" { | ||
toFlatten["subnet_ids"] = v.SubnetIds | ||
} | ||
|
||
for k, v := range flatmap.Flatten(toFlatten) { | ||
s.Attributes[k] = v | ||
} | ||
|
||
return s, nil | ||
} | ||
|
||
func resource_aws_db_subnet_group_retrieve(name string, conn *rds.Rds) (*rds.DBSubnetGroup, error) { | ||
opts := rds.DescribeDBSubnetGroups{ | ||
DBSubnetGroupName: name, | ||
} | ||
|
||
log.Printf("[DEBUG] DB Subnet Group describe configuration: %#v", opts) | ||
|
||
resp, err := conn.DescribeDBSubnetGroups(&opts) | ||
|
||
if err != nil { | ||
if strings.Contains(err.Error(), "DBSubnetGroupNotFound") { | ||
return nil, nil | ||
} | ||
return nil, fmt.Errorf("Error retrieving DB Subnet Groups: %s", err) | ||
} | ||
|
||
if len(resp.DBSubnetGroups) != 1 || | ||
resp.DBSubnetGroups[0].Name != name { | ||
if err != nil { | ||
return nil, nil | ||
} | ||
} | ||
|
||
v := resp.DBSubnetGroups[0] | ||
|
||
return &v, nil | ||
} | ||
|
||
func resource_aws_db_subnet_group_validation() *config.Validator { | ||
return &config.Validator{ | ||
Required: []string{ | ||
"name", | ||
"description", | ||
"subnet_ids.*", | ||
}, | ||
} | ||
} | ||
|
||
func DBSubnetGroupStateRefreshFunc(name string, conn *rds.Rds) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
v, err := resource_aws_db_subnet_group_retrieve(name, conn) | ||
|
||
if err != nil { | ||
log.Printf("Error on retrieving DB Subnet Group when waiting: %s", err) | ||
return nil, "", err | ||
} | ||
|
||
return v, v.Status, nil | ||
} | ||
} |
143 changes: 143 additions & 0 deletions
143
builtin/providers/aws/resource_aws_db_subnet_group_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
"github.com/mitchellh/goamz/rds" | ||
) | ||
|
||
func TestAccAWSDBSubnetGroup(t *testing.T) { | ||
var v rds.DBSubnetGroup | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSDBSubnetGroupDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testAccAWSDBSubnetGroupConfig, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSDBSubnetGroupExists("aws_db_subnet_group.foo", &v), | ||
testAccCheckAWSDBSubnetGroupAttributes(&v), | ||
resource.TestCheckResourceAttr( | ||
"aws_db_subnet_group.foo", "name", "subgroup-terraform"), | ||
resource.TestCheckResourceAttr( | ||
"aws_db_subnet_group.foo", "description", "just cuz"), | ||
// TODO check subnet ID contents | ||
resource.TestCheckResourceAttr( | ||
"aws_db_subnet_group.foo", "subnet_ids.#", "2"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAWSDBSubnetGroupDestroy(s *terraform.State) error { | ||
conn := testAccProvider.rdsconn | ||
|
||
for _, rs := range s.Resources { | ||
if rs.Type != "aws_db_subnet_group" { | ||
continue | ||
} | ||
|
||
// Try to find the Group | ||
resp, err := conn.DescribeDBSubnetGroups( | ||
&rds.DescribeDBSubnetGroups{ | ||
DBSubnetGroupName: rs.ID, | ||
}) | ||
|
||
if err == nil { | ||
if len(resp.DBSubnetGroups) != 0 && | ||
resp.DBSubnetGroups[0].Name == rs.ID { | ||
return fmt.Errorf("DB Subnet Group still exists") | ||
} | ||
} | ||
|
||
// Verify the error | ||
_, ok := err.(*rds.Error) | ||
if !ok { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccCheckAWSDBSubnetGroupAttributes(group *rds.DBSubnetGroup) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
if len(group.SubnetIds) == 0 { | ||
return fmt.Errorf("no subnets: %#v", group.SubnetIds) | ||
} | ||
|
||
if group.Name != "subgroup-terraform" { | ||
return fmt.Errorf("bad name: %#v", group.Name) | ||
} | ||
|
||
if group.Description != "just cuz" { | ||
return fmt.Errorf("bad description: %#v", group.Description) | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckAWSDBSubnetGroupExists(n string, v *rds.DBSubnetGroup) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
|
||
if rs.ID == "" { | ||
return fmt.Errorf("No DB Subnet Group ID is set") | ||
} | ||
|
||
conn := testAccProvider.rdsconn | ||
|
||
opts := rds.DescribeDBSubnetGroups{ | ||
DBSubnetGroupName: rs.ID, | ||
} | ||
|
||
resp, err := conn.DescribeDBSubnetGroups(&opts) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(resp.DBSubnetGroups) != 1 || | ||
resp.DBSubnetGroups[0].Name != rs.ID { | ||
return fmt.Errorf("DB Subnet Group not found") | ||
} | ||
|
||
*v = resp.DBSubnetGroups[0] | ||
|
||
return nil | ||
} | ||
} | ||
|
||
const testAccAWSDBSubnetGroupConfig = ` | ||
resource "aws_vpc" "foo" { | ||
cidr_block = "10.0.0.0/16" | ||
} | ||
resource "aws_subnet" "foo" { | ||
cidr_block = "10.0.0.0/24" | ||
vpc_id = "${aws_vpc.foo.id}" | ||
availability_zone = "us-west-2a" | ||
} | ||
resource "aws_subnet" "bar" { | ||
cidr_block = "10.0.1.0/24" | ||
vpc_id = "${aws_vpc.foo.id}" | ||
availability_zone = "us-west-2b" | ||
} | ||
resource "aws_db_subnet_group" "foo" { | ||
name = "subgroup-terraform" | ||
description = "just cuz" | ||
subnet_ids = ["${aws_subnet.foo.id}", "${aws_subnet.bar.id}"] | ||
} | ||
` |
Oops, something went wrong.