In this guide we will demonstrate how to use to AttiniLambdaInvoke step to call a Lambda function from our deployment plan.
Needing to invoke a Lambda during a deployment is a common and straightforward use case. It could be for testing purposes or to trigger some other task. Calling a Lambda from a StepFunction is not very complicated and can be done without the help of an Attini type. However, the AttiniLambdaInvoke step is still convenient to use because:
The step itself looks like this:
Type: AttiniLambdaInvoke
Parameters:
FunctionName: String
Payload: Object
The only mandatory field is “FunctionName”. By default, the entire payload of the deployment plan is passed to the function as input. This can be overridden by setting the “Payload” field. It takes an object that uses json-path syntax to map values from the deployment plan payload, just like normal AWS State Language. So for example, if we would like to only pass two selected values to the Lambda, we could do:
Type: AttiniLambdaInvoke
Parameters:
FunctionName: my-function
Payload:
FirstValue.$: $.output.Step1.FirstValue
SecondValue.$: $.output.Step1.SecondValue
The above example would pass an object to a Lambda looking like this:
{
"FirstValue": "the-first-value",
"SecondValue": "the-second-value"
}
We will look more at how to work with the payload in the following examples.
In this demo we will create a Distribution containing a deployment plan with two steps. It has the following file structure:
.
├── attini-config.yaml
├── deployment-plan.yaml
└── lambda.yaml
The first step will create a Lambda using CloudFormation. The Lambda will simply return whatever value it receives. How to build a Lambda is a bit out of scope for this demo, but you can find the template together with the rest of the files we are using at the end of this page.
Our deployment plan looks like this:
EchoLambda:
Type: Attini::Deploy::DeploymentPlan
Properties:
DeploymentPlan:
- Name: Deploy_EchoLambda
Type: AttiniCfn
Properties:
StackName: !Sub ${AttiniEnvironmentName}-echo-lambda
Template: /lambda.yaml
- Name: Invoke_EchoLambda
Type: AttiniLambdaInvoke
Parameters:
FunctionName.$: $.output.Deploy_EchoLambda.FunctionName
The first step deploys the Lambda using the AttiniCfn step. Because the template will output the function name we can read it from the payload and use it to invoke the Lambda.
You can read more about deploying CloudFormation with the AttiniCfn step here.
Let’s deploy it by running the “deploy run” command from the root of the project.
attini deploy run .
And success! We called the Lambda and as we can see in the image below it did return the entire deployment plan payload.
However, that’s a lot of data, and we probably don’t need all of it. So we can use the “Payload” field to be a bit more selective about what we pass. Let’s change the deployment plan to look like this:
EchoLambda:
Type: Attini::Deploy::DeploymentPlan
Properties:
DeploymentPlan:
- Name: Deploy_EchoLamda
Type: AttiniCfn
Properties:
StackName: !Sub ${AttiniEnvironmentName}-echo-lambda
Template: /lambda.yaml
- Name: Invoke_EchoLamda
Type: AttiniLambdaInvoke
Parameters:
FunctionName.$: $.output.Deploy_EchoLambda.FunctionName
Payload:
DistributionName.$: $.deploymentOriginData.distributionName
Instead of passing the entire payload to the Lambda we choose to simply pass the distribution name. We get the name from the metadata in the payload.
When we run it again, we get the following result:
Success! We selected some data and passed it to Lambda. The keys of the result is determined by the keys in the “Payload”. We only used one field here, but you can add as many as needed. If you don’t want to read the value from the deployment plan payload, simply remove the “.$” at the end of the key and the “$.” at the start of the value.
You can also find the complete demo on Github.
Below are all the files we used in the example.
AWSTemplateFormatVersion: "2010-09-09"
Transform:
- AttiniDeploymentPlan
- AWS::Serverless-2016-10-31
Parameters:
AttiniEnvironmentName:
Type: String
Resources:
EchoLambda:
Type: Attini::Deploy::DeploymentPlan
Properties:
DeploymentPlan:
- Name: Deploy_EchoLambda
Type: AttiniCfn
Properties:
StackName: !Sub ${AttiniEnvironmentName}-echo-lambda
Template: /lambda.yaml
- Name: Invoke_EchoLambda
Type: AttiniLambdaInvoke
Parameters:
FunctionName.$: $.output.Deploy_EchoLambda.FunctionName
Payload:
DistributionName.$: $.deploymentOriginData.distributionName
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Parameters:
AttiniEnvironmentName:
Type: String
Resources:
HelloWorldLambda:
Type: AWS::Serverless::Function
Properties:
Description: A Lambda that returns whatever us passed to it.
FunctionName: !Sub ${AttiniEnvironmentName}-echo-function
InlineCode: |
def lambda_handler(event, context):
return event;
Handler: index.lambda_handler
Runtime: python3.9
HelloWorldLambdaLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldLambda}
RetentionInDays: 30
Outputs:
FunctionName:
Value: !Ref HelloWorldLambda
distributionName: invoke-lambda-demo
initDeployConfig:
template: deployment-plan.yaml
stackName: ${environment}-${distributionName}-deployment-plan
package:
prePackage:
commands:
- attini configure set-dist-id --random