diff --git a/aws/resource_aws_cloudhsm2_cluster.go b/aws/resource_aws_cloudhsm2_cluster.go index b8adbf005e9..fa40dda55ef 100644 --- a/aws/resource_aws_cloudhsm2_cluster.go +++ b/aws/resource_aws_cloudhsm2_cluster.go @@ -286,23 +286,11 @@ func resourceAwsCloudHsm2ClusterDelete(d *schema.ResourceData, meta interface{}) } if err != nil { - return err + return fmt.Errorf("error deleting CloudHSMv2 Cluster (%s): %s", d.Id(), err) } - log.Println("[INFO] Waiting for CloudHSMv2 Cluster to be deleted") - stateConf := &resource.StateChangeConf{ - Pending: []string{cloudhsmv2.ClusterStateDeleteInProgress}, - Target: []string{cloudhsmv2.ClusterStateDeleted}, - Refresh: resourceAwsCloudHsm2ClusterRefreshFunc(cloudhsm2, d.Id()), - Timeout: d.Timeout(schema.TimeoutCreate), - MinTimeout: 30 * time.Second, - Delay: 30 * time.Second, - } - - // Wait, catching any errors - _, errWait := stateConf.WaitForState() - if errWait != nil { - return fmt.Errorf("Error waiting for CloudHSMv2 Cluster state to be \"DELETED\": %s", errWait) + if err := waitForCloudhsmv2ClusterDeletion(cloudhsm2, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil { + return fmt.Errorf("error waiting for CloudHSMv2 Cluster (%s) deletion: %s", d.Id(), err) } return nil @@ -367,3 +355,18 @@ func readCloudHsm2ClusterCertificates(cluster *cloudhsmv2.Cluster) []map[string] } return []map[string]interface{}{} } + +func waitForCloudhsmv2ClusterDeletion(conn *cloudhsmv2.CloudHSMV2, id string, timeout time.Duration) error { + stateConf := &resource.StateChangeConf{ + Pending: []string{cloudhsmv2.ClusterStateDeleteInProgress}, + Target: []string{cloudhsmv2.ClusterStateDeleted}, + Refresh: resourceAwsCloudHsm2ClusterRefreshFunc(conn, id), + Timeout: timeout, + MinTimeout: 30 * time.Second, + Delay: 30 * time.Second, + } + + _, err := stateConf.WaitForState() + + return err +} diff --git a/aws/resource_aws_cloudhsm2_cluster_test.go b/aws/resource_aws_cloudhsm2_cluster_test.go index e13e8cb96f4..89cf39c6bdd 100644 --- a/aws/resource_aws_cloudhsm2_cluster_test.go +++ b/aws/resource_aws_cloudhsm2_cluster_test.go @@ -2,14 +2,88 @@ package aws import ( "fmt" + "log" "testing" + "time" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudhsmv2" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" ) +func init() { + resource.AddTestSweepers("aws_cloudhsm_v2_cluster", &resource.Sweeper{ + Name: "aws_cloudhsm_v2_cluster", + F: testSweepCloudhsmv2Clusters, + }) +} + +func testSweepCloudhsmv2Clusters(region string) error { + client, err := sharedClientForRegion(region) + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + conn := client.(*AWSClient).cloudhsmv2conn + + input := &cloudhsmv2.DescribeClustersInput{} + + err = conn.DescribeClustersPages(input, func(page *cloudhsmv2.DescribeClustersOutput, lastPage bool) bool { + for _, cluster := range page.Clusters { + clusterID := aws.StringValue(cluster.ClusterId) + input := &cloudhsmv2.DeleteClusterInput{ + ClusterId: cluster.ClusterId, + } + + for _, hsm := range cluster.Hsms { + hsmID := aws.StringValue(hsm.HsmId) + input := &cloudhsmv2.DeleteHsmInput{ + ClusterId: cluster.ClusterId, + HsmId: hsm.HsmId, + } + + log.Printf("[INFO] Deleting CloudHSMv2 Cluster (%s) HSM: %s", clusterID, hsmID) + _, err := conn.DeleteHsm(input) + + if err != nil { + log.Printf("[ERROR] Error deleting CloudHSMv2 Cluster (%s) HSM (%s): %s", clusterID, hsmID, err) + continue + } + + if err := waitForCloudhsmv2HsmDeletion(conn, hsmID, 120*time.Minute); err != nil { + log.Printf("[ERROR] Error waiting for CloudHSMv2 Cluster (%s) HSM (%s) deletion: %s", clusterID, hsmID, err) + } + } + + log.Printf("[INFO] Deleting CloudHSMv2 Cluster: %s", clusterID) + _, err := conn.DeleteCluster(input) + + if err != nil { + log.Printf("[ERROR] Error deleting CloudHSMv2 Cluster (%s): %s", clusterID, err) + continue + } + + if err := waitForCloudhsmv2ClusterDeletion(conn, clusterID, 120*time.Minute); err != nil { + log.Printf("[ERROR] Error waiting for CloudHSMv2 Cluster (%s) deletion: %s", clusterID, err) + } + } + + return !lastPage + }) + + if testSweepSkipSweepError(err) { + log.Printf("[WARN] Skipping CloudHSMv2 Cluster sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("error describing CloudHSMv2 Clusters: %s", err) + } + + return nil +} + func TestAccAWSCloudHsm2Cluster_basic(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, diff --git a/aws/resource_aws_cloudhsm2_hsm.go b/aws/resource_aws_cloudhsm2_hsm.go index ac6d7966d0b..d07a37e0459 100644 --- a/aws/resource_aws_cloudhsm2_hsm.go +++ b/aws/resource_aws_cloudhsm2_hsm.go @@ -100,17 +100,16 @@ func describeHsm(conn *cloudhsmv2.CloudHSMV2, hsmId string) (*cloudhsmv2.Hsm, er return hsm, nil } -func resourceAwsCloudHsm2HsmRefreshFunc( - d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc { +func resourceAwsCloudHsm2HsmRefreshFunc(conn *cloudhsmv2.CloudHSMV2, id string) resource.StateRefreshFunc { return func() (interface{}, string, error) { - hsm, err := describeHsm(meta.(*AWSClient).cloudhsmv2conn, d.Id()) + hsm, err := describeHsm(conn, id) if hsm == nil { return 42, "destroyed", nil } if hsm.State != nil { - log.Printf("[DEBUG] CloudHSMv2 Cluster status (%s): %s", d.Id(), *hsm.State) + log.Printf("[DEBUG] CloudHSMv2 Cluster status (%s): %s", id, *hsm.State) } return hsm, aws.StringValue(hsm.State), err @@ -174,22 +173,9 @@ func resourceAwsCloudHsm2HsmCreate(d *schema.ResourceData, meta interface{}) err } d.SetId(aws.StringValue(output.Hsm.HsmId)) - log.Printf("[INFO] CloudHSMv2 HSM Id: %s", d.Id()) - log.Println("[INFO] Waiting for CloudHSMv2 HSM to be available") - stateConf := &resource.StateChangeConf{ - Pending: []string{cloudhsmv2.HsmStateCreateInProgress, "destroyed"}, - Target: []string{cloudhsmv2.HsmStateActive}, - Refresh: resourceAwsCloudHsm2HsmRefreshFunc(d, meta), - Timeout: d.Timeout(schema.TimeoutCreate), - MinTimeout: 30 * time.Second, - Delay: 30 * time.Second, - } - - // Wait, catching any errors - _, errWait := stateConf.WaitForState() - if errWait != nil { - return fmt.Errorf("Error waiting for CloudHSMv2 HSM state to be \"ACTIVE\": %s", errWait) + if err := waitForCloudhsmv2HsmActive(cloudhsm2, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil { + return fmt.Errorf("error waiting for CloudHSMv2 HSM (%s) creation: %s", d.Id(), err) } return resourceAwsCloudHsm2HsmRead(d, meta) @@ -246,22 +232,40 @@ func resourceAwsCloudHsm2HsmDelete(d *schema.ResourceData, meta interface{}) err if err != nil { return fmt.Errorf("error deleting CloudHSM v2 HSM module (%s): %s", d.Id(), err) } - log.Println("[INFO] Waiting for CloudHSMv2 HSM to be deleted") + if err := waitForCloudhsmv2HsmDeletion(cloudhsm2, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil { + return fmt.Errorf("error waiting for CloudHSMv2 HSM (%s) deletion: %s", d.Id(), err) + } + + return nil +} + +func waitForCloudhsmv2HsmActive(conn *cloudhsmv2.CloudHSMV2, id string, timeout time.Duration) error { + stateConf := &resource.StateChangeConf{ + Pending: []string{cloudhsmv2.HsmStateCreateInProgress, "destroyed"}, + Target: []string{cloudhsmv2.HsmStateActive}, + Refresh: resourceAwsCloudHsm2HsmRefreshFunc(conn, id), + Timeout: timeout, + MinTimeout: 30 * time.Second, + Delay: 30 * time.Second, + } + + _, err := stateConf.WaitForState() + + return err +} + +func waitForCloudhsmv2HsmDeletion(conn *cloudhsmv2.CloudHSMV2, id string, timeout time.Duration) error { stateConf := &resource.StateChangeConf{ Pending: []string{cloudhsmv2.HsmStateDeleteInProgress}, Target: []string{"destroyed"}, - Refresh: resourceAwsCloudHsm2HsmRefreshFunc(d, meta), - Timeout: d.Timeout(schema.TimeoutCreate), + Refresh: resourceAwsCloudHsm2HsmRefreshFunc(conn, id), + Timeout: timeout, MinTimeout: 30 * time.Second, Delay: 30 * time.Second, } - // Wait, catching any errors - _, errWait := stateConf.WaitForState() - if errWait != nil { - return fmt.Errorf("Error waiting for CloudHSMv2 HSM state to be \"DELETED\": %s", errWait) - } + _, err := stateConf.WaitForState() - return nil + return err } diff --git a/aws/resource_aws_subnet_test.go b/aws/resource_aws_subnet_test.go index e0c89109eab..440f679f8e9 100644 --- a/aws/resource_aws_subnet_test.go +++ b/aws/resource_aws_subnet_test.go @@ -23,6 +23,7 @@ func init() { "aws_autoscaling_group", "aws_batch_compute_environment", "aws_beanstalk_environment", + "aws_cloudhsm_v2_cluster", "aws_db_subnet_group", "aws_directory_service_directory", "aws_ec2_client_vpn_endpoint",