3个不稳定版本
使用旧的Rust 2015
0.1.1 | 2018年1月24日 |
---|---|
0.1.0 | 2018年1月20日 |
0.0.1 | 2017年11月25日 |
#27 在 #configure
700 每月下载量
用于 6 个crate(通过 configure)
8KB
170 行
configure - 从环境中提取配置
"12因素应用" 有关于管理配置的非常好建议
将配置存储在环境中
应用程序的配置是可能在不同部署(测试、生产、开发者环境等)之间变化的任何东西。这包括
- 到数据库、Memcached和其他后端服务的资源句柄
- 到外部服务(如Amazon S3或Twitter)的凭据
- 每个部署的值,例如部署的主机名
如链接网页中所述的原因,将此类信息直接存储在源代码中是不好的做法。即使不考虑他们的理由,对于像Rust这样的编译语言来说,这尤其不方便,因为它需要在部署环境之间重新编译整个项目,并且更改这些值之一意味着进行完全的重部署。
然而,今天的大多数库都将这些类型的配置作为构造函数的参数,让应用程序作者负责开发自己的系统来从环境中提取这些配置。Configure是创建库从环境中提取配置的标准方式的尝试,使最终用户更容易遵循有关配置的最佳实践。
这并不适用于所有类型的“配置”。例如,如果必须在编译时应用配置(例如,为了驱动单态化以获得内联优势),则使用此库是不合适的。如果配置可以在每次执行操作时变化(例如,因为它配置了一种类型的格式化器),则使用此库可能也不合适。
Configure特质
采用此模式的库应将所有适当的配置放入一个结构体中
struct Config {
socket_addr: SocketAddr,
tls_cert: Option<PathBuf>,
// ... etc
}
这个需要实现 Configure
的结构体。正确实现 Configure
的最简单方法是通过派生。派生 Configure
要求结构体还实现 Deserialize
,这也可以通过派生来实现
#[macro_use] extern crate configure;
extern crate serde;
#[macro_use] extern crate serde_derive;
#[derive(Deserialize, Configure)]
struct Config {
socket_addr: SocketAddr,
tls_cert: Option<PathBuf>,
// ... etc
}
配置特徵提供了两个函数
Configure::generate
,一个构造函数,用于从环境变量生成配置。Configure::regenerate
,一个方法,通过再次从环境变量中拉取来更新配置。
Configure
生成的实现都从配置源拉取配置,该源由最终应用程序控制。
配置源
最终,最终应用程序控制配置生成的源。这种控制通过CONFIGURATION
静态来实现。《Configure》实现将使用CONFIGURATION.get
访问源。
提供了一个默认源供您使用,因此对于默认值令人满意的应用程序不需要做任何事情。想要存储配置的应用程序可以覆盖该源。
默认源
默认情况下,configure
提供了一种用户可以依赖的配置源。用户可以在主函数的开始处使用use_default_config!
宏来使用此源。默认源针对网络服务,可能不适合所有其他领域。
它的工作方式如下
- 默认情况下,它使用环境变量查找配置值。例如,如果库
foo
有一个具有字段bar
的配置结构体,则该字段将由FOO_BAR
环境变量控制。 - 如果没有设置环境变量,它将回退到查找
Cargo.toml
。如果有Cargo.toml
存在,并且它包含一个[package.metadata.foo]
表(其中foo
是库的名称),则该表中的bar
成员将控制foo
的配置结构体中的bar
字段。
一般来说,建议大多数环境使用环境变量来控制配置。Cargo.toml
回退是针对开发环境的,这样您就可以将这些值检查到Cargo.toml
中,并在每个开发人员的机器上保持一致。
自定义配置源
用户可以使用use_config_from!
宏覆盖他们应用程序的默认配置。此宏应在最终二进制文件的末尾调用一次。首先,您需要准备一个实现ConfigSource
的类型,用作配置源。
这允许用户控制他们的配置源,而无需重新编译所有依赖的库代码,如果配置源是类型参数,则会发生这种情况。
依赖项
~2.5MB
~49K SLoC