forked from lblod/docker-monitor-service
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
128 lines (117 loc) · 4.08 KB
/
app.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
import { app, query, sparqlEscapeUri } from 'mu';
import Docker from 'dockerode';
import Container from './container';
const docker = new Docker({ socketPath: process.env.MONITOR_DOCKER_SOCKET });
const listContainers = function() {
return new Promise(function(resolve, reject) {
docker.listContainers(
{ all : true },
function(err, containers) {
if (err)
reject(err);
else
resolve(containers);
});
});
};
const getCurrentContainers = async function() {
let filter = process.env.MONITOR_FILTER_LABEL ? {filter: process.env.MONITOR_FILTER_LABEL } : {};
let containers = await listContainers();
return containers.map( (container) => {
const labels = {};
for (let key of Object.keys(container["Labels"])) {
labels[key] = {value: container["Labels"][key]};
}
return {
id: container["Id"],
name: container["Names"][0],
status: container["State"],
image: container["Image"],
labels: labels
};
});
};
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
};
const awaitGeneric = async function(successMessage, errorMessage, call) {
let delay = 1;
while (true) {
try {
const list = await call();
console.info(successMessage);
return;
}
catch(e) {
console.warn(e);
console.warn(`ERROR: ${errorMessage}, waiting ${delay} seconds and retrying`);
await timeout(1000*delay);
delay = delay * 2;
}
}
}
const awaitDb = async function() {
let call = async function () {
await query('ASK {?s ?p ?o}');
};
await awaitGeneric('successfully connected to database', 'failed to connect to database', call);
};
const awaitDocker = async function() {
await awaitGeneric('successfully connected to docker daemon', 'failed to connect to docker daemon', listContainers);
};
let syncStatePromise = null;
const syncState = async function() {
try {
if (syncStatePromise) {
// we may return after an _older_ syncState finishes rather than
// after the one ran after we are called but because this is called
// every so often, that's not an effective problem at this point in
// time.
console.log(`Waiting for existing syncStatePromise to finish`);
await syncStatePromise;
return;
} else {
syncStatePromise = new Promise(async (acc, rej) => {
try {
console.log(`Syncing container state in triplestore with containers running on the system`);
let containersInDocker = await getCurrentContainers(docker);
console.log(`Found ${containersInDocker.length} docker containers running on the system`);
let activeContainersInDb = await Container.findAll();
console.log(`Found ${activeContainersInDb.length} existing docker containers in the triplestore.`);
// update stale_information
for (let container of activeContainersInDb) {
let index = containersInDocker.findIndex((c) => c.id === container.id);
if (index > -1) {
let current_container_info = containersInDocker[index];
container.update(current_container_info);
await container.save();
containersInDocker.splice(index, 1);
}
else if (container.status != "removed") {
console.log(`Set container ${container.name} status to removed because it is no longer running.`);
await container.remove();
}
}
// create missing containers
for (let newContainer of containersInDocker) {
console.log(`New container found: ${newContainer.name}.`);
await (new Container(newContainer)).save(true);
}
acc();
} catch (e) {
rej(e);
}
});
try {
await syncStatePromise;
} finally {
syncStatePromise = null;
return;
}
}
} catch(e) {
console.error(`Failed to sync state`);
console.trace(e);
}
};
awaitDb().then( () => awaitDocker().then( () => setInterval(syncState, process.env.MONITOR_SYNC_INTERVAL)));