linting
This commit is contained in:
parent
0c6bb04356
commit
04e7315d4d
@ -870,10 +870,21 @@ const deploymentCli = walletCli.subcommand("deploymentArgs", "deployment", {
|
|||||||
help: "Subcommands for handling GNU Taler deployments.",
|
help: "Subcommands for handling GNU Taler deployments.",
|
||||||
});
|
});
|
||||||
|
|
||||||
deploymentCli.subcommand("lintExchange", "lint-exchange", {
|
deploymentCli
|
||||||
help: "Run checks on the exchange deployment."
|
.subcommand("lintExchange", "lint-exchange", {
|
||||||
}).action(async (args) => {
|
help: "Run checks on the exchange deployment.",
|
||||||
await lintExchangeDeployment();
|
})
|
||||||
|
.flag("cont", ["--continue"], {
|
||||||
|
help: "Continue after errors if possible",
|
||||||
|
})
|
||||||
|
.flag("debug", ["--debug"], {
|
||||||
|
help: "Output extra debug info",
|
||||||
|
})
|
||||||
|
.action(async (args) => {
|
||||||
|
await lintExchangeDeployment(
|
||||||
|
args.lintExchange.debug,
|
||||||
|
args.lintExchange.cont,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
deploymentCli
|
deploymentCli
|
||||||
|
@ -55,13 +55,31 @@ interface ShellResult {
|
|||||||
status: number;
|
status: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface LintContext {
|
||||||
|
/**
|
||||||
|
* Be more verbose.
|
||||||
|
*/
|
||||||
|
verbose: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always continue even after errors.
|
||||||
|
*/
|
||||||
|
cont: boolean;
|
||||||
|
|
||||||
|
cfg: Configuration;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a shell command, return stdout.
|
* Run a shell command, return stdout.
|
||||||
*/
|
*/
|
||||||
export async function sh(
|
export async function sh(
|
||||||
|
context: LintContext,
|
||||||
command: string,
|
command: string,
|
||||||
env: { [index: string]: string | undefined } = process.env,
|
env: { [index: string]: string | undefined } = process.env,
|
||||||
): Promise<ShellResult> {
|
): Promise<ShellResult> {
|
||||||
|
if (context.verbose) {
|
||||||
|
console.log("executing command:", command);
|
||||||
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const stdoutChunks: Buffer[] = [];
|
const stdoutChunks: Buffer[] = [];
|
||||||
const stderrChunks: Buffer[] = [];
|
const stderrChunks: Buffer[] = [];
|
||||||
@ -100,12 +118,14 @@ export async function sh(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkBasicConf(cfg: Configuration): BasicConf {
|
function checkBasicConf(context: LintContext): BasicConf {
|
||||||
|
const cfg = context.cfg;
|
||||||
const currencyEntry = cfg.getString("taler", "currency");
|
const currencyEntry = cfg.getString("taler", "currency");
|
||||||
let mainCurrency: string | undefined;
|
let mainCurrency: string | undefined;
|
||||||
|
|
||||||
if (!currencyEntry.value) {
|
if (!currencyEntry.value) {
|
||||||
console.log("error: currency not defined in section TALER option CURRENCY");
|
console.log("error: currency not defined in section TALER option CURRENCY");
|
||||||
|
console.log("Aborting further checks.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
mainCurrency = currencyEntry.value.toUpperCase();
|
mainCurrency = currencyEntry.value.toUpperCase();
|
||||||
@ -126,7 +146,8 @@ function checkBasicConf(cfg: Configuration): BasicConf {
|
|||||||
return { mainCurrency };
|
return { mainCurrency };
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkCoinConfig(cfg: Configuration, basic: BasicConf): void {
|
function checkCoinConfig(context: LintContext, basic: BasicConf): void {
|
||||||
|
const cfg = context.cfg;
|
||||||
const coinPrefix1 = "COIN_";
|
const coinPrefix1 = "COIN_";
|
||||||
const coinPrefix2 = "COIN-";
|
const coinPrefix2 = "COIN-";
|
||||||
let numCoins = 0;
|
let numCoins = 0;
|
||||||
@ -147,7 +168,8 @@ function checkCoinConfig(cfg: Configuration, basic: BasicConf): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkWireConfig(cfg: Configuration): Promise<void> {
|
async function checkWireConfig(context: LintContext): Promise<void> {
|
||||||
|
const cfg = context.cfg;
|
||||||
const accountPrefix = "EXCHANGE-ACCOUNT-";
|
const accountPrefix = "EXCHANGE-ACCOUNT-";
|
||||||
const accountCredentialsPrefix = "EXCHANGE-ACCOUNTCREDENTIALS-";
|
const accountCredentialsPrefix = "EXCHANGE-ACCOUNTCREDENTIALS-";
|
||||||
|
|
||||||
@ -174,51 +196,126 @@ async function checkWireConfig(cfg: Configuration): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const acc of accounts) {
|
||||||
|
// test debit history
|
||||||
|
{
|
||||||
const res = await sh(
|
const res = await sh(
|
||||||
"sudo -u taler-exchange-wirewatch taler-exchange-wirewatch -t",
|
context,
|
||||||
|
"su -l --shell /bin/sh " +
|
||||||
|
"-c 'taler-exchange-wire-gateway-client -s exchange-accountcredentials-${acc} --debit-history'" +
|
||||||
|
"taler-exchange-wire",
|
||||||
|
);
|
||||||
|
if (res.status != 0) {
|
||||||
|
console.log(res.stdout);
|
||||||
|
console.log(res.stderr);
|
||||||
|
console.log(
|
||||||
|
"error: Could not run wirewatch. Please review logs above.",
|
||||||
|
);
|
||||||
|
if (!context.cont) {
|
||||||
|
console.log("Aborting further checks.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TWG client
|
||||||
|
{
|
||||||
|
const res = await sh(
|
||||||
|
context,
|
||||||
|
`su -l --shell /bin/sh -c 'taler-exchange-wirewatch -t' taler-exchange-wire`,
|
||||||
|
);
|
||||||
|
if (res.status != 0) {
|
||||||
|
console.log(res.stdout);
|
||||||
|
console.log(res.stderr);
|
||||||
|
console.log("error: Could not run wirewatch. Please review logs above.");
|
||||||
|
if (!context.cont) {
|
||||||
|
console.log("Aborting further checks.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wirewatch
|
||||||
|
{
|
||||||
|
const res = await sh(
|
||||||
|
context,
|
||||||
|
`su -l --shell /bin/sh -c 'taler-exchange-wirewatch -t' taler-exchange-wire`,
|
||||||
|
);
|
||||||
|
if (res.status != 0) {
|
||||||
|
console.log(res.stdout);
|
||||||
|
console.log(res.stderr);
|
||||||
|
console.log("error: Could not run wirewatch. Please review logs above.");
|
||||||
|
if (!context.cont) {
|
||||||
|
console.log("Aborting further checks.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closer
|
||||||
|
{
|
||||||
|
const res = await sh(
|
||||||
|
context,
|
||||||
|
`su -l --shell /bin/sh -c 'taler-exchange-closer -t' taler-exchange-closer`,
|
||||||
|
);
|
||||||
|
if (res.status != 0) {
|
||||||
|
console.log(res.stdout);
|
||||||
|
console.log(res.stderr);
|
||||||
|
console.log("error: Could not run closer. Please review logs above.");
|
||||||
|
if (!context.cont) {
|
||||||
|
console.log("Aborting further checks.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkAggregatorConfig(context: LintContext) {
|
||||||
|
const res = await sh(
|
||||||
|
context,
|
||||||
|
"su -l --shell /bin/sh -c 'taler-exchange-aggregator -t' taler-exchange-aggregator",
|
||||||
);
|
);
|
||||||
if (res.status != 0) {
|
if (res.status != 0) {
|
||||||
console.log(res.stdout);
|
console.log(res.stdout);
|
||||||
console.log(res.stderr);
|
console.log(res.stderr);
|
||||||
console.log("error: Could not run aggregator. Please review logs above.");
|
console.log("error: Could not run aggregator. Please review logs above.");
|
||||||
|
if (!context.cont) {
|
||||||
|
console.log("Aborting further checks.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// FIXME: run wirewatch in test mode here?
|
|
||||||
// FIXME: run transfer in test mode here?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkAggregatorConfig(cfg: Configuration) {
|
async function checkCloserConfig(context: LintContext) {
|
||||||
const res = await sh(
|
const res = await sh(
|
||||||
"sudo -u taler-exchange-aggregator taler-exchange-aggregator -t",
|
context,
|
||||||
|
`su -l --shell /bin/sh -c 'taler-exchange-closer -t' taler-exchange-closer`,
|
||||||
);
|
);
|
||||||
if (res.status != 0) {
|
if (res.status != 0) {
|
||||||
console.log(res.stdout);
|
console.log(res.stdout);
|
||||||
console.log(res.stderr);
|
console.log(res.stderr);
|
||||||
console.log("error: Could not run aggregator. Please review logs above.");
|
console.log("error: Could not run closer. Please review logs above.");
|
||||||
|
if (!context.cont) {
|
||||||
|
console.log("Aborting further checks.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkCloserConfig(cfg: Configuration) {
|
|
||||||
const res = await sh("sudo -u taler-exchange-close taler-exchange-closer -t");
|
|
||||||
if (res.status != 0) {
|
|
||||||
console.log(res.stdout);
|
|
||||||
console.log(res.stderr);
|
|
||||||
console.log("error: Could not run aggregator. Please review logs above.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkMasterPublicKeyConfig(cfg: Configuration): PubkeyConf {
|
function checkMasterPublicKeyConfig(context: LintContext): PubkeyConf {
|
||||||
|
const cfg = context.cfg;
|
||||||
const pub = cfg.getString("exchange", "master_public_key");
|
const pub = cfg.getString("exchange", "master_public_key");
|
||||||
|
|
||||||
const pubDecoded = decodeCrock(pub.required());
|
const pubDecoded = decodeCrock(pub.required());
|
||||||
|
|
||||||
if (pubDecoded.length != 32) {
|
if (pubDecoded.length != 32) {
|
||||||
console.log("error: invalid master public key");
|
console.log("error: invalid master public key");
|
||||||
|
if (!context.cont) {
|
||||||
|
console.log("Aborting further checks.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
masterPublicKey: pub.required(),
|
masterPublicKey: pub.required(),
|
||||||
@ -226,9 +323,10 @@ function checkMasterPublicKeyConfig(cfg: Configuration): PubkeyConf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function checkExchangeHttpd(
|
export async function checkExchangeHttpd(
|
||||||
cfg: Configuration,
|
context: LintContext,
|
||||||
pubConf: PubkeyConf,
|
pubConf: PubkeyConf,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const cfg = context.cfg;
|
||||||
const baseUrlEntry = cfg.getString("exchange", "base_url");
|
const baseUrlEntry = cfg.getString("exchange", "base_url");
|
||||||
|
|
||||||
if (!baseUrlEntry.isDefined) {
|
if (!baseUrlEntry.isDefined) {
|
||||||
@ -312,7 +410,10 @@ export async function checkExchangeHttpd(
|
|||||||
/**
|
/**
|
||||||
* Do some basic checks in the configuration of a Taler deployment.
|
* Do some basic checks in the configuration of a Taler deployment.
|
||||||
*/
|
*/
|
||||||
export async function lintExchangeDeployment(): Promise<void> {
|
export async function lintExchangeDeployment(
|
||||||
|
verbose: boolean,
|
||||||
|
cont: boolean,
|
||||||
|
): Promise<void> {
|
||||||
if (process.getuid() != 0) {
|
if (process.getuid() != 0) {
|
||||||
console.log(
|
console.log(
|
||||||
"warning: the exchange deployment linter is designed to be run as root",
|
"warning: the exchange deployment linter is designed to be run as root",
|
||||||
@ -321,17 +422,23 @@ export async function lintExchangeDeployment(): Promise<void> {
|
|||||||
|
|
||||||
const cfg = Configuration.load();
|
const cfg = Configuration.load();
|
||||||
|
|
||||||
const basic = checkBasicConf(cfg);
|
const context: LintContext = {
|
||||||
|
cont,
|
||||||
|
verbose,
|
||||||
|
cfg,
|
||||||
|
};
|
||||||
|
|
||||||
checkCoinConfig(cfg, basic);
|
const basic = checkBasicConf(context);
|
||||||
|
|
||||||
await checkWireConfig(cfg);
|
checkCoinConfig(context, basic);
|
||||||
|
|
||||||
await checkAggregatorConfig(cfg);
|
await checkWireConfig(context);
|
||||||
|
|
||||||
await checkCloserConfig(cfg);
|
await checkAggregatorConfig(context);
|
||||||
|
|
||||||
const pubConf = checkMasterPublicKeyConfig(cfg);
|
await checkCloserConfig(context);
|
||||||
|
|
||||||
await checkExchangeHttpd(cfg, pubConf);
|
const pubConf = checkMasterPublicKeyConfig(context);
|
||||||
|
|
||||||
|
await checkExchangeHttpd(context, pubConf);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user