-
Notifications
You must be signed in to change notification settings - Fork 9.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement aws_db_subnet_group resource #164
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I imagine this won't work as is, due to this. If we run the acceptance tests it should give us the various states. Are you familiar with how to run those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but they all pass - the DB subnet group is created so quickly that I can't issue a request fast enough to discover its intermediate state. The docs and a fair amount of googling have turned up no answers, but we have an AWS enterprise support account; I'll ask them. In the meantime, can this be merged, as the lack of intermediate states is fine in practice?