terraform
terraform copied to clipboard
Terraform does not apply planned changes if -target passed to plan
If I change the name of a lambda function terraform correctly creates a plan about resources to create/destroy/update, but it won't do anything after running the apply command on the created plan.
Terraform Version
Terraform v0.11.14
Terraform Configuration Files
resource "aws_api_gateway_rest_api" "TestApi" {
name = "TestApi"
}
resource "aws_api_gateway_resource" "TestApiGWResource" {
rest_api_id = "${aws_api_gateway_rest_api.TestApi.id}"
parent_id = "${aws_api_gateway_rest_api.TestApi.root_resource_id}"
path_part = "{proxy+}"
}
resource "aws_api_gateway_method" "TestApiGWMethod" {
rest_api_id = "${aws_api_gateway_rest_api.TestApi.id}"
resource_id = "${aws_api_gateway_resource.TestApiGWResource.id}"
http_method = "ANY"
authorization = "NONE"
}
resource "aws_lambda_function" "TestFunction" {
function_name = "Test-${terraform.workspace}"
filename = "./lambda_payload.zip"
source_code_hash = "${base64sha256(file("./lambda_payload.zip"))}"
handler = "index.server"
runtime = "nodejs10.x"
role = "${aws_iam_role.lambda_execute.arn}"
}
resource "aws_api_gateway_integration" "TestApiGWIntegration" {
rest_api_id = "${aws_api_gateway_rest_api.TestApi.id}"
resource_id = "${aws_api_gateway_method.TestApiGWMethod.resource_id}"
http_method = "${aws_api_gateway_method.TestApiGWMethod.http_method}"
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "${aws_lambda_function.TestFunction.invoke_arn}"
}
resource "aws_api_gateway_deployment" "TestApiGWDeployment" {
depends_on = [
"aws_api_gateway_integration.TestApiGWIntegration"]
rest_api_id = "${aws_api_gateway_rest_api.TestApi.id}"
stage_name = "${terraform.workspace}"
}
Expected Behavior
After changing function name and creating the plan the apply should apply those changes
Actual Behavior
terraform plan
: Plan: 1 to add, 1 to change, 1 to destroy.
terraform apply out.plan
: Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Steps to Reproduce
After created all the resources change the value of function_name
in "aws_lambda_function.TestFunction"
terraform plan -target="aws_api_gateway_deployment.TestApiGWDeployment" -out out.plan
terraform apply out.plan
or
terraform apply -target="aws_api_gateway_deployment.TestApiGWDeployment" out.plan
Additional Context
It works if I omit the -target, but I pass target as I want to target a specific deployment:( Trace log: trace log of apply
References
- #20576 (but I don't use count)
Okey, I've found a workaround, idk if it can help narrow down the problem:
Instead of targeting TestApiGWDeployment only, I must target every resources which my original target depends on.
So this is working:
terraform plan -target="aws_api_gateway_deployment.TestApiGWDeployment" -target="aws_api_gateway_integration.TestApiGWIntegration" -out dev.plan
terraform apply out dev.plan
It is quite strange as I can omit the -target totally from apply, it is working with this two commands.
Found another case when this happens and I can't use that workaround above for some unknown reason. And just noticed that this is labeled as v0.12.
Is there any plan to even look into this on v0.11 or I should start moving to v0.12?
Also I would like to detect that there were any errors during apply. Currently I had the false impression that everything was fine with deploy as terraform apply
returned no error.
Am I right if I assume that the numbers in the last line of plan
must always match with the numbers of apply
?
Btw, shouldn't terraform apply
return with non-zero code if it was planned to add something then it adds nothing?
Just for clarification, I'm pretty sure this issue is meant to reference issue #20567. I can't tell if this has been addressed in 0.12 or not as we just had a similar issue.
I've had a similar problem: when I ran terraform apply while targeting two resources, then the listed planned changes are telling me that it's going to update a related resource, and when I say yes to apply, then it doesn't. I figured out why this happens and how to fix it in my case.
(Specific details of my situation - feel free to skip this) My source code is: https://gist.github.com/VelizarHristov/d751000d9a92e28a400e53fd458f9146
In my case, I have a policy which gives my EC2 instances access to an S3 bucket. It's implemented with the following resources:
- "aws_iam_role" "main_server_role"
- "aws_iam_policy" "access_to_s3_bucket_policy"
- "aws_iam_role_policy_attachment" "s3_policy_attachment"
- "aws_iam_instance_profile" "main_server_profile"
I was running apply with the last two as targets: -target=aws_iam_instance_profile.main_server_profile -target=aws_iam_role_policy_attachment.s3_policy_attachment
Then Terraform was telling me that it wanted to change the second one, "aws_iam_policy" "access_to_s3_bucket_policy"
. This made sense because I had changed it to add the "s3:ListBucket" permission under "Action". It also seemed to make sense because the S3 policy attachment was targeted, and it directly referenced this policy:
resource "aws_iam_role_policy_attachment" "s3_policy_attachment" {
role = aws_iam_role.main_server_role.name
policy_arn = aws_iam_policy.access_to_s3_bucket_policy.arn
}
However, even though plan listed it ("Plan: 0 to add, 1 to change, 0 to destroy."), apply didn't do anything ("Apply complete! Resources: 0 added, 0 changed, 0 destroyed."), and when I re-ran the command, it was again in plan. (End of specific details of my situation)
I think that what's going on is that since I'm not explicitly targeting the resource which had the change ("access_to_s3_bucket_policy"), Terraform didn't change it, since it was already existent, and in its current state it was good enough for the actually targeted resource ("s3_policy_attachment") to be up to date. So in order to fix it, you need to explicitly target the resource that showed up in plan, "access_to_s3_bucket_policy" - that worked for me.
I think this still indicates some sort of bug in Terraform, because plan lied to the end user, as it said that it will change this resource, but it didn't because it was inconsistent with how apply worked. I don't know which one of plan or apply should change to match the other, although the behaviour of apply feels more intuitive to me than the behaviour of plan. After all, to target an association means that you care about the association, but since you're not targeting the things it's associating, that means you don't care about them being right, as long as the association can exist. In my case, I actually cared about them, but I was being lazy and overlooked the fact that if they're dependencies which I'm not directly targeting then Terraform might not want to keep them up to date, just to ensure their existence. I wouldn't mind a flag to switch to this behaviour, i.e. all dependencies of your targets to be treated as targets. Actually I changed my mind, this seems more desirable as a default behaviour than what apply is doing right now.