Crate plugx_config
source ·Expand description
Plugin configuration manager (work-in-progress)
Package | Documentation | Repository
// In this example we're going to load our plugins' configurations from
// a directory and environment-variables.
// Here we have 4 plugins `foo`, `bar`, `baz`, and `qux`.
use plugx_config::Configuration;
use std::{collections::HashMap, env, fs};
use tempdir::TempDir;
use url::Url;
// Set some configurations in environment-variables:
env::set_var("APP_NAME__FOO__SERVER__ADDRESS", "127.0.0.1");
env::set_var("APP_NAME__BAR__SQLITE__FILE", "/path/to/app.db");
env::set_var("APP_NAME__BAZ__LOGGING__LEVEL", "debug");
env::set_var("APP_NAME__QUX__HTTPS__INSECURE", "false");
// Create a temporary directory `/tmp/.../etc/app-name` (which will be removed after running our example)
let root_tmp = TempDir::new("example").expect("Create temporary directory");
let cfg_dir = root_tmp.path().join("etc").join("app.d");
fs::create_dir_all(cfg_dir.clone()).unwrap();
// Write some configurations inside and example directory `/tmp/.../etc/app.d/`:
fs::write(
cfg_dir.join("foo.env"),
"SERVER__PORT=8080 # This is a comment",
)
.unwrap();
fs::write(
cfg_dir.join("bar.json"),
"{\"sqlite\": {\"recreate\": true}}",
)
.unwrap();
fs::write(
cfg_dir.join("baz.toml"),
"[logging]\noutput_serialize_format = \"json\"",
)
.unwrap();
fs::write(
cfg_dir.join("qux.yaml"),
"https:\n follow_redirects: false",
)
.unwrap();
// Create a URL for our environment-variables configuration:
let env_url: Url = "env://?prefix=APP_NAME__&key_separator=__"
.parse()
.expect("Valid URL");
// Create a URL for our `/tmp/.../etc/app.d/` directory:
// `skippable` query-string key is list of skippable error names.
// Here we want to skip `not found` error if the directory does not exists:
let file_url: Url = format!("file://{}?skippable[0]=notfound", cfg_dir.to_str().unwrap())
.parse()
.expect("Valid URL");
// We want to check our plugins' configurations for them but we do not know what they want!
// We can load them and ask them what keys and values they expect to have before loading
// and checking configurations.
// Here for example we asked them about their configuration and collected their rules in
// JSON format:
let rules_json = r#"
{
"foo": {
"type": "static_map",
"definitions": {
"server": {
"definition": {
"type": "static_map",
"definitions": {
"address": {"definition": {"type": "ip"}},
"port": {"definition": {"type": "integer", "range": {"min": 1, "max": 65535}}}
}
}
}
}
},
"bar": {
"type": "static_map",
"definitions": {
"sqlite": {
"definition": {
"type": "static_map",
"definitions": {
"recreate": {"definition": {"type": "boolean"}, "default": true},
"file": {"definition": {"type": "path", "file_type": "file", "access": ["write"]}}
}
}
}
}
},
"baz": {
"type": "static_map",
"definitions": {
"logging": {
"definition": {
"type": "static_map",
"definitions": {
"level": {"definition": {"type": "log_level"}, "default": "info"},
"output_serialize_format": {"definition": {"type": "enum", "items": ["json", "logfmt"]}}
}
}
}
}
},
"qux": {
"type": "static_map",
"definitions": {
"https": {
"definition": {
"type": "static_map",
"definitions": {
"insecure": {"definition": {"type": "boolean"}},
"follow_redirects": {"definition": {"type": "boolean"}}
}
}
}
}
}
}
"#;
let rules: HashMap<_, _> = serde_json::from_str(rules_json).unwrap();
// Here's the actual work:
let mut configuration = Configuration::default()
.with_url(env_url)
.with_url(file_url);
let apply_akippable_errors = true;
configuration
.try_load_parse_merge_validate(apply_akippable_errors, &rules)
.unwrap();
configuration
.configuration()
.iter()
.for_each(|(plugin, config)| println!("{plugin}: {config:#}"));
// Prints:
// foo: {"server": {"address": "127.0.0.1", "port": 8080}}
// baz: {"logging": {"output_serialize_format": "json", "level": "debug"}}
// bar: {"sqlite": {"file": "/path/to/app.db", "recreate": true}}
// qux: {"https": {"insecure": false, "follow_redirects": false}}Modules
- Configuration entity for each plugin.
- All possible error types.
- Extern other crates.
- Configuration loader trait and implementations.
- Configuration parser trait and implementations.
Structs
Enums
- Main error wrapper.