Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: -target option is not respected #34962

Closed
EugenKon opened this issue Apr 8, 2024 · 8 comments
Closed

[Bug]: -target option is not respected #34962

EugenKon opened this issue Apr 8, 2024 · 8 comments
Labels
bug working as designed confirmed as reported and closed because the behavior is intended

Comments

@EugenKon
Copy link

EugenKon commented Apr 8, 2024

Terraform Core Version

1.7.4

AWS Provider Version

4.67.0

Affected Resource(s)

  • aws_autoscaling_group
  • aws_lb_target_group.www-http
  • aws_lb_target_group.www-https
    and others

Expected Behavior

If I provide -target option only target resources should be planned

Actual Behavior

Other resources planned

Relevant Error/Panic Output Snippet

TF plan
$ terraform plan -target aws_autoscaling_group.www -out wg1
data.aws_iam_policy_document.ec2-assume-role-policy: Reading...
aws_vpc.prd_plntr: Refreshing state... [id=vpc-1014dc74]
data.aws_iam_policy_document.ec2-assume-role-policy: Read complete after 0s [id=1903849331]
aws_iam_role.www: Refreshing state... [id=www-role]
aws_iam_instance_profile.www: Refreshing state... [id=www-role]
aws_security_group.internal_traffic: Refreshing state... [id=sg-dc8b9abb]
aws_security_group.ssh_for_all: Refreshing state... [id=sg-d28b9ab5]
aws_lb_target_group.www-https: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:402716384312:targetgroup/www-https/61d8e68586fb095a]
aws_lb_target_group.www-http: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:402716384312:targetgroup/www-http/136c8e539e6a0847]
aws_subnet.b_prd_plntr: Refreshing state... [id=subnet-7c834d1b]
aws_security_group.all_egress: Refreshing state... [id=sg-db8b9abc]
aws_security_group.www: Refreshing state... [id=sg-dd8b9aba]
aws_lb_target_group.www-https-autoscale: Refreshing state... [id=arn:aws:elasticloadbalancing:us-east-1:402716384312:targetgroup/www-https-autoscale/0d5221715c5a0646]
aws_security_group.etcd: Refreshing state... [id=sg-df8b9ab8]
aws_launch_template.www: Refreshing state... [id=lt-0a94ff57d3cb40f85]
aws_autoscaling_group.www: Refreshing state... [id=www-autoscale]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_autoscaling_group.www will be updated in-place
  ~ resource "aws_autoscaling_group" "www" {
        id                        = "www-autoscale"
        name                      = "www-autoscale"
        # (25 unchanged attributes hidden)

      ~ launch_template {
            id      = "lt-0a94ff57d3cb40f85"
            name    = "www-autoscale"
          ~ version = "$Latest" -> "4"
        }

        # (3 unchanged blocks hidden)
    }

  # aws_lb_target_group.www-http will be updated in-place
  ~ resource "aws_lb_target_group" "www-http" {
        id                                 = "arn:aws:elasticloadbalancing:us-east-1:402716384312:targetgroup/www-http/136c8e539e6a0847"
        name                               = "www-http"
        tags                               = {}
        # (16 unchanged attributes hidden)

      ~ health_check {
          ~ matcher             = "200-299" -> "200-399"
            # (8 unchanged attributes hidden)
        }

        # (2 unchanged blocks hidden)
    }

  # aws_lb_target_group.www-https will be updated in-place
  ~ resource "aws_lb_target_group" "www-https" {
        id                                 = "arn:aws:elasticloadbalancing:us-east-1:402716384312:targetgroup/www-https/61d8e68586fb095a"
        name                               = "www-https"
        tags                               = {}
        # (16 unchanged attributes hidden)

      ~ health_check {
          ~ matcher             = "200-299" -> "200-399"
            # (8 unchanged attributes hidden)
        }

      ~ stickiness {
          ~ cookie_duration = 10 -> 300
            # (2 unchanged attributes hidden)
        }

        # (1 unchanged block hidden)
    }

  # aws_lb_target_group.www-https-autoscale will be updated in-place
  ~ resource "aws_lb_target_group" "www-https-autoscale" {
      + connection_termination             = false
        id                                 = "arn:aws:elasticloadbalancing:us-east-1:402716384312:targetgroup/www-https-autoscale/0d5221715c5a0646"
      + lambda_multi_value_headers_enabled = false
        name                               = "www-https-autoscale"
      + proxy_protocol_v2                  = false
        tags                               = {}
        # (13 unchanged attributes hidden)

      ~ health_check {
          ~ matcher             = "200-299" -> "200"
            # (8 unchanged attributes hidden)
        }

      ~ stickiness {
          ~ cookie_duration = 10 -> 86400
          ~ enabled         = true -> false
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

Plan: 0 to add, 4 to change, 0 to destroy.
╷
│ Warning: Resource targeting is in effect
│
│ You are creating a plan with the -target option, which means that the result of this plan may not represent
│ all of the changes requested by the current configuration.
│
│ The -target option is not for routine use, and is provided only for exceptional situations such as recovering
│ from errors or mistakes, or when Terraform specifically suggests to use it as part of an error message.
╵

it tries to change other resources despite on target

Terraform Configuration Files

not relevant

Steps to Reproduce

  1. Deploy some cluster
  2. Do some changes via AWS Console
  3. terraform plan with -target option

Despite I have planned only one resource the other resources changed via AWS Console are also planned.

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

Copied from here: hashicorp/terraform-provider-aws#36698

Would you like to implement a fix?

None

@EugenKon EugenKon added bug new new issue not yet triaged labels Apr 8, 2024
@EugenKon EugenKon changed the title asdfasdfasdfasdf [Bug]: -target option is not respected Apr 8, 2024
@liamcervante
Copy link
Member

Hi @EugenKon, can you share the configuration you are using to reproduce this?

The target option will automatically select any resources that the target resource depends on. Is this the case here? If so, Terraform is behaving as expected. When targeting a specific resource, Terraform will need to fetch the values for any references within that resource. As such, it must refresh and update any resources that contain those references. The whole chain of dependencies must be applied as one.

Given that you've mentioned that you've applied some changes within the AWS Console, I think you can avoid including those changes with the -refresh=false option. Something like: terraform -target=<target> -refresh=false might execute the behaviour you are looking for.

@liamcervante liamcervante added the waiting-response An issue/pull request is waiting for a response from the community label Apr 9, 2024
@liamcervante
Copy link
Member

Hi @EugenKon, I'm going to close this issue as I believe this is a case of Terraform behaving as expected in terms of applying changes to the complete chain of dependencies for a given target.

If your targeted resource does not depend on the resources that are being included in the plan, please leave a comment and I will reopen this.

Thanks!

@liamcervante liamcervante closed this as not planned Won't fix, can't repro, duplicate, stale Apr 11, 2024
@liamcervante liamcervante added working as designed confirmed as reported and closed because the behavior is intended and removed waiting-response An issue/pull request is waiting for a response from the community new new issue not yet triaged labels Apr 11, 2024
@EugenKon
Copy link
Author

I believe that the resources does not depend on the resources that are being included in the plan. Sorry, I can return to this during the month or even later. I hope I will not lose this closed issue. Thank you.

@EugenKon
Copy link
Author

@liamcervante
Here is my configuration:

resource "aws_autoscaling_group" "www" {
  name                  = "www-autoscale"
  desired_capacity      = 2
  min_size              = 2
  max_size              = 2
  protect_from_scale_in = true

  launch_template {
    id = aws_launch_template.www.id
    version = "5"
  }

  target_group_arns = [
    aws_lb_target_group.www-http.arn,
    aws_lb_target_group.www-https.arn,
    aws_lb_target_group.www-https-autoscale.arn,
  ]

  lifecycle {
    create_before_destroy = true
  }

}

TF plan
Terraform will perform the following actions:
  # aws_autoscaling_group.www will be updated in-place
  ~ resource "aws_autoscaling_group" "www" {
        id                        = "www-autoscale"
        name                      = "www-autoscale"
        # (25 unchanged attributes hidden)

      ~ launch_template {
            id      = "lt-0a94***"
            name    = "www-autoscale"
          ~ version = "4" -> "5"
        }

        # (3 unchanged blocks hidden)
    }

  # aws_eip.nat-prd_plntr will be created
  + resource "aws_eip" "nat-prd_plntr" {
      + allocation_id        = (known after apply)
      + association_id       = (known after apply)
      + carrier_ip           = (known after apply)
      + customer_owned_ip    = (known after apply)
      + domain               = (known after apply)
      + id                   = (known after apply)
      + instance             = (known after apply)
      + network_border_group = (known after apply)
      + network_interface    = (known after apply)
      + private_dns          = (known after apply)
      + private_ip           = (known after apply)
      + public_dns           = (known after apply)
      + public_ip            = (known after apply)
      + public_ipv4_pool     = (known after apply)
      + tags                 = {
          + "Name" = "Public IP for plntr-nat-gateway"
        }
      + tags_all             = {
          + "Name" = "Public IP for plntr-nat-gateway"
        }
      + vpc                  = (known after apply)
    }

  # aws_lb_target_group.www-http will be updated in-place
  ~ resource "aws_lb_target_group" "www-http" {
        id                                 = "arn:aws:elasticloadbalancing:***"
        name                               = "www-http"
        tags                               = {}
        # (16 unchanged attributes hidden)

      ~ health_check {
          ~ matcher             = "200-299" -> "200-399"
            # (8 unchanged attributes hidden)
        }

        # (2 unchanged blocks hidden)
    }

  # aws_lb_target_group.www-https will be updated in-place
  ~ resource "aws_lb_target_group" "www-https" {
        id                                 = "arn:aws:elasticloadbalancing:***"
        name                               = "www-https"
        tags                               = {}
        # (16 unchanged attributes hidden)

      ~ health_check {
          ~ matcher             = "200-299" -> "200-399"
            # (8 unchanged attributes hidden)
        }

      ~ stickiness {
          ~ cookie_duration = 10 -> 300
            # (2 unchanged attributes hidden)
        }

        # (1 unchanged block hidden)
    }

  # aws_lb_target_group.www-https-autoscale will be updated in-place
  ~ resource "aws_lb_target_group" "www-https-autoscale" {
      + connection_termination             = false
        id                                 = "arn:aws:elasticloadbalancing:us***"
      + lambda_multi_value_headers_enabled = false
        name                               = "www-https-autoscale"
      + proxy_protocol_v2                  = false
        tags                               = {}
        # (13 unchanged attributes hidden)

      ~ health_check {
          ~ matcher             = "200-299" -> "200"
            # (8 unchanged attributes hidden)
        }

      ~ stickiness {
          ~ cookie_duration = 10 -> 86400
          ~ enabled         = true -> false
            # (1 unchanged attribute hidden)
        }

        # (1 unchanged block hidden)
    }

How to reproduce:

terraform plan -target aws_launch_template.www -target aws_eip.nat-prd_plntr -target aws_autoscaling_group.www -out subnet

So here I added Elastic IP and switched www autoscale group to use a different Launch Template. Somebody changed a load balancer configuration directly via AWS Console (Unfortunately that exists in our workflow). I do not want to revert those changes thus I explicitly target resources I want to update via Terraform.

But terraform still want to update them.

Terraform should not updated resources if it was told to not do so.

@liamcervante
Copy link
Member

liamcervante commented Apr 22, 2024

Hi @EugenKon, based on your configuration the new aws_autoscaling_group.www resource depends on, for example, the aws_lb_target_group.www-http resource via the target_group_arns attribute. Terraform will therefore attempt to refresh/update the parents of the target resource even with the -target command included. I think this is a case of Terraform working as intended.

If you don't want Terraform to overwrite changes to your infrastructure made outside of Terraform you can:

  • Use the -refresh=false argument: terraform plan -refresh=false -target aws_launch_template.www -target aws_eip.nat-prd_plntr -target aws_autoscaling_group.www -out subnet. This will make Terraform skip the refresh stage of the plan, and so will only report or apply changes between the last-applied state and the configuration.
  • Use the ignore_changes meta-attribute on the attributes you don't want updated. This means any future changes to those attributes will also be ignored if this is a recurring problem.
  • You can also just update your configuration to match the changes that were made externally. Then Terraform will also not attempt to make changes.

I'm sorry that we can't really change the behaviour of the -target argument here. Terraform does need to update and refresh all the resources required for the targeted resource, otherwise commands could fail as the information Terraform is using in the requests isn't up-to-date. Hopefully one of the suggested workarounds works for you!

@EugenKon
Copy link
Author

EugenKon commented Apr 22, 2024

@liamcervante I'll try to look at -refresh=false with more attention. Thank you.

But I am curious. The aws_autoscaling_group.www resource depends on the aws_launch_template.www resource via the launch_template attribute. Why terraform does not attempt to refresh/updated it too??

To improve the behaviour of terraform in such situations, I want to propose next:

  • If -target option was used
  • And other resource need to be refreshed/updated that is not listed in -target options.

Show the warning message with a list of resources need to be refreshed/updated and mention -refresh=false option. Eg.

These XXX, YYY resources additionally to -target are planned to be refreshed/updated.
Use -refresh=false if you want to prevent this refresh/udpate.

@liamcervante
Copy link
Member

The aws_autoscaling_group.www resource depends on the aws_launch_template.www resource via the launch_template attribute. Why terraform does not attempt to refresh/updated it too?

I'm afraid I can't say for sure. There may not be changes to the aws_launch_template.www that need to be updated so it would still be refreshed but that refresh would show no changes. Or, potentially there are other additional changes that are being reported for the other resources due to a mismatch between state and config which results in them being included in the plan.

If you run terraform plan -refresh-only, that should provide a plan that ignores your configuration and only shows the updates made externally to Terraform. That might give you more insight into why certain resources are being included in the normal plan and others aren't. Note, you shouldn't apply the plan that results from the refresh command as that would mean the -refresh=false workaround would stop working.

Show the warning message with a list of resources need to be refreshed/updated and mention -refresh=false option

This is something we could think about. You should file another issue with this as an enhancement / feature request rather than a bug. This would then be picked up by our product and community team for triage, discovery and prioritisation. You can link back to the discussion here to add more context.

Copy link
Contributor

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug working as designed confirmed as reported and closed because the behavior is intended
Projects
None yet
Development

No branches or pull requests

2 participants