test: also test env vars
							parent
							
								
									44aa7c9dc9
								
							
						
					
					
						commit
						997e9611eb
					
				
							
								
								
									
										37
									
								
								conf.v
								
								
								
								
							
							
						
						
									
										37
									
								
								conf.v
								
								
								
								
							| 
						 | 
				
			
			@ -4,16 +4,25 @@ import os
 | 
			
		|||
import toml
 | 
			
		||||
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
 | 
			
		||||
// looks for either `${env.prefix}${field_name.to_upper()}` or
 | 
			
		||||
// `${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
 | 
			
		||||
// function returns an error.
 | 
			
		||||
fn get_env_var(prefix string, field_name string, file_suffix string) !string {
 | 
			
		||||
	env_var_name := '$prefix$field_name.to_upper()'
 | 
			
		||||
	env_file_name := '$prefix$field_name.to_upper()$file_suffix'
 | 
			
		||||
	env_var := os.getenv(env_var_name)
 | 
			
		||||
	env_file := os.getenv(env_file_name)
 | 
			
		||||
fn (ld LoadConfig) get_env_var(field_name string) !string {
 | 
			
		||||
	env_var_name := '$ld.prefix$field_name.to_upper()'
 | 
			
		||||
	env_file_name := '$ld.prefix$field_name.to_upper()$ld.file_suffix'
 | 
			
		||||
	env_var := ld.env[env_var_name] or { '' }
 | 
			
		||||
	env_file := ld.env[env_file_name] or { '' }
 | 
			
		||||
 | 
			
		||||
	// If both are missing, we return an empty string
 | 
			
		||||
	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
 | 
			
		||||
// 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
 | 
			
		||||
// configured default if present, in that order.
 | 
			
		||||
pub fn load<T>(conf LoadConfig) !T {
 | 
			
		||||
pub fn load<T>(ld LoadConfig) !T {
 | 
			
		||||
	mut res := T{}
 | 
			
		||||
 | 
			
		||||
	// 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>{}
 | 
			
		||||
 | 
			
		||||
	// Later, this could be read from an env var as well.
 | 
			
		||||
	path := conf.default_path
 | 
			
		||||
	path := ld.default_path
 | 
			
		||||
 | 
			
		||||
	if os.exists(path) {
 | 
			
		||||
		// 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 {
 | 
			
		||||
		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
 | 
			
		||||
		// 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
 | 
			
		||||
        // error.
 | 
			
		||||
		// If there's no value provided in any way, we notify the user with an
 | 
			
		||||
		// error.
 | 
			
		||||
		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 res
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,14 @@ struct SingleConfDefault {
 | 
			
		|||
	some_string string = 'default'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const env = {
 | 
			
		||||
	'SOME_STRING': 'env'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const prefix_env = {
 | 
			
		||||
	'TEST_SOME_STRING': 'env'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_string_present_no_default() {
 | 
			
		||||
	conf := load<SingleConf>(default_path: 'test/string.toml')!
 | 
			
		||||
	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() {
 | 
			
		||||
	conf := load<SingleConf>(default_path: 'test/empty.toml') or { return }
 | 
			
		||||
	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() {
 | 
			
		||||
	conf := load<SingleConfDefault>(default_path: 'test/string.toml')!
 | 
			
		||||
	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() {
 | 
			
		||||
	conf := load<SingleConfDefault>(default_path: 'test/empty.toml')!
 | 
			
		||||
	assert conf == SingleConfDefault{
 | 
			
		||||
		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