From 8c65ee7636346e4104cb0196d0d0b87f8fac6e04 Mon Sep 17 00:00:00 2001 From: Tigran Mkrtchyan Date: Tue, 17 Oct 2023 14:27:45 +0200 Subject: [PATCH] config: add support for environment variable injection Motivation: in container world it's common to use environment variables to pass the configuration parameters. Currently dCache doesn't support such injects, which makes container-based deployments more complicated. Modification: Update ConfigurationProperties to resolve environment variables when reading the property (layout, conf) files. The syntax is: dcache.net.wan.port.min=${env.DCACHE_WAN_PORT_MIN} dcache.net.wan.port.max=${env.DCACHE_WAN_PORT_MAX} Result: dcache properties can be controlled by env variables, if desired. Acked-by: Albert Rossi Target: master Require-book: yes Require-notes: yes --- .../configuration/ConfigurationProperties.java | 18 ++++++++++++++++-- .../ConfigurationPropertiesTests.java | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/modules/dcache/src/main/java/org/dcache/util/configuration/ConfigurationProperties.java b/modules/dcache/src/main/java/org/dcache/util/configuration/ConfigurationProperties.java index 0ba3b660614..ca4a7300d4a 100644 --- a/modules/dcache/src/main/java/org/dcache/util/configuration/ConfigurationProperties.java +++ b/modules/dcache/src/main/java/org/dcache/util/configuration/ConfigurationProperties.java @@ -247,14 +247,28 @@ public synchronized Object put(Object rawKey, Object value) { _prefixes.add(key.getPropertyName() + PREFIX_SEPARATOR); } - checkIsAllowed(key, (String) value); + // the reset of the code expects `value` to be an instance of String + assert value instanceof String; + + String stringValue = (String) value; + // REVISIT: do we need to resolve it here or on get ? + if (stringValue.startsWith("${env.") && stringValue.endsWith("}")) { + String envKey = stringValue.substring(6, stringValue.length() - 1); + stringValue = System.getenv(envKey); + if (stringValue == null) { + _problemConsumer.error("Environment variable " + envKey + " for property " + rawKey + " undefined."); + return null; + } + } + + checkIsAllowed(key, stringValue); if (key.hasAnnotations()) { putAnnotatedKey(key); } return key.hasAnyOf(OBSOLETE_FORBIDDEN) ? null - : super.put(name, canonicalizeValue(name, value)); + : super.put(name, canonicalizeValue(name, stringValue)); } private String canonicalizeValue(String key, Object value) { diff --git a/modules/dcache/src/test/java/org/dcache/util/configuration/ConfigurationPropertiesTests.java b/modules/dcache/src/test/java/org/dcache/util/configuration/ConfigurationPropertiesTests.java index 5dbbf49f6a4..c1ebd943380 100644 --- a/modules/dcache/src/test/java/org/dcache/util/configuration/ConfigurationPropertiesTests.java +++ b/modules/dcache/src/test/java/org/dcache/util/configuration/ConfigurationPropertiesTests.java @@ -399,6 +399,20 @@ public void testGetReplacementExpandingWithSpace() { assertEquals(valueWithSpace, _standardProperties.getValue(EXPANDING_PROPERTY_NAME)); } + @Test + public void testGetReplacementExpandingEnv() { + // we assume that this SHELL env variable always set + _standardProperties.setProperty(SIMPLE_PROPERTY_NAME, propertyReference("env.SHELL")); + _standardProperties.getProperty(SIMPLE_PROPERTY_NAME); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetReplacementMissingEnv() { + // we assume that this env variable actually never exists + _standardProperties.setProperty(SIMPLE_PROPERTY_NAME, propertyReference("env.NO_NO_NO")); + _standardProperties.getProperty(SIMPLE_PROPERTY_NAME); + } + @Test public void testTwoDeepExpansion() { String expanding1Value = propertyReference(SIMPLE_PROPERTY_NAME);