I have an an AWS Lambda function that needs to connect to a remote TCP service. Is there any way to configure the Lambda function with the IP address of the remote service after the Lambda function has been deployed to AWS? Or do I have to bake the configuration into the packaged Lambda function before it's deployed?
I found a way that I use for supporting a test environment and a production environment that will help you.
For the test version of the function, I am calling it TEST-ConnectToRemoteTcpService and for the production version of the function I am naming the function PRODUCTION-ConnectToRemoteTcpService. This allows me pull out the environment name using a regular expression.
Then I am storing config/test.json and config/production.json in the zip file that I upload as code for the function. This zip file will be extracted into the directory process.env.LAMBDA_TASK_ROOT when the function runs. So I can load that file and get the config I need.
Some people don't like storing the config in the code zip file, which is fine - you can just load a file from S3 or use whatever strategy you like.
Code for reading the file from the zip:
const readConfiguration = () => {
return new Promise((resolve, reject) => {
let environment = /^(.*?)-.*/.exec(process.env.AWS_LAMBDA_FUNCTION_NAME)[1].toLowerCase();
console.log(`environment is ${environment}`);
fs.readFile(`${process.env.LAMBDA_TASK_ROOT}/config/${environment}.json`, 'utf8', function (err,data) {
if (err) {
reject(err);
} else {
var config = JSON.parse(data);
console.log(`configuration is ${data}`);
resolve(config);
}
});
});
};
Support for environment variables was added for AWS Lambda starting November 18, 2016. Adding a variable to an existing function can be done via command line as shown below or from the AWS Console.
aws lambda update-function-configuration \
--function-name MyFunction \
--environment Variables={REMOTE_SERVICE_IP=100.100.100.100}
Documentation can be found here.
You can invoke the Lambda function via SNS topic subscription and have it configure itself from the payload inside the SNS event.
Here's the official guide on how to do that Invoking Lambda via SNS.
A few options, depending on the use-case
If your config will not change then you can use S3 objects and access from Lambda or set your Lambda to trigger on new config changes. (Though this is the cheapest way, you are limited in what you can do compared to other alternatives)
If the config is changing constantly, then DynamoDB - Key/value is an alternative.
If DynamoDB is expensive for the frequent read/writes and not worth the value then you can have TCP service post config into a SQS queue. (or an SNS if you want to trigger when the service posts a new config)
Related
Is it possible to trigger a local cloud function when a firestore document is modified on production? The function below works when it is deployed on google cloud with a cloud trigger. How can I run it on my machine and specify a firestore trigger?
import functions_framework
#functions_framework.cloud_event
def hello_firestore(event, context):
resource_string = context.resource
# print out the resource string that triggered the function
print(f"Function triggered by change to: {resource_string}.")
# now print out the entire event object
print(str(event))
Our team has decided to adopt the AWS CDKV2.0 to build and manage our AWS resources. We are also using The AWS Deployment Framework to manage the deployment process by creating Code Pipelines and using AWS Code build.
The Setup we currently have works for the most part. We seem to have stumbled upon an issue when we attempt to deploy any of our resource that contain assets such as lambdas. Specifically I am talking about lambdas which are not included in-line within the synthezied cloudformation template as per this example.
In other words our lambda code is expected to be uploaded to S3 before being deployed,I am looking for best practice guides on how to configure our accounts and ADF with the CDK to deploy assets which require uploading to S3. At the moment all I can think of is either Bootstrapping the accounts we deploy to and/or customising the CDK synthesizer as part of our stack definition, any guidance or thoughts would be appreciated!
In other words our lambda code is expected to be uploaded to S3 before being deployed
Luckily, no. The CDK's lambda constructs automagically handle local asset bundling and S3 uploading out of the box. The CDK also accepts inline code an existing S3 buckets as code sources. And Docker images.
// aws_cdk.aws_lambda
const fn = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_12_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
});
Even better, the CDK provides runtime-specific lambda constructs (in dedicated modules) to make life even easier. For instance, CDK will transpile your ts or build your go executable for you and send the artifacts to a CDK-managed S3 bucket on cdk deploy.
// aws_cdk.aws_lambda_nodejs
new NodejsFunction(this, 'MyFunction', {
entry: '/path/to/my/file.ts', // accepts .js, .jsx, .ts and .tsx files
handler: 'myExportedFunc', // defaults to 'handler'
});
// aws_cdk.aws_lambda_go_alpha
new GoFunction(this, 'handler', {
entry: 'app/cmd/api',
});
// aws_cdk.aws_lambda_python_alpha
new PythonFunction(this, 'MyFunction', {
entry: '/path/to/my/function', // required
runtime: Runtime.PYTHON_3_8, // required
index: 'my_index.py', // optional, defaults to 'index.py'
handler: 'my_exported_func', // optional, defaults to 'handler'
});
I am using aws lambda with an application load balancer. I have been fighting to figure out why I am getting only a piece of my content (a few bytes).
I am try to return a PDF file as binary data. This works local and it works when my application is deployed to ec2 or anywhere other than lambda.
I have looked at answers like this one AWS Lambda fails to return PDF file
but these answers are all discussing lambda settings in regards to API gateway. I am not using API gateway I am using the application load balancer. Any ideas?
Found the answer! I am using serverless-http with express. I needed to add the binary parameter for my return content type.
const serverless = require('serverless-http');
const app = require("./index");
const handler = serverless(app, {
binary: ['application/pdf']
});
exports.handler = async (event, context) => {
return await handler(event, context);
};
I have an NestJS application which consist of many modules: databaseModule, userModule, devicesModule, etc. They all packaged to one module ApplicationModule, which handle server actions.
But now I need to add some lambda function to my project and I need to exec some methods from databaseModule, but I don't know how to do it.
Pseudo code that I imagine:
export const handler: Handler = (event: any, context: Context, callback) => {
const dbModule = DataBaseModule.build();
dbModule.get(UserService).createProject('my_project');
callback(null, event);
};
I think that nestjs should have similar functionality but I can't find it on official page.
P.S. I can't use just UserService because it depends on other services and providers in DatabaseModule. That is why I want this module to be fully configured and I can use its services
I found an answer https://docs.nestjs.com/application-context
We can use our submodules in the next way:
const app = await NestFactory.create(ApplicationModule);
const tasksService = app.get(TasksService);
You can use the Lifecycle events from NestJS (https://docs.nestjs.com/fundamentals/lifecycle-events).
That way, you can implement OnModuleInit() on the Service and set the desired function to run when the Module is loaded (it can be sync or async).
There are some other events that can also be useful, like onApplicationBootstrap()
I'm using jovo framework (version 1.0.0) and I'm facing the following problem:
In app.js:
app.setHandler({
'LAUNCH': function() {
if(this.user().isNewUser()) {
this.tell('This will never be told on AWS Lambda.');
}
}
});
Running locally I can distinguish between (isNewUser === true) and (isNewUser === false) but as soon as I'm executing it as a lambda function on AWS isNewUser is always false. Why is that?
and additionally
NEW_USER': function() {
}
Isn't triggered either.
System Environment on local machine:
Windows 10 Home
NodeJS: v8.9.1
Lambda function:
NodeJS 6.10
I really appreciate any help you can provide.
Both 'NEW_USER' and this.user().isNewUser() need to have access to a database, where the number of sessions is stored for each user.
When you're prototyping locally, it uses the default File Persistence database integration, which saves the data to a local db/db.json file.
However, on AWS Lambda, the local db doesn't work, so you need to set up a DynamoDB configuration. Learn more here: Jovo Framework Docs > Database Integrations > DynamoDB.
Please remember to give your Lambda function role the right permission to access DynamoDB data: AWS Lambda Permissions Model.