amplify-cli
amplify-cli copied to clipboard
Support for Mocking functions with layers and Docker
Note: If your feature-request is regarding the AWS Amplify Console service, please log it in the official AWS Amplify Console forum
Is your feature request related to a problem? Please describe. When I try to test layers locally I've seen errors which shows that it's not implemented yet. It would be nice if we could install yumda packages using Docker.
Unable to mock function. Mocking a function with layers is not supported. To test in the cloud: run "amplify push" to deploy your function to the cloud and then run "amplify console function" to test your function in the Lambda console.
Describe the solution you'd like
Use Docker to install yumda packages and test it locally, maybe with a flag --docker
Describe alternatives you've considered Test locally using common mocks
I have the same problem...
Same problem here...
Same, amplify should support testing all the features with Docker, like Sam does at least
Any updates on it ?
same problem i am facing while running this command amplify mock function storageTrigger
Unable to mock storageTrigger. Mocking a function with layers is not supported. To test in the cloud: run "amplify push" to deploy your function to the cloud and then run "amplify console function" to test your function in the Lambda console.
I wonder what's the challenge with enabling mocks for functions with layers? From what I saw, we just need to setup the correct NODE_PATH
to the layer modules during runtime in order to make require
work.
I've noticed this only seems to be a soft limitation of Amplify, since by temporarily removing the associated layer from the function's dependsOn
array within amplify-meta.json
, I'm still able to mock these functions as long as the assets for the layer are otherwise provided.
I've been working around this limitation using this method for a while now and haven't found any drawbacks of it as long as the dev env and build process are set up properly, so is there any chance this could be made toggleable with a switch on the mock command or a feature flag?
Any progress on the topic?
@mewtlu Thanks for sharing your solution.
Could please share some code examples? with all the things you tweaked.
Some more context of my case:
I use the Appsync graphql layer (const API = require('@aws-amplify/api').default;) inside a lambda function.
That lambda function is used to handle one route of the API Gateway.
@mewtlu Thanks for sharing your solution.
Could please share some code examples? with all the things you tweaked.
Some more context of my case:
I use the Appsync graphql layer (const API = require('@aws-amplify/api').default;) inside a lambda function.
That lambda function is used to handle one route of the API Gateway.
I'm not sure if there are any further issues related to the specifics of your situation, but to be able to mock any function that has a Lambda layer all that is required is manually editing your local amplify/backend/amplify-meta.json
file to remove the Lambda Layer from the dependsOn
array within that function's block in the Resource
object.
I run the following bash script using jq whilst in in amplify/backend/
to do this automatically for me:
cat amplify-meta.json | jq \". * { function: .function | map_values(if .dependsOn then del(.dependsOn[] | select(.resourceName == \\\"MyLambdaLayerName\\\")) else . end) }\" > amplify-meta.n.json
(replacing MyLambdaLayerName
with the name of your Lambda Layer)
Hope this helps.
@mewtlu how does your solution gets the related code stored in the lambda layer folders?
@mewtlu how does your solution gets the related code stored in the lambda layer folders?
If you're asking how we provide the code in the layer to the functions within the dev environment I simply use local npm dependencies, within my frontend application's package.json I have an npm dependency on the package within the monorepo which contains the code used for the Lambda Layer such as:
"@org/shared": "../lib/shared"
and the backend functions have a dependency on the same local package such as:
"@org/shared": "../../../../lib/shared"
As the Lambda layer contains TypeScript code/types we also use TS project references to support this which nicely links up in a similar manner using relative paths within the monorepo, then we simply have a deployment step that builds and copies the code from lib/shared
into amplify/backend/functions/MyLambdaLayerName/lib/nodejs
ready for Amplify to use for deployment.
@mewtlu So you manually remove these local dependencies before you run amplify push/publish?
Ah no, these changes are only ever made to the amplify-meta file which I believe should always be overwritten automatically before any deploys (with the built contents of the backend-config file).
This change is only made to affect the amplify mock
command which appears to begin with a local check on the amplify-meta.json to see if the function depends on any layers, meaning that if the specified change has been made this check will pass and we are able to mock the function, without actually affecting the function/layer in any way.
@mewtlu Thanks for sharing your solution. Could please share some code examples? with all the things you tweaked. Some more context of my case: I use the Appsync graphql layer (const API = require('@aws-amplify/api').default;) inside a lambda function. That lambda function is used to handle one route of the API Gateway.
I'm not sure if there are any further issues related to the specifics of your situation, but to be able to mock any function that has a Lambda layer all that is required is manually editing your local
amplify/backend/amplify-meta.json
file to remove the Lambda Layer from thedependsOn
array within that function's block in theResource
object.I run the following bash script using jq whilst in in
amplify/backend/
to do this automatically for me:cat amplify-meta.json | jq \". * { function: .function | map_values(if .dependsOn then del(.dependsOn[] | select(.resourceName == \\\"MyLambdaLayerName\\\")) else . end) }\" > amplify-meta.n.json
(replacingMyLambdaLayerName
with the name of your Lambda Layer)Hope this helps.
Thanks a lot @mewtlu . I'll give it a shot.
@mewtlu how does your solution gets the related code stored in the lambda layer folders?
If you're asking how we provide the code in the layer to the functions within the dev environment I simply use local npm dependencies, within my frontend application's package.json I have an npm dependency on the package within the monorepo which contains the code used for the Lambda Layer such as:
"@org/shared": "../lib/shared"
and the backend functions have a dependency on the same local package such as:"@org/shared": "../../../../lib/shared"
As the Lambda layer contains TypeScript code/types we also use TS project references to support this which nicely links up in a similar manner using relative paths within the monorepo, then we simply have a deployment step that builds and copies the code from
lib/shared
intoamplify/backend/functions/MyLambdaLayerName/lib/nodejs
ready for Amplify to use for deployment.
How do you handle the layer paths within the lambda function? Ex: /opt/folder/file.js ? Could you share your whole solution step by step?
Man... not being able to test locally is doing my head. I not only have to deploy my whole application in order to test, i often get an error because of the number of layers it get created
Name: LambdaLayerPermissionAwsAccounts533367446078faf35141Legacy155 (AWS::Lambda::LayerVersionPermission), Event Type: create, Reason: Resource handler returned message: "1 validation error detected: Value '533367446078faf35141' at 'principal' failed to satisfy constraint: Member must satisfy regular expression pattern: \d{12}|\*|arn:(aws[a-zA-Z-]*):iam::\d{12}:root (Service: AWSLambdaInternal; Status Code: 400; Error Code: ValidationException; Request ID: eef4dc1a-035b-4405-ad3b-4a7d4f3bf196; Proxy: null)" (RequestToken: 226e2302-7f1d-e1b4-e21b-f8a3b271113b, HandlerErrorCode: GeneralServiceException), IsCustomResource: false