-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7123 from fewstera/aws_docdb_cluster_snapshot
DocumentDB: aws_docdb_cluster_snapshot resource added
- Loading branch information
Showing
6 changed files
with
462 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,206 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/docdb" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func resourceAwsDocDBClusterSnapshot() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsDocDBClusterSnapshotCreate, | ||
Read: resourceAwsDocDBClusterSnapshotRead, | ||
Delete: resourceAwsDocDBClusterSnapshotDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Create: schema.DefaultTimeout(20 * time.Minute), | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"db_cluster_snapshot_identifier": { | ||
Type: schema.TypeString, | ||
ValidateFunc: validateDocDBClusterSnapshotIdentifier, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"db_cluster_identifier": { | ||
Type: schema.TypeString, | ||
ValidateFunc: validateDocDBClusterIdentifier, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"availability_zones": { | ||
Type: schema.TypeList, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
Computed: true, | ||
}, | ||
"db_cluster_snapshot_arn": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"storage_encrypted": { | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
}, | ||
"engine": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"engine_version": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"kms_key_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"port": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
"source_db_cluster_snapshot_arn": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"snapshot_type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"status": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"vpc_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsDocDBClusterSnapshotCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).docdbconn | ||
|
||
params := &docdb.CreateDBClusterSnapshotInput{ | ||
DBClusterIdentifier: aws.String(d.Get("db_cluster_identifier").(string)), | ||
DBClusterSnapshotIdentifier: aws.String(d.Get("db_cluster_snapshot_identifier").(string)), | ||
} | ||
|
||
_, err := conn.CreateDBClusterSnapshot(params) | ||
if err != nil { | ||
return fmt.Errorf("error creating DocDB Cluster Snapshot: %s", err) | ||
} | ||
d.SetId(d.Get("db_cluster_snapshot_identifier").(string)) | ||
|
||
stateConf := &resource.StateChangeConf{ | ||
Pending: []string{"creating"}, | ||
Target: []string{"available"}, | ||
Refresh: resourceAwsDocDBClusterSnapshotStateRefreshFunc(d.Id(), conn), | ||
Timeout: d.Timeout(schema.TimeoutCreate), | ||
MinTimeout: 10 * time.Second, | ||
Delay: 5 * time.Second, | ||
} | ||
|
||
// Wait, catching any errors | ||
_, err = stateConf.WaitForState() | ||
if err != nil { | ||
return fmt.Errorf("error waiting for DocDB Cluster Snapshot %q to create: %s", d.Id(), err) | ||
} | ||
|
||
return resourceAwsDocDBClusterSnapshotRead(d, meta) | ||
} | ||
|
||
func resourceAwsDocDBClusterSnapshotRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).docdbconn | ||
|
||
params := &docdb.DescribeDBClusterSnapshotsInput{ | ||
DBClusterSnapshotIdentifier: aws.String(d.Id()), | ||
} | ||
resp, err := conn.DescribeDBClusterSnapshots(params) | ||
if err != nil { | ||
if isAWSErr(err, docdb.ErrCodeDBClusterSnapshotNotFoundFault, "") { | ||
log.Printf("[WARN] DocDB Cluster Snapshot %q not found, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
return fmt.Errorf("error reading DocDB Cluster Snapshot %q: %s", d.Id(), err) | ||
} | ||
|
||
if resp == nil || len(resp.DBClusterSnapshots) == 0 || resp.DBClusterSnapshots[0] == nil || aws.StringValue(resp.DBClusterSnapshots[0].DBClusterSnapshotIdentifier) != d.Id() { | ||
log.Printf("[WARN] DocDB Cluster Snapshot %q not found, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
snapshot := resp.DBClusterSnapshots[0] | ||
|
||
if err := d.Set("availability_zones", flattenStringList(snapshot.AvailabilityZones)); err != nil { | ||
return fmt.Errorf("error setting availability_zones: %s", err) | ||
} | ||
d.Set("db_cluster_identifier", snapshot.DBClusterIdentifier) | ||
d.Set("db_cluster_snapshot_arn", snapshot.DBClusterSnapshotArn) | ||
d.Set("db_cluster_snapshot_identifier", snapshot.DBClusterSnapshotIdentifier) | ||
d.Set("engine_version", snapshot.EngineVersion) | ||
d.Set("engine", snapshot.Engine) | ||
d.Set("kms_key_id", snapshot.KmsKeyId) | ||
d.Set("port", snapshot.Port) | ||
d.Set("snapshot_type", snapshot.SnapshotType) | ||
d.Set("source_db_cluster_snapshot_arn", snapshot.SourceDBClusterSnapshotArn) | ||
d.Set("status", snapshot.Status) | ||
d.Set("storage_encrypted", snapshot.StorageEncrypted) | ||
d.Set("vpc_id", snapshot.VpcId) | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsDocDBClusterSnapshotDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).docdbconn | ||
|
||
params := &docdb.DeleteDBClusterSnapshotInput{ | ||
DBClusterSnapshotIdentifier: aws.String(d.Id()), | ||
} | ||
_, err := conn.DeleteDBClusterSnapshot(params) | ||
if err != nil { | ||
if isAWSErr(err, docdb.ErrCodeDBClusterSnapshotNotFoundFault, "") { | ||
return nil | ||
} | ||
return fmt.Errorf("error deleting DocDB Cluster Snapshot %q: %s", d.Id(), err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsDocDBClusterSnapshotStateRefreshFunc(dbClusterSnapshotIdentifier string, conn *docdb.DocDB) resource.StateRefreshFunc { | ||
return func() (interface{}, string, error) { | ||
opts := &docdb.DescribeDBClusterSnapshotsInput{ | ||
DBClusterSnapshotIdentifier: aws.String(dbClusterSnapshotIdentifier), | ||
} | ||
|
||
log.Printf("[DEBUG] DocDB Cluster Snapshot describe configuration: %#v", opts) | ||
|
||
resp, err := conn.DescribeDBClusterSnapshots(opts) | ||
if err != nil { | ||
if isAWSErr(err, docdb.ErrCodeDBClusterSnapshotNotFoundFault, "") { | ||
return nil, "", nil | ||
} | ||
return nil, "", fmt.Errorf("Error retrieving DocDB Cluster Snapshots: %s", err) | ||
} | ||
|
||
if resp == nil || len(resp.DBClusterSnapshots) == 0 || resp.DBClusterSnapshots[0] == nil { | ||
return nil, "", fmt.Errorf("No snapshots returned for %s", dbClusterSnapshotIdentifier) | ||
} | ||
|
||
snapshot := resp.DBClusterSnapshots[0] | ||
|
||
return resp, aws.StringValue(snapshot.Status), nil | ||
} | ||
} |
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,153 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/docdb" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSDocDBClusterSnapshot_basic(t *testing.T) { | ||
var dbClusterSnapshot docdb.DBClusterSnapshot | ||
rName := acctest.RandomWithPrefix("tf-acc-test") | ||
resourceName := "aws_docdb_cluster_snapshot.test" | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckDocDBClusterSnapshotDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccAwsDocDBClusterSnapshotConfig(rName), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckDocDBClusterSnapshotExists(resourceName, &dbClusterSnapshot), | ||
resource.TestCheckResourceAttrSet(resourceName, "availability_zones.#"), | ||
testAccMatchResourceAttrRegionalARN(resourceName, "db_cluster_snapshot_arn", "rds", regexp.MustCompile(`cluster-snapshot:.+`)), | ||
resource.TestCheckResourceAttrSet(resourceName, "engine"), | ||
resource.TestCheckResourceAttrSet(resourceName, "engine_version"), | ||
resource.TestCheckResourceAttr(resourceName, "kms_key_id", ""), | ||
resource.TestCheckResourceAttrSet(resourceName, "port"), | ||
resource.TestCheckResourceAttr(resourceName, "snapshot_type", "manual"), | ||
resource.TestCheckResourceAttr(resourceName, "source_db_cluster_snapshot_arn", ""), | ||
resource.TestCheckResourceAttr(resourceName, "status", "available"), | ||
resource.TestCheckResourceAttr(resourceName, "storage_encrypted", "false"), | ||
resource.TestCheckResourceAttrPair(resourceName, "vpc_id", "aws_vpc.test", "id"), | ||
), | ||
}, | ||
{ | ||
ResourceName: resourceName, | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckDocDBClusterSnapshotDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).docdbconn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_docdb_cluster_snapshot" { | ||
continue | ||
} | ||
|
||
input := &docdb.DescribeDBClusterSnapshotsInput{ | ||
DBClusterSnapshotIdentifier: aws.String(rs.Primary.ID), | ||
} | ||
|
||
output, err := conn.DescribeDBClusterSnapshots(input) | ||
if err != nil { | ||
if isAWSErr(err, docdb.ErrCodeDBClusterSnapshotNotFoundFault, "") { | ||
continue | ||
} | ||
return err | ||
} | ||
|
||
if output != nil && len(output.DBClusterSnapshots) > 0 && output.DBClusterSnapshots[0] != nil && aws.StringValue(output.DBClusterSnapshots[0].DBClusterSnapshotIdentifier) == rs.Primary.ID { | ||
return fmt.Errorf("DocDB Cluster Snapshot %q still exists", rs.Primary.ID) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccCheckDocDBClusterSnapshotExists(resourceName string, dbClusterSnapshot *docdb.DBClusterSnapshot) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", resourceName) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No ID is set for %s", resourceName) | ||
} | ||
|
||
conn := testAccProvider.Meta().(*AWSClient).docdbconn | ||
|
||
request := &docdb.DescribeDBClusterSnapshotsInput{ | ||
DBClusterSnapshotIdentifier: aws.String(rs.Primary.ID), | ||
} | ||
|
||
response, err := conn.DescribeDBClusterSnapshots(request) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if response == nil || len(response.DBClusterSnapshots) == 0 || response.DBClusterSnapshots[0] == nil || aws.StringValue(response.DBClusterSnapshots[0].DBClusterSnapshotIdentifier) != rs.Primary.ID { | ||
return fmt.Errorf("DocDB Cluster Snapshot %q not found", rs.Primary.ID) | ||
} | ||
|
||
*dbClusterSnapshot = *response.DBClusterSnapshots[0] | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccAwsDocDBClusterSnapshotConfig(rName string) string { | ||
return fmt.Sprintf(` | ||
data "aws_availability_zones" "available" {} | ||
resource "aws_vpc" "test" { | ||
cidr_block = "192.168.0.0/16" | ||
tags = { | ||
Name = %q | ||
} | ||
} | ||
resource "aws_subnet" "test" { | ||
count = 2 | ||
availability_zone = "${data.aws_availability_zones.available.names[count.index]}" | ||
cidr_block = "192.168.${count.index}.0/24" | ||
vpc_id = "${aws_vpc.test.id}" | ||
tags = { | ||
Name = %q | ||
} | ||
} | ||
resource "aws_docdb_subnet_group" "test" { | ||
name = %q | ||
subnet_ids = ["${aws_subnet.test.*.id}"] | ||
} | ||
resource "aws_docdb_cluster" "test" { | ||
cluster_identifier = %q | ||
db_subnet_group_name = "${aws_docdb_subnet_group.test.name}" | ||
master_password = "barbarbarbar" | ||
master_username = "foo" | ||
skip_final_snapshot = true | ||
} | ||
resource "aws_docdb_cluster_snapshot" "test" { | ||
db_cluster_identifier = "${aws_docdb_cluster.test.id}" | ||
db_cluster_snapshot_identifier = %q | ||
} | ||
`, rName, rName, rName, rName, rName) | ||
} |
Oops, something went wrong.