Test dropped requests during a rolling kubernetes deployment.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM node:alpine | |
WORKDIR /app | |
COPY server.js . | |
CMD node /app/server.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}\"}]" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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')}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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