I'm working on a sample AWS project that creates two lambda functions. These functions share common code from node_modules which has been placed in a separate layer (specifically AWS::Lambda::LayerVersion, not AWS::Serverless::LayerVersion). I can deploy this code and it works correctly when I test the deployed version.
However, when I try to test the code locally using sam invoke local, the common code is not found. I get this error (I'm trying to use the npm package "axios"):
{"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'axios'\nRequire stack:\n- /var/task/get-timezone.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js"}
This is my template.yaml:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS Sample
Globals:
Function:
Timeout: 30
Resources:
SampleCommonLayer:
Type: AWS::Lambda::LayerVersion
Properties:
CompatibleRuntimes:
- nodejs12.x
Content: nodejs.zip
Description: Sample Common LayerVersion
LayerName: SampleCommonLayer
GetTimezoneFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: dist/get-timezone
Handler: get-timezone.getTimezone
Runtime: nodejs12.x
Layers:
- !Ref SampleCommonLayer
Events:
GetTimezone:
Type: Api
Properties:
Path: /get-timezone
Method: get
ReverseFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: dist/reverse
Handler: reverse.reverse
Runtime: nodejs12.x
Layers:
- !Ref SampleCommonLayer
Events:
Reverse:
Type: Api
Properties:
Path: /reverse
Method: get
Outputs:
GetTimezoneApi:
Description: "API Gateway endpoint URL for Prod stage for getTimezone function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/get-timezone/"
GetTimezoneFunction:
Description: "getTimezone Lambda Function ARN"
Value: !GetAtt GetTimezoneFunction.Arn
GetTimezoneFunctionIamRole:
Description: "Implicit IAM Role created for getTimezone function"
Value: !GetAtt GetTimezoneFunctionRole.Arn
ReverseApi:
Description: "API Gateway endpoint URL for Prod stage for reverse function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/reverse/"
ReverseFunction:
Description: "reverse Lambda Function ARN"
Value: !GetAtt ReverseFunction.Arn
ReverseFunctionIamRole:
Description: "Implicit IAM Role created for reverse function"
Value: !GetAtt ReverseFunctionRole.Arn
I'm invoking the GetTimezone function like this:
sam local invoke --layer-cache-basedir layer-cache --force-image-build \"GetTimezoneFunction\" --event events/event-timezone.json -d 5858
Nothing ever gets copied into the layer-cache directory, and I'm sure that's part of the problem, but I can't figure out how I'd fix that.
I've searched for answers to this problem, but so far I've only found unanswered questions, or answers that don't match my particular situation.
Most of the somewhat-related questions involve AWS::Serverless::LayerVersion, not AWS::Lambda::LayerVersion. I've tried using Serverless instead, but that hasn't helped.
UPDATE:
If I change...
Layers:
- !Ref SampleCommonLayer
...to...
Layers:
- arn:aws:lambda:us-east-2:xxxxxxxxxxxx:layer:SampleCommonLayer:y
...using an already-deployed layer (where xxxxxxxxxxxx and y are a specific ID and version) then sam local invoke works. But I don't want to use something I have to deploy first, I want to use the latest local not-yet-deployed code.
This is known issue: https://github.com/awslabs/aws-sam-cli/issues/947
Currently the "workaround" is to use the directory of the layer instead of a zip file.
Related
I have a reusable workflow (i.e. triggered by the workflow_call event)
I also have the following input defined in it:
do_something:
description: whether to do something
required: true
type: boolean
default: false
I use the github actions script to invoke a script from a separate file as instructed here, passing the core package as input
- name: checkout the project
uses: actions/checkout#v2
- uses: actions/github-script#v6
id: set-images
with:
script: |
const script = require('./.github/workflows/myscript.js')
console.log(script({core}))
Here is myscript.js
module.exports = ({core}) => {
console.log(core.getBooleanInput['do_something'])
return 0
}
This comes from the documentation of core package found here.
However the specific input seems undefined, here is what gets printed
undefined
0
Why is that?
I would like to take a param from a result of an external JS function but I retrieve this error:
Cannot resolve serverless.yml: Variables resolution errored with:
- Cannot resolve variable at "resources.Resources.FileBucket.Properties.BucketName": Value not found at "file" source
This is my (a piece) serverless file:
service: backend-uploader
frameworkVersion: '3'
variablesResolutionMode: 20210326
provider:
name: aws
runtime: nodejs16.x
region: eu-west-1
resources:
Resources:
FileBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: ${file(./unique-bucket-name.cjs):bucketName}
This is my file unique-bucket-name.cjs in the same directory:
module.export = async function () {
return { bucketName: 'something' }
}
I have tried using self and importing the file as custom but the error still.
I have tried to use a Json with the same response and it works.
Why my JS file can't be taken from serverless?
Thanks.
Technically there's no much difference between using a JSON file to store the variables and a cjs. Looks like internally Serverless has some logic to parse the files and fetch the values
Serverless documentation points towards using a JSON file:
${file(./config.${opt:stage, 'dev'}.json):CREDS}
But, I've also seen some examples of people referencing to YML files instead.
I'm quite new to using Gatsby and for this reason I wanted to start using it by following the official tutorial. Everything went well until I came across the 4th part of it : https://www.gatsbyjs.com/docs/tutorial/part-4/#task-use-graphiql-to-build-the-query-1
When I update my gatsby-config.js file with the gatsby-source-filesystem configuration, I can't run my website locally.
When running the gatsby develop command in my terminal, I have the following error when trying to build schema :
gatsby develop
success compile gatsby files - 1.288s
success load gatsby config - 0.013s
success load plugins - 0.303s
success onPreInit - 0.004s
success initialize cache - 0.074s
success copy gatsby files - 0.049s
success Compiling Gatsby Functions - 0.080s
success onPreBootstrap - 0.087s
success createSchemaCustomization - 0.002s
success Checking for changed pages - 0.002s
success source and transform nodes - 0.089s
ERROR
Missing onError handler for invocation 'building-schema', error was 'Error: TypeError[File.publicURL]: Cannot convert to OutputType the following value: Object({ type: String, args: Object({ }), description: "Copy file to static directory and return public url to it", resolve: [function resolve] })'. Stacktrace was 'Error: TypeError[File.publicURL]: Cannot convert to OutputType the following value: Object({ type: String, args: Object({ }), description: "Copy file to static directory and return public url to it", resolve: [function resolve] })
at TypeMapper.convertOutputFieldConfig (/Users/nicolas/my-gatsby-site/node_m odules/graphql-compose/src/TypeMapper.ts:419:13)
at ObjectTypeComposer.setField (/Users/nicolas/my-gatsby-site/node_modules/g raphql-compose/src/ObjectTypeComposer.ts:445:40)
at /Users/nicolas/my-gatsby-site/node_modules/graphql-compose/src/ObjectType Composer.ts:479:14
at Array.forEach (<anonymous>)
at ObjectTypeComposer.addNestedFields (/Users/nicolas/my-gatsby-site/node_mo dules/graphql-compose/src/ObjectTypeComposer.ts:468:28)
at forEach (/Users/nicolas/my-gatsby-site/node_modules/gatsby/src/schema/schema.js:764:39)
at Array.forEach (<anonymous>)
at /Users/nicolas/my-gatsby-site/node_modules/gatsby/src/schema/schema.js:764:18
at async Promise.all (index 54)
at updateSchemaComposer (/Users/nicolas/my-gatsby-site/node_modules/gatsby/src/schema/schema.js:168:3)
at buildSchema (/Users/nicolas/my-gatsby-site/node_modules/gatsby/src/schema/schema.js:71:3)
at build (/Users/nicolas/my-gatsby-site/node_modules/gatsby/src/schema/index.js:112:18)
at buildSchema (/Users/nicolas/my-gatsby-site/node_modules/gatsby/src/servic es/build-schema.ts:19:3)'
⠸ building schema
Then the building schema command is running forever and my site can't launch.
I know the issue is when adding gatsby-source-filesystem into the gatsby-config.js file because when I delete it, I can run gatsby develop without any issue.
Here is my gatsby-config.js file, nearly identical to the one in the tutorial (I just changed the blog title) :
module.exports = {
siteMetadata: {
title: `Arckablog`,
siteUrl: `https://www.yourdomain.tld`,
},
plugins: [
"gatsby-plugin-image",
"gatsby-plugin-sharp",
{
resolve: "gatsby-source-filesystem",
options: {
name: `blog`,
path: `${__dirname}/blog`,
}
},
],
}
I have seen a similar question on stackoverflow here : Error building schema with gatsby-source-filesystem config (following official tutorial) and I tried updating both my Gatsby version and the gatsby-source-filesystem version but none of it worked out for me.
Can you maybe advise me please ?
Thank you for your help !
Nicolas
I encountered same problem.
I was running
npm install gatsby-source-filesystem
from different folder. Then I changed my current folder to project directory and ran npm install gatsby-source-filesystem everything worked fine
When deploying lambdas with serverless, the following error occurs:
The CloudFormation template is invalid: Template format error: Output ServerlessDeploymentBucketName is malformed. The Name field of every Export member must be specified and consist only of alphanumeric characters, colons, or hyphens.
I don't understand what the problem is.
Serverless config file:
service: lambdas-${opt:region}
frameworkVersion: '2'
provider:
name: aws
runtime: nodejs12.x
memorySize: 512
timeout: 10
lambdaHashingVersion: 20201221
region: ${opt:region}
stackName: lambdas-${opt:region}
logRetentionInDays: 14
deploymentBucket:
name: lambdas-${opt:region}
plugins:
- serverless-deployment-bucket
functions:
function1:
handler: function1/index.handler
name: function1-${opt:stage}
description: This function should call specific API on Backend server
events:
- schedule: cron(0 0 * * ? *)
environment:
ENV: ${opt:stage}
function2:
handler: function2/index.handler
name: function2-${opt:stage}
description: Function should be triggered by invocation from backend.
environment:
ENV: ${opt:stage}
I ran into this same problem.
In the serverless.yml I changed service that I had it as lambda_function and put it as lambdaFunction
The error was solved and it deployed correctly.
Most likely your stage name contains an illegal character. Serverless auto-generates a name for your s3 bucket based on your stage name. If you look at the generated template file you will see the full export, which will look something like the following:
"ServerlessDeploymentBucketName": {
"Value": "api-deployment",
"Export": {
"Name": "sls-api_stage-ServerlessDeploymentBucketName"
}
}
The way around this (assuming you don't want to change your stage name) is to explicitly set the output by adding something like this to your serverless config (in this case the illegal character was the underscore)
resources: {
Outputs: {
ServerlessDeploymentBucketName: {
Export: {
Name: `sls-${stageKey.replace('api_', 'api-')}-ServerlessDeploymentBucketName`
}
}
}
}
Unfortunately this has to be done for every export... It is a better option to update your stage name to not include illegal characters
Consider a piece of serverless code:
functions:
MyFunc:
handler: index.handler
name: "my_name"
runtime: nodejs12.x
memorySize: 512
timeout: 30
inlineCode: |
exports.handler = function(event, context) {
console.log("ok");
};
description: description
This leads to pacakge everything in source folder. I can not disable it. Event if I add:
package:
artifact: dummy.zip
Deploy failed because dummy.zip is empty file. But why I need a zip file when specified inlineCode? Is there a way to disable packaging and deploy nodejs function with inlineCode parameter only?
The workaround is to define lambda function deginition as normal cloudformation resource like that:
resources:
Resources:
MyFunc:
Type: AWS::Lambda::Function
Properties:
FunctionName: "my_name"
Handler: index.handler
Runtime: nodejs10.x
Role: !GetAtt LambdaRole.Arn # do not forget to define role by hand :(
Code:
ZipFile: |
exports.handler = function(event, context, callback) {
console.log(event);
const response = {
statusCode: 200,
body: JSON.stringify('Hello Node')
};
callback(null, response);
};
The concept of an inlineCode parameter is supported by AWS::Serverless::Function, but not serverless-framework. The YAML you pasted is not a 1:1 mapping to the AWS::Serverless::Function, it's specific to sls itself.
Store your code in files/directories until the sls team adds support for inlineCode. I didn't see any feature requests for it. I'm sure they'd be glad to get one from you.