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 }