Skip to content

Instantly share code, notes, and snippets.

@tizzo
Last active January 23, 2020 16:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tizzo/4937e577f3100e3828f57bdd92d187fd to your computer and use it in GitHub Desktop.
Save tizzo/4937e577f3100e3828f57bdd92d187fd to your computer and use it in GitHub Desktop.
Test dropped requests during a rolling kubernetes deployment.
const fetch = require('node-fetch');
const aggregation = [];
function getTextFromFetchError(error) {
let message = '';
switch (error.message) {
case 'Only HTTP(S) protocols are supported':
message = 'Did you forget the scheme (http:// or https://) in the cli argument?';
break;
default:
message = error.message;
break;
}
return message;
}
async function makeRequest() {
const time = Date.now();
try {
const response = await fetch(process.argv[2]);
const text = await response.text()
aggregation.push({ time: Date.now(), text, status: await response.status});
console.log(`${text} ${response.status} ${Date.now() - time}ms`);
} catch(e) {
const text = getTextFromFetchError(e);
aggregation.push({ time: Date.now(), text, status: await -1 });
console.log(`Errored connection after ${Date.now() - time}ms - ${text}`);
}
}
function printSummary() {
const summary = aggregation.reduce((memo, current) => {
if (memo.responses[current.text] === undefined) {
memo.responses[current.text] = 0;
} else {
memo.responses[current.text]++;
}
if (memo.statusCodes[current.status] === undefined) {
memo.statusCodes[current.status] = 0;
} else {
memo.statusCodes[current.status]++;
}
return memo;
}, {responses: {}, statusCodes: {}});
console.log(summary);
}
function signalHandler(interval) {
console.log('Signal received');
clearInterval(interval);
}
async function main() {
const interval = setInterval(makeRequest, 500);
const handler = signalHandler.bind(null, interval);
process.on('SIGINT', handler);
process.on('SIGHUP', handler);
process.on('SIGTERM', handler);
process.on('exit', printSummary);
}
try {
main();
} catch (e) {
console.log(e);
}
FROM node:alpine
WORKDIR /app
COPY server.js .
CMD node /app/server.js
CURRENT="$(kubectl --context=minikube get deployment -o json hello-world | jq -r '.spec.template.spec.containers[0].env[0].value')"
if [ "${CURRENT}" = "Response A" ]; then
MESSAGE="Response B"
else
MESSAGE="Response A"
fi
##kubectl --containers=minikube patch deployment hello-world --context=$ENV --patch "{\"spec\": {\"template\": {\"spec\": {\"containers\": [{\"name\": \"${SERVICE}\",\"env\": [ {\"NAME\": \"${MESSAGE}\"}]}]}}}}"
kubectl --context=minikube patch deployment hello-world --type='json' -p="[{\"op\": \"replace\", \"path\": \"/spec/template/spec/containers/0/env/0/value\", \"value\": \"${MESSAGE}\"}]"
const http = require('http');
const server = http.createServer((req, res) => {
console.log('Request received');
if (process.env.SIMULATE_CONNECTION_FAIULRE) {
res.socket.destroy();
console.log('Killing the connection');
return;
} else {
setTimeout(() => {
const message = `Response sent by ${process.env.NAME ? process.env.NAME : 'Node service' } ${process.env.HOSTNAME || '' }`;
console.log(message);
res.end(message);
}, process.env.TIMEOUT || 10000);
}
});
function signalHandler() {
console.log('Signal received, shutting down.');
server.close()
}
if (process.env.HANDLE_SIGNALS) {
console.log('Properly handling signals');
process.on('SIGINT', signalHandler);
process.on('SIGHUP', signalHandler);
process.on('SIGTERM', signalHandler);
} else {
console.log('Not handling signals!');
}
server.listen(process.env.PORT || 3333, () => {console.log('now listening')});
kind: Service
apiVersion: v1
metadata:
name: hello-world
spec:
selector:
app: hello-world
type: NodePort
ports:
- protocol: TCP
port: 3333
targetPort: 3333
nodePort: 32222
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
labels:
app: hello-world
spec:
replicas: 2
selector:
matchLabels:
app: hello-world
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: hello-world:hostname
env:
- name: NAME
value: "Response A"
- name: TIMEOUT
value: "15000"
- name: HANDLE_SIGNALS
value: "1"
ports:
- containerPort: 3333
terminationGracePeriodSeconds: 16
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
bluebird@^3.5.0:
version "3.5.4"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.4.tgz#d6cc661595de30d5b3af5fcedd3c0b3ef6ec5714"
integrity sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==
lodash@^4.17.11:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
node-fetch@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5"
integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA==
psl@^1.1.28:
version "1.1.31"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184"
integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==
punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
request-promise-core@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346"
integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==
dependencies:
lodash "^4.17.11"
request-promise@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.4.tgz#1c5ed0d71441e38ad58c7ce4ea4ea5b06d54b310"
integrity sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==
dependencies:
bluebird "^3.5.0"
request-promise-core "1.1.2"
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
stealthy-require@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
tough-cookie@^2.3.3:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment