libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

Cli.kt (4091B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2023-2025 Taler Systems S.A.
      4 
      5  * LibEuFin is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU Affero General Public License as
      7  * published by the Free Software Foundation; either version 3, or
      8  * (at your option) any later version.
      9 
     10  * LibEuFin is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
     13  * Public License for more details.
     14 
     15  * You should have received a copy of the GNU Affero General Public
     16  * License along with LibEuFin; see the file COPYING.  If not, see
     17  * <http://www.gnu.org/licenses/>
     18  */
     19 
     20 package tech.libeufin.common
     21 
     22 import com.github.ajalt.clikt.core.CliktCommand
     23 import com.github.ajalt.clikt.core.Context
     24 import com.github.ajalt.clikt.core.ProgramResult
     25 import com.github.ajalt.clikt.core.subcommands
     26 import com.github.ajalt.clikt.parameters.arguments.argument
     27 import com.github.ajalt.clikt.parameters.groups.OptionGroup
     28 import com.github.ajalt.clikt.parameters.groups.provideDelegate
     29 import com.github.ajalt.clikt.parameters.options.default
     30 import com.github.ajalt.clikt.parameters.options.flag
     31 import com.github.ajalt.clikt.parameters.options.option
     32 import com.github.ajalt.clikt.parameters.types.enum
     33 import com.github.ajalt.clikt.parameters.types.path
     34 import kotlinx.coroutines.runBlocking
     35 import org.slf4j.Logger
     36 import org.slf4j.LoggerFactory
     37 import org.slf4j.event.Level
     38 
     39 private val logger: Logger = LoggerFactory.getLogger("libeufin-config")
     40 
     41 abstract class TalerCmd(name: String? = null): CliktCommand(name) {
     42     val config by option(
     43         "--config", "-c",
     44         help = "Specifies the configuration file",
     45         metavar = "config_file"
     46     ).path()
     47     val log by option(
     48         "--log", "-L",
     49         help = "Configure logging to use LOGLEVEL"
     50     ).enum<Level>().default(Level.INFO)
     51 
     52     fun cliCmd(logger: Logger, lambda: suspend () -> Unit) {
     53         // Set log level
     54         TalerServiceProvider.currentLevel = log
     55         // Run cli command catching all errors
     56         try {
     57             runBlocking {
     58                 lambda()
     59             }
     60         } catch (e: ProgramResult) {
     61             throw e
     62         } catch (e: Throwable) {
     63             e.fmtLog(logger)
     64             throw ProgramResult(1)
     65         }
     66     }
     67 }
     68 
     69 class CliConfigCmd(configSource: ConfigSource) : TalerCmd("config") {
     70     init {
     71         subcommands(CliConfigGet(configSource), CliConfigDump(configSource), CliConfigPathsub(configSource))
     72     }
     73 
     74     override fun help(context: Context) = "Inspect or change the configuration"
     75 
     76     override fun run() = Unit
     77 }
     78 
     79 private class CliConfigGet(private val configSource: ConfigSource) : TalerCmd("get") {
     80     override fun help(context: Context) = "Lookup config value"
     81 
     82     private val isPath by option(
     83         "--filename", "-f",
     84         help = "Interpret value as path with dollar-expansion"
     85     ).flag()
     86     private val section by argument()
     87     private val option by argument()
     88 
     89     override fun run() = cliCmd(logger) {
     90         val config = configSource.fromFile(config)
     91         val sect = config.section(section)
     92         if (isPath) {
     93             println(sect.path(option).require())
     94         } else {
     95             println(sect.string(option).require())
     96         }
     97     }
     98 }
     99 
    100 
    101 
    102 private class CliConfigPathsub(private val configSource: ConfigSource) : TalerCmd("pathsub") {
    103     override fun help(context: Context) = "Substitute variables in a path"
    104 
    105     private val pathExpr by argument()
    106 
    107     override fun run() = cliCmd(logger) {
    108         val config = configSource.fromFile(config)
    109         println(config.pathsub(pathExpr))
    110     }
    111 }
    112 
    113 private class CliConfigDump(private val configSource: ConfigSource) : TalerCmd("dump") {
    114     override fun help(context: Context) = "Dump the configuration"
    115 
    116     override fun run() = cliCmd(logger) {
    117         val config = configSource.fromFile(config)
    118         println("# install path: ${configSource.installPath()}")
    119         println(config.stringify())
    120     }
    121 }