Skip to content

Commit 5d97db0

Browse files
authored
Merge pull request #107 from CodeNow/SAN-4866-cleanup-old-instances
SAN-4866 Cleanup Old Instances
2 parents 8e0f8e3 + 944dbfe commit 5d97db0

File tree

5 files changed

+136
-1
lines changed

5 files changed

+136
-1
lines changed

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const tasks = {
3131
'khronos:images:prune': require('tasks/images/prune'),
3232
'khronos:images:prune-dock': require('tasks/images/prune-dock'),
3333
'khronos:images:remove': require('tasks/images/remove'),
34+
'khronos:instances:cleanup': require('tasks/instances/cleanup'),
3435
'khronos:metrics:container-status': require('tasks/metrics/container-status'),
3536
'khronos:metrics:report-org-container-status': require('tasks/metrics/report-org-container-status'),
3637
'khronos:weave:prune': require('tasks/weave/prune'),

lib/models/rabbitmq.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const publisher = new RabbitMQ({
1616
username: process.env.RABBITMQ_USERNAME,
1717
password: process.env.RABBITMQ_PASSWORD,
1818
events: [
19-
'instance.container.health-check.failed'
19+
'instance.container.health-check.failed',
20+
'instance.expired'
2021
],
2122
tasks: [
2223
'khronos:canary:build',
@@ -39,6 +40,7 @@ const publisher = new RabbitMQ({
3940
'khronos:images:prune',
4041
'khronos:images:prune-dock',
4142
'khronos:images:remove',
43+
'khronos:instances:cleanup',
4244
'khronos:metrics:container-status',
4345
'khronos:metrics:report-org-container-status',
4446
'khronos:weave:prune',

lib/tasks/instances/cleanup.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict'
2+
3+
// external
4+
const Promise = require('bluebird')
5+
const rabbitmq = require('models/rabbitmq')
6+
const mongodbHelper = require('tasks/utils/mongodb')
7+
const moment = require('moment')
8+
9+
// internal
10+
const logger = require('logger').getChild(__filename)
11+
12+
module.exports = CleanupInstances
13+
14+
function CleanupInstances () {
15+
const cleanupDate = moment().subtract(7, 'days').toDate()
16+
var log = logger.child({
17+
cleanupCutoff: cleanupDate
18+
})
19+
log.info('CleanupInstances')
20+
21+
return Promise.using(mongodbHelper(), function (mongoClient) {
22+
return mongoClient.fetchInstancesAsync({
23+
masterPod: false,
24+
'contextVersion.created': { $lt: cleanupDate },
25+
$or: [
26+
{ isolated: { $exists: false } },
27+
{ isIsolationGroupMaster: true }
28+
]
29+
})
30+
})
31+
.then(function (instances) {
32+
log.info({
33+
instanceCount: instances.length,
34+
instanceIds: instances.map(function (instance) {
35+
return instance._id
36+
})
37+
}, 'Found instances to cleanup')
38+
instances.forEach(function (instance) {
39+
rabbitmq.publishEvent('instance.expired', {
40+
instanceId: instance._id
41+
})
42+
})
43+
})
44+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"keypather": "^1.10.1",
6565
"loadenv": "^2.2.0",
6666
"lodash": "^4.14.0",
67+
"moment": "^2.14.1",
6768
"mongodb": "2.1.7",
6869
"monitor-dog": "^1.5.0",
6970
"ponos": "^4.6.0",
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
'use strict'
2+
3+
require('loadenv')({ debugName: 'khronos:test' })
4+
5+
var chai = require('chai')
6+
var assert = chai.assert
7+
chai.use(require('chai-as-promised'))
8+
9+
// external
10+
var rabbitmq = require('models/rabbitmq')
11+
var sinon = require('sinon')
12+
require('sinon-as-promised')(require('bluebird'))
13+
14+
// Internal
15+
const MongoDB = require('models/mongodb')
16+
17+
// internal (being tested)
18+
var CleanupInstances = require('tasks/instances/cleanup')
19+
20+
describe('khronos:instances:cleanup', function () {
21+
var mockInstances
22+
23+
beforeEach(function () {
24+
mockInstances = [
25+
{
26+
_id: '1234'
27+
},
28+
{
29+
_id: '5678'
30+
}
31+
]
32+
sinon.stub(MongoDB.prototype, 'close').yieldsAsync()
33+
sinon.stub(MongoDB.prototype, 'connect').yieldsAsync()
34+
sinon.stub(MongoDB.prototype, 'fetchInstances').yieldsAsync(null, mockInstances)
35+
sinon.stub(rabbitmq, 'publishEvent').resolves()
36+
})
37+
38+
afterEach(function () {
39+
MongoDB.prototype.close.restore()
40+
MongoDB.prototype.connect.restore()
41+
MongoDB.prototype.fetchInstances.restore()
42+
rabbitmq.publishEvent.restore()
43+
})
44+
45+
describe('when there are instances to cleanup', function () {
46+
it('should fetch instances with the propery query parameters', function (done) {
47+
return assert.isFulfilled(CleanupInstances({}))
48+
.then(function () {
49+
sinon.assert.calledOnce(MongoDB.prototype.fetchInstances)
50+
sinon.assert.calledWith(
51+
MongoDB.prototype.fetchInstances,
52+
{
53+
masterPod: false,
54+
'contextVersion.created': { $lt: sinon.match.date },
55+
$or: [
56+
{ isolated: { $exists: false } },
57+
{ isIsolationGroupMaster: true }
58+
]
59+
}
60+
)
61+
})
62+
.asCallback(done)
63+
})
64+
65+
it('should cleanup the old instances', function (done) {
66+
return assert.isFulfilled(CleanupInstances({}))
67+
.then(function () {
68+
sinon.assert.calledTwice(rabbitmq.publishEvent)
69+
sinon.assert.calledWith(
70+
rabbitmq.publishEvent,
71+
'instance.expired',
72+
{
73+
instanceId: '1234'
74+
}
75+
)
76+
sinon.assert.calledWith(
77+
rabbitmq.publishEvent,
78+
'instance.expired',
79+
{
80+
instanceId: '5678'
81+
}
82+
)
83+
})
84+
.asCallback(done)
85+
})
86+
})
87+
})

0 commit comments

Comments
 (0)