accounts health checks and testing improvements (#717)

* add account health check

* circular dep resolution

* error cannot be undefined
This commit is contained in:
Karol Wypchło 2021-05-05 14:18:10 +02:00 committed by GitHub
parent b3ca64ed98
commit 0c0be50e89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 85 additions and 32 deletions

View File

@ -15,6 +15,10 @@ services:
depends_on:
- accounts
health-check:
environment:
- ACCOUNTS_ENABLED=1
accounts:
build:
context: ./docker/accounts

View File

@ -80,7 +80,6 @@ services:
- 80
depends_on:
- sia
- health-check
- handshake-api
- website
@ -155,12 +154,12 @@ services:
networks:
shared:
ipv4_address: 10.10.10.60
env_file:
- .env
environment:
- HOSTNAME=0.0.0.0
- PORTAL_URL=http://nginx
- STATE_DIR=/usr/app/state
expose:
- 3100
depends_on:
- handshake
- handshake-api
- caddy

View File

@ -65,7 +65,7 @@
preserve_host: true
url: "http://accounts:3000"
match:
url: "http://oathkeeper<{,:4455}>/<{stripe/prices,stripe/webhook}>"
url: "http://oathkeeper<{,:4455}>/<{health,stripe/prices,stripe/webhook}>"
methods:
- GET
- POST

View File

@ -12,4 +12,4 @@ RUN echo '0 * * * * /usr/app/cli/run extended > /dev/stdout' >> /etc/crontabs/ro
EXPOSE 3100
ENV NODE_ENV production
CMD [ "sh", "-c", "crond ; node --max-http-header-size=64000 src/index.js" ]
CMD [ "sh", "-c", "crond ; echo $(node src/whatismyip.js) siasky.net account.siasky.net >> /etc/hosts ; node --max-http-header-size=64000 src/index.js" ]

View File

@ -7,26 +7,28 @@ const { calculateElapsedTime, getResponseContent } = require("../utils");
async function uploadCheck(done) {
const time = process.hrtime();
const form = new FormData();
const data = Buffer.from(new Date()); // current date to ensure data uniqueness
const payload = Buffer.from(new Date()); // current date to ensure data uniqueness
const data = { up: false };
form.append("file", data, { filename: "time.txt", contentType: "text/plain" });
let statusCode, errorResponseContent;
form.append("file", payload, { filename: "time.txt", contentType: "text/plain" });
try {
const response = await got.post(`${process.env.PORTAL_URL}/skynet/skyfile`, { body: form });
const response = await got.post(`${process.env.SKYNET_PORTAL_API}/skynet/skyfile`, { body: form });
statusCode = response.statusCode;
data.statusCode = response.statusCode;
data.up = true;
data.ip = response.ip;
} catch (error) {
statusCode = error?.response?.statusCode || error.statusCode || error.status;
errorResponseContent = getResponseContent(error?.response);
data.statusCode = error.response?.statusCode || error.statusCode || error.status;
data.errorMessage = error.message;
data.errorResponseContent = getResponseContent(error.response);
data.ip = error?.response?.ip ?? null;
}
done({
name: "upload_file",
up: statusCode === StatusCodes.OK,
statusCode,
errorResponseContent,
time: calculateElapsedTime(time),
...data,
});
}
@ -34,26 +36,57 @@ async function uploadCheck(done) {
async function downloadCheck(done) {
const time = process.hrtime();
const skylink = "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q";
let statusCode, errorMessage, errorResponseContent;
const data = { up: false };
try {
const response = await got(`${process.env.PORTAL_URL}/${skylink}?nocache=true`);
const response = await got(`${process.env.SKYNET_PORTAL_API}/${skylink}?nocache=true`);
statusCode = response.statusCode;
data.statusCode = response.statusCode;
data.up = true;
data.ip = response.ip;
} catch (error) {
statusCode = error?.response?.statusCode || error.statusCode || error.status;
errorMessage = error.message;
errorResponseContent = getResponseContent(error.response);
data.statusCode = error?.response?.statusCode || error.statusCode || error.status;
data.errorMessage = error.message;
data.errorResponseContent = getResponseContent(error.response);
data.ip = error?.response?.ip ?? null;
}
done({
name: "download_file",
up: statusCode === StatusCodes.OK,
statusCode,
errorMessage,
errorResponseContent,
time: calculateElapsedTime(time),
...data,
});
}
module.exports = [uploadCheck, downloadCheck];
async function accountHealthCheck(done) {
const time = process.hrtime();
const data = { up: false };
try {
const response = await got(`${process.env.SKYNET_DASHBOARD_URL}/health`, { responseType: "json" });
data.statusCode = response.statusCode;
data.response = response.body;
data.up = response.body.dbAlive === true;
data.ip = response.ip;
} catch (error) {
data.statusCode = error?.response?.statusCode || error.statusCode || error.status;
data.errorMessage = error.message;
data.errorResponseContent = getResponseContent(error.response);
data.ip = error?.response?.ip ?? null;
}
done({
name: "account_health",
time: calculateElapsedTime(time),
...data,
});
}
const checks = [uploadCheck, downloadCheck];
if (process.env.ACCOUNTS_ENABLED) {
checks.push(accountHealthCheck);
}
module.exports = checks;

View File

@ -1059,7 +1059,7 @@ async function skylinkVerification(done, expected, { followRedirect = true, meth
const details = { name: expected.name, skylink: expected.skylink };
try {
const query = `${process.env.PORTAL_URL}/${expected.skylink}`;
const query = `${process.env.SKYNET_PORTAL_API}/${expected.skylink}`;
const response = await got[method](query, { followRedirect, headers: { cookie: "nocache=true" } });
const entry = { ...details, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) };
const info = {};

View File

@ -1,7 +1,11 @@
process.env.NODE_ENV = process.env.NODE_ENV || "development";
if (!process.env.PORTAL_URL) {
throw new Error("You need to provide PORTAL_URL environment variable");
if (!process.env.SKYNET_PORTAL_API) {
throw new Error("You need to provide SKYNET_PORTAL_API environment variable");
}
if (process.env.ACCOUNTS_ENABLED && !process.env.SKYNET_DASHBOARD_URL) {
throw new Error("You need to provide SKYNET_DASHBOARD_URL environment variable when accounts are enabled");
}
const express = require("express");

View File

@ -12,7 +12,7 @@ require("yargs/yargs")(process.argv.slice(2)).command(
})
.option("portal-url", {
describe: "Skynet portal url",
default: process.env.PORTAL_URL || "https://siasky.net",
default: process.env.SKYNET_PORTAL_API || "https://siasky.net",
type: "string",
})
.option("state-dir", {
@ -22,7 +22,7 @@ require("yargs/yargs")(process.argv.slice(2)).command(
});
},
async ({ type, portalUrl, stateDir }) => {
process.env.PORTAL_URL = portalUrl;
process.env.SKYNET_PORTAL_API = portalUrl;
process.env.STATE_DIR = stateDir;
const db = require("../src/db");

View File

@ -0,0 +1,13 @@
const http = require("http");
const request = http.request({ host: "whatismyip.akamai.com" }, (response) => {
response.on("data", (data) => {
process.stdout.write(data);
});
});
request.on("error", (error) => {
console.error(error);
});
request.end();