serverless .yml environment variable issues - aws-lambda

I am on this page of a serverless with Lambdas and Dynamo DB exercise.
I am on the " Add a Create Note API" section and am having trouble with testing the API
the command:
serverless invoke local --function create --path mocks/create-event.json
produces this error
Serverless: DOTENV: Loading environment variables from .env:
Serverless: - tableName
Serverless: Bundling with Webpack...
error is : ResourceNotFoundException: Requested resource not found
at Request.extractError (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/protocol/json.js:51:27)
at Request.callListeners (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
at Request.emit (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
at callNextListener (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/sequential_executor.js:96:12)
at IncomingMessage.onEnd (/Users/dannybyrne/notes-app-api/node_modules/aws-sdk/lib/event_listeners.js:307:13)
at IncomingMessage.emit (events.js:215:7)
at IncomingMessage.EventEmitter.emit (domain.js:476:20)
at endReadableNT (_stream_readable.js:1183:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
message: 'Requested resource not found',
code: 'ResourceNotFoundException',
time: 2019-12-10T18:33:00.494Z,
requestId: '4D2O3VOI437AE9MTH1M4UPGDUVVV4KQNSO5AEMVJF66Q9ASUAAJG',
statusCode: 400,
retryable: false,
retryDelay: 28.999931507407407
}
{
"statusCode": 500,
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true
},
"body": "{\"status\":false}"
}
I have edited the .env file to have
tableName='notes'
though in the .yml file is says
# These environment variables are made available to our functions
# under process.env.
environment:
tableName: notes
I'm assuming this means that in the create.js file, under the params object
TableName: process.env.tableName,
In the instructions it says
" We read the name of our DynamoDB table from the environment variable using  process.env.tableName . We’ll be setting this in our  serverless.yml  below. We do this so we won’t have to hardcode it in every function."
Does this mean that I don't have to set it in the .env file that is included? when I rename this file to not be included in the build it also throws an error asking for it. When I define tableName in .env and set it to 'notes', as is defined in the .yml file and is the name of the dynamoDB table, it throws the above error.
I'm basically trying to figure out hoew .yml pull from .env (or not)

Yes if you define the variable under the provider it'll be available to all the functions.

Related

Heroku returns "Error: listen EADDRNOTAVAIL: address not available" on starting Strapi CMS

I am trying to deploy Strapi on Heroku
But it does not work. I get this log
2020-05-27T15:04:05.012958+00:00 app[web.1]: > strapi-oskogen-mongodb#0.1.0 start /app
2020-05-27T15:04:05.012959+00:00 app[web.1]: > node server.js
2020-05-27T15:04:05.012960+00:00 app[web.1]:
2020-05-27T15:04:08.188595+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'count' of module exports inside circular dependency
2020-05-27T15:04:08.188639+00:00 app[web.1]: (Use `node --trace-warnings ...` to show where the warning was created)
2020-05-27T15:04:08.189164+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'findOne' of module exports inside circular dependency
2020-05-27T15:04:08.189299+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'remove' of module exports inside circular dependency
2020-05-27T15:04:08.189381+00:00 app[web.1]: (node:23) Warning: Accessing non-existent property 'updateOne' of module exports inside circular dependency
2020-05-27T15:04:12.308848+00:00 app[web.1]: [2020-05-27T15:04:12.308Z] error Error: listen EADDRNOTAVAIL: address not available 52.54.48.43:31639
2020-05-27T15:04:12.308857+00:00 app[web.1]: at Server.setupListenHandle [as _listen2] (net.js:1296:21)
2020-05-27T15:04:12.308858+00:00 app[web.1]: at listenInCluster (net.js:1361:12)
2020-05-27T15:04:12.308859+00:00 app[web.1]: at GetAddrInfoReqWrap.doListen [as callback] (net.js:1498:7)
2020-05-27T15:04:12.308859+00:00 app[web.1]: at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:68:8)
2020-05-27T15:04:22.927720+00:00 heroku[web.1]: Stopping all processes with SIGTERM
I use MongoDB on Atlas. It works well on localhost both dev and prod environment.
My production files:
server.js
database.js
response.js
app settings
Where did I miss something?
Which is the value of process.env.HOST. For some reason different from 0.0.0.0 (just a shot in the dark - https://strapi.io/documentation/3.0.0-beta.x/migration-guide/migration-guide-beta.19-to-beta.19.4.html#listened-host-changed)
I had to change server.js file (port 443):
module.exports = ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 443),
admin: {
auth: {
secret: env('ADMIN_JWT_SECRET'),
},
},
});
My database.js file:
module.exports = ({ env }) => ({
defaultConnection: "default",
connections: {
default: {
connector: "mongoose",
settings: {
uri: env("DATABASE_URI"),
ssl: { rejectUnauthorized: false }
},
options: {
ssl: true,
authenticationDatabase: "",
useUnifiedTopology: true,
pool: {
min: 0,
max: 10,
idleTimeoutMillis: 30000,
createTimeoutMillis: 30000,
acquireTimeoutMillis: 30000
}
},
},
},
});
I hope it will help to somebody who has the same problem :-)
Not sure if it's what #Rochadsouza meant, but I got the same error and what finally solved the issue in my case was to set the host to 0.0.0.0. For some reasons, the host cannot be the app url, it needs to allow all hosts on Heroku. I was setting the host in server.js using env('HOST', '0.0.0.0') but had the HOST env var set to my app url on Heroku...
Hope it saves some time to others facing the same error.

Cannot find module 'handler' when running simple lambda deployed by serverless

I am trying to start learning serverless / lambda so I created a simple lambda and deployed it with serverless which worked.
However when I want to test the endpoint of the lampbda I get a 502 back. When I look in the logs it tells me that it can not find the module handler which does not make any sense...
here is the log:
{
"errorType": "Runtime.ImportModuleError",
"errorMessage": "Error: Cannot find module 'handler'\nRequire stack:\n-
/var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Runtime.ImportModuleError: Error: Cannot find module 'handler'",
"Require stack:",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
" at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
" at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
" at Object.<anonymous> (/var/runtime/index.js:43:30)",
" at Module._compile (internal/modules/cjs/loader.js:1158:30)",
" at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)",
" at Module.load (internal/modules/cjs/loader.js:1002:32)",
" at Function.Module._load (internal/modules/cjs/loader.js:901:14)",
" at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)",
" at internal/main/run_main_module.js:18:47"
]
}
This normally means that it can not find the method that is the starting point to execute.
For example on your serverless.yml you can have something like this
functions:
getUsers:
handler: userFile.handler
this would mean that it's required to have a userFile in the same folder of the serverless.yml with the method handler exported.
module.exports.hello = async event => {
return {
statusCode: 200,
body: JSON.stringify(
{
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event,
},
null,
2
),
};
};
Note that it does not need to be named handler function, just needs to have the same name defined on the serverless.yml
I ran into the same error when launching a lambda locally using AWS sam, with Webstorm.
Turns out a previous run had not correctly stopped and destroyed the docker container running the lambda. Stopping and removing said docker container fixed the problem for me.

Adding IoT rule with an error action through cloudformation yaml

I am trying to add an iot rule with error action using following cloudformation yaml file
extract from yaml:
DaIoTRule:
Type: AWS::IoT::TopicRule
Properties:
RuleName: sda
TopicRulePayload:
RuleDisabled: false
Sql: SELECT *, topic(2) AS source FROM 'topic/sensors/+'
Actions:
- Lambda:
FunctionArn: !GetAtt LambdaFunction.Arn
ErrorAction:
S3:
RoleArn: !GetAtt DAIoTRuleErrorActionIamRole.Arn
Bucket: iot-message-dump
Key: "errors/${topic()}/${timestamp()}"
But I keep getting this error:
{
"StackId": "arn:aws:cloudformation:us-east-1:961234632786:stack/wx-da-lambda/91423s00-4e97-11ea-aedd-0ee829hbc650",
"EventId": "DAIoTRule-CREATE_FAILED-2020-02-17T06:51:38.299Z",
"StackName": "da-lambda",
"LogicalResourceId": "DaIoTRule",
"PhysicalResourceId": "",
"ResourceType": "AWS::IoT::TopicRule",
"Timestamp": "2020-02-17T06:51:38.299Z",
"ResourceStatus": "CREATE_FAILED",
"ResourceStatusReason": "Encountered unsupported property bucket"
}
I created this yaml using https://docs.aws.amazon.com/iot/latest/developerguide/rule-error-handling.html as reference.
Can someone point me to what I am doing wrong ?
CloudFormation uses the BucketName property instead of Bucket for S3 actions (including error actions).
See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-topicrule-s3action.html#cfn-iot-topicrule-s3action-bucketname

IAM Cannot Access Launch Template

I am using the AWS Node SDK to try and use a launch template to launch an EC2 instance. In the web console for the same user I have access to the Launch Template ID, but in the Node API it tells me the Launch Template with ID does not exist:
version: aws-sdk#2.606.0
Screenshot in AWS Console
Screenshot in my config file
(I've blocked the last few characters for security but they are the same)
This is the Node
AWS = require('aws-sdk');
AWS.config.update({region: global.settings.aws.region});
let instanceParams = {
LaunchTemplate: {
LaunchTemplateId: global.settings.aws.ltId
},
InstanceType: 't2.micro',
MinCount: 1,
MaxCount: 1
};
let instancePromise = new AWS.EC2().runInstances(instanceParams).promise();
instancePromise.then(
function(data) {
console.log(data);
}).catch(
function(err) {
console.error(err, err.stack);
});
This is the error the API returns:
InvalidLaunchTemplateId.NotFound: The specified launch template, with template ID lt-03969d13638b5XXXX, does not exist.
at Request.extractError (/ApplicationPath/node_modules/aws-sdk/lib/services/ec2.js:50:35)
at Request.callListeners (/ApplicationPath/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
at Request.emit (/ApplicationPath/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/ApplicationPath/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/ApplicationPath/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/ApplicationPath/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /ApplicationPath/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request. (/ApplicationPath/node_modules/aws-sdk/lib/request.js:38:9)
at Request. (/ApplicationPath/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/ApplicationPath/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
at Request.emit (/ApplicationPath/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/ApplicationPath/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/ApplicationPath/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/ApplicationPath/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /ApplicationPath/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request. (/ApplicationPath/node_modules/aws-sdk/lib/request.js:38:9)
at Request. (/ApplicationPath/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/ApplicationPath/node_modules/aws-sdk/lib/sequential_executor.js:116:18)
at callNextListener (/ApplicationPath/node_modules/aws-sdk/lib/sequential_executor.js:96:12)
at IncomingMessage.onEnd (/ApplicationPath/node_modules/aws-sdk/lib/event_listeners.js:307:13)
at IncomingMessage.emit (events.js:214:15)
at IncomingMessage.EventEmitter.emit (domain.js:476:20) {
message: 'The specified launch template, with template ID lt-03969d13638b5XXXX, does not exist.',
code: 'InvalidLaunchTemplateId.NotFound',
time: 2020-01-22T15:29:18.641Z,
requestId: '16082702-49c0-4451-a3b7-570b930b5238',
statusCode: 400,
retryable: false,
retryDelay: 47.92654090836894
}
The IAM access includes both:
AmazonEC2FullAccess
AmazonEC2FullAccess
(The JSON are super long but I am happy to post those in here if needed)
My thought is that there is some permissioning error for the IAM but I can't determine what that might be. Thank you for the help and please let me know if there is any other clarity I can provide.
When you can see that a given AWS resource exists in the AWS console, but it is not returned by the awscli or SDK calls, (or vice-versa) then one of the following is likely the cause:
you have queried the wrong region
you have queried the wrong AWS account (your effective credentials are for a 2nd, different account)
you have mis-typed the resource name/id
your browser has cached results that no longer exist (refresh your browser)

serverless-offline basic example no routes listed or available

I'm following this basic example (https://medium.com/hackernoon/tdd-means-zen-along-with-serverless-means-nirvana-a39a76ee8e63) to setup serverless-offline for unit testing a serverless project.
Unfortunately, I can't get the initial run of serverless-offline to work correctly. After running "serverless offline start", the console output does not display a GET method and a request to localhost:3000 only returns "Cannot GET /".
Any ideas what I'm missing here? Thanks in advance.
My serverless.yml:
provider:
name: aws
runtime: nodejs10.x
functions:
hello:
handler: handler.hello
events:
- http:
path: ''
method: get
plugins:
- serverless-offline
- serverless-mocha-plugin
My package.json:
"name": "my-api",
"version": "1.0.0",
"description": "",
"main": "handler.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"mongodb": "^3.3.3"
},
"devDependencies": {
"serverless-mocha-plugin": "^1.11.0",
"serverless-offline": "^5.12.0"
}
}
My handler.js:
module.exports.hello = async event => {
return {
statusCode: 200,
body: JSON.stringify(
{
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event
},
null,
2
)
};
};
Console output:
$ sls offline start
Serverless: Load command interactiveCli
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command config:tabcompletion
Serverless: Load command config:tabcompletion:install
Serverless: Load command config:tabcompletion:uninstall
Serverless: Load command create
Serverless: Load command install
Serverless: Load command package
Serverless: Load command deploy
Serverless: Load command deploy:function
Serverless: Load command deploy:list
Serverless: Load command deploy:list:functions
Serverless: Load command invoke
Serverless: Load command invoke
Serverless: Load command invoke:local
Serverless: Load command info
Serverless: Load command logs
Serverless: Load command metrics
Serverless: Load command print
Serverless: Load command remove
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command slstats
Serverless: Load command plugin
Serverless: Load command plugin
Serverless: Load command plugin:install
Serverless: Load command plugin
Serverless: Load command plugin:uninstall
Serverless: Load command plugin
Serverless: Load command plugin:list
Serverless: Load command plugin
Serverless: Load command plugin:search
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command offline
Serverless: Load command offline:start
Serverless: Load command create
Serverless: Load command create:test
Serverless: Load command create:function
Serverless: Load command invoke
Serverless: Load command invoke:test
Serverless: Load command login
Serverless: Load command logout
Serverless: Load command generate-event
Serverless: Load command test
Serverless: Load command dashboard
Serverless: Invoke offline:start
Serverless: Starting Offline: dev/us-east-1.
[offline] options: { apiKey: 'XXXXXXXXXXXXXXXXXX',
cacheInvalidationRegex: /node_modules/,
corsAllowOrigin: [ '*' ],
corsAllowCredentials: true,
corsAllowHeaders: [ 'accept', 'content-type', 'x-api-key', 'authorization' ],
corsExposedHeaders: [ 'WWW-Authenticate', 'Server-Authorization' ],
`
disableCookieValidation: false,
enforceSecureCookies: false,
exec: '',
hideStackTraces: false,
host: 'localhost',
httpsProtocol: '',
location: '.',
noAuth: false,
noEnvironment: false,
noTimeout: false,
port: 3000,
prefix: '/',
preserveTrailingSlash: false,
printOutput: false,
providedRuntime: '',
showDuration: false,
stage: 'dev',
region: 'us-east-1',
resourceRoutes: false,
skipCacheInvalidation: false,
useSeparateProcesses: false,
websocketPort: 3001,
corsConfig:
{ credentials: true,
exposedHeaders: [ 'WWW-Authenticate', 'Server-Authorization' ],
headers: [ 'accept', 'content-type', 'x-api-key', 'authorization' ],
origin: [ '*' ] } }
[offline] funOptions {
"funName": "hello",
"funTimeout": 30000,
"handlerName": "hello",
"handlerPath": "/Users/rocky/Documents/Projects/garmin/sls-troubleshooting/my-api/ha
ndler",
"runtime": "nodejs10.x"
}
[offline] hello runtime nodejs10.x
Serverless: Routes for hello:
[offline] Response Content-Type application/json
Serverless: POST /{apiVersion}/functions/my-api-dev-hello/invocations
Serverless: Offline [HTTP] listening on http://localhost:3000
Serverless: Enter "rp" to replay the last request
It turns out that this was an indenting issue in my serverless.yml. The example blog did not indent path, method, or cors following -http. Thank you to https://stackoverflow.com/a/58226113/296047 for pointing me in the right direction.
Side note, after restarting my computer and trying this blog example from scratch, I also received the error message:
{"statusCode":404,"error":"Serverless-offline: route not found.","currentRoute":"get - /","existingRoutes":["post - /{apiVersion}/functions/my-api-prod-hello/invocations"]}
Hopefully this helps someone else who is also going through the day-long troubleshooting I just went through.

Resources