amplify-category-api
amplify-category-api copied to clipboard
ConnectionStack has template error due to missing conditions
How did you install the Amplify CLI?
npm
If applicable, what version of Node.js are you using?
No response
Amplify CLI Version
10.5.2
What operating system are you using?
Linux (Fedora)
Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.
No manual changes made
Describe the bug
I am using the flutter amplify_flutter packages that are in developer preview: https://pub.dev/packages/amplify_flutter/versions/1.0.0-next.2
When I run amplify push the deployment fails. The issue is the ConnectionStack:
The following resource(s) failed to create: [ConnectionStack].
Template error: unresolved condition dependency HasEnvironmentParameter in Fn::If
When I look inside ConnectionStack.json I notice it's missing conditions. I believe the following would resolve the error:
"Conditions": {
"HasEnvironmentParameter": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "referencetotransformerrootstackenvXXXXXXRef"
},
"NONE"
]
}
]
},
I've tried adding the condition to ConnectionStack.json manually but it gets wiped out whenever I run amplify push.
Amplify push worked fine until I modified my schema.graphql with the following to connect two models:
comments: [Comment] @hasMany
The only thing unusual about my setup is that I configured amplify with amplify import auth but then added the rest of the resources from amplify, e.g. amplify add api
Let me know if you need more information!
Expected behavior
amplify pushes the stack ConnectionStack to AWS and graphql works.
Reproduction steps
- amplify push
Project Identifier
No response
Log output
# Put your logs below this line
Additional information
No response
Before submitting, please confirm:
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
- [X] I have removed any sensitive information from my code snippets and submission.
I've fixed it with a workaround!!
I ended up adding the missing json Conditions block to my S3 amplify deployment bucket in the cloud right after it got updated by amplify push so that the custom modified cloudformation template wouldn't get wiped out (this is what kept happening if I modified the file locally):
File s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/stacks/ConnectionStack.json
"Conditions": {
"HasEnvironmentParameter": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "referencetotransformerrootstackenvXXXXXXRef"
},
"NONE"
]
}
]
}
}
}
EOF
But the error remains if you don't use my workaround.
With each new iteration of amplify push, it gets more complicated to go through all the ConnectionStack.json template files and repair them. My current workaround is to do an initial amplify push that fails due to the missing Conditions block. Then I download each ConnectionStack.json template file and repair each locally by adding the Conditions block:
- s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/stacks/ConnectionStack.json
- s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/states/initial-stack/stacks/ConnectionStack.json
- s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/states/01/stacks/ConnectionStack.json
- s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/states/02/stacks/ConnectionStack.json
After that I delete the deployment-state.json file in the S3 bucket so that the next amplish push doesn't show the error ["Index: 0 State: {"deploy":"waitingForDeployment"} Message: Resource is not in the state stackUpdateComplete"]
Now I run amplify push again. It's a race against the clock to update all 4 versions of the ConnectionStack.json template in the S3 bucket before the cloudformation stack jobs run and use those templates.
This still works.
My schema.graphql is getting increasingly complex but the issue with ConnectionStack persists and the workaround continues to be to simply have a modified ConnectionStack.json prepared and to upload it to the S3 appsync deployment bucket as a replacement as soon as amplify push has uploaded the templates for cloudformation. Just as the first time, all I have to do is add the following at the very end of the ConnectionStack.json:
"Conditions": {
"HasEnvironmentParameter": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "referencetotransformerrootstackenvXXXXXXRef"
},
"NONE"
]
}
]
}
}
}
EOF
I've also described a more complex workaround where I had to modify multiple ConnectionStack.json files, but I haven't had to do that again recently.
Just realized I omitted that I am using the amplify_flutter packages that are in developer preview: https://pub.dev/packages/amplify_flutter/versions/1.0.0-next.2
I fixed this issue after a bunch of trial and error. In my case, the issue seemed to appear when I used the combo of 1) a @hasMany relationship in my schema (like the Blog/Post/Comment example), 2) Use of DataStore with conflict detection 3) a custom Lambda for resolution conflicts. In this scenario the deployments always resulted in ConnectionStack errors and were rolled back.
Reading about the issue here:
https://github.com/aws-amplify/amplify-category-api/issues/628
inspired me to look into the file at amplify/backend/api/<apiName>/cli-inputs.json
which looked like this
"conflictResolution": {
"defaultResolutionStrategy": {
"type": "LAMBDA",
"resolver": {
"type": "EXISTING",
"name": "<functionName>-${env}"
}
}
}
My solution was to add the ARN address to this section and remove the ${env}
part of the function name.
{
...,
"conflictResolution": {
"defaultResolutionStrategy": {
"type": "LAMBDA",
"resolver": {
"type": "EXISTING",
"name": "<functionName>",
"arn": "arn:aws:lambda:<region>:<accountID>:function:<functionName>"
}
}
}
}
}
Now deployments work, yet I still have no idea why adding the ARN was the solution and why the CLI doesn't handle this properly.
/cli-inputs.json
So far, your solution seems to work, though I kept the -${env} in the name and even added it into the arn:
"conflictResolution": {
"defaultResolutionStrategy": {
"type": "LAMBDA",
"resolver": {
"type": "EXISTING",
"name": "<functionName>-${env}",
"arn": "arn:aws:lambda:<region>:<accountID>:function:<functionName>-${env}"
}
}
},
Note: The -${env} will be replaced by the cli, but the rest needs to be pulled from the lambda function, so filling in <region>, <accountId>, and <functionName>.
Nice detective work! If this issue comes back, I'll update here.
Actually, not sure if I've just not managed to trigger the issue I had before with subsequent deployments, since when I took a look at ConnectionStack.json the missing condition HasEnvironmentParameter was not there.
The solution gave me the following issue when a conflict happens:
DataStore {"cause": {"data": null, "errorInfo": null, "errorType": "ConflictError", "locations": [[Object]], "message": "1 validation error detected: Value "arn:aws:lambda:region:accountID:function:functionName-${env}" at 'functionName' failed to satisfy constraint: Member must satisfy regular expression pattern: (arn:(aws[a-zA-Z-]*)?:lambda:)?([a-z]{2}((-gov)|(-iso(b?)))?-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-\.]+)(:(\$LATEST|[a-zA-Z0-9-]+))?
I assume it's not replacing the -${env} correctly.
Any updates for this? This is still an issue when trying to set up custom lambda conflict resolution for a model with these relational appsync directives.
Any updates for this? This is still an issue when trying to set up custom lambda conflict resolution for a model with these relational appsync directives.
For custom lambda conflict resolution specificaly there was an issue where the ${env} wasn't being replaced as others have noticed. My stack works properly if I just write out the actual env in the lambda name as opposed to only your lambda name.
Inside your /backend/api/<name_of_your_api>/cli-inputs.json
:
"conflictResolution": {
"defaultResolutionStrategy": {
"type": "LAMBDA",
"resolver": {
"type": "EXISTING",
"name": "syncConflictResolution-staging", // explicitly write out the whole name-${env} here
"arn": "arn:aws:lambda:<region>:<account>:function:syncConflictResolution-staging" // same here
}
}
},
Thanks for your suggestion, @kevinlam92. But wouldn't that hardcode the environment name though? We have multiple environments matching multiple branches so I would think we need the ${env}
interpolation, right?