Search code examples
amazon-web-servicesterraformamazon-ecsterraform-provider-aws

Can AWS ECS capacity provider be updated using Terraform?


I was planning to provision Amazon ECS capacity provider via Terraform but I saw a few questions which talk about the updating of Amazon ECS capacity provider via Terraform was not possible. Is the feature safe to be used now?


Solution

  • As of 21st June 2021, Terraform's AWS provider is currently unable to update ECS capacity providers.

    When ECS capacity providers were first introduced in v2.42.0 you couldn't update them or even delete them via the API or console and so the initial support that added ECS capacity providers to the Terraform AWS provider didn't handle deleting capacity providers or allow updating anything other than the tags. Deletion support was added in the later v2.67.0 release.

    There's an open merge request that adds support for updating ECS capacity providers but it hasn't been merged and released yet.

    Currently, when you attempt to update an ECS capacity provider Terraform will handle it like it does with all immutable resources and destroy the resource and recreate it. This can cause issues with Terraform because you can't delete a capacity provider that is in use by an ECS cluster (it will error with The capacity provider cannot be deleted because it is associated with cluster: $CAPACITY_PROVIDER_NAME. Remove the capacity provider from the cluster and try again.).

    To work around this you can use a destroy-time provisioner to detach the capacity provider from the ECS cluster which then allows Terraform to delete the capacity provider and create a new one.

    resource "aws_autoscaling_group" "test" {
      # ... other configuration, including potentially other tags ...
    
      tag {
        key                 = "AmazonECSManaged"
        value               = ""
        propagate_at_launch = true
      }
    }
    
    resource "aws_ecs_capacity_provider" "capacity_provider" {
      name = var.cluster_name
    
      auto_scaling_group_provider {
        auto_scaling_group_arn         = aws_autoscaling_group.test.arn
        managed_termination_protection = "ENABLED"
    
        managed_scaling {
          maximum_scaling_step_size = 1000
          minimum_scaling_step_size = 1
          status                    = "ENABLED"
          target_capacity           = 10
        }
      }
    
      provisioner "local-exec" {
        when = destroy
    
        command = "aws ecs put-cluster-capacity-providers --cluster ${self.name} --capacity-providers [] --default-capacity-provider-strategy []"
      }
    }
    
    resource "aws_ecs_cluster" "cluster" {
      name = var.cluster_name
      capacity_providers = [
        aws_ecs_capacity_provider.capacity_provider.name,
      ]
    }
    

    You will then need to run terraform apply twice to have it then reattach the new capacity provider after the first run detaches it, deletes it and then creates the new capacity provider.

    When the pull request to add support for in place updates is merged and released you can then remove the destroy-time provisioner and it will just work as expected, avoiding the need to run terraform apply twice.