Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add some extra detail to docs #45

Closed
wants to merge 2 commits into from
Closed

Conversation

Shamazo
Copy link

@Shamazo Shamazo commented Feb 14, 2021

closes #44
This doesn't cover all functionality, but it covers a bunch of common use cases I had to figure out to use this crate for another project.

Question, if I use the conf_file_param I find that options set in that config file overwrite options set in environment variables. Is that intentional?

This crate aims to help with reading configuration of application from files,
environment variables and command line arguments, merging it together and
validating. It auto-generates most of the code for you based on configuration (heh)
file. It creates a struct for you, which contains all the parsed and validated
fields, so you can access the information quickly easily and idiomatically.

This is currently only a facade for the dependencies, the core of the crate is in
`configure_me_codegen` crate.

**Important:** In order to use this crate, you need to create a build script using
`configure_me_codegen` to generate the code that will use this crate! See the example.

Wait a second, why this crate doesn't use derive?
-------------------------------------------------

I'd love to use derive. Unfortunately it doesn't compose well with man page generation and other tooling.

For a longer version, see [docs/why\_not\_derive.md](docs/why_not_derive.md)

Example
-------

Let's say, your application needs these parametrs to run:

* Port - this is mandatory
* IP address to bind to - defaults to 0.0.0.0
* Path to TLS certificate - optional, the server will be unsecure if not given
* RunFast - switch, if present the server will run in fast mode

First create `config_spec.toml` configuration file specifying all the parameters:

```toml
[[param]]
# short param, e.g -p
abbr = "p"
# long arg, e.g --port
name = "port"
type = "u16"
optional = false

# This text will be used in the documentation (help etc)
# It's not mandatory, but your progam will be ugly without it.
doc = "Port to listen on."

[[param]]
name = "bind_addr"
# merge from env var. e.g BIND_ADDR
env_var = true
# Yes, this works and  you can use your own T: Deserialize + ParseArg as well!
type = "::std::net::Ipv4Addr"
default = "::std::net::Ipv4Addr::new(0, 0, 0, 0)" # Rust expression that creates the value
doc = "IP address to bind to."

[[param]]
name = "tls_cert"
type = "::std::path::PathBuf"
doc = "Path to the TLS certificate. The connections will be unsecure if it isn't provided."
# optional = true is the default, no need to add it here
# If the type is optional, it will be represented as Option<T>
# e.g. Option<::std::path::PathBuf> in this case.

[[switch]]
# switches are parsed as bools, true if present false otherwise
name = "run_fast"
doc = "Will make the server run in fast mode"
```

Then, create a simple build script:

```rust
extern crate configure_me;

fn main() {
    configure_me::build_script_auto().unwrap_or_exit();
}
```

Add dependencies to `Cargo.toml`:

```toml
[package]
# ...
build = "build.rs"

# This tells auto build script and other tools where to look for your specificcation
[package.metadata.configure_me]
spec = "config_spec.toml"

[dependencies]
configure_me = "0.3.3"

[build-dependencies]
configure_me_codegen = "0.3.3"
```

And finally add appropriate incantations into `src/main.rs`:

```rust
#[macro_use]
extern crate configure_me;

include_config!();

fn main() {
    // This will read configuration from "/etc/my_awesome_server/server.conf" file, environment variables and
    // the command-line arguments.
    let (server_config, _remaining_args) = Config::including_optional_config_files(&["/etc/my_awesome_server/server.conf]").unwrap_or_exit();

    // Your code here
    // E.g.:
    let listener = std::net::TcpListener::bind((server_config.bind_addr, server_config.port)).expect("Failed to bind socket");
}
```
Configuration
-------------
Configuration of the code generation is set in the same toml file as the specification
```toml
[general]
# Prefix for all env vars - enables all env vars by default if present
build = "build.rs"

# The name of the parameter which, if specified causes parameter parsing to
# immediately load a config file, parse it, and override all configuration
# provided so far with that file.
conf_file_param = "/path/to/conf/file.toml"
```
If you need to generate different files for multiple binaries, create a separate file for each binary and then define them separately in `Cargo.toml`:

```toml
[package.metadata.configure_me.bin]
# config for binary foo
foo = "foo_config_spec.toml"
# config for binary bar
bar = "bar_config_spec.toml"
```

And include the file in `foo` like this:

```rust
include_config!("foo");
```

This needs to be specific because there's no way to detect binary name.

License: MITNFA
@Shamazo
Copy link
Author

Shamazo commented Feb 14, 2021

Is the main README.md just a copy of the one in configure_me

Copy link
Owner

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for contribution! I wanted to review it sooner but was unable to do so. I found some issues, even a few serious ones - those definitely need to be addressed.

Question, if I use the conf_file_param I find that options set in that config file overwrite options set in environment variables. Is that intentional?

Yes, it's intentional.


```rust
extern crate configure_me_codegen;
extern crate configure_me;
Copy link
Owner

@Kixunil Kixunil Feb 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect, it must be configure_me_codegen in build script as mentioned above.
This particular case could be removed entirely thanks to edition 2018.

fn main() -> Result<(), configure_me_codegen::Error> {
configure_me_codegen::build_script_auto()
fn main() {
configure_me::build_script_auto().unwrap_or_exit();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to stay configure_me_codegen

}
```

*Tip: use [`cfg_me`](https://github.com/Kixunil/cfg_me) to generate a man page for your program.*
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed? There's no way for people to generate man page without knowing about cfg_me.


[build-dependencies]
configure_me_codegen = "0.3.11"
configure_me_codegen = "0.3"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, just realized I forgot to push the new version - 0.4 to git - it was in crates.io for a while. Pushed it now. Sorry about that.

@@ -92,24 +107,36 @@ extern crate configure_me;
include_config!();

fn main() {
// Don't worry, unwrap_or_exit() prints a nice message instead of ugly panic
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should still be mentioned, maybe using different wording?

```toml
[general]
# Prefix for all env vars - enables all env vars by default if present
build = "build.rs"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did git screw up the diff somehow? env var prefix is configured using env_prefix, not build

//! ```toml
//! [general]
//! # Prefix for all env vars - enables all env vars by default if present
//! build = "build.rs"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same mistake as above

@Shamazo
Copy link
Author

Shamazo commented Feb 14, 2021

thanks for catching all of that, I think most of them are due to subtle differences between the documentation in the .rs and the documentation in the readme. I'll go back over it and clean things up and get them properly in sync.

@Kixunil
Copy link
Owner

Kixunil commented Dec 15, 2021

Ping, do you intend to continue working on this?

@Kixunil
Copy link
Owner

Kixunil commented Dec 26, 2022

Closing due to inactivity. Feel free to open a new one when you're ready.

@Kixunil Kixunil closed this Dec 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for multiple binaries mis-documented
2 participants