-
Notifications
You must be signed in to change notification settings - Fork 0
/
backup_instance.js
137 lines (122 loc) · 5.06 KB
/
backup_instance.js
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
125
126
127
128
129
130
131
132
133
134
135
136
137
'use strict';
/*
Make sure that you set the required environment variables:
INSTANCE_NAME: the name of the lightsail instance you want this function to backup
BACKUP_DAYS_MAX: keep the last BACKUP_DAYS_MAX daily backups
BACKUP_WEEKS_MAX: keep at least BACKUP_WEEKS_MAX weekly backups
BACKUP_MONTHS_MAX: keep at least BACKUP_MONTHS_MAX monthly backups
LIGHTSAIL_REGION: the region where your lightsail instance is located (e.g. us-east-1)
And any optional environment variables:
PREFIX: prefix for snapshot names (prevents conflicts with other instance snapshots)
*/
exports.handler = (event, context, callback) => {
/*
* Load configuration from environment variables
*/
console.log('Initializing...');
if (!process.env.INSTANCE_NAME) { throw new Error('INSTANCE_NAME environment variable required!'); }
const instanceName = process.env.INSTANCE_NAME;
if (!process.env.BACKUP_DAYS_MAX) { throw new Error('BACKUP_DAYS_MAX environment variable required!'); }
const backupDaysMax = process.env.BACKUP_DAYS_MAX;
if (!process.env.BACKUP_WEEKS_MAX) { throw new Error('BACKUP_WEEKS_MAX environment variable required!'); }
const backupWeeksMax = process.env.BACKUP_WEEKS_MAX;
if (!process.env.BACKUP_MONTHS_MAX) { throw new Error('BACKUP_MONTHS_MAX environment variable required!'); }
const backupMonthsMax = process.env.BACKUP_MONTHS_MAX;
let prefix;
if (!process.env.PREFIX) {
console.warn('No PREFIX environment variable defined; defaulting to INSTANCE_NAME');
prefix = instanceName;
} else {
prefix = process.env.PREFIX;
}
const AWS = require('aws-sdk');
if (!process.env.LIGHTSAIL_REGION) { throw new Error('LIGHTSAIL_REGION environment variable required!'); }
AWS.config.update({ region: process.env.LIGHTSAIL_REGION });
const Lightsail = new AWS.Lightsail();
/*
* Create today's snapshot
*/
const NOW = new Date();
const currName = `${prefix}-auto-${NOW.getFullYear().toString()}-${NOW.getMonth().toString()}-${NOW.getDate().toString()}`;
const oneDAY = 1000 * 60 * 60 * 24;
Lightsail.getInstanceSnapshot({
'instanceSnapshotName': currName
}, function (err, data) {
if (err) {
console.log('Creating today\'s snapshot...');
// no auto snapshot exists for today, so let's make it
Lightsail.createInstanceSnapshot({
instanceName: instanceName,
'instanceSnapshotName': currName
}, function (err, data) {
if (err) {
console.warn('Snapshot creation failed!');
console.error(err);
} else {
console.log('Snapshot creation succeeded');
console.log(data);
}
});
} else {
console.warn('Skipping snapshot creation because there is already an automatic backup for this instance for today.');
console.log(data);
}
});
/*
* Delete old snapshots
*/
// setup the recursive function
function handleSnapshots(err, data) {
if (err) {
console.error(err);
} else {
console.log('Looking for old snapshots to delete/expire, if any...');
// browse through snapshots...
for (let i = 0; i < data.instanceSnapshots.length; i++) {
const snapshotName = data.instanceSnapshots[i].name;
const snapshotInstanceName = data.instanceSnapshots[i].fromInstanceName;
if (
(snapshotInstanceName === instanceName) && // match this instance
(snapshotName.startsWith(`${prefix}-auto-`)) // only match automated snapshots
) {
let keepSnapshot = false;
const snapshotDate = new Date(data.instanceSnapshots[i].createdAt);
const snapshotDaysAgo = Math.floor((NOW - snapshotDate) / oneDAY);
const snapshotWeeksAgo = Math.floor((NOW - snapshotDate) / (oneDAY * 7));
const snapshotMonthsAgo = Math.floor((NOW - snapshotDate) / (oneDAY * 30));
if (snapshotDaysAgo <= backupDaysMax) {
keepSnapshot = true;
} else if (snapshotWeeksAgo <= backupWeeksMax && snapshotDate.getDay() === 0) {
keepSnapshot = true;
} else if (snapshotMonthsAgo <= backupMonthsMax && snapshotDate.getDate() === 0) {
keepSnapshot = true;
}
if (keepSnapshot) {
console.log(`Keeping ${snapshotName}`);
} else {
console.log(`Deleting ${snapshotName}`);
Lightsail.deleteInstanceSnapshot({
'instanceSnapshotName': snapshotName
}, function (err2, data2) {
if (err2) {
console.error(err2);
} else {
console.log(`Deleted ${snapshotName}`);
console.log(data2);
}
});
}
}
}
// pagenate and use recursion (for when we have lots of snapshots)
if (typeof data.nextPageToken != 'undefined') {
console.log('Recursing to next page (old snapshots)...');
Lightsail.getInstanceSnapshots({
pageToken: data.nextPageToken
}, handleSnapshots);
}
}
}
// run the recursive function
Lightsail.getInstanceSnapshots({}, handleSnapshots);
};