Skip to content

Commit 854154e

Browse files
Replace environment variable only for dab start (#1641)
## Why make this change? - Closes #1632 - it's an unintended side effect of an optimisation pathway was added to the deserializer in #1402. Previously, deserializing the JSON config and replacing environment variables were done as two separate parses of the config JSON blob. First the JSON would be read from disk and then we'd create a JSON reader that would walk all the tokens in the file, we'd check the token to see if it matched the regex for an environment variable, we'd replace it and then return the updated JSON string. Next this would be given to the deserializer and it would be turned into the .NET object that we would use throughout the engine. This meant that we'd end up walking the AST for the JSON twice. - With #1402, when we are doing deserialization we would also do the environment variable replacement, meaning that we'd only walk the JSON AST once, thus improving performance. - There is a downside to this - the CLI doesn't need to do environment variable replacements (since we don't need to actually connect to the DB or anything, except for start, but that doesn't write out an updated config). ## What is this change? - Introduces a flag replaceEnvVar to determine whether to do the environment variable replacement in the JsonConverters when being used from the CLI commands. For `start` command this will be `true`, for all other commands this is `false`. - To minimize changes, default value of this argument was kept false. All occurrences of callers requiring this flag were modified and set to `true` in case of `start` or running the engine. - For Enums, always replace the environment variable with its value for appropriate deserialization into an Enum value. ## How was this tested? - [X] Integration Tests - Modified the End2EndTests, to test the commands `add`, `update` dont replace the environment variables, but `start` replaces it. - [X] Unit Tests - Modified the `CheckConfigEnvParsingTest` to test when replaceEnvVar is `false` we dont replace them. The `true` scenario was already being tested. Also modified the `database-type` property to be an env variable for testing enums are always replaced with values. --------- Co-authored-by: Sean Leonard <[email protected]>
1 parent 5e3874e commit 854154e

20 files changed

+486
-307
lines changed

src/Cli.Tests/EndToEndTests.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public void TestInitialize()
3535
_cliLogger = loggerFactory.CreateLogger<Program>();
3636
SetLoggerForCliConfigGenerator(loggerFactory.CreateLogger<ConfigGenerator>());
3737
SetCliUtilsLogger(loggerFactory.CreateLogger<Utils>());
38+
39+
Environment.SetEnvironmentVariable($"connection-string", TEST_CONNECTION_STRING);
3840
}
3941

4042
[TestCleanup]
@@ -52,7 +54,7 @@ public void TestCleanup()
5254
public Task TestInitForCosmosDBNoSql()
5355
{
5456
string[] args = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--database-type", "cosmosdb_nosql",
55-
"--connection-string", "localhost:5000", "--cosmosdb_nosql-database",
57+
"--connection-string", TEST_ENV_CONN_STRING, "--cosmosdb_nosql-database",
5658
"graphqldb", "--cosmosdb_nosql-container", "planet", "--graphql-schema", TEST_SCHEMA_FILE, "--cors-origin", "localhost:3000,www.nolocalhost.com:80" };
5759
Program.Execute(args, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
5860

@@ -109,7 +111,10 @@ public void TestInitializingRestAndGraphQLGlobalSettings()
109111
string[] args = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--connection-string", SAMPLE_TEST_CONN_STRING, "--database-type", "mssql", "--rest.path", "/rest-api", "--rest.disabled", "--graphql.path", "/graphql-api" };
110112
Program.Execute(args, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
111113

112-
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? runtimeConfig));
114+
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(
115+
TEST_RUNTIME_CONFIG_FILE,
116+
out RuntimeConfig? runtimeConfig,
117+
replaceEnvVar: true));
113118

114119
SqlConnectionStringBuilder builder = new(runtimeConfig.DataSource.ConnectionString);
115120
Assert.AreEqual(DEFAULT_APP_NAME, builder.ApplicationName);
@@ -129,7 +134,8 @@ public void TestInitializingRestAndGraphQLGlobalSettings()
129134
[TestMethod]
130135
public void TestAddEntity()
131136
{
132-
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--host-mode", "development", "--database-type", "mssql", "--connection-string", SAMPLE_TEST_CONN_STRING, "--auth.provider", "StaticWebApps" };
137+
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--host-mode", "development", "--database-type",
138+
"mssql", "--connection-string", TEST_ENV_CONN_STRING, "--auth.provider", "StaticWebApps" };
133139
Program.Execute(initArgs, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
134140

135141
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? runtimeConfig));
@@ -145,6 +151,7 @@ public void TestAddEntity()
145151

146152
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? addRuntimeConfig));
147153
Assert.IsNotNull(addRuntimeConfig);
154+
Assert.AreEqual(TEST_ENV_CONN_STRING, addRuntimeConfig.DataSource.ConnectionString);
148155
Assert.AreEqual(1, addRuntimeConfig.Entities.Count()); // 1 new entity added
149156
Assert.IsTrue(addRuntimeConfig.Entities.ContainsKey("todo"));
150157
Entity entity = addRuntimeConfig.Entities["todo"];
@@ -379,7 +386,7 @@ public Task TestConfigGeneratedAfterAddingEntityWithSourceWithDefaultType()
379386
public void TestUpdateEntity()
380387
{
381388
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--database-type",
382-
"mssql", "--connection-string", SAMPLE_TEST_CONN_STRING };
389+
"mssql", "--connection-string", TEST_ENV_CONN_STRING };
383390
Program.Execute(initArgs, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
384391

385392
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? runtimeConfig));
@@ -421,6 +428,7 @@ public void TestUpdateEntity()
421428

422429
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? updateRuntimeConfig));
423430
Assert.IsNotNull(updateRuntimeConfig);
431+
Assert.AreEqual(TEST_ENV_CONN_STRING, updateRuntimeConfig.DataSource.ConnectionString);
424432
Assert.AreEqual(2, updateRuntimeConfig.Entities.Count()); // No new entity added
425433

426434
Assert.IsTrue(updateRuntimeConfig.Entities.ContainsKey("todo"));

src/Cli.Tests/EnvironmentTests.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ public void TestSystemEnvironmentVariableIsUsedInAbsenceOfEnvironmentFile()
123123
[TestMethod]
124124
public void TestStartWithEnvFileIsSuccessful()
125125
{
126-
BootstrapTestEnvironment("CONN_STRING=test_connection_string");
126+
string expectedEnvVarName = "CONN_STRING";
127+
BootstrapTestEnvironment(expectedEnvVarName + "=test_connection_string", expectedEnvVarName);
127128

128129
// Trying to start the runtime engine
129130
using Process process = ExecuteDabCommand(
@@ -148,10 +149,11 @@ public void TestStartWithEnvFileIsSuccessful()
148149
/// I feel confident that the overarching scenario is covered through other testing
149150
/// so disabling temporarily while we investigate should be acceptable.
150151
/// </summary>
151-
[TestMethod, Ignore]
152+
[TestMethod]
152153
public async Task FailureToStartEngineWhenEnvVarNamedWrong()
153154
{
154-
BootstrapTestEnvironment("COMM_STRINX=test_connection_string");
155+
string expectedEnvVarName = "WRONG_CONN_STRING";
156+
BootstrapTestEnvironment("COMM_STRINX=test_connection_string", expectedEnvVarName);
155157

156158
// Trying to start the runtime engine
157159
using Process process = ExecuteDabCommand(
@@ -160,11 +162,12 @@ public async Task FailureToStartEngineWhenEnvVarNamedWrong()
160162
);
161163

162164
string? output = await process.StandardError.ReadLineAsync();
163-
StringAssert.Contains(output, "Environmental Variable, CONN_STRING, not found.", StringComparison.Ordinal);
165+
StringAssert.Contains(output, "Environmental Variable, "
166+
+ expectedEnvVarName + ", not found.", StringComparison.Ordinal);
164167
process.Kill();
165168
}
166169

167-
private static void BootstrapTestEnvironment(string envFileContents)
170+
private static void BootstrapTestEnvironment(string envFileContents, string connStringEnvName)
168171
{
169172
// Creating environment variable file
170173
File.Create(".env").Close();
@@ -174,7 +177,8 @@ private static void BootstrapTestEnvironment(string envFileContents)
174177
File.Delete(TEST_RUNTIME_CONFIG_FILE);
175178
}
176179

177-
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--database-type", "mssql", "--connection-string", "@env('CONN_STRING')" };
180+
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--database-type", "mssql",
181+
"--connection-string", "@env('" + connStringEnvName + "')" };
178182
Program.Main(initArgs);
179183
}
180184

src/Cli.Tests/TestHelper.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ public static class TestHelper
88
// Config file name for tests
99
public const string TEST_RUNTIME_CONFIG_FILE = "dab-config-test.json";
1010

11+
public const string TEST_CONNECTION_STRING = "testconnectionstring";
12+
public const string TEST_ENV_CONN_STRING = "@env('connection-string')";
13+
1114
public const string SAMPLE_TEST_CONN_STRING = "Data Source=<>;Initial Catalog=<>;User ID=<>;Password=<>;";
1215

1316
// test schema for cosmosDB
@@ -41,6 +44,7 @@ public static Process ExecuteDabCommand(string command, string flags)
4144
StartInfo =
4245
{
4346
FileName = @"./Microsoft.DataApiBuilder",
47+
CreateNoWindow = true,
4448
Arguments = $"{command} {flags}",
4549
WindowStyle = ProcessWindowStyle.Hidden,
4650
UseShellExecute = false,

src/Cli/ConfigGenerator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,8 @@ public static bool TryStartEngineWithOptions(StartOptions options, FileSystemRun
969969
loader.UpdateBaseConfigFileName(runtimeConfigFile);
970970

971971
// Validates that config file has data and follows the correct json schema
972-
if (!loader.TryLoadKnownConfig(out RuntimeConfig? deserializedRuntimeConfig))
972+
// Replaces all the environment variables while deserializing when starting DAB.
973+
if (!loader.TryLoadKnownConfig(out RuntimeConfig? deserializedRuntimeConfig, replaceEnvVar: true))
973974
{
974975
_logger.LogError("Failed to parse the config file: {configFile}.", runtimeConfigFile);
975976
return false;

src/Cli/Exporter.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ public static void Export(ExportOptions options, ILogger logger, FileSystemRunti
2626
return;
2727
}
2828

29-
if (!loader.TryLoadConfig(runtimeConfigFile, out RuntimeConfig? runtimeConfig) || runtimeConfig is null)
29+
if (!loader.TryLoadConfig(
30+
runtimeConfigFile,
31+
out RuntimeConfig? runtimeConfig,
32+
replaceEnvVar: true) || runtimeConfig is null)
3033
{
3134
logger.LogError("Failed to read the config file: {runtimeConfigFile}.", runtimeConfigFile);
3235
return;

src/Config/Converters/EntityGraphQLOptionsConverter.cs

Lines changed: 0 additions & 133 deletions
This file was deleted.

0 commit comments

Comments
 (0)