From ff6cc0185762ed60734343bc40261b8c88a6006a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Uhl=C3=AD=C5=99?= Date: Tue, 2 May 2023 15:06:34 +0200 Subject: [PATCH] feat: adding config and env. variable support (#379) Co-authored-by: Eric Mastro --- README.md | 39 ++++++++++++++++++++++++++++++++++- codex.nim | 13 +++++++++++- codex/conf.nim | 22 ++++++++++++++++++-- vendor/nim-confutils | 2 +- vendor/nim-stew | 2 +- vendor/nim-toml-serialization | 2 +- 6 files changed, 73 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d1736fb5..4527c18e 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,35 @@ Run the client with: ```bash build/codex ``` +## Configuration + +It is possible to configure a Codex node in several ways: + 1. CLI options + 2. Env. variable + 3. Config + +The order of priority is the same as above: Cli arguments > Env variables > Config file values. + +### Environment variables + +In order to set a configuration option using environment variables, first find the desired CLI option +and then transform it in the following way: + + 1. prepend it with `CODEX_` + 2. make it uppercase + 3. replace `-` with `_` + +For example, to configure `--log-level`, use `CODEX_LOG_LEVEL` as the environment variable name. + +### Configuration file + +A [TOML](https://toml.io/en/) configuration file can also be used to set configuration values. Configuration option names and corresponding values are placed in the file, separated by `=`. Configuration option names can be obtained from the `codex --help` command, and should not include the `--` prefix. For example, a node's log level (`--log-level`) can be configured using TOML as follows: + +```toml +log-level = "TRACE" +``` + +The Codex node can then read the configuration from this file using the `--config-file` CLI parameter, like `codex --config-file=/path/to/your/config.toml`. ### CLI Options @@ -40,6 +69,7 @@ codex [OPTIONS]... command The following options are available: + --config-file Loads the configuration from a TOML file [=none]. --log-level Sets the log level [=INFO]. --metrics Enable the metrics server [=false]. --metrics-address Listening address of the metrics server [=127.0.0.1]. @@ -53,16 +83,23 @@ The following options are available: -b, --bootstrap-node Specifies one or more bootstrap nodes to use when connecting to the network.. --max-peers The maximum number of peers to connect to [=160]. --agent-string Node agent string which is used as identifier in network [=Codex]. + --api-bindaddr The REST API bind address [=127.0.0.1]. -p, --api-port The REST Api port [=8080]. --repo-kind backend for main repo store (fs, sqlite) [=fs]. -q, --storage-quota The size of the total storage quota dedicated to the node [=8589934592]. - -t, --block-ttl Default block timeout in seconds - 0 disables the ttl [=86400]. + -t, --block-ttl Default block timeout in seconds - 0 disables the ttl [=$DefaultBlockTtl]. + --block-mi Time interval in seconds - determines frequency of block maintenance cycle: how + often blocks are checked for expiration and cleanup. + [=$DefaultBlockMaintenanceInterval]. + --block-mn Number of blocks to check every maintenance cycle. [=1000]. -c, --cache-size The size in MiB of the block cache, 0 disables the cache - might help on slow hardrives [=0]. --persistence Enables persistence mechanism, requires an Ethereum node [=false]. --eth-provider The URL of the JSON-RPC API of the Ethereum node [=ws://localhost:8545]. --eth-account The Ethereum account that is used for storage contracts [=EthAddress.none]. --eth-deployment The json file describing the contract deployment [=string.none]. + --validator Enables validator, requires an Ethereum node [=false]. + --validator-max-slots Maximum number of slots that the validator monitors [=1000]. Available sub-commands: diff --git a/codex.nim b/codex.nim index b5d71eaa..be012992 100644 --- a/codex.nim +++ b/codex.nim @@ -9,7 +9,14 @@ import pkg/chronicles import pkg/chronos +import pkg/questionable import pkg/confutils +import pkg/confutils/defs +import pkg/confutils/std/net +import pkg/confutils/toml/defs as confTomlDefs +import pkg/confutils/toml/std/net as confTomlNet +import pkg/confutils/toml/std/uri as confTomlUri +import pkg/toml_serialization import pkg/libp2p import ./codex/conf @@ -37,7 +44,11 @@ when isMainModule: Running let config = CodexConf.load( - version = codexFullVersion + version = codexFullVersion, + envVarsPrefix = "codex", + secondarySources = proc (config: CodexConf, sources: auto) = + if configFile =? config.configFile: + sources.addConfigFile(Toml, configFile) ) config.setupLogging() config.setupMetrics() diff --git a/codex/conf.nim b/codex/conf.nim index 5fb4c51e..f7e75787 100644 --- a/codex/conf.nim +++ b/codex/conf.nim @@ -23,6 +23,7 @@ import pkg/chronicles/helpers import pkg/chronicles/topics_registry import pkg/confutils/defs import pkg/confutils/std/net +import pkg/toml_serialization import pkg/metrics import pkg/metrics/chronos_httpserver import pkg/stew/shims/net as stewnet @@ -51,6 +52,12 @@ type repoSQLite = "sqlite" CodexConf* = object + configFile* {. + desc: "Loads the configuration from a TOML file" + defaultValueDesc: "none" + defaultValue: InputFile.none + name: "config-file" }: Option[InputFile] + logLevel* {. defaultValue: "INFO" desc: "Sets the log level", @@ -268,7 +275,7 @@ proc defaultDataDir*(): string = getHomeDir() / dataDir func parseCmdArg*(T: type MultiAddress, input: string): T - {.raises: [ValueError, LPError, Defect].} = + {.upraises: [ValueError, LPError].} = MultiAddress.init($input).tryGet() proc parseCmdArg*(T: type SignedPeerRecord, uri: string): T = @@ -285,6 +292,17 @@ proc parseCmdArg*(T: type SignedPeerRecord, uri: string): T = func parseCmdArg*(T: type EthAddress, address: string): T = EthAddress.init($address).get() +proc readValue*(r: var TomlReader, val: var EthAddress) + {.upraises: [SerializationError, IOError].} = + val = EthAddress.init(r.readValue(string)).get() + +proc readValue*(r: var TomlReader, val: var SignedPeerRecord) = + without uri =? r.readValue(string).catch, err: + error "invalid SignedPeerRecord configuration value", error = err.msg + quit QuitFailure + + val = SignedPeerRecord.parseCmdArg(uri) + # no idea why confutils needs this: proc completeCmdArg*(T: type EthAddress; val: string): seq[string] = discard @@ -325,7 +343,7 @@ proc stripAnsi(v: string): string = res -proc updateLogLevel*(logLevel: string) {.raises: [Defect, ValueError].} = +proc updateLogLevel*(logLevel: string) {.upraises: [ValueError].} = # Updates log levels (without clearing old ones) let directives = logLevel.split(";") try: diff --git a/vendor/nim-confutils b/vendor/nim-confutils index 0435e678..2028b416 160000 --- a/vendor/nim-confutils +++ b/vendor/nim-confutils @@ -1 +1 @@ -Subproject commit 0435e67832b6bb8dfdf0ddb102903e9d820206d2 +Subproject commit 2028b41602b3abf7c9bf450744efde7b296707a2 diff --git a/vendor/nim-stew b/vendor/nim-stew index 0c379cf1..e18f5a62 160000 --- a/vendor/nim-stew +++ b/vendor/nim-stew @@ -1 +1 @@ -Subproject commit 0c379cf1d8d3d9db07af108cc78ff542b2105914 +Subproject commit e18f5a62af2ade7a1fd1d39635d4e04d944def08 diff --git a/vendor/nim-toml-serialization b/vendor/nim-toml-serialization index 4e15e00e..86d47713 160000 --- a/vendor/nim-toml-serialization +++ b/vendor/nim-toml-serialization @@ -1 +1 @@ -Subproject commit 4e15e00ed9e27a8d28b40b69ef06c6a4a388ae93 +Subproject commit 86d477136f105f04bfd0dd7c0e939593d81fc581