Skip to content

Commit 738061a

Browse files
authored
feat(config): env support for nested fields (#276)
* feat(config): env support for nested fields Signed-off-by: Alexis Asseman <[email protected]> * docs(config): update env config example fixes #256 Signed-off-by: Alexis Asseman <[email protected]> --------- Signed-off-by: Alexis Asseman <[email protected]>
1 parent fbecf74 commit 738061a

File tree

4 files changed

+80
-7
lines changed

4 files changed

+80
-7
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ serde_ignored = "0.1.10"
1919
[dev-dependencies]
2020
sealed_test = "1.1.0"
2121
serde_test = "1.0.176"
22+
tempfile = "3.10.1"
2223
toml = "0.8.12"
2324
tracing-test = "0.2.5"

config/maximal-config-example.toml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
# Some of the config below are global graph network values, which you can find here:
1010
# https://github.com/graphprotocol/indexer/tree/main/docs/networks
1111
#
12-
# Pro tip: if you need to load some values from the environment into this config, you
13-
# can overwrite with environment variables. For example, the following can be replaced
14-
# by [PREFIX]_DATABASE_POSTGRESURL, where PREFIX can be `INDEXER_SERVICE` or `TAP_AGENT`:
12+
# If you want to supply some or all of the configuration below using environment variables,
13+
# use the prefix "INDEXER_SERVICE" or "TAP_AGENT" for indexer-service or tap-agent, respectively,
14+
# followed by the name of the field, using double underscores "__" for nesting. Example:
1515
#
16-
# [database]
17-
# postgres_url = "postgresql://indexer:${POSTGRES_PASSWORD}@postgres:5432/indexer_components_0"
18-
16+
# INDEXER_SERVICE_SUBGRAPHS__NETWORK__QUERY_URL = [...]
17+
#
18+
# For
19+
#
20+
# [subgraphs.network]
21+
# query_url = [...]
1922

2023
[indexer]
2124
indexer_address = "0x1111111111111111111111111111111111111111"

config/src/config.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl Config {
7474
let config: ConfigWrapper = Figment::new()
7575
.merge(Toml::string(config_defaults))
7676
.merge(Toml::file(filename))
77-
.merge(Env::prefixed(prefix.get_prefix()))
77+
.merge(Env::prefixed(prefix.get_prefix()).split("__"))
7878
.extract()
7979
.map_err(|e| e.to_string())?;
8080
config.0.validate()?;
@@ -330,4 +330,72 @@ mod tests {
330330
"Ignoring unknown configuration field: plumbus"
331331
));
332332
}
333+
334+
// Test that we can fill in mandatory config fields missing from the config file with
335+
// environment variables
336+
#[sealed_test(files = ["minimal-config-example.toml"])]
337+
fn test_fill_in_missing_with_env() {
338+
let mut minimal_config: toml::Value = toml::from_str(
339+
fs::read_to_string("minimal-config-example.toml")
340+
.unwrap()
341+
.as_str(),
342+
)
343+
.unwrap();
344+
// Remove the subgraphs.network.query_url field from minimal config
345+
minimal_config
346+
.get_mut("subgraphs")
347+
.unwrap()
348+
.get_mut("network")
349+
.unwrap()
350+
.as_table_mut()
351+
.unwrap()
352+
.remove("query_url");
353+
354+
// Save the modified minimal config to a named temporary file using tempfile
355+
let temp_minimal_config_path = tempfile::NamedTempFile::new().unwrap();
356+
fs::write(
357+
temp_minimal_config_path.path(),
358+
toml::to_string(&minimal_config).unwrap(),
359+
)
360+
.unwrap();
361+
362+
// This should fail because the subgraphs.network.query_url field is missing
363+
Config::parse(
364+
ConfigPrefix::Service,
365+
&PathBuf::from(temp_minimal_config_path.path()),
366+
)
367+
.unwrap_err();
368+
369+
let test_value = "http://localhost:8000/testvalue";
370+
std::env::set_var("INDEXER_SERVICE_SUBGRAPHS__NETWORK__QUERY_URL", test_value);
371+
372+
let config = Config::parse(
373+
ConfigPrefix::Service,
374+
&PathBuf::from(temp_minimal_config_path.path()),
375+
)
376+
.unwrap();
377+
378+
assert_eq!(
379+
config.subgraphs.network.config.query_url.as_str(),
380+
test_value
381+
);
382+
}
383+
384+
// Test that we can override nested config values with environment variables
385+
#[sealed_test(files = ["minimal-config-example.toml"])]
386+
fn test_override_with_env() {
387+
let test_value = "http://localhost:8000/testvalue";
388+
std::env::set_var("INDEXER_SERVICE_SUBGRAPHS__NETWORK__QUERY_URL", test_value);
389+
390+
let config = Config::parse(
391+
ConfigPrefix::Service,
392+
&PathBuf::from("minimal-config-example.toml"),
393+
)
394+
.unwrap();
395+
396+
assert_eq!(
397+
config.subgraphs.network.config.query_url.as_str(),
398+
test_value
399+
);
400+
}
333401
}

0 commit comments

Comments
 (0)