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!
Top comments (0)