forked from digi-serve/ab_runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
171 lines (157 loc) · 5.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
const net = require("net");
const fs = require("fs");
const shell = require("shelljs");
const async = require("async");
const AB = require("ab-utils");
// const SOCKETFILE = "1338";
// const SOCKETFILE = "/tmp/ab.sock";
let connections = {};
let server = null;
let currStream = null;
var isReportRunning = false;
var checkID = null;
// Net
// Connections to the running bot_manager in our swarm.
//
const config = AB.config("bot_manager");
var isSockConnection = true;
var SOCKETFILE = "/tmp/ab.sock";
var PORT = "1338";
var ACCESSTOKEN = "ThereIsN0Sp00n";
if (
!config.hostConnection.sharedSock ||
!config.hostConnection.sharedSock.path
) {
isSockConnection = false;
if (
!config.hostConnection.tcp ||
!config.hostConnection.tcp.port ||
!config.hostConnection.tcp.accessToken
) {
console.error(
"ERROR: config/local.js must specify a bot_manager.hostConnection."
);
process.exit(1);
}
}
if (isSockConnection) {
SOCKETFILE = config.hostConnection.sharedSock.path;
} else {
PORT = config.hostConnection.tcp.port;
ACCESSTOKEN = config.hostConnection.tcp.accessToken;
}
/**
* checkRunning
* A repeated check to see if all services are up and running.
* it performs a : docker service ls
* and scans stdout to see if any of the service report 0/x
* If everything seems to be running, a "__running" message is sent
* to our connected botManager.
* If a downed service is detected, then a "__offline:[service,...]"
* is sent to our connected botManager.
*/
var downCheck = /0\/\d/;
var parseLine = /(\w+)\s+(\w+)\s+\w+\s+0\/\d+\s+([\w\/:-]+)/g;
// ID NAME MODE REPLICAS IMAGE PORTS
// h8bx5qewkeaq ab_apiSails replicated 1/1 skipdaddy/ab-api-sails:master *:1337->1337/tcp
// parseLine 1:ID, 2:Name, 3:Image
function checkRunning() {
// make sure our connection to our botManager is ok before trying:
if (currStream && !currStream.destroyed) {
shell.exec("docker service ls", (code, stdout, stderr) => {
if (code == 0) {
if (stdout.search(downCheck) == -1) {
if (isReportRunning) {
console.log("... looks like server is running.");
currStream.write("__running");
isReportRunning = false;
}
} else {
var lines = stdout.split("\n");
var offlineContainers = [];
lines.forEach(l => {
var match = parseLine.exec(l);
if (match) {
offlineContainers.push(`${match[2]}`); // ${match[2]}(${match[3]})
}
});
if (offlineContainers.length > 0) {
currStream.write("__offline:" + offlineContainers.join(","));
isReportRunning = true;
}
}
}
});
} else {
console.log("connection to botManager is not active.");
}
}
function createServer(socket) {
console.log("Creating server.");
var server = net
.createServer(function(stream) {
console.log("Connection acknowledged.");
currStream = stream;
stream._sentValidToken = false;
// Store all connections so we can terminate them if the server closes.
// An object is better than an array for these.
var self = Date.now();
connections[self] = stream;
stream.on("end", function() {
console.log("Client disconnected.");
delete connections[self];
});
// Messages are buffers. use toString
stream.on("data", function(msg) {
msg = msg.toString();
console.log("Client:", msg);
// verify access token if necessary
if (!isSockConnection && !stream._sentValidToken) {
if (msg == ACCESSTOKEN) {
stream._sentValidToken = true;
console.log("... accessToken accepted.");
} else {
console.log("... accessToken REJECTED!");
}
} else {
// else execute a command:
shell.exec(msg, (code, stdout, stderr) => {
// console.log("code:", code);
// console.log("stdout:", stdout);
// console.log("stderr:", stderr);
// indicate we need to report when everything is running
isReportRunning = true;
stream.write("__done"); // command is done
});
}
});
})
.listen(socket)
.on("connection", function(socket) {
console.log("Client connected.");
});
return server;
}
// manage unix socket:
console.log("Checking for leftover socket.");
fs.stat(SOCKETFILE, function(err, stats) {
if (err) {
// start server
console.log("No leftover socket found.");
server = createServer(isSockConnection ? SOCKETFILE : PORT);
return;
}
// remove file then start server
console.log("Removing leftover socket.");
fs.unlink(SOCKETFILE, function(err) {
if (err) {
// This should never happen.
console.error(err);
process.exit(0);
}
server = createServer(isSockConnection ? SOCKETFILE : PORT);
return;
});
});
// now setup our checkRunning() operation
setInterval(checkRunning, 5 * 1000);