Skip to content

Commit a124052

Browse files
authored
Merge pull request #177 from StackStorm/refactor-stackstorm.js
Refactor stackstorm.js a bit
2 parents 9ff1f43 + cddd43a commit a124052

10 files changed

+313
-136
lines changed

CHANGELOG.rst

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ in development
55
--------------
66

77
* Move babel-eslint dependency to devDependencies (bug fix)
8+
* Small refactor and more tests (for `scripts/stackstorm.js`) (improvement)
89

910
0.9.6
1011
-----

lib/slack-messages.js

-31
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,6 @@
1616

1717
var utils = require('./utils.js');
1818

19-
// Polyfill from:
20-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
21-
if (typeof Object.assign !== 'function') {
22-
// Must be writable: true, enumerable: false, configurable: true
23-
Object.defineProperty(Object, "assign", {
24-
value: function assign(target, varArgs) { // .length of function is 2
25-
if (target === null) { // TypeError if undefined or null
26-
throw new TypeError('Cannot convert undefined or null to object');
27-
}
28-
29-
var to = Object(target);
30-
31-
for (var index = 1; index < arguments.length; index++) {
32-
var nextSource = arguments[index];
33-
34-
if (nextSource !== null) { // Skip over if undefined or null
35-
for (var nextKey in nextSource) {
36-
// Avoid bugs when hasOwnProperty is shadowed
37-
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
38-
to[nextKey] = nextSource[nextKey];
39-
}
40-
}
41-
}
42-
}
43-
return to;
44-
},
45-
writable: true,
46-
configurable: true
47-
});
48-
}
49-
5019
var buildMessagesWithChunkedFieldValue = function (msg) {
5120
var msgs;
5221

lib/slack_monkey_patch.js

+12
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ function patchSendMessage(robot) {
2424
// formatted and parsed on the server side.
2525
// NOTE / TODO: We can get rid of this nasty patch once our node-slack-client and hubot-slack pull
2626
// requests are merged.
27+
// This code was refactored in https://github.com/StackStorm/hubot-stackstorm/pull/6
28+
// which was opened and merged by Kami on 2015-06-04.
29+
// As of 2019-05-22, these were the PRs I could find for the node-slack-client
30+
// hubot-slack repositories:
31+
// * https://github.com/slackapi/node-slack-sdk/pull/42
32+
// - which was closed during a refactor and converted into an issue:
33+
// https://github.com/slackapi/node-slack-sdk/issues/138
34+
// * https://github.com/slackapi/hubot-slack/pull/544
35+
// - which was opened on 2018-11-14, which seems to be too late to actually
36+
// apply to this code
37+
// So...I'm not entirely sure this monkey patch is still necessary.
38+
// End-to-end testing is required to figure out for sure.
2739
if (robot.adapter && robot.adapter.constructor && robot.adapter.constructor.name === 'SlackBot') {
2840
for (var channel in robot.adapter.client.channels) {
2941
robot.adapter.client.channels[channel].sendMessage = sendMessageRaw.bind(robot.adapter.client.channels[channel]);

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,15 @@
4040
"eslint": "^5.16.0",
4141
"eslint-plugin-notice": "0.7.8",
4242
"gulp": "^3.9.1",
43-
"gulp-load-plugins": "1.5.0",
4443
"gulp-eslint": "^5.0.0",
44+
"gulp-load-plugins": "1.5.0",
4545
"gulp-mocha": "^6.0.0",
4646
"gulp-plumber": "^1.2.0",
4747
"hubot": "^3.1.1",
4848
"hubot-help": "0.2.2",
4949
"hubot-mock-adapter": "^1.1.1",
5050
"log": "1.4.0",
51+
"mocked-env": "^1.3.1",
5152
"nock": "^10.0.0",
5253
"nyc": "^13.0.1",
5354
"sinon": "^6.3.5",

scripts/stackstorm.js

+53-53
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,16 @@ module.exports = function(robot) {
129129
if (env.ST2_API) {
130130
robot.logger.warning("ST2_API is deprecated and will be removed in a future releases. Instead, please use the ST2_API_URL environment variable.");
131131
}
132-
var url = utils.parseUrl(env.ST2_API_URL);
133-
134-
var opts = {
135-
protocol: url.protocol,
136-
host: url.hostname,
137-
port: url.port,
138-
prefix: url.path,
139-
rejectUnauthorized: false
140-
};
132+
var self = this,
133+
authenticated = Promise.resolve(),
134+
url = utils.parseUrl(env.ST2_API_URL),
135+
opts = {
136+
protocol: url.protocol,
137+
host: url.hostname,
138+
port: url.port,
139+
prefix: url.path,
140+
rejectUnauthorized: false
141+
};
141142

142143
if (env.ST2_STREAM_URL) {
143144
var stream_url = utils.parseUrl(env.ST2_STREAM_URL);
@@ -149,16 +150,10 @@ module.exports = function(robot) {
149150
};
150151
}
151152

152-
var api = st2client(opts);
153-
154-
if (env.ST2_API_KEY) {
155-
api.setKey({ key: env.ST2_API_KEY });
156-
} else if (env.ST2_AUTH_TOKEN) {
157-
api.setToken({ token: env.ST2_AUTH_TOKEN });
158-
}
153+
var api_client = st2client(opts);
159154

160155
function authenticate() {
161-
api.removeListener('expiry', authenticate);
156+
api_client.removeListener('expiry', authenticate);
162157

163158
// API key gets precedence 1
164159
if (env.ST2_API_KEY) {
@@ -175,7 +170,7 @@ module.exports = function(robot) {
175170

176171
var url = utils.parseUrl(env.ST2_AUTH_URL);
177172

178-
var client = st2client({
173+
var auth_client = st2client({
179174
auth: {
180175
protocol: url.protocol,
181176
host: url.hostname,
@@ -184,11 +179,11 @@ module.exports = function(robot) {
184179
}
185180
});
186181

187-
return client.authenticate(env.ST2_AUTH_USERNAME, env.ST2_AUTH_PASSWORD)
182+
return auth_client.authenticate(env.ST2_AUTH_USERNAME, env.ST2_AUTH_PASSWORD)
188183
.then(function (token) {
189184
robot.logger.info('Token received. Expiring ' + token.expiry);
190-
api.setToken(token);
191-
client.on('expiry', authenticate);
185+
api_client.setToken(token);
186+
auth_client.on('expiry', authenticate);
192187
})
193188
.catch(function (err) {
194189
robot.logger.error('Failed to authenticate: ' + err.message);
@@ -197,21 +192,6 @@ module.exports = function(robot) {
197192
});
198193
}
199194

200-
if (env.ST2_API_KEY || env.ST2_AUTH_TOKEN || env.ST2_AUTH_USERNAME || env.ST2_AUTH_PASSWORD) {
201-
// If using username and password then all are required.
202-
if ((env.ST2_AUTH_USERNAME || env.ST2_AUTH_PASSWORD) &&
203-
!(env.ST2_AUTH_USERNAME && env.ST2_AUTH_PASSWORD && env.ST2_AUTH_URL)) {
204-
throw new Error('Env variables ST2_AUTH_USERNAME, ST2_AUTH_PASSWORD and ST2_AUTH_URL should only be used together.');
205-
}
206-
promise = authenticate();
207-
}
208-
209-
// Pending 2-factor auth commands
210-
if (env.HUBOT_2FA) {
211-
var twofactor = {};
212-
robot.logger.info('Two-factor auth is enabled');
213-
}
214-
215195
// factory to manage commands
216196
var command_factory = new CommandFactory(robot);
217197

@@ -224,7 +204,7 @@ module.exports = function(robot) {
224204
var loadCommands = function() {
225205
robot.logger.info('Loading commands....');
226206

227-
api.actionAlias.list({limit: -1})
207+
api_client.actionAlias.list({limit: -1})
228208
.then(function (aliases) {
229209
// Remove all the existing commands
230210
command_factory.removeCommands();
@@ -288,7 +268,7 @@ module.exports = function(robot) {
288268
var sendAliasExecutionRequest = function (msg, payload) {
289269
robot.logger.debug('Sending command payload:', JSON.stringify(payload));
290270

291-
api.aliasExecution.create(payload)
271+
api_client.aliasExecution.create(payload)
292272
.then(function (res) { sendAck(msg, res); })
293273
.catch(function (err) {
294274
// Compatibility with older StackStorm versions
@@ -331,7 +311,7 @@ module.exports = function(robot) {
331311
var twofactor_id = uuid.v4();
332312
robot.logger.debug('Requested an action that requires 2FA. Guid: ' + twofactor_id);
333313
msg.send(TWOFACTOR_MESSAGE);
334-
api.executions.create({
314+
api_client.executions.create({
335315
'action': env.HUBOT_2FA,
336316
'parameters': {
337317
'uuid': twofactor_id,
@@ -350,7 +330,7 @@ module.exports = function(robot) {
350330
};
351331

352332
robot.respond(/([\s\S]+?)$/i, function(msg) {
353-
var command, result, command_name, format_string, action_alias;
333+
var command, result;
354334

355335
// Normalize the command and remove special handling provided by the chat service.
356336
// e.g. slack replace quote marks with left double quote which would break behavior.
@@ -363,9 +343,7 @@ module.exports = function(robot) {
363343
return;
364344
}
365345

366-
command_name = result[0];
367-
format_string = result[1];
368-
action_alias = result[2];
346+
var [command_name, format_string, action_alias] = result;
369347

370348
executeCommand(msg, command_name, format_string, command, action_alias);
371349
});
@@ -392,17 +370,17 @@ module.exports = function(robot) {
392370
var commands_load_interval;
393371

394372
function start() {
395-
api.stream.listen().catch(function (err) {
373+
api_client.stream.listen().catch(function (err) {
396374
robot.logger.error('Unable to connect to stream:', err);
397-
}).then(function (source) {
398-
source.onerror = function (err) {
375+
}).then(function (st2stream) {
376+
st2stream.onerror = function (err) {
399377
// TODO: squeeze a little bit more info out of evensource.js
400-
robot.logger.error('Stream error:', err);
378+
robot.logger.warning('Stream error:', err);
401379
if (err.status === 401) {
402380
throw err;
403381
}
404382
};
405-
source.addEventListener('st2.announcement__chatops', function (e) {
383+
st2stream.addEventListener('st2.announcement__chatops', function (e) {
406384
var data;
407385

408386
robot.logger.debug('Chatops message received:', e.data);
@@ -417,7 +395,7 @@ module.exports = function(robot) {
417395
});
418396

419397
if (env.HUBOT_2FA) {
420-
source.addEventListener('st2.announcement__2fa', function (e) {
398+
st2stream.addEventListener('st2.announcement__2fa', function (e) {
421399
var data;
422400

423401
robot.logger.debug('Successfull two-factor auth:', e.data);
@@ -447,21 +425,43 @@ module.exports = function(robot) {
447425

448426
function stop() {
449427
clearInterval(commands_load_interval);
450-
api.stream.listen().then(function (source) {
451-
source.removeAllListeners();
452-
source.close();
428+
api_client.stream.listen().then(function (st2stream) {
429+
st2stream.removeAllListeners();
430+
st2stream.close();
453431
});
454432
}
455433

456434
function install_sigusr2_handler() {
457435
process.on('SIGUSR2', function() {
436+
robot.logger.debug("Caught SIGUSR2, reloading commands");
458437
loadCommands();
459438
});
460439
}
461440

441+
if (env.ST2_API_KEY) {
442+
api_client.setKey({ key: env.ST2_API_KEY });
443+
} else if (env.ST2_AUTH_TOKEN) {
444+
api_client.setToken({ token: env.ST2_AUTH_TOKEN });
445+
}
446+
447+
if (env.ST2_API_KEY || env.ST2_AUTH_TOKEN || env.ST2_AUTH_USERNAME || env.ST2_AUTH_PASSWORD) {
448+
// If using username and password then all are required.
449+
if ((env.ST2_AUTH_USERNAME || env.ST2_AUTH_PASSWORD) &&
450+
!(env.ST2_AUTH_USERNAME && env.ST2_AUTH_PASSWORD && env.ST2_AUTH_URL)) {
451+
throw new Error('Env variables ST2_AUTH_USERNAME, ST2_AUTH_PASSWORD and ST2_AUTH_URL should only be used together.');
452+
}
453+
authenticated = authenticate();
454+
}
455+
456+
// Pending 2-factor auth commands
457+
if (env.HUBOT_2FA) {
458+
var twofactor = {};
459+
robot.logger.info('Two-factor auth is enabled');
460+
}
461+
462462
// Authenticate with StackStorm backend and then call start.
463463
// On a failure to authenticate log the error but do not quit.
464-
return promise.then(function () {
464+
return authenticated.then(function () {
465465
start();
466466
return stop;
467467
});

tests/dummy-logger.js

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
Licensed to the StackStorm, Inc ('StackStorm') under one or more
3+
contributor license agreements. See the NOTICE file distributed with
4+
this work for additional information regarding copyright ownership.
5+
The ASF licenses this file to You under the Apache License, Version 2.0
6+
(the "License"); you may not use this file except in compliance with
7+
the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
"use strict";
19+
20+
21+
22+
function Logger(enabled) {
23+
this.enabled = enabled;
24+
this.logs = {
25+
error: [],
26+
warning: [],
27+
info: [],
28+
debug: []
29+
};
30+
31+
this.error = function(msg) {
32+
if (this.enabled) {
33+
this.logs.error.push(msg);
34+
}
35+
};
36+
37+
this.warning = function(msg) {
38+
if (this.enabled) {
39+
this.logs.warning.push(msg);
40+
}
41+
};
42+
43+
this.info = function(msg) {
44+
if (this.enabled) {
45+
this.logs.info.push(msg);
46+
}
47+
};
48+
49+
this.debug = function(msg) {
50+
if (this.enabled) {
51+
this.logs.debug.push(msg);
52+
}
53+
};
54+
}
55+
56+
module.exports = Logger;

0 commit comments

Comments
 (0)