accounts health checks and testing improvements (#717)
* add account health check * circular dep resolution * error cannot be undefined
This commit is contained in:
parent
b3ca64ed98
commit
0c0be50e89
|
@ -15,6 +15,10 @@ services:
|
||||||
depends_on:
|
depends_on:
|
||||||
- accounts
|
- accounts
|
||||||
|
|
||||||
|
health-check:
|
||||||
|
environment:
|
||||||
|
- ACCOUNTS_ENABLED=1
|
||||||
|
|
||||||
accounts:
|
accounts:
|
||||||
build:
|
build:
|
||||||
context: ./docker/accounts
|
context: ./docker/accounts
|
||||||
|
|
|
@ -80,7 +80,6 @@ services:
|
||||||
- 80
|
- 80
|
||||||
depends_on:
|
depends_on:
|
||||||
- sia
|
- sia
|
||||||
- health-check
|
|
||||||
- handshake-api
|
- handshake-api
|
||||||
- website
|
- website
|
||||||
|
|
||||||
|
@ -155,12 +154,12 @@ services:
|
||||||
networks:
|
networks:
|
||||||
shared:
|
shared:
|
||||||
ipv4_address: 10.10.10.60
|
ipv4_address: 10.10.10.60
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
environment:
|
environment:
|
||||||
- HOSTNAME=0.0.0.0
|
- HOSTNAME=0.0.0.0
|
||||||
- PORTAL_URL=http://nginx
|
|
||||||
- STATE_DIR=/usr/app/state
|
- STATE_DIR=/usr/app/state
|
||||||
expose:
|
expose:
|
||||||
- 3100
|
- 3100
|
||||||
depends_on:
|
depends_on:
|
||||||
- handshake
|
- caddy
|
||||||
- handshake-api
|
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
preserve_host: true
|
preserve_host: true
|
||||||
url: "http://accounts:3000"
|
url: "http://accounts:3000"
|
||||||
match:
|
match:
|
||||||
url: "http://oathkeeper<{,:4455}>/<{stripe/prices,stripe/webhook}>"
|
url: "http://oathkeeper<{,:4455}>/<{health,stripe/prices,stripe/webhook}>"
|
||||||
methods:
|
methods:
|
||||||
- GET
|
- GET
|
||||||
- POST
|
- POST
|
||||||
|
|
|
@ -12,4 +12,4 @@ RUN echo '0 * * * * /usr/app/cli/run extended > /dev/stdout' >> /etc/crontabs/ro
|
||||||
|
|
||||||
EXPOSE 3100
|
EXPOSE 3100
|
||||||
ENV NODE_ENV production
|
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" ]
|
||||||
|
|
|
@ -7,26 +7,28 @@ const { calculateElapsedTime, getResponseContent } = require("../utils");
|
||||||
async function uploadCheck(done) {
|
async function uploadCheck(done) {
|
||||||
const time = process.hrtime();
|
const time = process.hrtime();
|
||||||
const form = new FormData();
|
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" });
|
form.append("file", payload, { filename: "time.txt", contentType: "text/plain" });
|
||||||
let statusCode, errorResponseContent;
|
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (error) {
|
||||||
statusCode = error?.response?.statusCode || error.statusCode || error.status;
|
data.statusCode = error.response?.statusCode || error.statusCode || error.status;
|
||||||
errorResponseContent = getResponseContent(error?.response);
|
data.errorMessage = error.message;
|
||||||
|
data.errorResponseContent = getResponseContent(error.response);
|
||||||
|
data.ip = error?.response?.ip ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
done({
|
done({
|
||||||
name: "upload_file",
|
name: "upload_file",
|
||||||
up: statusCode === StatusCodes.OK,
|
|
||||||
statusCode,
|
|
||||||
errorResponseContent,
|
|
||||||
time: calculateElapsedTime(time),
|
time: calculateElapsedTime(time),
|
||||||
|
...data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,26 +36,57 @@ async function uploadCheck(done) {
|
||||||
async function downloadCheck(done) {
|
async function downloadCheck(done) {
|
||||||
const time = process.hrtime();
|
const time = process.hrtime();
|
||||||
const skylink = "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q";
|
const skylink = "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q";
|
||||||
let statusCode, errorMessage, errorResponseContent;
|
const data = { up: false };
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (error) {
|
||||||
statusCode = error?.response?.statusCode || error.statusCode || error.status;
|
data.statusCode = error?.response?.statusCode || error.statusCode || error.status;
|
||||||
errorMessage = error.message;
|
data.errorMessage = error.message;
|
||||||
errorResponseContent = getResponseContent(error.response);
|
data.errorResponseContent = getResponseContent(error.response);
|
||||||
|
data.ip = error?.response?.ip ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
done({
|
done({
|
||||||
name: "download_file",
|
name: "download_file",
|
||||||
up: statusCode === StatusCodes.OK,
|
|
||||||
statusCode,
|
|
||||||
errorMessage,
|
|
||||||
errorResponseContent,
|
|
||||||
time: calculateElapsedTime(time),
|
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;
|
||||||
|
|
|
@ -1059,7 +1059,7 @@ async function skylinkVerification(done, expected, { followRedirect = true, meth
|
||||||
const details = { name: expected.name, skylink: expected.skylink };
|
const details = { name: expected.name, skylink: expected.skylink };
|
||||||
|
|
||||||
try {
|
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 response = await got[method](query, { followRedirect, headers: { cookie: "nocache=true" } });
|
||||||
const entry = { ...details, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) };
|
const entry = { ...details, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) };
|
||||||
const info = {};
|
const info = {};
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || "development";
|
process.env.NODE_ENV = process.env.NODE_ENV || "development";
|
||||||
|
|
||||||
if (!process.env.PORTAL_URL) {
|
if (!process.env.SKYNET_PORTAL_API) {
|
||||||
throw new Error("You need to provide PORTAL_URL environment variable");
|
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");
|
const express = require("express");
|
||||||
|
|
|
@ -12,7 +12,7 @@ require("yargs/yargs")(process.argv.slice(2)).command(
|
||||||
})
|
})
|
||||||
.option("portal-url", {
|
.option("portal-url", {
|
||||||
describe: "Skynet 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",
|
type: "string",
|
||||||
})
|
})
|
||||||
.option("state-dir", {
|
.option("state-dir", {
|
||||||
|
@ -22,7 +22,7 @@ require("yargs/yargs")(process.argv.slice(2)).command(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async ({ type, portalUrl, stateDir }) => {
|
async ({ type, portalUrl, stateDir }) => {
|
||||||
process.env.PORTAL_URL = portalUrl;
|
process.env.SKYNET_PORTAL_API = portalUrl;
|
||||||
process.env.STATE_DIR = stateDir;
|
process.env.STATE_DIR = stateDir;
|
||||||
|
|
||||||
const db = require("../src/db");
|
const db = require("../src/db");
|
||||||
|
|
|
@ -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();
|
Reference in New Issue