amplify-category-api icon indicating copy to clipboard operation
amplify-category-api copied to clipboard

ConnectionStack has template error due to missing conditions

Open assemblethis opened this issue 2 years ago • 11 comments

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

  1. 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.

assemblethis avatar Dec 10 '22 08:12 assemblethis

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.

assemblethis avatar Dec 11 '22 18:12 assemblethis

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:

  1. s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/stacks/ConnectionStack.json
  2. s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/states/initial-stack/stacks/ConnectionStack.json
  3. s3/buckets/amplify-FAKENAME-dev-XXXXXX-deployment/amplify-appsync-files/{guid}/states/01/stacks/ConnectionStack.json
  4. 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.

assemblethis avatar Dec 13 '22 05:12 assemblethis

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.

assemblethis avatar Dec 23 '22 04:12 assemblethis

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

assemblethis avatar Dec 23 '22 04:12 assemblethis

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.

stokaace avatar Jan 11 '23 22:01 stokaace

/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.

assemblethis avatar Feb 05 '23 06:02 assemblethis

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.

assemblethis avatar Feb 05 '23 21:02 assemblethis

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.

hanuruh avatar Jul 31 '23 14:07 hanuruh

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.

brauliolledo avatar Apr 24 '24 16:04 brauliolledo

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
        }
      }
    },

kevinlam92 avatar Apr 24 '24 17:04 kevinlam92

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?

brauliolledo avatar Apr 25 '24 14:04 brauliolledo