Skip to content

Commit 64752bf

Browse files
authored
Merge pull request #22 from gunnargrosch/develop
Develop
2 parents 08ff4c5 + d643638 commit 64752bf

File tree

1 file changed

+104
-61
lines changed

1 file changed

+104
-61
lines changed

lib/failure.js

+104-61
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,137 @@
1-
'use strict'
2-
const aws = require('aws-sdk')
3-
const ssm = new aws.SSM()
4-
const fetch = require('node-fetch')
5-
const childProcess = require('child_process')
6-
const Mitm = require('mitm')
1+
"use strict";
2+
const aws = require("aws-sdk");
3+
const ssm = new aws.SSM();
4+
const fetch = require("node-fetch");
5+
const childProcess = require("child_process");
6+
const Mitm = require("mitm");
77

8-
async function getConfig () {
9-
const defaults = {
10-
isEnabled: false
8+
var mitm = null;
9+
10+
function clearMitm() {
11+
if (mitm != null) {
12+
mitm.disable();
1113
}
14+
}
15+
16+
async function getConfig() {
17+
const defaults = {
18+
isEnabled: false,
19+
};
1220
if (process.env.FAILURE_APPCONFIG_CONFIGURATION) {
1321
try {
1422
if (process.env.AWS_APPCONFIG_EXTENSION_HTTP_PORT) {
15-
var appconfigPort = process.env.AWS_APPCONFIG_EXTENSION_HTTP_PORT
23+
var appconfigPort = process.env.AWS_APPCONFIG_EXTENSION_HTTP_PORT;
1624
} else {
17-
var appconfigPort = 2772
25+
var appconfigPort = 2772;
1826
}
19-
const url = 'http://localhost:' + appconfigPort + '/applications/' + process.env.FAILURE_APPCONFIG_APPLICATION + '/environments/' + process.env.FAILURE_APPCONFIG_ENVIRONMENT + '/configurations/' + process.env.FAILURE_APPCONFIG_CONFIGURATION
20-
const response = await fetch(url)
21-
const json = await response.json()
22-
return json
27+
const url =
28+
"http://localhost:" +
29+
appconfigPort +
30+
"/applications/" +
31+
process.env.FAILURE_APPCONFIG_APPLICATION +
32+
"/environments/" +
33+
process.env.FAILURE_APPCONFIG_ENVIRONMENT +
34+
"/configurations/" +
35+
process.env.FAILURE_APPCONFIG_CONFIGURATION;
36+
const response = await fetch(url);
37+
const json = await response.json();
38+
return json;
2339
} catch (err) {
24-
console.error(err)
25-
return defaults
40+
console.error(err);
41+
return defaults;
2642
}
2743
} else if (process.env.FAILURE_INJECTION_PARAM) {
2844
try {
2945
let params = {
30-
Name: process.env.FAILURE_INJECTION_PARAM
31-
}
32-
let response = await ssm.getParameter(params).promise()
33-
let json = JSON.parse(response.Parameter.Value)
34-
return json
46+
Name: process.env.FAILURE_INJECTION_PARAM,
47+
};
48+
let response = await ssm.getParameter(params).promise();
49+
let json = JSON.parse(response.Parameter.Value);
50+
return json;
3551
} catch (err) {
36-
console.error(err)
37-
return defaults
52+
console.error(err);
53+
return defaults;
3854
}
3955
} else {
40-
return defaults
56+
return defaults;
4157
}
4258
}
4359
var injectFailure = function (fn) {
4460
return async function () {
4561
try {
46-
let config = await getConfig()
62+
let config = await getConfig();
63+
64+
if (config.isEnabled === false || config.failureMode != "denylist") {
65+
clearMitm();
66+
}
67+
4768
if (config.isEnabled === true && Math.random() < config.rate) {
48-
if (config.failureMode === 'latency') {
49-
let latencyRange = config.maxLatency - config.minLatency
50-
let setLatency = Math.floor(config.minLatency + Math.random() * latencyRange)
51-
console.log('Injecting ' + setLatency + ' ms latency.')
52-
await new Promise(resolve => setTimeout(resolve, setLatency))
53-
} else if (config.failureMode === 'exception') {
54-
console.log('Injecting exception message: ' + config.exceptionMsg)
55-
throw new Error(config.exceptionMsg)
56-
} else if (config.failureMode === 'statuscode') {
57-
console.log('Injecting status code: ' + config.statusCode)
58-
let response = { statusCode: config.statusCode }
59-
return response
60-
} else if (config.failureMode === 'diskspace') {
61-
console.log('Injecting disk space: ' + config.diskSpace + ' MB')
62-
childProcess.spawnSync('dd', ['if=/dev/zero', 'of=/tmp/diskspace-failure-' + Date.now() + '.tmp', 'count=1000', 'bs=' + config.diskSpace * 1000])
63-
} else if (config.failureMode === 'denylist') {
64-
console.log('Injecting dependency failure through a network block for denylisted sites: ' + config.denylist)
65-
let mitm = Mitm()
66-
let blRegexs = []
69+
if (config.failureMode === "latency") {
70+
let latencyRange = config.maxLatency - config.minLatency;
71+
let setLatency = Math.floor(
72+
config.minLatency + Math.random() * latencyRange
73+
);
74+
console.log("Injecting " + setLatency + " ms latency.");
75+
await new Promise((resolve) => setTimeout(resolve, setLatency));
76+
} else if (config.failureMode === "exception") {
77+
console.log("Injecting exception message: " + config.exceptionMsg);
78+
throw new Error(config.exceptionMsg);
79+
} else if (config.failureMode === "statuscode") {
80+
console.log("Injecting status code: " + config.statusCode);
81+
let response = { statusCode: config.statusCode };
82+
return response;
83+
} else if (config.failureMode === "diskspace") {
84+
console.log("Injecting disk space: " + config.diskSpace + " MB");
85+
childProcess.spawnSync("dd", [
86+
"if=/dev/zero",
87+
"of=/tmp/diskspace-failure-" + Date.now() + ".tmp",
88+
"count=1000",
89+
"bs=" + config.diskSpace * 1000,
90+
]);
91+
} else if (config.failureMode === "denylist") {
92+
console.log(
93+
"Injecting dependency failure through a network block for denylisted sites: " +
94+
config.denylist
95+
);
96+
97+
// if the global mitm doesn't yet exist, create it now
98+
if (mitm == null) {
99+
mitm = Mitm();
100+
}
101+
mitm.enable();
102+
103+
// attach a handler to filter the configured deny patterns
104+
let blRegexs = [];
67105
config.denylist.forEach(function (regexStr) {
68-
blRegexs.push(new RegExp(regexStr))
69-
})
70-
mitm.on('connect', function (socket, opts) {
71-
let block = false
106+
blRegexs.push(new RegExp(regexStr));
107+
});
108+
mitm.on("connect", function (socket, opts) {
109+
let block = false;
72110
blRegexs.forEach(function (blRegex) {
73111
if (blRegex.test(opts.host)) {
74-
console.log('Intercepted network connection to ' + opts.host)
75-
block = true
112+
console.log("Intercepted network connection to " + opts.host);
113+
block = true;
76114
}
77-
})
115+
});
78116
if (block) {
79-
socket.end()
117+
socket.end();
80118
} else {
81-
socket.bypass()
119+
socket.bypass();
82120
}
83-
})
121+
});
122+
123+
// remove any previously attached handlers, leaving only the most recently added
124+
while (typeof mitm._events.connect != "function") {
125+
mitm.removeListener("connect", mitm._events.connect[0]);
126+
}
84127
}
85128
}
86-
return fn.apply(this, arguments)
129+
return fn.apply(this, arguments);
87130
} catch (ex) {
88-
console.log(ex)
89-
throw ex
131+
console.log(ex);
132+
throw ex;
90133
}
91-
}
92-
}
134+
};
135+
};
93136

94-
module.exports = injectFailure
137+
module.exports = injectFailure;

0 commit comments

Comments
 (0)