-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathindex.js
More file actions
executable file
·124 lines (111 loc) · 4.54 KB
/
Copy pathindex.js
File metadata and controls
executable file
·124 lines (111 loc) · 4.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
var AWS = require('aws-sdk');
var apiVersion = "2015-10-01";
var results = {};
var semaphore = { "describe": 0, "terminate": 0}; // A quick and CPU cheap way to enforce asynchronous signaling (essentially a Promise)
var shouldTerminateInstances = false; // For testing purposes
/**
* The "main" function which AWS Lambda executes.
*/
exports.handler = function(event, context) {
// Corner cases in which Lambda ought not to run
if(!event.region) { announce(null, "No region(s) specified."); context.fail(event); return; }
if(event.region.length === 0) { announce(null, results); context.succeed(results); return; }
// For each region specified in the event...
for(var i = 0; i < event.region.length; i++) {
semaphore.describe++;
var region = event.region[i];
var ec2 = new AWS.EC2({region:region, apiVersion:apiVersion});
var request = ec2.describeInstances({DryRun:false});
// On a successful describe, execute the following callback
request.on("success", function(response) {
var region = response.request.service.config.region;
var data = response.data;
var ids = [];
for(var i = 0; i < data.Reservations.length; i++) {
var Instances = data.Reservations[i].Instances;
for(var j = 0; j < Instances.length; j++) {
var instance = Instances[j];
if(isTagless(instance))
ids.push(instance.InstanceId);
}
}
announce(region, ids);
// If some Instances have been identified, attempt to terminate
if(ids.length > 0) {
semaphore.terminate++;
var ec2 = new AWS.EC2(response.request.service.config);
var request = ec2.terminateInstances({DryRun:!shouldTerminateInstances, InstanceIds:ids}); // Defaulting to DryRun true when terminating Instances
// Callback for successful terminate
request.on("success", function(response) {
var region = response.request.service.config.region;
var body = JSON.stringify(response.data);
results[region] = response.data;
announce(region, body);
});
// Callback for error terminate
request.on("error", cbError);
// Callback when terminating attempt has finished, successful or not -- decrement the terminate semaphore and check if finished
request.on("complete", function() {
semaphore.terminate--;
if(describingDone() && terminatingDone()) {
context.succeed(results);
}
});
request.send(); // Issue the terminate request
}
});
// Callback for error describe
request.on("error", cbError);
// Callback when describing attempt has finished, successful or not -- decrement the describe semaphore and check if finished
request.on("complete", function() {
semaphore.describe--;
if(describingDone() && terminatingDone()) {
context.succeed(results);
}
});
request.send(); // Issue the describe request
}
};
/**
* A simple logging function used for printing to AWS Lambda logs.
*/
function announce(region, message) {
if(region !== null) { d = "=========="; console.log(d + " " + region + " " + d); }
console.log(message);
}
/**
* Generic callback used for error responses.
*/
function cbError(error, response) {
results[response.request.service.config.region] = error;
announce(response.request.service.config.region, JSON.stringify(error));
}
/**
* Return true if all describing calls are finished, false otherwise.
*/
function describingDone() {
if(isDone(semaphore.describe)) { return true; }
return false;
}
/**
* Return true if all terminating calls are finished, false otherwise.
*/
function terminatingDone() {
if(isDone(semaphore.terminate)) { return true; }
return false;
}
function isDone(counter) {
return counter === 0;
}
/**
* Return true if a given Instance is considered tagless, false otherwise.
*/
function isTagless(instance) {
try {
if(!instance.Tags || instance.Tags.length === 0) { return true; }
if(instance.Tags.length == 1)
if(instance.Tags[0].Key == "Name" && instance.Tags[0].Value === "")
return true;
} catch(e) {}
return false;
}