hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.83k stars 9.17k forks source link

[Bug]: Cannot add tags to aws_appautoscaling_target resource #31839

Open imanAzi opened 1 year ago

imanAzi commented 1 year ago

Terraform Core Version

v1.4.6

AWS Provider Version

v4.67.0

Affected Resource(s)

aws_appautoscaling_target

Expected Behavior

Terraform should create these resources and manage the tags automatically by seeing the default_tags configuration on the provider

Actual Behavior

When creating the these resources for the first time, we receive the following error:

aws_appautoscaling_target.service_scaling: Creating...
╷
│ Error: creating Application AutoScaling Target (service/content-available-service-nonprod-ecs-cluster/content-available-service-nonprod-ecs-service): ValidationException: The scalable target that you tried to tag already exists. To update tags on an existing scalable target, use the TagResource API.
│ 
│   with aws_appautoscaling_target.service_scaling,
│   on autoscaling.tf line 1, in resource "aws_appautoscaling_target" "service_scaling":
│    1: resource "aws_appautoscaling_target" "service_scaling" {
│ 
╵

Relevant Error/Panic Output Snippet

No response

Terraform Configuration Files

terraform {
  backend "s3" {
    bucket         = "xxxx"
    key            = "content-available-service"
    dynamodb_table = "terraform-state"
    region         = "xxxx"
  }
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

#Provider configuration
provider "aws" {
  region = var.aws_region
  default_tags {
    tags = {
      application = var.project
      stage       = var.env
      squad       = var.squad
      terraform   = "true"
      repository  = var.repository_name
    }
  }
}

resource "aws_appautoscaling_target" "service_scaling" {
  min_capacity       = var.min_container_count
  max_capacity       = var.max_container_count
  resource_id        = "service/${aws_ecs_cluster.ecs_cluster.name}/${aws_ecs_service.ecs_service.name}"
  role_arn           = aws_iam_role.autoscaling_role.arn
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"

  depends_on = [aws_ecs_service.ecs_service, aws_iam_role.autoscaling_role]
}

resource "aws_appautoscaling_policy" "service_scale_out" {
  name               = "${var.project}-${var.env}-scale-out-policy"
  policy_type        = "StepScaling"
  resource_id        = aws_appautoscaling_target.service_scaling.resource_id
  scalable_dimension = aws_appautoscaling_target.service_scaling.scalable_dimension
  service_namespace  = aws_appautoscaling_target.service_scaling.service_namespace

  step_scaling_policy_configuration {
    adjustment_type         = "ChangeInCapacity"
    cooldown                = 60
    metric_aggregation_type = "Average"

    step_adjustment {
      scaling_adjustment          = 1
      metric_interval_lower_bound = 0
    }
  }

  depends_on = [aws_appautoscaling_target.service_scaling]
}

Steps to Reproduce

Terraform apply

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

Yes

github-actions[bot] commented 1 year ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

imanAzi commented 1 year ago

I have tried to set the tags property explicitly in the resource like this:

resource "aws_appautoscaling_target" "service_scaling" {
  min_capacity       = var.min_container_count
  max_capacity       = var.max_container_count
  resource_id        = "service/${aws_ecs_cluster.ecs_cluster.name}/${aws_ecs_service.ecs_service.name}"
  role_arn           = aws_iam_role.autoscaling_role.arn
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"

  tags = {
    "stage"       = var.env
    "application" = var.project
    "squad"       = var.squad
    "terraform"   = "true"
    "repository"  = var.repository_name
  }

  depends_on = [aws_ecs_service.ecs_service, aws_iam_role.autoscaling_role]
}

But that still gives the same error. The weird thing is that the error states the scaleable target already exists, but if I check the Terraform state it's not listed as a resource:

terraform state list                                                                                                   

aws_ecs_cluster.ecs_cluster
aws_ecs_service.ecs_service
aws_ecs_task_definition.ecs_task
aws_iam_policy.autoscaling_policy
aws_iam_policy.ecs_execution_policy
aws_iam_policy.ecs_task_policy
aws_iam_role.autoscaling_role
aws_iam_role.ecs_execution_role
aws_iam_role.ecs_task_role
aws_lb.lb_public
aws_lb_listener.https_redirect
aws_lb_listener.listener_https
aws_lb_target_group.target_group
aws_route53_record.lb_a_record_nonprod[0]
aws_security_group.ecs_tasks_sg
aws_security_group.lb_sg
aws_security_group.sg

But when I run aws application-autoscaling describe-scalable-targets --service-namespace ecs I get:

{
    "ScalableTargets": [
        {
            "ServiceNamespace": "ecs",
            "ResourceId": "service/content-available-service-nonprod-ecs-cluster/content-available-service-nonprod-ecs-service",
            "ScalableDimension": "ecs:service:DesiredCount",
            "MinCapacity": 1,
            "MaxCapacity": 2,
            "RoleARN": "arn:aws:iam::xxxxx:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService",
            "CreationTime": "2023-06-07T15:32:25.300000+02:00",
            "SuspendedState": {
                "DynamicScalingInSuspended": false,
                "DynamicScalingOutSuspended": false,
                "ScheduledScalingSuspended": false
            },
            "ScalableTargetARN": "arn:aws:application-autoscaling:xxxx:xxxxx:scalable-target/0ec59a87599dd3474d8aa363fccf97a98653"
        }
    ]
}

Which indicates that this resource does exist? But how come I can't find it in the TF state?

imanAzi commented 1 year ago

I downgraded my aws provider to 4.65, and now I don't have this issue anymore. This bug seems to be introduced from v4.66

The resource is created and is been shown when I do terraform state list

aws_appautoscaling_policy.service_scale_in
aws_appautoscaling_policy.service_scale_out
aws_appautoscaling_target.service_scaling
aws_ecs_cluster.ecs_cluster
aws_ecs_service.ecs_service
aws_ecs_task_definition.ecs_task
aws_iam_policy.autoscaling_policy
aws_iam_policy.ecs_execution_policy
aws_iam_policy.ecs_task_policy
aws_iam_role.autoscaling_role
aws_iam_role.ecs_execution_role
aws_iam_role.ecs_task_role
aws_lb.lb_public
aws_lb_listener.https_redirect
aws_lb_listener.listener_https
aws_lb_target_group.target_group
aws_route53_record.lb_a_record_nonprod[0]
aws_security_group.ecs_tasks_sg
aws_security_group.lb_sg
aws_security_group.sg
ewbankkit commented 1 year ago

Relates https://github.com/hashicorp/terraform-provider-aws/issues/31180.

imanAzi commented 1 year ago

@ewbankkit, just as extra information: I tried version 4.67, 5.0 and all had the same error. It seems that there is a bug around tagging introduced since 4.66

ChenTsungYu commented 1 year ago

Hello, I got the same problem. Screenshot 2023-08-04 at 9 02 01 AM

keoma-di commented 1 year ago

Same error happens on v5.10.0. Seems to be fixed by adding

lifecycle {
    ignore_changes = [
      tags_all
    ]
  }

to the aws_appautoscaling_target.

singhbabanjot commented 11 months ago

@ewbankkit. I am facing this issue. Even though using the latest provider version.

Error Getting

ValidationException: The scalable target that you tried to tag already exists. 
To update tags on an existing scalable target, use the TagResource API.
jvnsg commented 10 months ago

@ewbankkit I am facing this issue too. @singhbabanjot have you found a workaround/ solution?

matisilva commented 10 months ago

I tried lot of things but the only that work for me was to import the resource manipulating tf state For RDS for example:

Suppose you have a resource called my-aurora-cluster which has a rds:cluster:ReadReplicaCount conflict trying to run the following in TF

resource "aws_appautoscaling_target" "my_rds_target" {
  service_namespace  = "rds"
  scalable_dimension = "rds:cluster:ReadReplicaCount"
  resource_id        = "cluster:my-aurora-cluster"
  min_capacity       = 1
  max_capacity       = 15
}

you can import the target as follows

terraform import aws_appautoscaling_target.my_rds_target rds/cluster:my-aurora-cluster/rds:cluster:ReadReplicaCount

And in case you have created the policy and wanted to be imported you can also use

terraform import aws_appautoscaling_policy.my_rds_autoscaling_policy rds/cluster:my-aurora-cluster/rds:cluster:ReadReplicaCount/my-policy-cpu-auto-scaling
herrbpl commented 8 months ago

Still exists with v5.36.0

herrbpl commented 8 months ago

Found out that actually there probably is existing autoscalable target in existance (this is not obvious anywhere), so when you get

module.rds["postgres-cluster"].aws_appautoscaling_target.this[0]: Creating...
╷
│ Error: creating Application AutoScaling Target (cluster:postgres-cluster): ValidationException: The scalable target that you tried to tag already exists. To update tags on an existing scalable target, use the TagResource API.
│ 
│   with module.rds["postgres-cluster"].aws_appautoscaling_target.this[0],
│   on .terraform/modules/rds/main.tf line 270, in resource "aws_appautoscaling_target" "this":
│  270: resource "aws_appautoscaling_target" "this" {

try:

aws application-autoscaling describe-scalable-targets --service-namespace rds
{
    "ScalableTargets": [
        {
            "ServiceNamespace": "rds",
            "ResourceId": "cluster:posgres-cluster",
            "ScalableDimension": "rds:cluster:ReadReplicaCount",
            "MinCapacity": 1,
            "MaxCapacity": 15,
            "RoleARN": "arn:aws:iam::1234567890:role/aws-service-role/rds.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_RDSCluster",
            "CreationTime": "2024-01-08T12:37:24.566000+00:00",
            "SuspendedState": {
                "DynamicScalingInSuspended": false,
                "DynamicScalingOutSuspended": false,
                "ScheduledScalingSuspended": false
            },
            "ScalableTargetARN": "arn:aws:application-autoscaling:eu-central-1:1234567890:scalable-target/03d....b6e"
        }
    ]
}

Maybe you had autoscaling created manually in console and deleted. This leaves this target behind.. Delete it and you can create another one with terraform.

bwhaley commented 3 months ago

This will happen with Dynamodb global tables also when converting from On Demand to Provisioned. Fix it with something like the following:

aws application-autoscaling deregister-scalable-target \
  --service-namespace dynamodb \
  --scalable-dimension dynamodb:table:ReadCapacityUnits \
  --resource-id table/<table name>
aws application-autoscaling delete-scaling-policy \
  --scalable-dimension "dynamodb:table:ReadCapacityUnits" \
  --service-namespace dynamodb \
  --resource-id table/<table name> \
  --policy-name DynamoDBReadCapacityUtilization:table/<table name>

aws application-autoscaling deregister-scalable-target \
  --service-namespace dynamodb \
  --scalable-dimension dynamodb:table:WriteCapacityUnits \
  --resource-id table/<table name>
aws application-autoscaling delete-scaling-policy \
  --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
  --service-namespace dynamodb \
  --resource-id table/<table name> \
  --policy-name DynamoDBWriteCapacityUtilization:table/<table name>

It's not clear to me if the scaling policies need to be deleted, but I don't think there's any harm in cleaning them up.