Skip to content

Commit d7d834c

Browse files
czentgrashkrisk
andcommitted
[native] Add support for env vars providing property values
This allows a user to configure the value of an environment variable to be used as value for a configuration property. For example, the configuration file may contain keys that would be hard coded. The values can now be replaced by environment variables that are read at startup time and the keys don't require hard coding in the configuration file. Co-authored-by: ashkrisk <[email protected]>
1 parent d1e7b5e commit d7d834c

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

presto-native-execution/presto_cpp/main/common/ConfigReader.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,29 @@
1919
#include "velox/common/config/Config.h"
2020

2121
namespace facebook::presto::util {
22+
23+
namespace {
24+
// Replaces strings of the form "${VAR}"
25+
// with the value of the environment variable "VAR" (if it exists).
26+
// Does nothing if the input doesn't look like "${...}".
27+
std::string replaceIfEnvironmentVariable(std::string_view str) {
28+
if (str.size() >= 3 && str.substr(0, 2) == "${" &&
29+
str[str.size() - 1] == '}') {
30+
auto env_name = std::string(str.substr(2, str.size() - 3));
31+
32+
char* envval = std::getenv(env_name.c_str());
33+
if (envval) {
34+
VELOX_CHECK_NE(
35+
strlen(envval),
36+
0,
37+
"The environment variable cannot be an empty string.");
38+
return std::string(envval);
39+
}
40+
}
41+
return std::string(str);
42+
}
43+
} // namespace
44+
2245
std::unordered_map<std::string, std::string> readConfig(
2346
const std::string& filePath) {
2447
// https://teradata.github.io/presto/docs/141t/configuration/configuration.html
@@ -45,7 +68,8 @@ std::unordered_map<std::string, std::string> readConfig(
4568
const auto name = line.substr(0, delimiterPos);
4669
VELOX_CHECK(!name.empty(), "property pair '{}' has empty key", line);
4770
const auto value = line.substr(delimiterPos + 1);
48-
properties.emplace(name, value);
71+
const auto adjustedValue = replaceIfEnvironmentVariable(value);
72+
properties.emplace(name, adjustedValue);
4973
}
5074

5175
return properties;

presto-native-execution/presto_cpp/main/common/tests/ConfigTest.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,33 @@ TEST_F(ConfigTest, optionalNodeId) {
255255
EXPECT_EQ(nodeId, config.nodeId());
256256
}
257257

258+
TEST_F(ConfigTest, readConfigEnvVarTest) {
259+
char path[] = "/tmp/velox_system_config_test_XXXXXX";
260+
const char* tempDirectoryPath = mkdtemp(path);
261+
if (tempDirectoryPath == nullptr) {
262+
throw std::logic_error("Cannot open temp directory");
263+
}
264+
265+
std::string propFilePath = tempDirectoryPath;
266+
propFilePath += "/envtest.properties";
267+
std::string ENV_VAR = "PRESTO_READ_CONFIG_TEST_VAR";
268+
269+
std::ofstream propFile(propFilePath);
270+
propFile << fmt::format("{}={}\n", "plain-text", "plain-text-value");
271+
propFile << fmt::format("{}=${{{}}}\n", "env-var", ENV_VAR);
272+
propFile << fmt::format("{}=${{{}\n", "env-var2", ENV_VAR);
273+
propFile << fmt::format("{}={}}}\n", "env-var3", ENV_VAR);
274+
propFile << fmt::format("{}=${{}}\n", "no-env-var");
275+
propFile.close();
276+
277+
setenv(ENV_VAR.c_str(), "env-var-value", 1);
278+
auto properties = facebook::presto::util::readConfig(propFilePath);
279+
ASSERT_EQ(properties["plain-text"], "plain-text-value");
280+
ASSERT_EQ(properties["env-var"], "env-var-value");
281+
ASSERT_EQ(properties["env-var2"], "${PRESTO_READ_CONFIG_TEST_VAR");
282+
ASSERT_EQ(properties["env-var3"], "PRESTO_READ_CONFIG_TEST_VAR}");
283+
ASSERT_EQ(properties["no-env-var"], "${}");
284+
unsetenv(ENV_VAR.c_str());
285+
}
286+
258287
} // namespace facebook::presto::test

0 commit comments

Comments
 (0)