From 8a44499ceb19f39e5524ddb1ed287550c83b3acb Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Tue, 26 Jan 2021 12:18:40 +0100 Subject: [PATCH 1/3] replace cronjs with crontab --- docker-compose.yml | 3 +- packages/handshake-api/package.json | 2 +- packages/health-check/Dockerfile | 5 ++- packages/health-check/cli/run | 5 +++ packages/health-check/package.json | 9 ++-- packages/health-check/src/checks/critical.js | 6 +-- packages/health-check/src/checks/verbose.js | 4 +- packages/health-check/src/db.js | 5 +-- packages/health-check/src/index.js | 2 - packages/health-check/src/run.js | 33 ++++++++++++++ packages/health-check/src/schedule.js | 45 -------------------- 11 files changed, 56 insertions(+), 63 deletions(-) create mode 100755 packages/health-check/cli/run create mode 100644 packages/health-check/src/run.js delete mode 100644 packages/health-check/src/schedule.js diff --git a/docker-compose.yml b/docker-compose.yml index 4f27b087..9794c911 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -156,7 +156,8 @@ services: ipv4_address: 10.10.10.60 environment: - HOSTNAME=0.0.0.0 - - PORTAL_URL=nginx + - PORTAL_URL=http://nginx + - STATE_DIR=/usr/app/state expose: - 3100 depends_on: diff --git a/packages/handshake-api/package.json b/packages/handshake-api/package.json index 1bd71cb3..2c89c5f2 100644 --- a/packages/handshake-api/package.json +++ b/packages/handshake-api/package.json @@ -10,6 +10,6 @@ "punycode": "^2.1.1" }, "devDependencies": { - "prettier": "^2.0.5" + "prettier": "^2.2.1" } } diff --git a/packages/health-check/Dockerfile b/packages/health-check/Dockerfile index 245a67fa..b666679a 100644 --- a/packages/health-check/Dockerfile +++ b/packages/health-check/Dockerfile @@ -7,6 +7,9 @@ RUN yarn --no-lockfile COPY src src COPY cli cli +RUN echo '*/5 * * * * /usr/app/cli/run critical' >> /etc/crontabs/root +RUN echo '0 * * * * /usr/app/cli/run verbose' >> /etc/crontabs/root + EXPOSE 3100 ENV NODE_ENV production -CMD [ "node", "--max-http-header-size=64000", "src/index.js" ] +CMD [ "sh", "-c", "crond -l 0 -L /usr/app/log.txt ; node --max-http-header-size=64000 src/index.js" ] diff --git a/packages/health-check/cli/run b/packages/health-check/cli/run new file mode 100755 index 00000000..a196b31b --- /dev/null +++ b/packages/health-check/cli/run @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = process.env.NODE_ENV || "production"; + +require("../src/run.js"); diff --git a/packages/health-check/package.json b/packages/health-check/package.json index 6a20807f..45dd3006 100644 --- a/packages/health-check/package.json +++ b/packages/health-check/package.json @@ -5,17 +5,16 @@ "license": "MIT", "dependencies": { "body-parser": "^1.19.0", - "cron": "^1.8.2", "deep-object-diff": "^1.1.0", "express": "^4.17.1", "http-status-codes": "^2.1.2", "lodash": "^4.17.20", "lowdb": "^1.0.0", - "ms": "^2.1.2", - "object-hash": "^2.0.3", - "superagent": "^6.0.0" + "object-hash": "^2.1.1", + "superagent": "^6.0.0", + "yargs": "^16.2.0" }, "devDependencies": { - "prettier": "^2.0.5" + "prettier": "^2.2.1" } } diff --git a/packages/health-check/src/checks/critical.js b/packages/health-check/src/checks/critical.js index 38c71277..8e04c0c3 100644 --- a/packages/health-check/src/checks/critical.js +++ b/packages/health-check/src/checks/critical.js @@ -7,7 +7,7 @@ async function uploadCheck(done) { const time = process.hrtime(); superagent - .post(`http://${process.env.PORTAL_URL}/skynet/skyfile`) + .post(`${process.env.PORTAL_URL}/skynet/skyfile`) .attach("file", "package.json", "package.json") .end((error, response) => { const statusCode = (response && response.statusCode) || (error && error.statusCode) || null; @@ -29,7 +29,7 @@ async function downloadCheck(done) { let statusCode, errorResponseContent; try { - const response = await superagent.get(`http://${process.env.PORTAL_URL}/${skylink}?nocache=true`); + const response = await superagent.get(`${process.env.PORTAL_URL}/${skylink}?nocache=true`); statusCode = response.statusCode; } catch (error) { @@ -46,4 +46,4 @@ async function downloadCheck(done) { }); } -module.exports.criticalChecks = [uploadCheck, downloadCheck]; +module.exports = [uploadCheck, downloadCheck]; diff --git a/packages/health-check/src/checks/verbose.js b/packages/health-check/src/checks/verbose.js index 1c9ded58..e7143fed 100644 --- a/packages/health-check/src/checks/verbose.js +++ b/packages/health-check/src/checks/verbose.js @@ -1037,7 +1037,7 @@ function skylinkVerification(done, { name, skylink, bodyHash, headers }) { const time = process.hrtime(); // Create the query for the skylink - const query = `http://${process.env.PORTAL_URL}/${skylink}?nocache=true`; + const query = `${process.env.PORTAL_URL}/${skylink}?nocache=true`; // Get the Skylink superagent @@ -1087,7 +1087,7 @@ function skylinkVerification(done, { name, skylink, bodyHash, headers }) { ); } -module.exports.verboseChecks = [ +module.exports = [ audioExampleCheck, covid19PaperCheck, covid19CoroNopePaperCheck, diff --git a/packages/health-check/src/db.js b/packages/health-check/src/db.js index bb4e7aad..760c217e 100644 --- a/packages/health-check/src/db.js +++ b/packages/health-check/src/db.js @@ -1,11 +1,10 @@ const fs = require("fs"); const low = require("lowdb"); const FileSync = require("lowdb/adapters/FileSync"); -const Memory = require("lowdb/adapters/Memory"); -if (!fs.existsSync("state")) fs.mkdirSync("state"); +if (!fs.existsSync(process.env.STATE_DIR)) fs.mkdirSync(process.env.STATE_DIR); -const adapter = new FileSync("state/state.json"); +const adapter = new FileSync(`${process.env.STATE_DIR}/state.json`); const db = low(adapter); db.defaults({ disabled: false, critical: [], verbose: [] }).write(); diff --git a/packages/health-check/src/index.js b/packages/health-check/src/index.js index 5ea907db..e7aff6d5 100644 --- a/packages/health-check/src/index.js +++ b/packages/health-check/src/index.js @@ -8,8 +8,6 @@ const express = require("express"); const bodyparser = require("body-parser"); const db = require("./db"); -require("./schedule"); - const host = process.env.HOSTNAME || "0.0.0.0"; const port = Number(process.env.PORT) || 3100; diff --git a/packages/health-check/src/run.js b/packages/health-check/src/run.js new file mode 100644 index 00000000..b6592727 --- /dev/null +++ b/packages/health-check/src/run.js @@ -0,0 +1,33 @@ +require('yargs/yargs')(process.argv.slice(2)) + .command('$0 ', 'Skynet portal health checks', (yargs) => { + yargs.positional('type', { + describe: 'Type of checks to run', + type: 'string', + choices: ["critical", "verbose"] + }) + .option("portal-url", { + describe: "Skynet portal url", + default: process.env.PORTAL_URL || "https://siasky.net", + type: "string", + }) + .option("state-dir", { + describe: "State directory", + default: process.env.STATE_DIR || "state", + type: "string", + }) + }, async ({ type, portalUrl, stateDir }) => { + process.env.PORTAL_URL = portalUrl; + process.env.STATE_DIR = stateDir; + + const db = require("../src/db"); + const checks = require(`../src/checks/${type}`); + + const entry = { + date: new Date().toISOString(), + checks: await Promise.all(checks.map((check) => new Promise(check))), + }; + + // read before writing to make sure no external changes are overwritten + db.read().get(type).push(entry).write(); + }) + .argv diff --git a/packages/health-check/src/schedule.js b/packages/health-check/src/schedule.js deleted file mode 100644 index 63b3a78f..00000000 --- a/packages/health-check/src/schedule.js +++ /dev/null @@ -1,45 +0,0 @@ -const { CronJob } = require("cron"); -const ms = require("ms"); -const db = require("./db"); -const { criticalChecks } = require("./checks/critical"); -const { verboseChecks } = require("./checks/verbose"); - -// use this timezone to run all cron instances at the same time regardless of the server location -const timezone = "UTC"; - -// critical health checks job definition -const criticalJobSchedule = "*/5 * * * *"; // on every 5 minute mark -const criticalJobOnTick = async () => { - const entry = { - date: new Date().toISOString(), - checks: await Promise.all(criticalChecks.map((check) => new Promise(check))), - }; - - // read before writing to make sure no external changes are overwritten - db.read().get("critical").push(entry).write(); -}; -const criticalJob = new CronJob(criticalJobSchedule, criticalJobOnTick, null, false, timezone); - -// verbose health checks job definition -const verboseJobSchedule = "0 * * * *"; // on every full hour mark -const verboseJobOnTick = async () => { - const entry = { - date: new Date().toISOString(), - checks: await Promise.all(verboseChecks.map((check) => new Promise(check))), - }; - - // read before writing to make sure no external changes are overwritten - db.read().get("verbose").push(entry).write(); -}; -const verboseJob = new CronJob(verboseJobSchedule, verboseJobOnTick, null, false, timezone); - -// fire all health checks on startup (with delay for other services to boot) -setTimeout(() => { - // fire first run manually - criticalJob.fireOnTick(); - verboseJob.fireOnTick(); - - // start cron schedule - criticalJob.start(); - verboseJob.start(); -}, ms("1 minute")); From 7b6bf6664f2573526d8455dc2f4508e0d135b89e Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Tue, 26 Jan 2021 12:44:34 +0100 Subject: [PATCH 2/3] fix health-check for upload --- packages/health-check/package.json | 1 + packages/health-check/src/checks/critical.js | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/health-check/package.json b/packages/health-check/package.json index 45dd3006..89b478de 100644 --- a/packages/health-check/package.json +++ b/packages/health-check/package.json @@ -12,6 +12,7 @@ "lowdb": "^1.0.0", "object-hash": "^2.1.1", "superagent": "^6.0.0", + "tmp": "^0.2.1", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/packages/health-check/src/checks/critical.js b/packages/health-check/src/checks/critical.js index 8e04c0c3..4fded35a 100644 --- a/packages/health-check/src/checks/critical.js +++ b/packages/health-check/src/checks/critical.js @@ -1,15 +1,22 @@ +const fs = require("fs"); const superagent = require("superagent"); +const tmp = require('tmp'); const { StatusCodes } = require("http-status-codes"); const { calculateElapsedTime, getResponseContent } = require("../utils"); // uploadCheck returns the result of uploading a sample file async function uploadCheck(done) { const time = process.hrtime(); + const file = tmp.fileSync(); + + fs.writeSync(file.fd, Buffer.from(new Date())); // write current date to temp file superagent .post(`${process.env.PORTAL_URL}/skynet/skyfile`) - .attach("file", "package.json", "package.json") + .attach("file", file.name, file.name) .end((error, response) => { + file.removeCallback(); + const statusCode = (response && response.statusCode) || (error && error.statusCode) || null; done({ From 65fd16392f8f1ecb2943a367ccb2063599868c55 Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Tue, 26 Jan 2021 12:48:45 +0100 Subject: [PATCH 3/3] run crond in prod mode --- packages/health-check/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/health-check/Dockerfile b/packages/health-check/Dockerfile index b666679a..71da10c5 100644 --- a/packages/health-check/Dockerfile +++ b/packages/health-check/Dockerfile @@ -12,4 +12,4 @@ RUN echo '0 * * * * /usr/app/cli/run verbose' >> /etc/crontabs/root EXPOSE 3100 ENV NODE_ENV production -CMD [ "sh", "-c", "crond -l 0 -L /usr/app/log.txt ; node --max-http-header-size=64000 src/index.js" ] +CMD [ "sh", "-c", "crond ; node --max-http-header-size=64000 src/index.js" ]