A shell script to deploy Lambda functions as components of GreengrassV2 to edge devices.
kazutaka nakamura
Posted on November 9, 2022
I wrote a shell script to deploy Lambda functions as components of GreengrassV2 to edge devices.
I write some programs for edge devices using Lambda functions (Node.js) + GreengrassV2.
Every time I do the test on the edge device, I have to have a lot of manual operations, deploying Lambda functions, creating Greengrass Components, and deploying them to the edge device… , so I wrote a shell script to automate these processes.
Why I wrote a shell script
- I developed the lambda function using Serverless Framework v2.
- I created a Greengrass Component using the AWS Console.
- I have a lot of manual operations, I have to set lambda function's version, topic that I want attach to the function, environment variables and so on.
I know AWS CLI makes it easy to complete the above operations, so I wrote a shell script which contains AWS CLI commands.
How to set up by AWS Console
https://docs.aws.amazon.com/ja_jp/greengrass/v2/developerguide/import-lambda-function-console.html
How to set up by AWS CLI
https://docs.aws.amazon.com/ja_jp/greengrass/v2/developerguide/import-lambda-function-cli.html
Operations Before/After
Before
- Deploy the Lambda function by Serverless Framework v2
sls deploy …
- Open the AWS Console and move to IoT Core menu
- Create the Greengrass Component
- Set the Lambda function's version
- Update the Component's version
- Set the topic that I want to attach to the Lambda function
- Set the environment variables
- Create the Greengrass Deployment settings
- Just click some times
After
- Run the script
sh ./scripts/deploy.sh
What I did
I wrote a shell script for the Lambda function's deployment based on the article which I wrote before.
https://zenn.dev/nkmrkz/articles/greengrass-deployment
(Japanese only)
Folder
scripts
|- template
| |- component_template.json
| |- deployment_template.json
|- deployment.sh
The sample lambda function is like that
- Lambda function can get a message from the MQTT topic and publish a message to the topic.
- it use some environment variables.
So I need set the following things to Greengrass component.
- Lambda function's version
- Component's version
- Topic that I want to attach to the Lambda function
- it can have wildcards
- Environment variables
template/component.json
{
"lambdaFunction":{
"lambdaArn": "LambdaFunctionのARN:$LAMBDA_LATEST_VERSION",
"componentName": "{ComponentName}",
"componentVersion": "$CUSTOM_COMPONENT_VERSION",
"componentDependencies": {
"aws.greengrass.LambdaLauncher": {
"versionRequirement": ">=2.0.0 <3.0.0",
"dependencyType": "HARD"
},
"aws.greengrass.TokenExchangeService": {
"versionRequirement": ">=2.0.0 <3.0.0",
"dependencyType": "HARD"
},
"aws.greengrass.LambdaRuntimes": {
"versionRequirement": ">=2.0.0 <3.0.0",
"dependencyType": "SOFT"
}
},
"componentLambdaParameters": {
"eventSources": [
{
"topic": "{Topic Name}",
"type": "IOT_CORE"
}
],
"maxQueueSize": 1000,
"maxInstancesCount": 100,
"maxIdleTimeInSeconds": 60,
"timeoutInSeconds": 3,
"statusTimeoutInSeconds": 60,
"pinned": true,
"inputPayloadEncodingType": "json",
"environmentVariables": {
"STAGE": "$STAGE_NAME",
"ENV1": "$ENV1",
"ENV2": "$ENV2"
},
"linuxProcessParams": {
"isolationMode": "NoContainer",
"containerParams": {}
}
}
}
}
templates/deployment.json
{
"targetArn": "arn:aws:iot:ap-northeast-1:$ACCOUNT_ID:thinggroup/{TargetGroupForDeployment}",
"deploymentName": "Deployment Setting Name",
"components": {
"aws.greengrass.Cli": {
"componentVersion": "2.7.0"
},
"aws.greengrass.LegacySubscriptionRouter": {
"componentVersion": "2.1.6",
"configurationUpdate": {
"merge": "{\"subscriptions\":{\"{SettingName}\":{\"id\":\"{Identifier}\",\"source\":\"component:{LambdaFunctionName}\",\"subject\":\"#\",\"target\":\"cloud\"}}}"
},
"runWith": {}
},
"aws.greengrass.Nucleus": {
"componentVersion": "2.7.0",
"runWith": {}
},
"{ComponentName}": {
"componentVersion": "$CUSTOM_COMPONENT_VERSION",
"runWith": {}
}
},
"deploymentPolicies": {
"failureHandlingPolicy": "DO_NOTHING",
"componentUpdatePolicy": {
"timeoutInSeconds": 60,
"action": "NOTIFY_COMPONENTS"
},
"configurationValidationPolicy": {
"timeoutInSeconds": 60
}
},
"iotJobConfiguration": {}
}
deploy.sh
#!/bin/bash
echo "StageName(dev/stg) : "
read stage_name
echo "start lambda function deployment"
./node_modules/.bin/sls deploy --stage $stage_name --aws-profile {AWS CLI Profile Name}
env1=`grep "ENV1=" ./scripts/.secrets | awk -F "=" '{print$2}'`
env2=`grep "ENV2=" ./scripts/.secrets | awk -F "=" '{print$2}'`
account_id=`aws sts get-caller-identity --profile {AWS CLI Profile Name} --query "Account" |sed -e 's/"//g'`
# component version: $LambdaLtestVersion.0.0
lambda_latest_version=`aws lambda list-versions-by-function --function-name {Function Name} --query 'Versions[-1].Version' --profile {AWS CLI Profile Name}| sed -e 's/"//g'`
custom_component_version=$lambda_latest_version.0.0
echo "create component.json"
cat ./scripts/templates/component_template.json | sed -e "s/\$ENV1/$env1/g"| sed -e "s/\$ENV2/$env2/g"| sed -e "s/\$CUSTOM_COMPONENT_VERSION/$custom_component_version/g" | sed -e "s/\$LAMBDA_LATEST_VERSION/$lambda_latest_version/g" | sed -e "s/\$STAGE_NAME/$stage_name/g" | sed -e "s/\$ACCOUNT_ID/$account_id/g" > ./scripts/component.json
echo "create deployment.json"
cat ./scripts/templates/deployment_template.json | sed -e "s/\$CUSTOM_COMPONENT_VERSION/$custom_component_version/g" | sed -e "s/\$STAGE_NAME/$stage_name/g" | sed -e "s/\$ACCOUNT_ID/$account_id/g" > ./scripts/deployment.json
echo "start create greengrass component"
aws greengrassv2 create-component-version --cli-input-json fileb://scripts/component.json --profile {AWS CLI Profile Name}
echo "start create greengrass deployment"
aws greengrassv2 create-deployment --cli-input-json fileb://scripts/deployment.json --profile {AWS CLI Profile Name}
- The script replace the value which is needed to deploy When it runs.
- I put some values on .secret
- I put some private values on .secret
grep "ENV2=" ./scripts/.secrets | awk -F "=" '{print$2}'
- By using AWS CLI, The script can get the AWS account ID and latest lambda version deployed in this script.
aws sts get-caller-identity - profile {AWS CLI Profile Name} - query "Account" |sed -e 's/"//g'
aws lambda list-versions-by-function - function-name {Function Name} - query 'Versions[-1].Version' - profile {AWS CLI Profile Name}| sed -e 's/"//g'
- The script dose not have any error handling. I will add them later, maybe.
.secrets
ENV1=xxxxx
ENV2=yyyyy
.gitignore(抜粋)
.secrets
component.json
deployment.json
That's all. Keep Playing!
Posted on November 9, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.