Open cdhesse opened 3 years ago
Hi @cdhesse , thank you for raising this issue. To further investigate the behavior you're seeing, do you mind describing what changes in your configuration between the first and second apply? also, if you have debug logs readily available or can reproduce the behavior in the meantime with the env TF_LOG=debug
, it would be greatly appreciated to add them to the description when you have a chance :)
Thanks @anGie44 - the point is nothing is changed from the first run to the second... aka - nothing changed... simply run terraform apply 2x's in a row and i get the error. The fact that it is saying that the changeset failed due to no changes found, is accurate. Seems to me that that the "-no-fail-on-empty-changeset" parameter, which is part of the API is set to "-fail-on-empty-changeset".
Following up here to provide sample code to re-create this error with the AWS provided standard "hello-world" application.
terraform {
required_version = "~> 0.13"
required_providers {
aws = "~> 3.18"
}
}
provider "aws" {
region = "us-east-1"
}
data aws_serverlessapplicationrepository_application app {
application_id = "arn:aws:serverlessrepo:us-east-1:077246666028:applications/hello-world"
semantic_version = "1.0.4"
}
resource aws_serverlessapplicationrepository_cloudformation_stack hello_world_stack {
name = "serverless-hello-world-test"
application_id = data.aws_serverlessapplicationrepository_application.app.application_id
capabilities = data.aws_serverlessapplicationrepository_application.app.required_capabilities
parameters = {
IdentityNameParameter: "MyName"
}
}
terraform apply
-> this succeedsterraform apply
a second time. This FAILS.Error aws_serverlessapplicationrepository_cloudformation_stack.hello_world_stack: Modifying... [id=arn:aws:cloudformation:us-east-1:XXXXXXXXX:stack/serverlessrepo-serverless-hello-world-test/7a6ef230-35a6-11zb-98ff-0ab512dce13f]
Error: error creating Serverless Application Repository CloudFormation Stack (arn:aws:cloudformation:us-east-1:XXXXXXXXX:stack/serverlessrepo-serverless-hello-world-test/7a6ef230-35a6-11zb-98ff-0ab512dce13f) change set: unexpected state 'FAILED', wanted target 'CREATE_COMPLETE'. last error: %!s(
Looking in Cloudformation you can see the error in the ChangeSet:
Status reason No updates are to be performed. Created time 2020-12-07 11:09:31 UTC-0500 Execution status UNAVAILABLE
Hi @cdhesse, apologies for the delay! Seems this may be a two-part problem but the most straightforward way to work around this in the meantime would be to set capabilities = ["CAPABILITY_IAM"]
in your config, and that should eliminate the need for the second terraform apply
.
For more background, it looks like data.aws_serverlessapplicationrepository_application.app
doesn't return any values in required_capabilities
and instead the aws_serverlessapplicationrepository_cloudformation_stack.hello_world_stack
resource returns the value CAPABILITY_IAM
as seen in this terraform plan
(after the first apply
), resulting in a perpetual diff:
# aws_serverlessapplicationrepository_cloudformation_stack.hello_world_stack will be updated in-place
~ resource "aws_serverlessapplicationrepository_cloudformation_stack" "hello_world_stack" {
~ capabilities = [
- "CAPABILITY_IAM",
]
id = "arn:aws:cloudformation:us-east-1:xxxxxxxxxx:stack/serverlessrepo-serverless-hello-world-test/bbaaf210-38e9-11eb-94f7-0acfa743837d"
name = "serverless-hello-world-test"
tags = {}
# (4 unchanged attributes hidden)
}
This implies the AWS Cloudformation API computes the capabilities
value, even when one is not provided, so that's a bug in the provider such that the capabilities
field should be considered an Optional/Computed
not Required
field.
The second issue regarding the error seen after terraform attempts to Modify
the resource: it could be a valid error from the AWS Cloudformation API as this troubleshooting error page describes (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html#troubleshooting-errors-no-updates-to-perform). We could follow-up with AWS support to see how they recommend making just a change to the capabilities
field or mark the field as ForceNew
as well if we can't update it after creation.
Hope this helps in the meantime @cdhesse!
Thanks for the workaround. Indeed I confirm that hard coding the capabilities to ["CAPABILITY_IAM"] allows it to work on subsequent apply runs. I thought the point was to grab the required capabilities from the serverless application repo definition in case they get updated from version to version. Is that not a right understanding?
capabilities = data.aws_serverlessapplicationrepository_application.app.required_capabilities
hi @cdhesse, indeed in general you could grab the required_capabilities
attribute from the data-source but it seems in the example that AWS provides, that serverless application doesn't have any set :/ . that field is set to an empty array []
in terraform and here's why I'm seeing in the Console (after being redirected from Serverless App Repository page):
So - interesting that there seems to be a second issue. For applications that require parameters (my real use case, not the hello-world one)... once i hard coded the CAPABILITY_IAM for this stack, I noticed a new bug. It seems that the parameters are not being persisted. Terraform refresh pulls back 4 parameters, even though there are 7 parameters in the configuration. I've not noticed anything strange about the parameters being dropped vs. kept, but something to look into. I'll try to dig deeper but the result is that this component is still not working for me given this second issue.
Hi, just checking to see if there have been any updates on this, please? we are currently facing the exact same issue with using aws_serverlessapplicationrepository_cloudformation_stack, we also use parameters and have not been able to get a second deployment to work.
Also seeing this issue.
We've deployed a stack using
resource "aws_serverlessapplicationrepository_cloudformation_stack" "salesforceIntegrationLambda" {
name = "salesforceIntegrationLambda"
application_id = "arn:aws:serverlessrepo:us-west-2:821825267871:applications/AmazonConnectSalesforceLambda"
capabilities = [
"CAPABILITY_IAM",
"CAPABILITY_NAMED_IAM"
]
parameters = {
...
}
}
which creates a cloudformation stack called serverlessrepo-salesforceIntegrationLambda.
However, on the second terraform apply
, we get a failure. Checking CloudTrail, I can see that a cloudformation.DescribeStacks
API call is failing with the error Stack with id aws-serverless-repository-salesforceIntegrationLambda does not exist
- it seems to be looking for the wrong stack name?
following up based on same example provided by @cdhesse , i've run the below and i didn't get the error on 2nd time when run terraform apply
terraform {
required_version = "~> 0.13"
required_providers {
aws = "~> 3.50.0"
}
}
provider "aws" {
region = "us-east-1"
profile = "xxx"
}
data aws_serverlessapplicationrepository_application app {
application_id = "arn:aws:serverlessrepo:us-east-1:077246666028:applications/hello-world"
semantic_version = "1.0.4"
}
resource aws_serverlessapplicationrepository_cloudformation_stack hello_world_stack {
name = "serverless-hello-world-test"
application_id = data.aws_serverlessapplicationrepository_application.app.application_id
capabilities = [
"CAPABILITY_IAM",
"CAPABILITY_NAMED_IAM"
]
parameters = {
IdentityNameParameter: "MyName"
}
}
not sure which version @simonhanmer been running with but you can see my aws provider version above. Hope that helps a bit
So - interesting that there seems to be a second issue. For applications that require parameters (my real use case, not the hello-world one)... once i hard coded the CAPABILITY_IAM for this stack, I noticed a new bug. It seems that the parameters are not being persisted. Terraform refresh pulls back 4 parameters, even though there are 7 parameters in the configuration. I've not noticed anything strange about the parameters being dropped vs. kept, but something to look into. I'll try to dig deeper but the result is that this component is still not working for me given this second issue.
I can confirm that this problem still exists in the latest version of the provider even after almost 2 year. As @cdhesse said, if you have more than 4 parameters, somehow the plan only refreshes up to 4 parameters from current stack that exists in AWS, and the rest of the parameters are treated as new, hence a diff is calculated. But when you apply the plan, since the diff that was calculated is not the reality, apply errors out with change set: unexpected state 'FAILED', wanted target 'CREATE_COMPLETE'. last error: No updates are to be performed
error
anGie44 and kgns I can also confirm this is still a problem. I am deploying "cloudfront-authorization-at-edge" and get the same errors, I also started off with using this option.
capabilities = data.aws_serverlessapplicationrepository_application.app.required_capabilitie
I then changed it to
capabilities = [ "CAPABILITY_IAM", "CAPABILITY_RESOURCE_POLICY" ]
I also checked, and unlike the above suggestion, both capabilities are listed.
Please advise if anyone has been able to find a working, workaround for this.
I'm pretty sure NoEcho
CFN parameters are triggering this same error as well:
~ "ParameterName" = "****" -> "ValueFromTerraform"
Terraform thinks the resource needs to be updated but on apply the CFN change-set reports an error of no changes to be performed.
I confirm Terraform try to update the cloudformation stack but as there is no change, the AWS Cloud formation Change Set is empty then enters in Failed status.
When I look at the Terraform state file, It seems that some credentials parameters are stored with "****"
My work around to this issue.
just use the local .json or .yml CloudFormation template with terraform aws_cloudformationn_stack
resource.
Then terraform apply
works fine without destroying the CloudFormation stack resource.
My work around to this issue. just use the local .json or .yml CloudFormation template with terraform
aws_cloudformationn_stack
resource. Thenterraform apply
works fine without destroying the CloudFormation stack resource.
I have done the same for the time being. The only problem with this is now I need to have that cloudformation template uploaded to an S3 bucket first, as it is too large. If would be great if it could all work as it is supposed to, but the workaround works for now.
My temporary solution for this was to add a tag with a random string. this forces an update on every apply though, so it's not ideal.
resource "aws_serverlessapplicationrepository_cloudformation_stack" "some_app" {
tags = {
RollMe = random_string.rollme.result
}
}
resource "random_string" "rollme" {
length = 16
special = false
keepers = {
uuid = "${uuid()}"
}
}
Very annoying issue.
Experiencing the same issue as everyone else on this thread, has anyone managed to find a workaround for this?
In my case we're using terraform cloud for state management and triggers from GHA.
My temporary solution for this was to add a tag with a random string. this forces an update on every apply though, so it's not ideal.
resource "aws_serverlessapplicationrepository_cloudformation_stack" "some_app" { tags = { RollMe = random_string.rollme.result } } resource "random_string" "rollme" { length = 16 special = false keepers = { uuid = "${uuid()}" } }
When testing this workaround i get the error:
Error: Provider produced inconsistent final plan
β
β When expanding the plan for
β aws_serverlessapplicationrepository_cloudformation_stack.datadog_rds_enhanced
β to include new values learned so far during apply, provider
β "registry.terraform.io/hashicorp/aws" produced an invalid new value for
β .tags_all: new element "RollMe" has appeared.
β
β This is a bug in the provider, which should be reported in the provider's
β own issue tracker.
-_- any suggestions?
After some tedious debugging we found two things that don't work as expected here:
Our solution/workaround/hack:
ignore_changes
block (beware if you actually want to change those!)UPDATE:
ignore_changes
also only works if there won't ever be changes to the resource. Any changes will otherwise lead to errors as secret/NoEcho parameter values will be set to *s then.
Only option then is to introduce some randomly generated tag which is ugly but kind-of works.
@tbalzer, could you provide an example on how to set these in the ignore changes block? I tried the following but this results in an error.
lifecycle {
ignore_changes = [
parameters[0].GoogleAdminEmail
]
}
Error:
Can't access attributes on a primitive-typed value (string).
@nickjmv This works with string indexes, e.g. parameters["GoogleAdminEmail"]
works fine
Community Note
Terraform CLI and Terraform AWS Provider Version
Terraform v0.13.5
Affected Resource(s)
aws_serverlessapplicationrepository_cloudformation_stack
Terraform Configuration Files
Expected Behavior
Running 2 times should not cause an error.
Actual Behavior
Doing a terraform apply the second time results in an error: Error: error creating Serverless Application Repository CloudFormation Stack (arn:aws:cloudformation:::stack//) change set: unexpected state 'FAILED', wanted target 'CREATE_COMPLETE'. last error: %!s()
Looking in cloudformation, the change set is Status: Failed, Status Reason: No updates are to be performed.
Steps to Reproduce
terraform apply
(my example is using Lambda at edge functions if this makes a difference)terraform apply
a second timeImportant Factoids
References