Skip to content

Commit

Permalink
Merge pull request #3 from Webiks/persistent_stress_tests
Browse files Browse the repository at this point in the history
Persistent stress tests
  • Loading branch information
shacharmo authored Nov 6, 2019
2 parents cb79839 + 1d26d99 commit 877b54a
Show file tree
Hide file tree
Showing 15 changed files with 166 additions and 108 deletions.
3 changes: 2 additions & 1 deletion config/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"server": {
"PORT": 3000
"PORT": 3000,
"cronJobFile": "stressTests.json"
},
"cron": {
"options": {
Expand Down
2 changes: 2 additions & 0 deletions config/stressTests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[
]
13 changes: 13 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: '3.2'

services:
cron_server:
image: 223455578796.dkr.ecr.us-west-2.amazonaws.com/monitor-stress:latest
restart: always
container_name: stress
volumes:
- $PWD/config/stressTests.json:/user/app/config/stressTests.json
ports:
- "3000:3000"
extra_hosts:
- "logstash:$ADDRESS"
24 changes: 14 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cron_server",
"version": "1.0.0",
"version": "1.2.1",
"description": "New Monitor Cron",
"author": "[email protected]",
"license": "MIT",
Expand All @@ -11,14 +11,17 @@
"start": "node src/server.js",
"dev": "src/node_modules/.bin/nodemon -L",
"test": "echo \"No test specified\" && exit 0",
"deploy:clean": "docker image prune -f",
"deploy:build": "docker build . -t webiks/cron_server:latest",
"deploy:tag": "docker tag webiks/cron_server:latest webiks/cron_server:latest",
"deploy:push": "docker push webiks/cron_server:latest",
"upload": "npm run deploy:build && npm run deploy:tag && npm run deploy:push",
"deploy:remove": "docker rm -f webiks/cron_server",
"deploy:run": "docker run --name stress -p 3000:3000 -e webiks/cron_server",
"deploy:full": "npm run deploy:build && npm run deploy:remove && npm run deploy:run"
"docker:build": "sh -x ./scripts/docker-build.sh",
"docker:start": "docker-compose up -d",
"docker:stop": "docker-compose down",
"docker:clean": "docker image prune -f",
"docker:remove": "docker rm -f webiks/cron_server",
"aws:deploy": "sh -x ./scripts/deploy.sh",
"aws:full": "npm run docker:build && npm run aws:deploy"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Webiks/stress-as-a-service.git"
},
"dependencies": {
"express": "^4.17.1",
Expand All @@ -32,5 +35,6 @@
"nodemon": "^1.18.3",
"npm": "^6.2.0",
"rimraf": "^2.6.3"
}
},
"homepage": "https://github.com/Webiks/stress-as-a-service#readme"
}
2 changes: 2 additions & 0 deletions scripts/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose build
8 changes: 8 additions & 0 deletions scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
eval "$(aws ecr get-login --no-include-email --region us-west-2)"

PACKAGE_VERSION=$(node -p "require('./package.json').version")
docker tag webiks/cron_server:"$PACKAGE_VERSION" 223455578796.dkr.ecr.us-west-2.amazonaws.com/monitor-stress:"$PACKAGE_VERSION"
docker tag webiks/cron_server:latest 223455578796.dkr.ecr.us-west-2.amazonaws.com/monitor-stress:latest
docker push 223455578796.dkr.ecr.us-west-2.amazonaws.com/monitor-stress:latest
docker push 223455578796.dkr.ecr.us-west-2.amazonaws.com/monitor-stress:"$PACKAGE_VERSION"
4 changes: 4 additions & 0 deletions scripts/docker-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
PACKAGE_VERSION=$(node -p "require('./package.json').version")
docker build . -t webiks/cron_server:"$PACKAGE_VERSION"
docker tag webiks/cron_server:"$PACKAGE_VERSION" webiks/cron_server:latest
3 changes: 3 additions & 0 deletions scripts/docker-tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
PACKAGE_VERSION=$(node -p "require('./package.json').version")
docker tag webiks/cron_server:"$PACKAGE_VERSION" webiks/cron_server:latest
81 changes: 81 additions & 0 deletions src/handlers/cronHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use strict';

const uuid = require('uuid/v4');
const cron = require('node-cron');

const stressTests = require('../../config/stressTests.json');
const config = require('../../config/config.json');
const storage = require('./storageHandler');

const {spawn} = require('child_process');

function execute(cmd, args) {
return new Promise((resolve, reject) => {
if (typeof (args) === 'string') {
args = args.split(' ');
}
if (!(args instanceof Array)) {
reject('Arguments must be string or array');
}
console.log(`${(new Date()).toISOString()} - Cmd: ${cmd}, Args: ${args}`);
const process = spawn(cmd, args);
process.on('exit', (code, signal) => {
if (code === 0) {
console.log(`${(new Date()).toISOString()} - Child process ${process.pid} exited with code ${code}`);
} else {
reject(`${(new Date()).toISOString()} - Child process ${process.pid} exit code: ${code}, exit signal: ${signal}`);
}
});
process.stdout.setEncoding('utf8');
process.stdout.on('data', (data) => {
console.log(`${(new Date()).toISOString()} - stdout: ${data}`);
});
process.stderr.setEncoding('utf8');
process.stderr.on('data', (data) => {
console.log(`${(new Date()).toISOString()} - stdout: ${data}`);
});
resolve(process.pid);
});
};

function setCron(exp, command, args) {
let processId = undefined;
const scheduledTask = cron.schedule(exp,
() => {
execute(command, args)
.then((pid) => {
processId = pid;
console.log(`${(new Date()).toISOString()} Spawning new task w/ PID ${pid} and Stress arguments < ${args} >`);
})
.catch((err) => {
console.log(`${(new Date()).toISOString()}`, err.stack);
});
},
{
scheduled: config.cron.options.scheduled,
timezone: config.cron.options.timezone
}
);
const task = {
processId,
scheduledTask,
exp,
args
};
return task;
}

function onload() {
const command = config.task.command;
const tests = stressTests;
tests.forEach((test) => {
const exp = test.exp;
const args = test.args;
const task = setCron(exp, command, args);
const id = test.id;
storage.set(id, task);
console.log(`${(new Date()).toISOString()} Id: ${id}, Exp: ${exp}, Args: ${args}`);
});
};

module.exports = {setCron, onload};
32 changes: 0 additions & 32 deletions src/handlers/cronHendler.js

This file was deleted.

5 changes: 5 additions & 0 deletions src/handlers/storageHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use strict';

const storage = new Map([]);

module.exports = storage;
4 changes: 2 additions & 2 deletions src/modules/errorHandling.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = (err, req, res, next) => {
console.error(`Something bad happened: ${err}`);
console.error(`${(new Date()).toISOString()}, Something bad happened: ${err}`);
if (err instanceof URIError) {
res.redirect('/error');
}
next();
};
};
4 changes: 2 additions & 2 deletions src/modules/logger.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = (req, res, next) => {
// task: save to a file
console.log(`Time: ${Date.now()} : ${req.url}`);
console.log(`${(new Date()).toISOString()}, URL: ${req.method} ${req.url}`);
next();
};
};
84 changes: 24 additions & 60 deletions src/routes/stress.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
'use strict';

// const {spawn} = require('child_process');
const fs = require('fs');
const uuid = require('uuid/v4');
const {Router} = require('express');
const cron = require('node-cron');

const config = require('../../config/config.json');
const logger = require('../modules/logger');
const execute = require('../handlers/cronHendler');
const stressTests = require('../../config/stressTests');
const cronHandler = require('../handlers/cronHandler');
const storage = require('../handlers/storageHandler');

const router = Router();

const command = config.task.command;

const storage = new Map([]);
const fileName = './config/' + config.server.cronJobFile;

router.get('/stress', (req, res) => {
const tasks = [];
Expand Down Expand Up @@ -42,40 +41,21 @@ router.post('/stress/?', (req, res) => {
}
const exp = req.query.exp.toString();
const args = req.query.args.toString();
let processId = undefined;
const scheduledTask = cron.schedule(exp,
() => {
execute(command, args)
.then( (pid) => {
processId = pid;
console.log(`${Date.now()} Spawning new task w/ PID ${pid} Exp ${exp}, Id:[${id}] and arguments < ${args} >`);
})
.catch((err) => {
console.log(`${Date.now()}`, err.stack);
});
},
{
scheduled: config.cron.options.scheduled,
timezone: config.cron.options.timezone
}
);
const task = {
processId,
scheduledTask,
exp,
args
};
const id = uuid();
const id = uuid();
const task = cronHandler.setCron(exp, command, args);
storage.set(id, task);
return res.json({ pid: processId, id: id, exp: exp, args: args });
addCronJobToFile( { id: id, exp: task.exp, args: task.args});
return res.json({ pid: task.processId, id: id, exp: task.exp, args: task.args });
});

router.delete('/stress', (req, res) => {
const tasks = [];
storage.forEach((task, id) => {
tasks.push( { pid: task.processId, id: id, exp: task.exp, args: task.args } );
task.scheduledTask.destroy();
console.log(`${(new Date()).toISOString()} Cron id ${id} with exp ${task.exp} and args ${task.args} has been deleted`);
storage.delete(id);
removeCronJobFromFile(id);
});
return res.json({ operation: 'Delete all tasks', tasks: tasks });
});
Expand All @@ -85,41 +65,25 @@ router.delete('/stress/:id', (req, res) => {
if (storage.has(id)) {
const task = storage.get(id);
task.scheduledTask.destroy();
console.log(`${(new Date()).toISOString()} Cron id ${id} with exp ${task.exp} and args ${task.args} has been deleted`);
storage.delete(id);
removeCronJobFromFile(id);
return res.json({ operation: 'Delete a task', pid: task.processId, id: id, exp: task.exp, args: task.args });
}
else
return res.status(404).send(`id [${id}] not found!`);
});

// function execute(args) {
// return new Promise((resolve, reject) => {
// if (typeof (args) === 'string') {
// args = args.split(' ');
// }
// if (!(args instanceof Array)) {
// reject('Arguments must be string or array');
// }
// const command = config.task.command;
// console.log(command, " ", args);
// const process = spawn(command, args);
// process.on('exit', (code, signal) => {
// if (code === 0) {
// console.log(`child process exited with code ${code}`);
// } else {
// reject(`Exit code: ${code}, exit signal: ${signal}`);
// }
// });
// process.stdout.setEncoding('utf8');
// process.stdout.on('data', (data) => {
// console.log(`stdout: ${data}`);
// });
// process.stderr.setEncoding('utf8');
// process.stderr.on('data', (data) => {
// console.log(`stdout: ${data}`);
// });
// resolve(process.pid);
// });
// }
function addCronJobToFile(obj) {
stressTests.push(obj);
fs.writeFileSync(fileName, JSON.stringify(stressTests, null, 2));
}

function removeCronJobFromFile(id) {
const arr = stressTests.filter( (obj) => {
return obj.id !== id
});
fs.writeFileSync(fileName, JSON.stringify(arr, null, 2));
}

module.exports = router;
5 changes: 4 additions & 1 deletion src/server.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict';


const express = require('express');
const bodyParser = require ('body-parser');
const cors = require ('cors');

const config = require('../config/config.json');
const cronHandler = require('./handlers/cronHandler');
const errorHandler = require('./modules/errorHandling');
const logger = require('./modules/logger');
const stress = require('./routes/stress');
Expand All @@ -20,12 +20,15 @@ app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(logger);
app.use(errorHandler);
app.use(stress);

app.get('/health', (req, res) => {
res.send('Server is up and running ...')
});

cronHandler.onload();

app.listen(port,
() => console.log(`New Monitor Cron API server listening on port ${port}!`)
);

0 comments on commit 877b54a

Please sign in to comment.