diff --git a/.changelog/19205.txt b/.changelog/19205.txt new file mode 100644 index 00000000000..b304309bb47 --- /dev/null +++ b/.changelog/19205.txt @@ -0,0 +1,7 @@ +```release-note:bug +aws_batch_compute_environment: `service_role` argument is optional +``` + +```release-note:bug +aws_batch_compute_environment: Allow update of just `service_role` for managed compute environments +``` \ No newline at end of file diff --git a/aws/resource_aws_batch_compute_environment.go b/aws/resource_aws_batch_compute_environment.go index 74cb2169efa..19f1be3bc81 100644 --- a/aws/resource_aws_batch_compute_environment.go +++ b/aws/resource_aws_batch_compute_environment.go @@ -165,7 +165,8 @@ func resourceAwsBatchComputeEnvironment() *schema.Resource { }, "service_role": { Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, ValidateFunc: validateArn, }, "state": { @@ -326,31 +327,28 @@ func resourceAwsBatchComputeEnvironmentUpdate(d *schema.ResourceData, meta inter // TODO See above on how to remove check on type. if computeEnvironmentType := strings.ToUpper(d.Get("type").(string)); computeEnvironmentType == batch.CETypeManaged { - if d.HasChange("compute_resources") { - computeResourceUpdate := &batch.ComputeResourceUpdate{} - - if d.HasChange("compute_resources.0.desired_vcpus") { - computeResourceUpdate.DesiredvCpus = aws.Int64(int64(d.Get("compute_resources.0.desired_vcpus").(int))) - } - - if d.HasChange("compute_resources.0.max_vcpus") { - computeResourceUpdate.MaxvCpus = aws.Int64(int64(d.Get("compute_resources.0.max_vcpus").(int))) - } + // "At least one compute-resources attribute must be specified" + computeResourceUpdate := &batch.ComputeResourceUpdate{ + MaxvCpus: aws.Int64(int64(d.Get("compute_resources.0.max_vcpus").(int))), + } - if d.HasChange("compute_resources.0.min_vcpus") { - computeResourceUpdate.MinvCpus = aws.Int64(int64(d.Get("compute_resources.0.min_vcpus").(int))) - } + if d.HasChange("compute_resources.0.desired_vcpus") { + computeResourceUpdate.DesiredvCpus = aws.Int64(int64(d.Get("compute_resources.0.desired_vcpus").(int))) + } - if d.HasChange("compute_resources.0.security_group_ids") { - computeResourceUpdate.SecurityGroupIds = expandStringSet(d.Get("compute_resources.0.security_group_ids").(*schema.Set)) - } + if d.HasChange("compute_resources.0.min_vcpus") { + computeResourceUpdate.MinvCpus = aws.Int64(int64(d.Get("compute_resources.0.min_vcpus").(int))) + } - if d.HasChange("compute_resources.0.subnets") { - computeResourceUpdate.Subnets = expandStringSet(d.Get("compute_resources.0.subnets").(*schema.Set)) - } + if d.HasChange("compute_resources.0.security_group_ids") { + computeResourceUpdate.SecurityGroupIds = expandStringSet(d.Get("compute_resources.0.security_group_ids").(*schema.Set)) + } - input.ComputeResources = computeResourceUpdate + if d.HasChange("compute_resources.0.subnets") { + computeResourceUpdate.Subnets = expandStringSet(d.Get("compute_resources.0.subnets").(*schema.Set)) } + + input.ComputeResources = computeResourceUpdate } log.Printf("[DEBUG] Updating Batch Compute Environment: %s", input) diff --git a/aws/resource_aws_batch_compute_environment_test.go b/aws/resource_aws_batch_compute_environment_test.go index 63e04501c05..6a57c285443 100644 --- a/aws/resource_aws_batch_compute_environment_test.go +++ b/aws/resource_aws_batch_compute_environment_test.go @@ -682,6 +682,8 @@ func TestAccAWSBatchComputeEnvironment_updateServiceRole(t *testing.T) { resourceName := "aws_batch_compute_environment.test" serviceRoleResourceName1 := "aws_iam_role.batch_service" serviceRoleResourceName2 := "aws_iam_role.batch_service_2" + securityGroupResourceName := "aws_security_group.test" + subnetResourceName := "aws_subnet.test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSBatch(t) }, @@ -690,37 +692,131 @@ func TestAccAWSBatchComputeEnvironment_updateServiceRole(t *testing.T) { CheckDestroy: testAccCheckBatchComputeEnvironmentDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSBatchComputeEnvironmentConfigBasic(rName), + Config: testAccAWSBatchComputeEnvironmentConfigFargate(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsBatchComputeEnvironmentExists(resourceName, &ce), testAccCheckResourceAttrRegionalARN(resourceName, "arn", "batch", fmt.Sprintf("compute-environment/%s", rName)), resource.TestCheckResourceAttr(resourceName, "compute_environment_name", rName), resource.TestCheckResourceAttr(resourceName, "compute_environment_name_prefix", ""), - resource.TestCheckResourceAttr(resourceName, "compute_resources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.allocation_strategy", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.bid_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.desired_vcpus", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.ec2_key_pair", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.image_id", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.instance_role", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.instance_type.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.launch_template.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.max_vcpus", "16"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.min_vcpus", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.security_group_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "compute_resources.0.security_group_ids.*", securityGroupResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.spot_iam_fleet_role", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.subnets.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "compute_resources.0.subnets.*", subnetResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.type", "FARGATE"), resource.TestCheckResourceAttrSet(resourceName, "ecs_cluster_arn"), resource.TestCheckResourceAttrPair(resourceName, "service_role", serviceRoleResourceName1, "arn"), resource.TestCheckResourceAttr(resourceName, "state", "ENABLED"), resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "status_reason"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), - resource.TestCheckResourceAttr(resourceName, "type", "UNMANAGED"), + resource.TestCheckResourceAttr(resourceName, "type", "MANAGED"), ), }, { - Config: testAccAWSBatchComputeEnvironmentConfigUpdatedServiceRole(rName), + Config: testAccAWSBatchComputeEnvironmentConfigFargateUpdatedServiceRole(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAwsBatchComputeEnvironmentExists(resourceName, &ce), testAccCheckResourceAttrRegionalARN(resourceName, "arn", "batch", fmt.Sprintf("compute-environment/%s", rName)), resource.TestCheckResourceAttr(resourceName, "compute_environment_name", rName), resource.TestCheckResourceAttr(resourceName, "compute_environment_name_prefix", ""), - resource.TestCheckResourceAttr(resourceName, "compute_resources.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.allocation_strategy", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.bid_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.desired_vcpus", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.ec2_key_pair", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.image_id", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.instance_role", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.instance_type.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.launch_template.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.max_vcpus", "16"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.min_vcpus", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.security_group_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "compute_resources.0.security_group_ids.*", securityGroupResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.spot_iam_fleet_role", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.subnets.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "compute_resources.0.subnets.*", subnetResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.type", "FARGATE"), resource.TestCheckResourceAttrSet(resourceName, "ecs_cluster_arn"), resource.TestCheckResourceAttrPair(resourceName, "service_role", serviceRoleResourceName2, "arn"), resource.TestCheckResourceAttr(resourceName, "state", "ENABLED"), resource.TestCheckResourceAttrSet(resourceName, "status"), resource.TestCheckResourceAttrSet(resourceName, "status_reason"), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), - resource.TestCheckResourceAttr(resourceName, "type", "UNMANAGED"), + resource.TestCheckResourceAttr(resourceName, "type", "MANAGED"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSBatchComputeEnvironment_defaultServiceRole(t *testing.T) { + var ce batch.ComputeEnvironmentDetail + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_batch_compute_environment.test" + securityGroupResourceName := "aws_security_group.test" + subnetResourceName := "aws_subnet.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccPreCheckAWSBatch(t) + testAccPreCheckIamServiceLinkedRole(t, "/aws-service-role/batch") + }, + ErrorCheck: testAccErrorCheck(t, batch.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckBatchComputeEnvironmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSBatchComputeEnvironmentConfigFargateDefaultServiceRole(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsBatchComputeEnvironmentExists(resourceName, &ce), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "batch", fmt.Sprintf("compute-environment/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "compute_environment_name", rName), + resource.TestCheckResourceAttr(resourceName, "compute_environment_name_prefix", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.#", "1"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.allocation_strategy", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.bid_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.desired_vcpus", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.ec2_key_pair", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.image_id", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.instance_role", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.instance_type.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.launch_template.#", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.max_vcpus", "16"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.min_vcpus", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.security_group_ids.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "compute_resources.0.security_group_ids.*", securityGroupResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.spot_iam_fleet_role", ""), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.subnets.#", "1"), + resource.TestCheckTypeSetElemAttrPair(resourceName, "compute_resources.0.subnets.*", subnetResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "compute_resources.0.type", "FARGATE"), + resource.TestCheckResourceAttrSet(resourceName, "ecs_cluster_arn"), + testAccMatchResourceAttrGlobalARN(resourceName, "service_role", "iam", regexp.MustCompile(`role/aws-service-role/batch`)), + resource.TestCheckResourceAttr(resourceName, "state", "ENABLED"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "status_reason"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + resource.TestCheckResourceAttr(resourceName, "type", "MANAGED"), ), }, { @@ -1671,6 +1767,76 @@ resource "aws_batch_compute_environment" "test" { `, rName)) } +func testAccAWSBatchComputeEnvironmentConfigFargateDefaultServiceRole(rName string) string { + return composeConfig( + testAccAWSBatchComputeEnvironmentConfigBase(rName), + fmt.Sprintf(` +resource "aws_batch_compute_environment" "test" { + compute_environment_name = %[1]q + + compute_resources { + max_vcpus = 16 + security_group_ids = [ + aws_security_group.test.id + ] + subnets = [ + aws_subnet.test.id + ] + type = "FARGATE" + } + + type = "MANAGED" +} +`, rName)) +} + +func testAccAWSBatchComputeEnvironmentConfigFargateUpdatedServiceRole(rName string) string { + return composeConfig( + testAccAWSBatchComputeEnvironmentConfigBase(rName), + fmt.Sprintf(` +resource "aws_batch_compute_environment" "test" { + compute_environment_name = %[1]q + + compute_resources { + max_vcpus = 16 + security_group_ids = [ + aws_security_group.test.id + ] + subnets = [ + aws_subnet.test.id + ] + type = "FARGATE" + } + + service_role = aws_iam_role.batch_service_2.arn + type = "MANAGED" + depends_on = [aws_iam_role_policy_attachment.batch_service_2] +} + +resource "aws_iam_role" "batch_service_2" { + name = "%[1]s_batch_service_2" + + assume_role_policy = <