summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine A <>2024-04-30 13:19:45 +0900
committerAntoine A <>2024-04-30 13:19:45 +0900
commit15ab519ed54c0d5ca5840c175f9aa0642a6ccf87 (patch)
tree91ca961f29f1510cf9b04146fd378e8683d7c5ed
parent602a3b6e8afa3462a4f34cd6bb92005fec84c90b (diff)
downloadlibeufin-nexus-wg.tar.gz
libeufin-nexus-wg.tar.bz2
libeufin-nexus-wg.zip
nexus: add libeufin-nexus servenexus-wg
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/Config.kt13
-rw-r--r--bank/src/main/kotlin/tech/libeufin/bank/Main.kt25
-rw-r--r--common/src/main/kotlin/Config.kt13
-rw-r--r--common/src/main/kotlin/TalerCommon.kt1
-rw-r--r--common/src/main/kotlin/api/server.kt24
-rw-r--r--contrib/nexus.conf14
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt2
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt6
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt2
-rw-r--r--nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt17
-rw-r--r--testbench/src/test/kotlin/IntegrationTest.kt6
11 files changed, 81 insertions, 42 deletions
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
index 9cdfcf0f..17fef641 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
@@ -68,11 +68,6 @@ data class ConversionRate (
val cashout_min_amount: TalerAmount,
)
-sealed interface ServerConfig {
- data class Unix(val path: String, val mode: Int): ServerConfig
- data class Tcp(val addr: String, val port: Int): ServerConfig
-}
-
fun talerConfig(configPath: Path?): TalerConfig = BANK_CONFIG_SOURCE.fromFile(configPath)
fun TalerConfig.loadDbConfig(): DatabaseConfig {
@@ -82,14 +77,6 @@ fun TalerConfig.loadDbConfig(): DatabaseConfig {
)
}
-fun TalerConfig.loadServerConfig(): ServerConfig {
- return when (val method = requireString("libeufin-bank", "serve")) {
- "tcp" -> ServerConfig.Tcp(lookupString("libeufin-bank", "address") ?: requireString("libeufin-bank", "bind_to"), requireNumber("libeufin-bank", "port"))
- "unix" -> ServerConfig.Unix(requireString("libeufin-bank", "unixpath"), requireNumber("libeufin-bank", "unixpath_mode"))
- else -> throw TalerConfigError.invalid("server method", "libeufin-bank", "serve", "expected 'tcp' or 'unix' got '$method'")
- }
-}
-
fun TalerConfig.loadBankConfig(): BankConfig {
val regionalCurrency = requireString("libeufin-bank", "currency")
var fiatCurrency: String? = null
diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
index 8733b907..9f581048 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Main.kt
@@ -62,8 +62,7 @@ import kotlin.io.path.exists
import kotlin.io.path.readText
private val logger: Logger = LoggerFactory.getLogger("libeufin-bank")
-// Dirty local variable to stop the server in test TODO remove this ugly hack
-var engine: ApplicationEngine? = null
+
/**
@@ -117,7 +116,7 @@ class ServeBank : CliktCommand("Run libeufin-bank HTTP server", name = "serve")
val cfg = talerConfig(common.config)
val ctx = cfg.loadBankConfig()
val dbCfg = cfg.loadDbConfig()
- val serverCfg = cfg.loadServerConfig()
+ val serverCfg = cfg.loadServerConfig("libeufin-bank")
Database(dbCfg, ctx.regionalCurrency, ctx.fiatCurrency).use { db ->
if (ctx.allowConversion) {
logger.info("Ensure exchange account exists")
@@ -142,25 +141,9 @@ class ServeBank : CliktCommand("Run libeufin-bank HTTP server", name = "serve")
db.conn { it.execSQLUpdate(sqlProcedures.readText()) }
// Remove conversion info from the database ?
}
-
- val env = applicationEngineEnvironment {
- when (serverCfg) {
- is ServerConfig.Tcp -> {
- for (addr in InetAddress.getAllByName(serverCfg.addr)) {
- connector {
- port = serverCfg.port
- host = addr.hostAddress
- }
- }
- }
- is ServerConfig.Unix ->
- throw Exception("Can only serve libeufin-bank via TCP")
- }
- module { corebankWebApp(db, ctx) }
+ serve(serverCfg) {
+ corebankWebApp(db, ctx)
}
- val local = embeddedServer(Netty, env)
- engine = local
- local.start(wait = true)
}
}
}
diff --git a/common/src/main/kotlin/Config.kt b/common/src/main/kotlin/Config.kt
index 95496839..536e88ff 100644
--- a/common/src/main/kotlin/Config.kt
+++ b/common/src/main/kotlin/Config.kt
@@ -33,4 +33,17 @@ fun getVersion(): String {
return Loader.getResource(
"version.txt", ClassLoader.getSystemClassLoader()
).readText()
+}
+
+sealed interface ServerConfig {
+ data class Unix(val path: String, val mode: Int): ServerConfig
+ data class Tcp(val addr: String, val port: Int): ServerConfig
+}
+
+fun TalerConfig.loadServerConfig(section: String): ServerConfig {
+ return when (val method = requireString(section, "serve")) {
+ "tcp" -> ServerConfig.Tcp(lookupString(section, "address") ?: requireString(section, "bind_to"), requireNumber(section, "port"))
+ "unix" -> ServerConfig.Unix(requireString(section, "unixpath"), requireNumber(section, "unixpath_mode"))
+ else -> throw TalerConfigError.invalid("server method", section, "serve", "expected 'tcp' or 'unix' got '$method'")
+ }
} \ No newline at end of file
diff --git a/common/src/main/kotlin/TalerCommon.kt b/common/src/main/kotlin/TalerCommon.kt
index 7dc72650..5596fb95 100644
--- a/common/src/main/kotlin/TalerCommon.kt
+++ b/common/src/main/kotlin/TalerCommon.kt
@@ -67,7 +67,6 @@ data class TalerProtocolTimestamp(
} else {
encoder.encodeLong(value.epochSecond)
}
-
}
override fun deserialize(decoder: Decoder): Instant {
diff --git a/common/src/main/kotlin/api/server.kt b/common/src/main/kotlin/api/server.kt
index ba6f2f61..43e37186 100644
--- a/common/src/main/kotlin/api/server.kt
+++ b/common/src/main/kotlin/api/server.kt
@@ -222,4 +222,28 @@ fun Application.talerApi(logger: Logger, routes: Routing.() -> Unit) {
}
}
routing { routes() }
+}
+
+// Dirty local variable to stop the server in test TODO remove this ugly hack
+var engine: ApplicationEngine? = null
+
+fun serve(cfg: ServerConfig, api: Application.() -> Unit) {
+ val env = applicationEngineEnvironment {
+ when (cfg) {
+ is ServerConfig.Tcp -> {
+ for (addr in InetAddress.getAllByName(cfg.addr)) {
+ connector {
+ port = cfg.port
+ host = addr.hostAddress
+ }
+ }
+ }
+ is ServerConfig.Unix ->
+ throw Exception("Can only serve via TCP")
+ }
+ module { api() }
+ }
+ val local = embeddedServer(Netty, env)
+ engine = local
+ local.start(wait = true)
} \ No newline at end of file
diff --git a/contrib/nexus.conf b/contrib/nexus.conf
index b5703208..94d203c7 100644
--- a/contrib/nexus.conf
+++ b/contrib/nexus.conf
@@ -56,9 +56,21 @@ FREQUENCY = 30m
FREQUENCY = 30m
[nexus-httpd]
-PORT = 8080
+# How "libeufin-nexus serve" serves its API, this can either be tcp or unix
SERVE = tcp
+# Port on which the HTTP server listens, e.g. 9967. Only used if SERVE is tcp.
+PORT = 8080
+
+# Which IP address should we bind to? E.g. ``127.0.0.1`` or ``::1``for loopback. Can also be given as a hostname. Only used if SERVE is tcp.
+BIND_TO = 0.0.0.0
+
+# Which unix domain path should we bind to? Only used if SERVE is unix.
+# UNIXPATH = libeufin-nexus.sock
+
+# What should be the file access permissions for UNIXPATH? Only used if SERVE is unix.
+# UNIXPATH_MODE = 660
+
[nexus-httpd-wire-gateway-api]
ENABLED = NO
AUTH_METHOD = bearer-token
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
index 8e876f20..43cef8ca 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsFetch.kt
@@ -364,7 +364,7 @@ class EbicsFetch: CliktCommand("Fetches EBICS files") {
* mode when no flags are passed to the invocation.
*/
override fun run() = cliCmd(logger, common.log) {
- val cfg = extractEbicsConfig(common.config)
+ val cfg = loadNexusConfig(common.config)
val dbCfg = cfg.config.dbConfig()
Database(dbCfg, cfg.currency).use { db ->
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
index 1c9ea902..7da7da07 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
@@ -155,7 +155,7 @@ suspend fun doKeysRequestAndUpdateState(
* @param configFile location of the configuration entry point.
* @return internal representation of the configuration.
*/
-fun extractEbicsConfig(configFile: Path?): NexusConfig {
+fun loadNexusConfig(configFile: Path?): NexusConfig {
val config = loadConfig(configFile)
return NexusConfig(config)
}
@@ -197,8 +197,8 @@ class EbicsSetup: CliktCommand("Set up the EBICS subscriber") {
* This function collects the main steps of setting up an EBICS access.
*/
override fun run() = cliCmd(logger, common.log) {
- val cfg = extractEbicsConfig(common.config)
- val client = HttpClient {
+ val cfg = loadNexusConfig(common.config)
+ val client = HttpClient {
install(HttpTimeout) {
// It can take a lot of time for the bank to generate documents
socketTimeoutMillis = 5 * 60 * 1000
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
index 947ecab6..c6a6ceef 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSubmit.kt
@@ -147,7 +147,7 @@ class EbicsSubmit : CliktCommand("Submits any initiated payment found in the dat
* FIXME: reduce code duplication with the fetch subcommand.
*/
override fun run() = cliCmd(logger, common.log) {
- val cfg = extractEbicsConfig(common.config)
+ val cfg = loadNexusConfig(common.config)
val dbCfg = cfg.config.dbConfig()
val (clientKeys, bankKeys) = expectFullKeys(cfg)
val ctx = SubmissionContext(
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index d4f133bd..c8b46008 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -146,6 +146,21 @@ class InitiatePayment: CliktCommand("Initiate an outgoing payment") {
}
}
+class Serve : CliktCommand("Run libeufin-nexus HTTP server", name = "serve") {
+ private val common by CommonOption()
+
+ override fun run() = cliCmd(logger, common.log) {
+ val cfg = loadNexusConfig(common.config)
+ val dbCfg = cfg.config.dbConfig()
+ val serverCfg = cfg.config.loadServerConfig("nexus-httpd")
+ Database(dbCfg, cfg.currency).use { db ->
+ serve(serverCfg) {
+ nexusApi(db, cfg)
+ }
+ }
+ }
+}
+
class ConvertBackup: CliktCommand("Convert an old backup to the new config format") {
private val backupPath by argument(
"backup",
@@ -302,7 +317,7 @@ class TestingCmd : CliktCommand("Testing helper commands", name = "testing") {
class LibeufinNexusCommand : CliktCommand() {
init {
versionOption(getVersion())
- subcommands(EbicsSetup(), DbInit(), EbicsSubmit(), EbicsFetch(), InitiatePayment(), CliConfigCmd(NEXUS_CONFIG_SOURCE), TestingCmd())
+ subcommands(EbicsSetup(), DbInit(), Serve(), EbicsSubmit(), EbicsFetch(), InitiatePayment(), CliConfigCmd(NEXUS_CONFIG_SOURCE), TestingCmd())
}
override fun run() = Unit
}
diff --git a/testbench/src/test/kotlin/IntegrationTest.kt b/testbench/src/test/kotlin/IntegrationTest.kt
index 8adc9782..ad425d38 100644
--- a/testbench/src/test/kotlin/IntegrationTest.kt
+++ b/testbench/src/test/kotlin/IntegrationTest.kt
@@ -29,6 +29,7 @@ import kotlinx.coroutines.runBlocking
import org.junit.Test
import tech.libeufin.bank.*
import tech.libeufin.common.*
+import tech.libeufin.common.api.engine
import tech.libeufin.common.db.one
import tech.libeufin.nexus.*
import java.time.Instant
@@ -111,6 +112,11 @@ class IntegrationTest {
}
bankCmd.run("gc $flags")
+
+ server {
+ nexusCmd.run("serve $flags")
+ }
+ engine?.stop(0, 0)
}
@Test