├── package.json
├── config.json
├── .gitattributes
├── LICENSE.md
├── sns.js
├── emr.js
├── ec2
├── ebs.js
├── elb.js
├── eip.js
├── as.js
└── ec2.js
├── cloudwatch.js
├── redshift
└── redshift.js
├── rds
└── rds.js
├── cleanup.js
├── README.md
└── .gitignore
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name":"aws-cleanup",
3 | "version":"0.2.0",
4 | "author":{
5 | "name":"Himanshu Sachdeva"
6 | },
7 | "homepage":"https://github.com/hsachdevah/aws-cleanup",
8 | "dependencies": {
9 | "aws-sdk": ">=1.8.0",
10 | "prompt":"*"
11 | }
12 | }
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "regions":{
3 | "us-east-1":"true",
4 | "us-west-1":"true",
5 | "us-west-2":"true",
6 | "eu-west-1":"true",
7 | "sa-east-1":"true",
8 | "ap-southeast-1":"true",
9 | "ap-southeast-2":"true",
10 | "ap-northeast-1":"true"
11 | },
12 | "services":{
13 | "ec2":true,
14 | "eip":true,
15 | "elb":true,
16 | "ebs":true,
17 | "rds":true,
18 | "as":true,
19 | "redshift":true,
20 | "sns":false,
21 | "cloudwatch":false
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) {{{2014}}} {{{Himanshu Sachdeva}}}
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/sns.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var sns = new AWS.SNS({region:region});
3 | var listTopics = sns.listTopics();
4 |
5 | listTopics.on('success',function(resp){
6 | if (resp.data.Topics.length>0) {
7 | for(var t in resp.data.Topics){
8 | var topicARN = resp.data.Topics[t].TopicArn;
9 | deleteTopic(AWS,region,topicARN);
10 | }
11 | };
12 | });
13 |
14 | listTopics.on('error',function(resp){
15 | if(resp['code']=='UnauthorizedOperation')
16 | console.log('ERROR: Access denied to list SNS topics in',region);
17 | else{
18 | console.log('Error occured while listing SNS topics: ');
19 | console.log(resp);
20 | }
21 | });
22 |
23 | listTopics.send();
24 | };
25 | module.exports.clean = clean;
26 |
27 | var deleteTopic = function(AWS,region,topicARN){
28 | var params = {
29 | TopicArn: topicARN
30 | };
31 |
32 | var sns = new AWS.SNS({region:region});
33 | var deleteTopic = sns.deleteTopic(params);
34 |
35 | deleteTopic.on('error',function(resp){
36 | console.log('Error occured while deleting SNS topic: ');
37 | console.log(resp);
38 | });
39 | deleteTopic.on('success',function(resp){
40 | console.log('Successfully deleted SNS Topic',topicARN);
41 | // console.log(resp);
42 | });
43 | deleteTopic.send();
44 | }
45 |
--------------------------------------------------------------------------------
/emr.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var sns = new AWS.EMR({region:region});
3 | var listClusters = sns.listClusters();
4 |
5 | listClusters.on('success',function(resp){
6 | console.log('EMR:',resp.data)
7 | // if (resp.data.Topics.length>0) {
8 | // for(var t in resp.data.Topics){
9 | // var topicARN = resp.data.Topics[t].TopicArn;
10 | // deleteTopic(AWS,region,topicARN);
11 | // }
12 | // };
13 | });
14 |
15 | listClusters.on('error',function(resp){
16 | if(resp['code']=='UnauthorizedOperation')
17 | console.log('ERROR: Access denied to list SNS topics in',region);
18 | else{
19 | console.log('Error occured while listing SNS topics: ');
20 | console.log(resp);
21 | }
22 | });
23 |
24 | listClusters.send();
25 | };
26 | module.exports.clean = clean;
27 |
28 | var deleteTopic = function(AWS,region,topicARN){
29 | var params = {
30 | TopicArn: topicARN
31 | };
32 |
33 | var sns = new AWS.SNS({region:region});
34 | var deleteTopic = sns.deleteTopic(params);
35 |
36 | deleteTopic.on('error',function(resp){
37 | console.log('Error occured while deleting SNS topic: ');
38 | console.log(resp);
39 | });
40 | deleteTopic.on('success',function(resp){
41 | console.log('Successfully deleted SNS Topic',topicARN);
42 | // console.log(resp);
43 | });
44 | deleteTopic.send();
45 | }
46 |
--------------------------------------------------------------------------------
/ec2/ebs.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var ec2 = new AWS.EC2({region:region});
3 | var describeVolumes = ec2.describeVolumes();
4 |
5 | describeVolumes.on('success',function(resp){
6 | if(resp['data']['Volumes'].length>0){
7 | for(var v in resp['data']['Volumes']){
8 | if(resp['data']['Volumes'][v]['State']=='available'){
9 | var volId = resp['data']['Volumes'][v]['VolumeId'];
10 | deleteVol(AWS,region,volId);
11 | }
12 |
13 | }
14 | }
15 | });
16 |
17 | describeVolumes.on('error',function(resp){
18 | if(resp['code']=='UnauthorizedOperation')
19 | console.log('ERROR: Access denied to describe EBS Volumes in',region);
20 | else{
21 | console.log('Error occured while describing EBS Volume: ');
22 | console.log(resp);
23 | }
24 | });
25 |
26 | describeVolumes.send();
27 | };
28 | module.exports.clean = clean;
29 |
30 | var deleteVol = function(AWS,region,volId){
31 | var params = {
32 | VolumeId: volId
33 | };
34 |
35 | var ec2 = new AWS.EC2({region:region});
36 | var deleteVolume = ec2.deleteVolume(params);
37 |
38 | deleteVolume.on('error',function(resp){
39 | console.log('Error occured while deleting EBS: ');
40 | console.log(resp);
41 | });
42 | deleteVolume.on('success',function(resp){
43 | console.log('Successfully deleted EBS volume',volId,'from region',region);
44 | // console.log(resp);
45 | });
46 | deleteVolume.send();
47 | }
48 |
--------------------------------------------------------------------------------
/ec2/elb.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var elb = new AWS.ELB({region:region});
3 | var describeLoadBalancers = elb.describeLoadBalancers();
4 |
5 |
6 | describeLoadBalancers.on('success',function(resp){
7 | if (resp.data.LoadBalancerDescriptions.length>0) {
8 | for(var lb in resp.data.LoadBalancerDescriptions){
9 | var name = resp.data.LoadBalancerDescriptions[lb].LoadBalancerName;
10 | deleteELB(AWS,region,name);
11 | }
12 | }
13 |
14 | });
15 |
16 | describeLoadBalancers.on('error',function(resp){
17 | if(resp['code']=='AccessDenied')
18 | console.log('ERROR: Access denied to describe load balancers in',region);
19 | else{
20 | console.log('Error occured while describing Balancers: ');
21 | console.log(resp);
22 | }
23 | });
24 |
25 | describeLoadBalancers.send()
26 | }
27 | module.exports.clean = clean;
28 |
29 |
30 | var deleteELB = function(AWS,region,name){
31 | var params = {
32 | LoadBalancerName: name // required
33 | };
34 |
35 | var elb = new AWS.ELB({region:region});
36 | var deleteLoadBalancer = elb.deleteLoadBalancer(params);
37 |
38 |
39 | deleteLoadBalancer.on('error',function(resp){
40 | console.log('Error occured while deleting ELB: ');
41 | console.log(resp);
42 | });
43 | deleteLoadBalancer.on('success',function(resp){
44 | console.log('Successfully deleted ELB',name,'from region',region);
45 | // console.log(resp);
46 | });
47 | deleteLoadBalancer.send();
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/ec2/eip.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var ec2 = new AWS.EC2({region:region});
3 | var describeAddresses = ec2.describeAddresses();
4 |
5 | describeAddresses.on('success',function(resp){
6 | if (resp.data.Addresses.length>0) {
7 | for(var a in resp.data.Addresses){
8 | if(resp.data.Addresses[a].Domain=='vpc'){
9 | var AllocationId = resp.data.Addresses[a].AllocationId;
10 | release(AWS,region,AllocationId);
11 | };
12 | }
13 | };
14 | });
15 |
16 | describeAddresses.on('error',function(resp){
17 | if(resp['code']=='UnauthorizedOperation')
18 | console.log('ERROR: Access denied to describe network addresses in',region);
19 | else{
20 | console.log('Error occured while describing Network Addresses: ');
21 | console.log(resp);
22 | }
23 | });
24 |
25 | describeAddresses.send();
26 | };
27 | module.exports.clean = clean;
28 |
29 | var release = function(AWS,region,AllocationId){
30 | var params = {
31 | AllocationId: AllocationId
32 | };
33 |
34 | var ec2 = new AWS.EC2({region:region});
35 | var releaseAddress = ec2.releaseAddress(params);
36 |
37 | releaseAddress.on('error',function(resp){
38 | console.log('Error occured while releasing Network Addresses: ');
39 | console.log(releaseAddress);
40 | console.log(resp);
41 | });
42 | releaseAddress.on('success',function(resp){
43 | console.log('Successfully released EIP from region',region);
44 | // console.log(resp);
45 | });
46 | releaseAddress.send();
47 | }
48 |
--------------------------------------------------------------------------------
/cloudwatch.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var cw = new AWS.CloudWatch({region:region});
3 | var describeAlarms = cw.describeAlarms();
4 |
5 | describeAlarms.on('success',function(resp){
6 |
7 | if(resp.data.MetricAlarms.length>0){
8 | for(var a in resp.data.MetricAlarms){
9 | var Namespace = resp.data.MetricAlarms[a].Namespace;
10 | var Alarms = new Array(); //AlarmName
11 | if(Namespace != 'AWS/Billing'){
12 | Alarms.push(resp.data.MetricAlarms[a].AlarmName);
13 | }
14 | }
15 | if(Alarms.length>0)
16 | deleteAlarms(AWS,region,Alarms);
17 | };
18 | });
19 |
20 | describeAlarms.on('error',function(resp){
21 |
22 | // if(resp['code']=='AccessDenied')
23 | // console.log('ERROR: Access denied to describe AutoScaling Groups in',region);
24 | // else{
25 | console.log('Error occured while describing CloudWatch Alarms: ');
26 | console.log(resp);
27 | // }
28 |
29 | });
30 |
31 | describeAlarms.send();
32 | };
33 | module.exports.clean = clean;
34 |
35 | var deleteAlarms = function(AWS,region,AlarmNames){
36 | var params = {
37 | AlarmNames: AlarmNames,
38 | };
39 |
40 | var cw = new AWS.CloudWatch({region:region});
41 | var deleteAlarms = cw.deleteAlarms(params);
42 |
43 | deleteAlarms.on('error',function(resp){
44 | console.log('Error occured while deleting CloudWatch alarm in region',region);
45 | console.log(resp);
46 | });
47 |
48 | deleteAlarms.on('success',function(resp){
49 | console.log('Successfully deleted CloudWatch alarms from region',region);
50 | // console.log(resp);
51 | });
52 | deleteAlarms.send();
53 | }
--------------------------------------------------------------------------------
/redshift/redshift.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var rs = new AWS.Redshift({region:region});
3 | var describeClusters = rs.describeClusters();
4 |
5 | describeClusters.on('success',function(resp){
6 | //Check if service is available in region
7 | if(resp['data']['Clusters'].length>0){
8 | for(var c in resp['data']['Clusters']){
9 | var clusterIdentifier = resp['data']['Clusters'][c]['ClusterIdentifier'];
10 | deleteCluster(AWS,region,clusterIdentifier);
11 | }
12 | }
13 | });
14 |
15 | describeClusters.on('error',function(resp){
16 | if(resp['code']=='UnauthorizedOperation')
17 | console.log('ERROR: Access denied to describe Redshift Clusters in',region);
18 | else if(resp['errno']=='ENOTFOUND'){
19 | console.log('Redshift service is not available in:',region);
20 | }
21 | else {
22 | console.log('Error occured while describing Redshift Cluster: ');
23 | console.log(resp);
24 | }
25 | });
26 |
27 | describeClusters.send();
28 | };
29 | module.exports.clean = clean;
30 |
31 | var deleteCluster = function(AWS,region,clusterIdentifier){
32 | var params = {
33 | ClusterIdentifier: clusterIdentifier,
34 | SkipFinalClusterSnapshot: true
35 | };
36 |
37 | var rs = new AWS.Redshift({region:region});
38 | var deleteCluster = rs.deleteCluster(params);
39 |
40 | deleteCluster.on('error',function(resp){
41 | console.log('Error occured while deleting resdhift cluster: ');
42 | console.log(resp);
43 | });
44 | deleteCluster.on('success',function(resp){
45 | console.log('Successfully Redshift Cluster',clusterIdentifier,'from region',region);
46 | // console.log(resp);
47 | });
48 | deleteCluster.send();
49 | }
50 |
--------------------------------------------------------------------------------
/rds/rds.js:
--------------------------------------------------------------------------------
1 | var DryRun = false;
2 |
3 | var clean = function clean(AWS,region){
4 | var rds = new AWS.RDS({region:region});
5 | var describeDBInstances = rds.describeDBInstances();
6 |
7 | describeDBInstances.on('success',function(resp){
8 | var response = resp.data;
9 | var Instances = new Array();
10 |
11 | for(var i in response['DBInstances']){
12 | if(response['DBInstances'][i]['DBInstanceStatus'] == 'available'){
13 | var DBInstanceIdentifier = response['DBInstances'][i]['DBInstanceIdentifier'];
14 | deleteIstances(AWS,region,DBInstanceIdentifier);
15 | }
16 | }
17 |
18 | if(Instances.length > 0)
19 | deleteIstances(AWS,region,Instances);
20 |
21 | });
22 |
23 | describeDBInstances.on('error',function(resp){
24 | if(resp['code']=='AccessDenied')
25 | console.log('ERROR: Access denied to describe DB Instances in',region);
26 | else{
27 | console.log('Error occured while describing DB Instances: ');
28 | console.log(resp);
29 | }
30 |
31 | });
32 | describeDBInstances.send();
33 | }
34 | module.exports.clean = clean;
35 |
36 | var deleteIstances = function(AWS,region, DBInstanceIdentifier){
37 | var params = {
38 | DBInstanceIdentifier: DBInstanceIdentifier,
39 | SkipFinalSnapshot: true
40 | };
41 | var rds = new AWS.RDS({region:region});
42 | var deleteDBInstance = rds.deleteDBInstance(params);
43 |
44 | deleteDBInstance.on('success',function(resp){
45 | console.log('Successfully deleted',DBInstanceIdentifier,'DB Instance from',region,'region');
46 | });
47 |
48 | deleteDBInstance.on('error',function(resp){
49 | console.log('Error occured while terminating Instances: ');
50 | console.log(resp);
51 | });
52 |
53 | deleteDBInstance.send();
54 | }
--------------------------------------------------------------------------------
/ec2/as.js:
--------------------------------------------------------------------------------
1 | var clean = function clean(AWS,region){
2 | var as = new AWS.AutoScaling({region:region});
3 | var describeAutoScalingGroups = as.describeAutoScalingGroups();
4 |
5 | describeAutoScalingGroups.on('success',function(resp){
6 | //resp['data']['AutoScalingGroups'][0]['AutoScalingGroupName']
7 | if (resp.data.AutoScalingGroups.length>0) {
8 | for(var a in resp.data.AutoScalingGroups){
9 | var ASGroupName = resp.data.AutoScalingGroups[a].AutoScalingGroupName;
10 | if(resp.data.AutoScalingGroups[a].DesiredCapacity != 0)
11 | // setCapacity(AWS,region,ASGroupName);
12 | updateASG(AWS,region,ASGroupName);
13 |
14 | }
15 | };
16 | });
17 |
18 | describeAutoScalingGroups.on('error',function(resp){
19 | if(resp['code']=='AccessDenied')
20 | console.log('ERROR: Access denied to describe AutoScaling Groups in',region);
21 | else{
22 | console.log('Error occured while describing AutoScaling Groups: ');
23 | console.log(resp);
24 | }
25 |
26 | });
27 |
28 | describeAutoScalingGroups.send();
29 | };
30 | module.exports.clean = clean;
31 |
32 | var setCapacity = function(AWS,region,ASGroupName){
33 | var params = {
34 | AutoScalingGroupName: ASGroupName, // required
35 | DesiredCapacity: 0, // required
36 | // HonorCooldown: true || false,
37 | };
38 |
39 | var as = new AWS.AutoScaling({region:region});
40 | var setDesiredCapacity = as.setDesiredCapacity(params);
41 |
42 | setDesiredCapacity.on('error',function(resp){
43 | console.log('Error occured while setting capacity of AutoScaling Group');
44 | console.log(resp);
45 | });
46 | setDesiredCapacity.on('success',function(resp){
47 | console.log('Successfully reset ASG', ASGroupName,'capacity in region',region);
48 | // console.log(resp);
49 | });
50 | setDesiredCapacity.send();
51 | }
52 |
53 | var updateASG = function(AWS,region,ASGroupName){
54 | var params = {
55 | AutoScalingGroupName: ASGroupName,
56 | DesiredCapacity: 0,
57 | MaxSize: 0,
58 | MinSize: 0,
59 | };
60 |
61 | var as = new AWS.AutoScaling({region:region});
62 | var updateAutoScalingGroup = as.updateAutoScalingGroup(params);
63 |
64 | updateAutoScalingGroup.on('error',function(resp){
65 | console.log('Error occured while setting capacity of AutoScaling Group');
66 | console.log(resp);
67 | });
68 | updateAutoScalingGroup.on('success',function(resp){
69 | console.log('Successfully reset ASG', ASGroupName,'capacity in region',region);
70 | // console.log(resp);
71 | });
72 | updateAutoScalingGroup.send();
73 |
74 | }
--------------------------------------------------------------------------------
/cleanup.js:
--------------------------------------------------------------------------------
1 | var AWS = require('aws-sdk');
2 | var config = require('./config.json');
3 | var ec2 = require('./ec2/ec2.js');
4 | var eip = require('./ec2/eip.js');
5 | var elb = require('./ec2/elb.js');
6 | var ebs = require('./ec2/ebs.js');
7 | var rds = require('./rds/rds.js');
8 | var as = require('./ec2/as.js');
9 | var redshift = require('./redshift/redshift.js');
10 | var sns = require('./sns.js');
11 | var emr = require('./emr.js');
12 | var cloudwatch = require('./cloudwatch.js');
13 | //var datapipeline = require('./datapipeline.js');
14 | var prompt = require('prompt');
15 | var fs = require('fs');
16 |
17 | config = JSON.parse(JSON.stringify(config));
18 | var cred = {};
19 |
20 | if (fs.existsSync('./aws-credentials.json')) {
21 | AWS.config.loadFromPath('./aws-credentials.json');
22 | confirm();
23 | }
24 | else{
25 | prompt.start();
26 | prompt.get(['AWS_Access_Key', 'AWS_Secret_Access_Key'], function (err, result) {
27 | cred['accessKeyId'] = result.AWS_Access_Key;
28 | cred['secretAccessKey'] = result.AWS_Secret_Access_Key;
29 | cred['region'] = "us-east-1";
30 |
31 | AWS.config.update(cred);
32 | confirm();
33 | });
34 |
35 | }
36 |
37 | function confirm(){
38 | console.log('WARNING: You are about to delete your AWS resources permanently. Are you sure you want to proceed?')
39 | var property = {
40 | name: 'yesno',
41 | message: 'yes/no?',
42 | validator: /y[es]*|n[o]?/,
43 | warning: 'Must respond yes or no',
44 | default: 'no'
45 | };
46 | prompt.get(property, function (err, result) {
47 | if(result.yesno == 'yes' || result.yesno == 'y')
48 | clean();
49 | });
50 | }
51 |
52 | function clean(){
53 | var regions = config['regions'];
54 | console.log("Starting cleanup process ...");
55 | for(var region in regions){
56 | if(regions[region]=="true"){
57 | if(config['services']['as'])
58 | as.clean(AWS,region);
59 | if(config['services']['ec2'])
60 | ec2.clean(AWS,region);
61 | if(config['services']['eip'])
62 | eip.clean(AWS,region);
63 | if(config['services']['elb'])
64 | elb.clean(AWS,region);
65 | if(config['services']['ebs'])
66 | ebs.clean(AWS,region);
67 | if(config['services']['rds'])
68 | rds.clean(AWS,region);
69 | if(config['services']['redshift'])
70 | redshift.clean(AWS,region);
71 | if(config['services']['sns'])
72 | sns.clean(AWS,region);
73 | if(config['services']['cloudwatch'])
74 | cloudwatch.clean(AWS,region);
75 | // if(config['services']['emr'])
76 | // emr.clean(AWS,region);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/ec2/ec2.js:
--------------------------------------------------------------------------------
1 | var DryRun = false;
2 |
3 | var clean = function clean(AWS,region){
4 | var ec2 = new AWS.EC2({region:region});
5 | var describeInstances = ec2.describeInstances();
6 |
7 | describeInstances.on('success',function(resp){
8 |
9 | var response = resp.data;
10 |
11 | // Get list of instances
12 | for (var i in response['Reservations']) {
13 | var reservation = response['Reservations'][i];
14 | for (var j in reservation['Instances']) {
15 | // console.log(reservation['Instances'][j]);
16 | if (reservation['Instances'][j]['State']['Name']=='running') {
17 | var InstanceId = reservation['Instances'][j]['InstanceId'];
18 | setForTermination(AWS,region,InstanceId);
19 | };
20 | };
21 | };
22 |
23 | });
24 |
25 | describeInstances.on('error',function(resp){
26 | if(resp['code']=='UnauthorizedOperation')
27 | console.log('ERROR: Access denied to describe instances in',region);
28 | else{
29 | console.log('Error occured while describing Instances: ');
30 | console.log(resp);
31 | }
32 |
33 | });
34 |
35 | describeInstances.send();
36 | }
37 | module.exports.clean = clean;
38 |
39 |
40 | var setForTermination = function(AWS,region,InstanceId){
41 | var params = {
42 | Attribute: 'disableApiTermination', /* required */
43 | InstanceId: InstanceId, /* required */
44 | };
45 |
46 | var Instances = new Array();
47 | var ec2 = new AWS.EC2({region:region});
48 | var describeInstanceAttribute = ec2.describeInstanceAttribute(params);
49 |
50 | describeInstanceAttribute.on('success',function(resp){
51 | if(resp.data.DisableApiTermination.Value == false){
52 | Instances.push(InstanceId);
53 | terminate(AWS,region,Instances);
54 | }
55 | else{
56 | console.log('WARNING: EC2 instance',InstanceId,'in',region,'has Termination Protection Enabled');
57 | }
58 |
59 | });
60 |
61 | describeInstanceAttribute.on('error',function(resp){
62 | console.log('Error Attribute: ',resp);
63 | });
64 |
65 | describeInstanceAttribute.send();
66 | }
67 |
68 |
69 |
70 | var terminate = function(AWS,region, Instances){
71 |
72 | var params = {
73 | DryRun: DryRun,
74 | InstanceIds: Instances
75 | };
76 |
77 | var ec2 = new AWS.EC2({region:region});
78 | var terminateInstances = ec2.terminateInstances(params);
79 |
80 | terminateInstances.on('success',function(resp){
81 | console.log('Successfully terminated',Instances.length,'Instances from ',region,'region');
82 | })
83 |
84 | terminateInstances.on('error',function(resp){
85 | console.log('Error occured while terminating Instances: ');
86 | console.log(resp);
87 | })
88 |
89 | terminateInstances.send();
90 | }
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # aws-cleanup
2 |
3 | This project helps to terminate/delete all the resources in a given AWS account.
4 |
5 | This is particularly useful if you are learning to work with AWS & don't want to accidentally leave any service in running state only to find out that you have been charged on your credit card at month end.
6 |
7 | ## Installing
8 |
9 | You would require node.js installed on your system to use aws-cleanup. In case its not already installed, you can get it from here: http://nodejs.org/
10 |
11 | You also need ```npm``` installed on your system so that required dependencies can be downloaded. Install it from the instructions provided at this site : https://www.npmjs.org/
12 |
13 | If these are successfully installed, you should be able to get a valid results from the commands below
14 |
15 | ```sh
16 | node -v
17 | npm -v
18 | ```
19 |
20 | You can get the code & required modules (including AWS-SDK for node.js) by executing the following commands
21 |
22 | ```sh
23 | git clone https://github.com/hsachdevah/aws-cleanup.git
24 | cd aws-cleanup
25 | npm install
26 | ```
27 | You can execute the cleanup task by running cleanup.js. You would be asked to provide access-key & secret-access-key, please make sure you have all the required permissions for terminating/deleting resources.
28 |
29 | ```sh
30 | node cleanup.js
31 | ```
32 |
33 | Note: You can also store credentials locally so you don't have to enter them every time you execute the cleanup task. Create a file with name "aws-credentials.json" in the same directory as cleanup.js with the following content
34 |
35 | ```json
36 | {
37 | "accessKeyId": "",
38 | "secretAccessKey": "",
39 | "region": "us-east-1"
40 | }
41 | ```
42 |
43 | The given access key & secret key should have all the permissions to list/delete AWS resources.
44 |
45 | ## Supported Services
46 |
47 | The following services are supported in latest version:
48 |
49 |
50 | | Services | Notes |
51 | | --------------------- | --------------------------------------------------------- |
52 | | AutoScalingGroups | Sets Desired Capacity to 0 |
53 | | CloudWatch | Disabled by default, check config.json. Billing Alarms are not deleted |
54 | | EBS | Only volumes with status 'available' will get deleted |
55 | | EC2 | Only instances with status 'running' & 'Termination Protection' disabled will get terminated |
56 | | Elastic IP | Only EIPs with scope 'vpc' will get released |
57 | | ELB | |
58 | | Redshift | |
59 | | RDS | Only DB instances with status 'available' will get deleted |
60 | | SNS | Disabled by default, check config.json |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | aws-credentials.json
3 | config.json
4 |
5 | =======
6 | #################
7 | ## Eclipse
8 | #################
9 |
10 | *.pydevproject
11 | .project
12 | .metadata
13 | bin/
14 | tmp/
15 | *.tmp
16 | *.bak
17 | *.swp
18 | *~.nib
19 | local.properties
20 | .classpath
21 | .settings/
22 | .loadpath
23 |
24 | # External tool builders
25 | .externalToolBuilders/
26 |
27 | # Locally stored "Eclipse launch configurations"
28 | *.launch
29 |
30 | # CDT-specific
31 | .cproject
32 |
33 | # PDT-specific
34 | .buildpath
35 |
36 |
37 | #################
38 | ## Visual Studio
39 | #################
40 |
41 | ## Ignore Visual Studio temporary files, build results, and
42 | ## files generated by popular Visual Studio add-ons.
43 |
44 | # User-specific files
45 | *.suo
46 | *.user
47 | *.sln.docstates
48 |
49 | # Build results
50 |
51 | [Dd]ebug/
52 | [Rr]elease/
53 | x64/
54 | build/
55 | [Bb]in/
56 | [Oo]bj/
57 |
58 | # MSTest test Results
59 | [Tt]est[Rr]esult*/
60 | [Bb]uild[Ll]og.*
61 |
62 | *_i.c
63 | *_p.c
64 | *.ilk
65 | *.meta
66 | *.obj
67 | *.pch
68 | *.pdb
69 | *.pgc
70 | *.pgd
71 | *.rsp
72 | *.sbr
73 | *.tlb
74 | *.tli
75 | *.tlh
76 | *.tmp
77 | *.tmp_proj
78 | *.log
79 | *.vspscc
80 | *.vssscc
81 | .builds
82 | *.pidb
83 | *.log
84 | *.scc
85 |
86 | # Visual C++ cache files
87 | ipch/
88 | *.aps
89 | *.ncb
90 | *.opensdf
91 | *.sdf
92 | *.cachefile
93 |
94 | # Visual Studio profiler
95 | *.psess
96 | *.vsp
97 | *.vspx
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | *.ncrunch*
114 | .*crunch*.local.xml
115 |
116 | # Installshield output folder
117 | [Ee]xpress/
118 |
119 | # DocProject is a documentation generator add-in
120 | DocProject/buildhelp/
121 | DocProject/Help/*.HxT
122 | DocProject/Help/*.HxC
123 | DocProject/Help/*.hhc
124 | DocProject/Help/*.hhk
125 | DocProject/Help/*.hhp
126 | DocProject/Help/Html2
127 | DocProject/Help/html
128 |
129 | # Click-Once directory
130 | publish/
131 |
132 | # Publish Web Output
133 | *.Publish.xml
134 | *.pubxml
135 |
136 | # NuGet Packages Directory
137 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
138 | #packages/
139 |
140 | # Windows Azure Build Output
141 | csx
142 | *.build.csdef
143 |
144 | # Windows Store app package directory
145 | AppPackages/
146 |
147 | # Others
148 | sql/
149 | *.Cache
150 | ClientBin/
151 | [Ss]tyle[Cc]op.*
152 | ~$*
153 | *~
154 | *.dbmdl
155 | *.[Pp]ublish.xml
156 | *.pfx
157 | *.publishsettings
158 |
159 | # RIA/Silverlight projects
160 | Generated_Code/
161 |
162 | # Backup & report files from converting an old project file to a newer
163 | # Visual Studio version. Backup files are not needed, because we have git ;-)
164 | _UpgradeReport_Files/
165 | Backup*/
166 | UpgradeLog*.XML
167 | UpgradeLog*.htm
168 |
169 | # SQL Server files
170 | App_Data/*.mdf
171 | App_Data/*.ldf
172 |
173 | #############
174 | ## Windows detritus
175 | #############
176 |
177 | # Windows image file caches
178 | Thumbs.db
179 | ehthumbs.db
180 |
181 | # Folder config file
182 | Desktop.ini
183 |
184 | # Recycle Bin used on file shares
185 | $RECYCLE.BIN/
186 |
187 | # Mac crap
188 | .DS_Store
189 |
190 |
191 | #############
192 | ## Python
193 | #############
194 |
195 | *.py[co]
196 |
197 | # Packages
198 | *.egg
199 | *.egg-info
200 | dist/
201 | build/
202 | eggs/
203 | parts/
204 | var/
205 | sdist/
206 | develop-eggs/
207 | .installed.cfg
208 |
209 | # Installer logs
210 | pip-log.txt
211 |
212 | # Unit test / coverage reports
213 | .coverage
214 | .tox
215 |
216 | #Translations
217 | *.mo
218 |
219 | #Mr Developer
220 | .mr.developer.cfg
221 |
222 |
--------------------------------------------------------------------------------