What I'm trying to do is create a lambda function where the function calls two commands on an ec2 instance. When I had trouble running this code in a lambda function, I removed the code from the exports.handler() method and ran the code in a standalone node.js file in the same ec2 instance and I was able to get the code to work. The command I ran was 'node app.js'.
exports.handler = async (event) => {
const AWS = require('aws-sdk')
AWS.config.update({region:'us-east-1'});
var ssm = new AWS.SSM();
var params = {
DocumentName: 'AWS-RunShellScript', /* required */
InstanceIds: ['i-xxxxxxxxxxxxxxxx'],
Parameters: {
'commands': [
'mkdir /home/ec2-user/testDirectory',
'php /home/ec2-user/helloWorld.php'
/* more items */
],
/* '<ParameterName>': ... */
}
};
ssm.sendCommand(params, function(err, data) {
if (err) {
console.log("ERROR!");
console.log(err, err.stack); // an error occurred
}
else {
console.log("SUCCESS!");
console.log(data);
} // successful response
});
const response = {
statusCode: 200,
ssm: ssm
};
return response;
};
I figured that it could have been a permissions related issue, but the lambda is apart of the same vpc that the ec2 instance is in.
Output from the lambda function:
{
"statusCode": 200,
"ssm": {
"config": {
"credentials": {
"expired": false,
"expireTime": null,
"refreshCallbacks": [],
"accessKeyId": "xxxxxxxxxxxxxxxxxxxxx",
"sessionToken": "...",
"envPrefix": "AWS"
},
"credentialProvider": {
"providers": [
null,
null,
null,
null,
null,
null,
null
],
"resolveCallbacks": []
},
"region": "us-east-1",
"logger": null,
"apiVersions": {},
"apiVersion": null,
"endpoint": "ssm.us-east-1.amazonaws.com",
"httpOptions": {
"timeout": 120000
},
"maxRedirects": 10,
"paramValidation": true,
"sslEnabled": true,
"s3ForcePathStyle": false,
"s3BucketEndpoint": false,
"s3DisableBodySigning": true,
"s3UsEast1RegionalEndpoint": "legacy",
"computeChecksums": true,
"convertResponseTypes": true,
"correctClockSkew": false,
"customUserAgent": null,
"dynamoDbCrc32": true,
"systemClockOffset": 0,
"signatureVersion": "v4",
"signatureCache": true,
"retryDelayOptions": {},
"useAccelerateEndpoint": false,
"clientSideMonitoring": false,
"endpointDiscoveryEnabled": false,
"endpointCacheSize": 1000,
"hostPrefixEnabled": true,
"stsRegionalEndpoints": "legacy"
},
"isGlobalEndpoint": false,
"endpoint": {
"protocol": "https:",
"host": "ssm.us-east-1.amazonaws.com",
"port": 443,
"hostname": "ssm.us-east-1.amazonaws.com",
"pathname": "/",
"path": "/",
"href": "https://ssm.us-east-1.amazonaws.com/"
},
"_events": {
"apiCallAttempt": [
null
],
"apiCall": [
null
]
},
"_clientId": 2
}
}
You're trying to combine async
/await
with callbacks. That won't work in a lambda AWS Lambda Function Handler in Node.js. The reason it's working locally, or in a node server, is because the server is still running when the function exits, so the callback still happens. In a Lambda the node process is gone as soon as the lambda exits if you are using async
(or Promises), so the callback is not able to be fired.