Skip to content

Latest commit

 

History

History

3_9_cmd_env_conf

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Step 3.9: Command-line arguments, environment variables and configs

Estimated time: 1 day

CLI

Rust provides a simple std::env::Arg iterator to access command-line arguments passed to a program.

However, most of the time you require more advanced tool for that, which provides --help and --version flags out-of-the-box and a convenient way to setup and describe custom options/flags to build your own CLI (command-line interface). For that case there is the well-known clap crate in Rust ecosystem.

The next level is structopt crate, which is built on top of clap, and allows to define CLI in a declarative and clean way.

For better understanding and familiarity with CLI tools in Rust ecosystem, read through the following articles:

Environment variables

Rust provides common primitives in std::env for working with environment variables as strings.

However, most of the time you want to operate with typed data, not with raw strings. Similarly to structopt for CLI, there is envy crate in Rust ecosystem, which uses serde as facade and allows to read data from environment variables in a declarative and clean way (due to serde attributes support).

Finally, dotenv crate should be mentioned. It sets environment variables basing on .env file contents, which is widely used convention to simplify environment configuration and to not declare all required environment variables by hand each time when running a program. This one is especially useful in development.

For better understanding and familiarity with environment variables tools in Rust ecosystem, read through the following articles:

Configuration

For dealing with configurations there is a well-known config crate in Rust ecosystem, which simplifies creation and usage of hierarchical typed configuration structures in a 12-factor way.

Config lets you set a set of default parameters and then extend them via merging in configuration from a variety of sources:

  • Environment variables
  • Another Config instance
  • Remote configuration: etcd, Consul
  • Files: JSON, YAML, TOML, HJSON
  • Manual, programmatic override (via a .set method on the Config instance)

Additionally, Config supports:

  • Live watching and re-reading of configuration files
  • Deep access into the merged configuration via a path syntax
  • Deserialization via serde of the configuration or any subset defined via a path

For better understanding and familiarity with config crate design, concepts, usage, and features, read through the following articles:

Task

Write a simple program which prints out its actual configuration. Configuration should be implemented as a typed hierarchical structure, which is able to be parsed from a specified file and/or environment variables.

The following priority should be applied (in ascending order) when merging:

  1. Default values declared directly in Rust sources;
  2. Values read from TOML file;
  3. Values set by environment variables with CONF_ prefix.

CLI of the program should look like:

$ cargo run -- --help
step_3_9 0.1.0
Prints its configuration to STDOUT.

USAGE:
    step_3_9 [FLAGS] [OPTIONS]

FLAGS:
    -d, --debug      Enables debug mode
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
    -c, --conf <conf>         Path to configuration file [env: CONF_FILE=]  [default: config.toml]