From 2f8221a6022335255e1d2f4f27ee6f5ca659920c Mon Sep 17 00:00:00 2001 From: Max Cai Date: Fri, 28 Aug 2020 14:46:18 -0400 Subject: [PATCH] resource/aws_emr_cluster: Prevent recreation when `ebs_config.volumes_per_instance` is greater than 1 (#14858) Output from acceptance testing (failure unrelated): ``` --- PASS: TestAccAWSEMRCluster_basic (418.45s) --- PASS: TestAccAWSEMRCluster_configurationsJson (422.65s) --- PASS: TestAccAWSEMRCluster_Step_Multiple (494.02s) --- PASS: TestAccAWSEMRCluster_security_config (500.29s) --- PASS: TestAccAWSEMRCluster_CoreInstanceGroup_AutoscalingPolicy (573.87s) --- PASS: TestAccAWSEMRCluster_Kerberos_ClusterDedicatedKdc (629.50s) --- PASS: TestAccAWSEMRCluster_Step_Basic (635.56s) --- PASS: TestAccAWSEMRCluster_additionalInfo (704.09s) --- FAIL: TestAccAWSEMRCluster_Ec2Attributes_DefaultManagedSecurityGroups (793.09s) --- PASS: TestAccAWSEMRCluster_keepJob (380.07s) --- PASS: TestAccAWSEMRCluster_disappears (806.34s) --- PASS: TestAccAWSEMRCluster_terminationProtected (442.90s) --- PASS: TestAccAWSEMRCluster_MasterInstanceGroup_InstanceType (881.22s) --- PASS: TestAccAWSEMRCluster_MasterInstanceGroup_Name (938.63s) --- PASS: TestAccAWSEMRCluster_Step_ConfigMode (958.46s) --- PASS: TestAccAWSEMRCluster_CoreInstanceGroup_BidPrice (971.37s) --- PASS: TestAccAWSEMRCluster_CoreInstanceGroup_InstanceType (1026.93s) --- PASS: TestAccAWSEMRCluster_CoreInstanceGroup_Name (1041.45s) --- PASS: TestAccAWSEMRCluster_step_concurrency_level (408.01s) --- PASS: TestAccAWSEMRCluster_MasterInstanceGroup_BidPrice (1050.70s) --- PASS: TestAccAWSEMRCluster_s3Logging (577.92s) --- PASS: TestAccAWSEMRCluster_ebs_config (430.41s) --- PASS: TestAccAWSEMRCluster_CoreInstanceGroup_InstanceCount (1167.50s) --- PASS: TestAccAWSEMRCluster_MasterInstanceGroup_InstanceCount (1227.66s) --- PASS: TestAccAWSEMRCluster_custom_ami_id (481.41s) --- PASS: TestAccAWSEMRCluster_visibleToAllUsers (830.64s) --- PASS: TestAccAWSEMRCluster_bootstrap_ordering (1382.29s) --- PASS: TestAccAWSEMRCluster_tags (817.81s) --- PASS: TestAccAWSEMRCluster_root_volume_size (816.65s) ``` --- aws/resource_aws_emr_cluster.go | 7 ++- aws/resource_aws_emr_cluster_test.go | 76 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/aws/resource_aws_emr_cluster.go b/aws/resource_aws_emr_cluster.go index 2a1613da142c..cfaf14850806 100644 --- a/aws/resource_aws_emr_cluster.go +++ b/aws/resource_aws_emr_cluster.go @@ -1411,7 +1411,7 @@ func flattenEmrStepSummary(stepSummary *emr.StepSummary) map[string]interface{} } func flattenEBSConfig(ebsBlockDevices []*emr.EbsBlockDevice) *schema.Set { - + uniqueEBS := make(map[int]int) ebsConfig := make([]interface{}, 0) for _, ebs := range ebsBlockDevices { ebsAttrs := make(map[string]interface{}) @@ -1425,10 +1425,13 @@ func flattenEBSConfig(ebsBlockDevices []*emr.EbsBlockDevice) *schema.Set { ebsAttrs["type"] = *ebs.VolumeSpecification.VolumeType } ebsAttrs["volumes_per_instance"] = 1 - + uniqueEBS[resourceAwsEMRClusterEBSConfigHash(ebsAttrs)] += 1 ebsConfig = append(ebsConfig, ebsAttrs) } + for _, ebs := range ebsConfig { + ebs.(map[string]interface{})["volumes_per_instance"] = uniqueEBS[resourceAwsEMRClusterEBSConfigHash(ebs)] + } return schema.NewSet(resourceAwsEMRClusterEBSConfigHash, ebsConfig) } diff --git a/aws/resource_aws_emr_cluster_test.go b/aws/resource_aws_emr_cluster_test.go index b276318284e5..d849595be079 100644 --- a/aws/resource_aws_emr_cluster_test.go +++ b/aws/resource_aws_emr_cluster_test.go @@ -1296,6 +1296,37 @@ func TestAccAWSEMRCluster_step_concurrency_level(t *testing.T) { }) } +func TestAccAWSEMRCluster_ebs_config(t *testing.T) { + var cluster emr.Cluster + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_emr_cluster.tf-test-cluster" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSEmrDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSEmrEbsConfig(rName, 2), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSEmrClusterExists(resourceName, &cluster), + resource.TestCheckResourceAttr(resourceName, "master_instance_group.0.ebs_config.0.volumes_per_instance", "2"), + resource.TestCheckResourceAttr(resourceName, "core_instance_group.0.ebs_config.0.volumes_per_instance", "2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "cluster_state", // Ignore RUNNING versus WAITING changes + "configurations", + "keep_job_flow_alive_when_no_steps", + }, + }, + }, + }) +} + func TestAccAWSEMRCluster_custom_ami_id(t *testing.T) { var cluster emr.Cluster @@ -3397,3 +3428,48 @@ EOF } `, r) } + +func testAccAWSEmrEbsConfig(rName string, volumesPerInstance int) string { + return testAccAWSEmrComposeConfig(false, fmt.Sprintf(` +resource "aws_emr_cluster" "tf-test-cluster" { + applications = ["Spark"] + keep_job_flow_alive_when_no_steps = true + name = "%[1]s" + release_label = "emr-5.28.0" + service_role = "EMR_DefaultRole" + + ec2_attributes { + emr_managed_master_security_group = aws_security_group.test.id + emr_managed_slave_security_group = aws_security_group.test.id + instance_profile = "EMR_EC2_DefaultRole" + subnet_id = aws_subnet.test.id + } + + master_instance_group { + instance_type = "m4.large" + ebs_config { + size = 32 + type = "gp2" + volumes_per_instance = %[2]d + } + ebs_config { + size = 50 + type = "gp2" + volumes_per_instance = %[2]d + } + } + core_instance_group { + instance_count = 1 + instance_type = "m4.large" + ebs_config { + size = 32 + type = "gp2" + volumes_per_instance = %[2]d + } + } + + depends_on = [aws_route_table_association.test] +} +`, rName, volumesPerInstance), + ) +}