diff options
author | Özgür Kesim <oec-taler@kesim.org> | 2023-10-10 10:08:02 +0200 |
---|---|---|
committer | Özgür Kesim <oec-taler@kesim.org> | 2023-10-10 10:08:02 +0200 |
commit | b5f5001249122ff611f16c043e72ccb174990654 (patch) | |
tree | 05968118a3d30b5c16874965d5fbb15b37d69434 /packages/taler-harness/src | |
parent | 2b293be4fed9b30d4bf6cf187f0f29046f2a3f5e (diff) | |
parent | 57f8cd3853ea33555faca57eec289482fc80ee58 (diff) |
Merge branch 'master' into age-withdraw
Diffstat (limited to 'packages/taler-harness/src')
-rw-r--r-- | packages/taler-harness/src/harness/harness.ts | 3 | ||||
-rw-r--r-- | packages/taler-harness/src/index.ts | 240 | ||||
-rw-r--r-- | packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts | 10 |
3 files changed, 234 insertions, 19 deletions
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index e30cbcb54..65a19959a 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -1652,9 +1652,6 @@ export class MerchantService implements MerchantServiceInterface { const body: MerchantInstanceConfig = { auth, - accounts: instanceConfig.paytoUris.map((x) => ({ - payto_uri: x, - })), id: instanceConfig.id, name: instanceConfig.name, address: instanceConfig.address ?? {}, diff --git a/packages/taler-harness/src/index.ts b/packages/taler-harness/src/index.ts index 82d8e4326..f06a66a21 100644 --- a/packages/taler-harness/src/index.ts +++ b/packages/taler-harness/src/index.ts @@ -28,9 +28,17 @@ import { MerchantApiClient, rsaBlind, setGlobalLogLevelFromString, + RegisterAccountRequest, + HttpStatusCode, + MerchantInstanceConfig, + Duration, + generateIban, } from "@gnu-taler/taler-util"; import { clk } from "@gnu-taler/taler-util/clk"; -import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; +import { + HttpResponse, + createPlatformHttpLib, +} from "@gnu-taler/taler-util/http"; import { CryptoDispatcher, downloadExchangeInfo, @@ -46,7 +54,11 @@ import { runBench2 } from "./bench2.js"; import { runBench3 } from "./bench3.js"; import { runEnvFull } from "./env-full.js"; import { runEnv1 } from "./env1.js"; -import { GlobalTestState, runTestWithState } from "./harness/harness.js"; +import { + GlobalTestState, + delayMs, + runTestWithState, +} from "./harness/harness.js"; import { getTestInfo, runTests } from "./integrationtests/testrunner.js"; import { lintExchangeDeployment } from "./lint.js"; @@ -312,8 +324,7 @@ deploymentCli const exchangeInfo = await downloadExchangeInfo(exchangeBaseUrl, http); await topupReserveWithDemobank({ amount: "KUDOS:10", - corebankApiBaseUrl: - "https://bank.demo.taler.net/", + corebankApiBaseUrl: "https://bank.demo.taler.net/", exchangeInfo, http, reservePub: reserveKeyPair.pub, @@ -341,8 +352,7 @@ deploymentCli const exchangeInfo = await downloadExchangeInfo(exchangeBaseUrl, http); await topupReserveWithDemobank({ amount: "TESTKUDOS:10", - corebankApiBaseUrl: - "https://bank.test.taler.net/", + corebankApiBaseUrl: "https://bank.test.taler.net/", exchangeInfo, http, reservePub: reserveKeyPair.pub, @@ -423,6 +433,224 @@ deploymentCli }); deploymentCli + .subcommand("waitService", "wait-taler-service", { + help: "Wait for the config endpoint of a Taler-style service to be available", + }) + .requiredArgument("serviceName", clk.STRING) + .requiredArgument("serviceConfigUrl", clk.STRING) + .action(async (args) => { + const serviceName = args.waitService.serviceName; + const serviceUrl = args.waitService.serviceConfigUrl; + console.log( + `Waiting for service ${serviceName} to be ready at ${serviceUrl}`, + ); + const httpLib = createPlatformHttpLib(); + while (1) { + console.log(`Fetching ${serviceUrl}`); + let resp: HttpResponse; + try { + resp = await httpLib.fetch(serviceUrl); + } catch (e) { + console.log( + `Got network error for service ${serviceName} at ${serviceUrl}`, + ); + await delayMs(1000); + continue; + } + if (resp.status != 200) { + console.log( + `Got unexpected status ${resp.status} for service at ${serviceUrl}`, + ); + await delayMs(1000); + continue; + } + let respJson: any; + try { + respJson = await resp.json(); + } catch (e) { + console.log( + `Got json error for service ${serviceName} at ${serviceUrl}`, + ); + await delayMs(1000); + continue; + } + const recServiceName = respJson.name; + console.log(`Got name ${recServiceName}`); + if (recServiceName != serviceName) { + console.log(`A different service is still running at ${serviceUrl}`); + await delayMs(1000); + continue; + } + console.log(`service ${serviceName} at ${serviceUrl} is now available`); + return; + } + }); + +deploymentCli + .subcommand("waitEndpoint", "wait-endpoint", { + help: "Wait for an endpoint to return an HTTP 200 Ok status with JSON body", + }) + .requiredArgument("serviceEndpoint", clk.STRING) + .action(async (args) => { + const serviceUrl = args.waitEndpoint.serviceEndpoint; + console.log(`Waiting for endpoint ${serviceUrl} to be ready`); + const httpLib = createPlatformHttpLib(); + while (1) { + console.log(`Fetching ${serviceUrl}`); + let resp: HttpResponse; + try { + resp = await httpLib.fetch(serviceUrl); + } catch (e) { + console.log(`Got network error for service at ${serviceUrl}`); + await delayMs(1000); + continue; + } + if (resp.status != 200) { + console.log( + `Got unexpected status ${resp.status} for service at ${serviceUrl}`, + ); + await delayMs(1000); + continue; + } + let respJson: any; + try { + respJson = await resp.json(); + } catch (e) { + console.log(`Got json error for service at ${serviceUrl}`); + await delayMs(1000); + continue; + } + return; + } + }); + +deploymentCli + .subcommand("genIban", "gen-iban", { + help: "Generate a random IBAN.", + }) + .requiredArgument("countryCode", clk.STRING) + .requiredArgument("length", clk.INT) + .action(async (args) => { + console.log(generateIban(args.genIban.countryCode, args.genIban.length)); + }); + +deploymentCli + .subcommand("provisionMerchantInstance", "provision-merchant-instance", { + help: "Provision a merchant backend instance.", + }) + .requiredArgument("merchantApiBaseUrl", clk.STRING) + .requiredOption("managementToken", ["--management-token"], clk.STRING) + .requiredOption("instanceToken", ["--instance-token"], clk.STRING) + .requiredOption("name", ["--name"], clk.STRING) + .requiredOption("id", ["--id"], clk.STRING) + .requiredOption("payto", ["--payto"], clk.STRING) + .action(async (args) => { + const httpLib = createPlatformHttpLib(); + const baseUrl = args.provisionMerchantInstance.merchantApiBaseUrl; + const managementToken = args.provisionMerchantInstance.managementToken; + const instanceToken = args.provisionMerchantInstance.instanceToken; + const instanceId = args.provisionMerchantInstance.id; + const body: MerchantInstanceConfig = { + address: {}, + auth: { + method: "token", + token: args.provisionMerchantInstance.instanceToken, + }, + default_pay_delay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ hours: 1 }), + ), + default_wire_transfer_delay: { d_us: 1 }, + id: instanceId, + jurisdiction: {}, + name: args.provisionMerchantInstance.name, + use_stefan: true, + }; + const url = new URL("management/instances", baseUrl); + const createResp = await httpLib.fetch(url.href, { + method: "POST", + body, + headers: { + Authorization: `Bearer ${managementToken}`, + }, + }); + if (createResp.status >= 200 && createResp.status <= 299) { + logger.info(`instance ${instanceId} created successfully`); + } else if (createResp.status === HttpStatusCode.Conflict) { + logger.info(`instance ${instanceId} already exists`); + } else { + logger.error( + `unable to create instance ${instanceId}, HTTP status ${createResp.status}`, + ); + } + + const accountsUrl = new URL( + `instances/${instanceId}/private/accounts`, + baseUrl, + ); + const accountBody = { + payto_uri: args.provisionMerchantInstance.payto, + }; + const createAccountResp = await httpLib.fetch(accountsUrl.href, { + method: "POST", + body: accountBody, + headers: { + Authorization: `Bearer ${instanceToken}`, + }, + }); + if (createAccountResp.status != 200) { + console.error( + `unable to configure bank account for instance ${instanceId}, status ${createAccountResp.status}`, + ); + const resp = await createAccountResp.json(); + console.error(j2s(resp)); + process.exit(2); + } + logger.info(`successfully configured bank account for ${instanceId}`); + }); + +deploymentCli + .subcommand("provisionBankAccount", "provision-bank-account", { + help: "Provision a corebank account.", + }) + .requiredArgument("corebankApiBaseUrl", clk.STRING) + .flag("exchange", ["--exchange"]) + .flag("public", ["--public"]) + .requiredOption("login", ["--login"], clk.STRING) + .requiredOption("name", ["--name"], clk.STRING) + .requiredOption("password", ["--password"], clk.STRING) + .maybeOption("internalPayto", ["--payto"], clk.STRING) + .action(async (args) => { + const httpLib = createPlatformHttpLib(); + const corebankApiBaseUrl = args.provisionBankAccount.corebankApiBaseUrl; + const url = new URL("accounts", corebankApiBaseUrl); + const accountLogin = args.provisionBankAccount.login; + const body: RegisterAccountRequest = { + name: args.provisionBankAccount.name, + password: args.provisionBankAccount.password, + username: accountLogin, + is_public: !!args.provisionBankAccount.public, + is_taler_exchange: !!args.provisionBankAccount.exchange, + internal_payto_uri: args.provisionBankAccount.internalPayto, + }; + const resp = await httpLib.fetch(url.href, { + method: "POST", + body, + }); + if (resp.status >= 200 && resp.status <= 299) { + logger.info(`account ${accountLogin} successfully provisioned`); + return; + } + if (resp.status === HttpStatusCode.Conflict) { + logger.info(`account ${accountLogin} already provisioned`); + return; + } + logger.error( + `unable to provision bank account, HTTP response status ${resp.status}`, + ); + process.exit(2); + }); + +deploymentCli .subcommand("coincfg", "gen-coin-config", { help: "Generate a coin/denomination configuration for the exchange.", }) diff --git a/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts b/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts index a037a01c5..7236436ac 100644 --- a/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts +++ b/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts @@ -72,11 +72,6 @@ export async function runMerchantInstancesUrlsTest(t: GlobalTestState) { ), jurisdiction: {}, name: "My Default Instance", - accounts: [ - { - payto_uri: generateRandomPayto("bar"), - }, - ], auth: { method: "token", token: "secret-token:i-am-default", @@ -95,11 +90,6 @@ export async function runMerchantInstancesUrlsTest(t: GlobalTestState) { ), jurisdiction: {}, name: "My Second Instance", - accounts: [ - { - payto_uri: generateRandomPayto("bar"), - }, - ], auth: { method: "token", token: "secret-token:i-am-myinst", |