Trying to test a basic lambda locally that runs fine in AWS but I keep getting
No response from invoke container for MyLambdaXXXXXXXX
'tsc' and 'synth' run fine and I get a proper cdk.out
The invoke command is
sam local invoke --region us-east-1 --env-vars .env.json -t ./cdk.out/my-project.template.json -e events/example.event.json MyLambdaXXXXXXXX
There is no api or anything docker related that I find in similar questions like the few listed below.
No response from invoke container when running sam local
No response from invoke container for FunctionName
https://github.com/aws/aws-sam-cli/issues/2837
The only output I see is this (no logs from even the first line of the lambda)
Invoking index.execute (nodejs14.x)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs14.x:rapid-1.46.0-x86_64.
Mounting /path-to-my-project/my-project/cdk.out/asset.aaaaa9999999cd5a9f38e9c4e503cc9c9bdf8ccdc8f9999991b12b6161e99999 as /var/task:ro,delegated inside runtime container
No response from invoke container for MyLambdaXXXXXXXX
Process finished with exit code 0
If it matters my handler structure for my lambda is async
export const execute = async (sqsEvent: SQSEvent): Promise<PutEventsCommandOutput> => {
await someAsyncStuffWithDocumentDB()
}
And I'm using NodejsFunction cdk with bundling like this
bundling: {
minify: true,
sourceMap: true,
externalModules: ['aws-lambda', 'aws-sdk'],
loader: { '.pem': 'file' }, // cert for DocumentDB
},
I came across similar issue and solved it by increasing 'Timeout' from 3 to 10 in [template.yaml] file.
When you import(or require) a number of npm packages, the loading time can be pretty long, maybe 3 secs are not enough. Just my guess
Related
AWS CDK provides great features for developers. Using CDK deveolper can manage not only total infrastructure but also security, codepipeline, ...
However I recently struggling something. I used to debug lambda using SAM for local debugging. I know how to set up CDK environment, and debug CDK application itself. But I can't figure out how to debug lambda application inside CDK.
Can anyone help me?
As of 4/29/2021, there's an additional option for debugging CDK apps via SAM. It's in preview but this blog post covers it : https://aws.amazon.com/blogs/compute/better-together-aws-sam-and-aws-cdk/.
Basically, install the AWS CLI and AWS CDK. The install the SAM CLI - beta, available here : https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk-getting-started.html.
Then you can run command's like:
sam-beta-cdk build sam-beta-cdk local invoke sam-beta-cdk local invoke start-api and even emulate the Lambda service with sam-beta-cdk local start-lambda
You can use SAM and CDK together as described here. In particular:
Run your AWS CDK app and create a AWS CloudFormation template
cdk synth --no-staging > template.yaml
Find the logical ID for your
Lambda function in template.yaml. It will look like
MyFunction12345678, where 12345678 represents an 8-character unique
ID that the AWS CDK generates for all resources. The line right
after it should look like: Type: AWS::Lambda::Function
Run the function by executing:
sam local invoke MyFunction12345678 --no-event
if you are using VSCode, you can set up a launch action to run the current file in node to test it locally. All you need to do is hit F5 on the file you want to test.
You will need to add the following at the end of your handler files so that when executed in node the handler gets executed:
if (process.env.NODE_ENV === "development" && process.argv.includes(__filename)) {
// Exercise the Lambda handler with a mock API Gateway event object.
handler(({
pathParameters: {
param1: "test",
param2: "code",
},
} as unknown) as APIGatewayProxyEvent)
.then((response) => {
console.log(JSON.stringify(response, null, 2));
return response;
})
.catch((err: any) => console.error(err));
}
Add this to your launch configurations in your .vscode/launch.json:
"configurations": [
{
"name": "Current TS File",
"type": "node",
"request": "launch",
"args": ["${relativeFile}", "-p", "${workspaceFolder}/tsconfig.json"],
"runtimeArgs": ["-r", "ts-node/register", "-r", "tsconfig-paths/register", "--nolazy"],
"cwd": "${workspaceRoot}",
"internalConsoleOptions": "openOnSessionStart",
"envFile": "${workspaceFolder}/.env",
"smartStep": true,
"skipFiles": ["<node_internals>/**", "node_modules/**"]
},
The ts-node and tsconfig-paths are only needed if using Typescript. You must add those with npm i -D ts-node tsconfig-paths if you dont already have them.
Before you run any of the sam local commands with a AWS CDK application, you must run cdk synth.
When running sam local invoke you need the function construct identifier that you want to invoke, and the path to your synthesized AWS CloudFormation template. If your application uses nested stacks, to resolve naming conflicts, you also need the stack name where the function is defined.
# Invoke the function FUNCTION_IDENTIFIER declared in the stack STACK_NAME
sam local invoke [OPTIONS] [STACK_NAME/FUNCTION_IDENTIFIER]
# Start all APIs declared in the AWS CDK application
sam local start-api -t ./cdk.out/CdkSamExampleStack.template.json [OPTIONS]
# Start a local endpoint that emulates AWS Lambda
sam local start-lambda -t ./cdk.out/CdkSamExampleStack.template.json [OPTIONS]
I followed the following tutorial to create a Lambda deploy pipeline using CDK. When I try to keep everything in the same account it works well.
https://docs.aws.amazon.com/cdk/latest/guide/codepipeline_example.html
But my scenario is slightly different from the example because it involves two AWS accounts instead one. I maintain application source code and pipeline
in the OPS account and this pipeline will deploy the Lambda application to the UAT account.
OPS Account (12345678) - CodeCommit repo & CodePipeline
UAT Account (87654321) - Lambda application
As per the aws following aws documentation (Cross-account actions section) I made the following changes to source code.
https://docs.aws.amazon.com/cdk/api/latest/docs/aws-codepipeline-actions-readme.html
Lambda stack expose deploy action role as follows
export class LambdaStack extends cdk.Stack {
public readonly deployActionRole: iam.Role;
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
...
this.deployActionRole = new iam.Role(this, 'ActionRole', {
assumedBy: new iam.AccountPrincipal('12345678'), //pipeline account
// the role has to have a physical name set
roleName: 'DeployActionRole',
});
}
}
In the pipeline stack,
new codePipeline.Pipeline(this, 'MicroServicePipeline', {
pipelineName: 'MicroServicePipeline',
stages: [
{
stageName: 'Deploy',
actions: [
new codePipelineAction.CloudFormationCreateUpdateStackAction({
role: props.deployActionRole,
....
})
]
}
]
});
Following is how I initiate stacks
const app = new cdk.App();
const opsEnv: cdk.Environment = {account: '12345678', region: 'ap-southeast-2'};
const uatEnv: cdk.Environment = {account: '87654321', region: 'ap-southeast-2'};
const lambdaStack = new LambdaStack(app, 'LambdaStack', {env: uatEnv});
const lambdaCode = lambdaStack.lambdaCode;
const deployActionRole = lambdaStack.deployActionRole;
new MicroServicePipelineStack(app, 'MicroServicePipelineStack', {
env: opsEnv,
stackName: 'MicroServicePipelineStack',
lambdaCode,
deployActionRole
});
app.synth();
AWS credentials profiles looks liks
[profile uatadmin]
role_arn=arn:aws:iam::87654321:role/PigletUatAdminRole
source_profile=opsadmin
region=ap-southeast-2
when I run cdk diff or deploy I get an error saying,
➜ infra git:(master) ✗ cdk diff MicroServicePipelineStack --profile uatadmin
Including dependency stacks: LambdaStack
Stack LambdaStack
Need to perform AWS calls for account 87654321, but no credentials have been configured.
What have I done wrong here? Is it my CDK code or is it the way I have configured my AWS profile?
Thanks,
Kasun
The problem is with your AWS CLI configuration. You cannot use the CDK CLI natively to deploy resources in two separate accounts with one CLI command. There is a recent blog post on how to tell CDK which credentials to use, depending on the stack environment parameter:
https://aws.amazon.com/blogs/devops/cdk-credential-plugin/
The way we use it is to deploy stacks into separate accounts with multiple CLI commands specifying the required profile. All parameters that need to be exchanged (such as the location of your lambdaCode) is passed via e.g. environment variables.
Just try to use using the environment variables:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
Or
~/.aws/credentials
[default]
aws_access_key_id=****
aws_secret_access_key=****
~/.aws/config
[default]
region=us-west-2
output=json
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html
It works for me.
I'm using cdk version 1.57.0
The issue is in the fact that you have resources that exist in multiple accounts and hence there are different credentials required to create those resources. However, CDK does not understand natively how to get credentials for those different accounts or when to swap between the different credentials. One way to fix this is to use cdk-assume-role-credential-plugin, which will allow you to use a single CDK deploy command to deploy to many different accounts.
I wrote a detailed tutorial here: https://johntipper.org/aws-cdk-cross-account-deployments-with-cdk-pipelines-and-cdk-assume-role-credential-plugin/
Is there a way to save & test an AWS Lambda function with a single click? Ideally, I'd like to be able to test unsaved changes but I don't see an option for this. I'm just finding it tedious to save each time I want to test out changes.
If you are creating your Lambda function via the AWS Lambda console, then you will need to Save the function before running Test. This is because the function runs on a Lambda container, not in the console.
Alternatively, you can run Lambda Local to test functions on your own computer rather than on the Lambda service. Once the code works, you can upload it to AWS.
See: Run AWS Lambda Functions Locally on a Windows Machine - DZone Cloud
How about using Endly automation runner with aws/lambda service
In this case, you would define your deployment workflow and just run it with
endly deploy
Where deploy.yaml defines automation workflow
init:
functionRole: lambda-helloworld-executor
functionName: HelloWorld
codeZip: /tmp/hello/main.zip
privilegePolicy: privilege-policy.json
pipeline:
deploy:
action: aws/lambda:deploy
credentials: aws
functionname: $functionName
runtime: go1.x
handler: helloworld
code:
zipfile: $LoadBinary(${codeZip})
rolename: lambda-helloworld-executor
define:
- policyname: my-bucket-role
policydocument: $Cat('${privilegePolicy}')
attach:
- policyarn: arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Finally, you might be in end to end testing automation here
I am trying to develop a google assistant app with actions sdk. I found lot of samples online which all are using google's firebase cloud functions to deploy.
From this link(https://actions-on-google.github.io/actions-on-google-nodejs/) I also found that it is possible to deploy the actions sdk functions into aws lambda.
But unfortunately I did not find any sample which is showing how to write and deploy actions sdk into aws lambda.
Can anybody help me to write an application which is similar to the one shown here(https://github.com/actions-on-google/actionssdk-say-number-nodejs) and deploy it into aws lambda?
I tried the following to do the same. But it did not worked.
Created a folder and initialized it with "npm init".
Added index.js file.
Then ran the command "npm install actions-on-google". It appeared in the package.json file.
Created a zip folder of the entire source inside that folder I created.
Created a aws lambda function and uploaded the zip folder and set the "Handler" of the lambda function as "index.fulfillment".
Created an api gateway and linked it to the lambda function and deployed it.
Then took the url and editted the "actions.json" file and ran the gactions command.
Then when I started testing the app in the actions console using the simulator I am getting the error "UnparseableJsonResponse API Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: "error_message: Cannot find field"
Here is the code inside index.js file
'use strict';
const {actionssdk, SimpleResponse} = require('actions-on-google');
const app = actionssdk({debug: true});
app.intent('actions.intent.MAIN', (conv) => {
conv.ask("welcome");
});
app.intent('actions.intent.TEXT', async (conv, input) => {
conv.ask('You said ' + input);
});
exports.fulfillment = app
Here is the cloud watch logs from aws
2018-11-10T08:35:46.715Z 9dbb17f8-e4c3-11e8-bce3-730a5244a300
{
"errorMessage": "Cannot convert undefined or null to object",
"errorType": "TypeError",
"stackTrace": [
"Function.keys (<anonymous>)",
"Lambda.<anonymous> (/var/task/node_modules/actions-on-google/dist/framework/lambda.js:36:36)",
"Generator.next (<anonymous>)",
"/var/task/node_modules/actions-on-google/dist/framework/lambda.js:22:71",
"new Promise (<anonymous>)",
"__awaiter (/var/task/node_modules/actions-on-google/dist/framework/lambda.js:18:12)",
"/var/task/node_modules/actions-on-google/dist/framework/lambda.js:30:46",
"omni (/var/task/node_modules/actions-on-google/dist/assistant.js:44:53)"
]
}
The code changes to host it on AWS are fairly straightforward. Instead of importing the firebase-functions library and using it, you just need to establish the lambda endpoint with the dialogflow app itself. So the code might look something like:
const { dialogflow } = require('actions-on-google')
const app = dialogflow()
// Setup intent handlers with app.intent() here
exports.factsAboutGoogle = app
I have started a aws project with help of serverless framework, but i have one question regarding run lambda function.
How can I run lambda function with input parameters? I can do it via amazon console, lambda test configuration->test event. but I cannot find a correspondning function in serverless, does anyone know?
Thanks
For the lambda part
You can use event.json file:
{
"principalId": "1234",
"inputVar": "foo"
}
and then run sls function run.
According to docs, if don't specify any stage, function will run locally, if you do specify a stage, function will run deployed code in corresponding stage. BUT the docs seems outdated, you also need to pass -d flag like:
sls function run myFunction -s dev -d
This command will invoke your deployed lambda function, with parameters from your local event.json file
Here is the source code for function run options.
For APIG integration
There are some samples in documentation.
If you don't want to use templates, you can just insert related code in your s-function.json, inside the endpoint description.
"endpoints": [
...
"requestTemplates": {
"application/json": {
"principalId": "$context.authorizer.principalId",
"apiKey": "$context.identity.apiKey",
"inputVar": "$input.json('inputVar')"
}
}
...
]
Syntax is as described in API Gateway Accessing the $input Variable doc.