Compare commits
2 Commits
921a9de90a
...
997e9611eb
Author | SHA1 | Date |
---|---|---|
Jef Roosens | 997e9611eb | |
Jef Roosens | 44aa7c9dc9 |
37
conf.v
37
conf.v
|
@ -4,16 +4,25 @@ import os
|
||||||
import toml
|
import toml
|
||||||
import datatypes { Set }
|
import datatypes { Set }
|
||||||
|
|
||||||
|
[params]
|
||||||
|
pub struct LoadConfig {
|
||||||
|
prefix string
|
||||||
|
file_suffix string = '_FILE'
|
||||||
|
default_path string
|
||||||
|
// Allows overwriting
|
||||||
|
env map[string]string = os.environ()
|
||||||
|
}
|
||||||
|
|
||||||
// get_env_var tries to read the contents of the given environment variable. It
|
// get_env_var tries to read the contents of the given environment variable. It
|
||||||
// looks for either `${env.prefix}${field_name.to_upper()}` or
|
// looks for either `${env.prefix}${field_name.to_upper()}` or
|
||||||
// `${env.prefix}${field_name.to_upper()}${env.file_suffix}`, returning the
|
// `${env.prefix}${field_name.to_upper()}${env.file_suffix}`, returning the
|
||||||
// contents of the file instead if the latter. If both or neither exist, the
|
// contents of the file instead if the latter. If both or neither exist, the
|
||||||
// function returns an error.
|
// function returns an error.
|
||||||
fn get_env_var(prefix string, field_name string, file_suffix string) !string {
|
fn (ld LoadConfig) get_env_var(field_name string) !string {
|
||||||
env_var_name := '$prefix$field_name.to_upper()'
|
env_var_name := '$ld.prefix$field_name.to_upper()'
|
||||||
env_file_name := '$prefix$field_name.to_upper()$file_suffix'
|
env_file_name := '$ld.prefix$field_name.to_upper()$ld.file_suffix'
|
||||||
env_var := os.getenv(env_var_name)
|
env_var := ld.env[env_var_name] or { '' }
|
||||||
env_file := os.getenv(env_file_name)
|
env_file := ld.env[env_file_name] or { '' }
|
||||||
|
|
||||||
// If both are missing, we return an empty string
|
// If both are missing, we return an empty string
|
||||||
if env_var == '' && env_file == '' {
|
if env_var == '' && env_file == '' {
|
||||||
|
@ -39,18 +48,11 @@ fn get_env_var(prefix string, field_name string, file_suffix string) !string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[params]
|
|
||||||
pub struct LoadConfig {
|
|
||||||
prefix string
|
|
||||||
file_suffix string = '_FILE'
|
|
||||||
default_path string
|
|
||||||
}
|
|
||||||
|
|
||||||
// load<T> attempts to create an object of type T from the given path to a toml
|
// load<T> attempts to create an object of type T from the given path to a toml
|
||||||
// file & environment variables. For each field, it will select either a value
|
// file & environment variables. For each field, it will select either a value
|
||||||
// given from an environment variable, a value defined in the config file or a
|
// given from an environment variable, a value defined in the config file or a
|
||||||
// configured default if present, in that order.
|
// configured default if present, in that order.
|
||||||
pub fn load<T>(conf LoadConfig) !T {
|
pub fn load<T>(ld LoadConfig) !T {
|
||||||
mut res := T{}
|
mut res := T{}
|
||||||
|
|
||||||
// This array allows us to determine later whether the variable is actually
|
// This array allows us to determine later whether the variable is actually
|
||||||
|
@ -58,7 +60,7 @@ pub fn load<T>(conf LoadConfig) !T {
|
||||||
mut has_value := Set<string>{}
|
mut has_value := Set<string>{}
|
||||||
|
|
||||||
// Later, this could be read from an env var as well.
|
// Later, this could be read from an env var as well.
|
||||||
path := conf.default_path
|
path := ld.default_path
|
||||||
|
|
||||||
if os.exists(path) {
|
if os.exists(path) {
|
||||||
// We don't use reflect here because reflect also sets any fields not
|
// We don't use reflect here because reflect also sets any fields not
|
||||||
|
@ -84,7 +86,7 @@ pub fn load<T>(conf LoadConfig) !T {
|
||||||
}
|
}
|
||||||
|
|
||||||
$for field in T.fields {
|
$for field in T.fields {
|
||||||
env_value := get_env_var(conf.prefix, field.name, conf.file_suffix)!
|
env_value := ld.get_env_var(field.name)!
|
||||||
|
|
||||||
// The value of an env var will always take precedence over the toml
|
// The value of an env var will always take precedence over the toml
|
||||||
// file.
|
// file.
|
||||||
|
@ -117,12 +119,11 @@ pub fn load<T>(conf LoadConfig) !T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's no value provided in any way, we notify the user with an
|
// If there's no value provided in any way, we notify the user with an
|
||||||
// error.
|
// error.
|
||||||
if !has_value.exists(field.name) {
|
if !has_value.exists(field.name) {
|
||||||
return error("Missing config variable '$field.name' with no provided default. Either add it to the config file or provide it using an environment variable.")
|
return error("Missing config variable '$field.name' with no provided default. Either add it to the config file or provide it using an environment variable.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -8,6 +8,14 @@ struct SingleConfDefault {
|
||||||
some_string string = 'default'
|
some_string string = 'default'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const env = {
|
||||||
|
'SOME_STRING': 'env'
|
||||||
|
}
|
||||||
|
|
||||||
|
const prefix_env = {
|
||||||
|
'TEST_SOME_STRING': 'env'
|
||||||
|
}
|
||||||
|
|
||||||
fn test_string_present_no_default() {
|
fn test_string_present_no_default() {
|
||||||
conf := load<SingleConf>(default_path: 'test/string.toml')!
|
conf := load<SingleConf>(default_path: 'test/string.toml')!
|
||||||
assert conf == SingleConf{
|
assert conf == SingleConf{
|
||||||
|
@ -15,11 +23,35 @@ fn test_string_present_no_default() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_string_present_no_default_env() {
|
||||||
|
conf := load<SingleConf>(default_path: 'test/string.toml', env: .env)!
|
||||||
|
assert conf == SingleConf{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
|
||||||
|
conf2 := load<SingleConf>(default_path: 'test/string.toml', env: .prefix_env, prefix: 'TEST_')!
|
||||||
|
assert conf2 == SingleConf{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_string_absent_no_default() {
|
fn test_string_absent_no_default() {
|
||||||
conf := load<SingleConf>(default_path: 'test/empty.toml') or { return }
|
conf := load<SingleConf>(default_path: 'test/empty.toml') or { return }
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_string_absent_no_default_env() {
|
||||||
|
conf := load<SingleConf>(default_path: 'test/string.toml', env: .env)!
|
||||||
|
assert conf == SingleConf{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
|
||||||
|
conf2 := load<SingleConf>(default_path: 'test/string.toml', env: .prefix_env, prefix: 'TEST_')!
|
||||||
|
assert conf2 == SingleConf{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_string_present_default() {
|
fn test_string_present_default() {
|
||||||
conf := load<SingleConfDefault>(default_path: 'test/string.toml')!
|
conf := load<SingleConfDefault>(default_path: 'test/string.toml')!
|
||||||
assert conf == SingleConfDefault{
|
assert conf == SingleConfDefault{
|
||||||
|
@ -27,9 +59,41 @@ fn test_string_present_default() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_string_present_default_env() {
|
||||||
|
conf := load<SingleConfDefault>(default_path: 'test/string.toml', env: .env)!
|
||||||
|
assert conf == SingleConfDefault{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
|
||||||
|
conf2 := load<SingleConfDefault>(
|
||||||
|
default_path: 'test/string.toml'
|
||||||
|
env: .prefix_env
|
||||||
|
prefix: 'TEST_'
|
||||||
|
)!
|
||||||
|
assert conf2 == SingleConfDefault{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn test_string_absent_default() {
|
fn test_string_absent_default() {
|
||||||
conf := load<SingleConfDefault>(default_path: 'test/empty.toml')!
|
conf := load<SingleConfDefault>(default_path: 'test/empty.toml')!
|
||||||
assert conf == SingleConfDefault{
|
assert conf == SingleConfDefault{
|
||||||
some_string: 'default'
|
some_string: 'default'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_string_absent_default_env() {
|
||||||
|
conf := load<SingleConfDefault>(default_path: 'test/empty.toml', env: .env)!
|
||||||
|
assert conf == SingleConfDefault{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
|
||||||
|
conf2 := load<SingleConfDefault>(
|
||||||
|
default_path: 'test/empty.toml'
|
||||||
|
env: .prefix_env
|
||||||
|
prefix: 'TEST_'
|
||||||
|
)!
|
||||||
|
assert conf2 == SingleConfDefault{
|
||||||
|
some_string: 'env'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue