Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Mocking functions with layers and Docker #4826

Open
ErickWendel opened this issue Jul 14, 2020 · 16 comments
Open

Support for Mocking functions with layers and Docker #4826

ErickWendel opened this issue Jul 14, 2020 · 16 comments
Labels
feature-request Request a new feature functions Issues tied to the functions category p3

Comments

@ErickWendel
Copy link

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

@UnleashedMind UnleashedMind added feature-request Request a new feature functions Issues tied to the functions category labels Jul 14, 2020
@abraira85
Copy link

I have the same problem...

@arturocanalda
Copy link

Same problem here...

@MontoyaAndres
Copy link

Same, amplify should support testing all the features with Docker, like Sam does at least

@nathanagez
Copy link

Any updates on it ?

@babaralishah
Copy link

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.

@ivadenis
Copy link

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.

@mewtlu
Copy link

mewtlu commented Jun 24, 2022

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?

@tb102122
Copy link
Contributor

Any progress on the topic?

@estebanmunchjones2019
Copy link

@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
Copy link

mewtlu commented Apr 14, 2023

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

@tb102122
Copy link
Contributor

@mewtlu how does your solution gets the related code stored in the lambda layer folders?

@mewtlu
Copy link

mewtlu commented Apr 15, 2023

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

@tb102122
Copy link
Contributor

@mewtlu So you manually remove these local dependencies before you run amplify push/publish?

@mewtlu
Copy link

mewtlu commented Apr 17, 2023

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.

@estebanmunchjones2019
Copy link

estebanmunchjones2019 commented Apr 18, 2023

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

Thanks a lot @mewtlu . I'll give it a shot.

@rafaelfaria
Copy link

rafaelfaria commented Mar 30, 2024

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request a new feature functions Issues tied to the functions category p3
Projects
None yet
Development

No branches or pull requests