Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Inicio rápido

English | 中文 | 日本語 | 한국어 | Français | Deutsch | Español | Português | Svenska | Suomi | Nederlands

Añade el crate y las bibliotecas de esquema/tiempo de ejecución que usa tu aplicación:

[dependencies]
rust-config-tree = "0.1"
confique = { version = "0.4", features = ["yaml", "toml", "json5"] }
figment = { version = "0.10", features = ["yaml", "toml", "json", "env"] }
schemars = { version = "1", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
clap = { version = "4", features = ["derive"] }

Define un esquema confique e implementa ConfigSchema para el tipo raíz:

#![allow(unused)]
fn main() {
use std::path::PathBuf;

use confique::Config;
use rust_config_tree::ConfigSchema;

#[derive(Debug, Config)]
struct AppConfig {
    #[config(default = [])]
    include: Vec<PathBuf>,

    #[config(nested)]
    server: ServerConfig,
}

#[derive(Debug, Config)]
struct ServerConfig {
    #[config(default = "127.0.0.1")]
    #[config(env = "APP_SERVER_BIND")]
    bind: String,

    #[config(default = 8080)]
    #[config(env = "APP_SERVER_PORT")]
    port: u16,
}

impl ConfigSchema for AppConfig {
    fn include_paths(layer: &<Self as Config>::Layer) -> Vec<PathBuf> {
        layer.include.clone().unwrap_or_default()
    }
}
}

Carga la configuración:

#![allow(unused)]
fn main() {
use rust_config_tree::load_config;

let config = load_config::<AppConfig>("config.yaml")?;
println!("{config:#?}");
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}

Usa un archivo raíz con includes recursivos:

# config.yaml
include:
  - config/server.yaml
# config/server.yaml
server:
  bind: 0.0.0.0
  port: 3000

La precedencia por defecto de load_config es:

environment variables
  > config files, with later merged files overriding earlier files
    > confique code defaults

Cuando los includes se cargan mediante la API de alto nivel, el archivo raíz tiene la prioridad de archivo más alta. Los archivos incluidos aportan valores de menor prioridad y pueden usarse para valores por defecto o archivos específicos de sección.

Los argumentos de línea de comandos son específicos de la aplicación, así que load_config no los lee automáticamente. Fusiona overrides de CLI después de build_config_figment cuando la aplicación tenga flags de override de configuración:

Los nombres de flags de CLI los elige la aplicación. No son automáticamente rutas de configuración a.b.c. Prefiere flags clap normales como --server-port, luego mapéalas a una estructura de override anidada. La forma serializada anidada controla la clave de configuración que se sobrescribe.

Solo los valores representados en el proveedor CliOverrides de la aplicación sobrescriben la configuración. Esto es útil para parámetros que se cambian con frecuencia para una ejecución sin editar el archivo de configuración. Los valores estables deberían permanecer en archivos de configuración.

#![allow(unused)]
fn main() {
use figment::providers::Serialized;
use serde::Serialize;
use rust_config_tree::{build_config_figment, load_config_from_figment};

#[derive(Debug, Serialize)]
struct CliOverrides {
    #[serde(skip_serializing_if = "Option::is_none")]
    server: Option<CliServerOverrides>,
}

#[derive(Debug, Serialize)]
struct CliServerOverrides {
    #[serde(skip_serializing_if = "Option::is_none")]
    port: Option<u16>,
}

let cli_overrides = CliOverrides {
    server: Some(CliServerOverrides { port: Some(9000) }),
};

let figment = build_config_figment::<AppConfig>("config.yaml")?
    .merge(Serialized::defaults(cli_overrides));

let config = load_config_from_figment::<AppConfig>(&figment)?;
let _ = config;
Ok::<(), Box<dyn std::error::Error + Send + Sync>>(())
}

Con overrides de CLI fusionados de esta forma, la precedencia completa es:

command-line overrides
  > environment variables
    > config files
      > confique code defaults