Skip to content

Commit 654cf06

Browse files
Backport ANCM environment variable additions (#20006)
1 parent 1040be3 commit 654cf06

File tree

9 files changed

+131
-14
lines changed

9 files changed

+131
-14
lines changed

src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/ShimOptions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ ShimOptions::ShimOptions(const ConfigurationSource &configurationSource) :
5454
.value_or(environmentVariables[CS_ASPNETCORE_ENVIRONMENT]);
5555
const auto dotnetEnvironment = Environment::GetEnvironmentVariableValue(CS_DOTNET_ENVIRONMENT)
5656
.value_or(environmentVariables[CS_DOTNET_ENVIRONMENT]);
57+
// We prefer the environment variables for LAUNCHER_PATH and LAUNCHER_ARGS
58+
m_strProcessPath = Environment::GetEnvironmentVariableValue(CS_ANCM_LAUNCHER_PATH)
59+
.value_or(m_strProcessPath);
60+
m_strArguments = Environment::GetEnvironmentVariableValue(CS_ANCM_LAUNCHER_ARGS)
61+
.value_or(m_strArguments);
5762

5863
auto detailedErrorsEnabled = equals_ignore_case(L"1", detailedErrors) || equals_ignore_case(L"true", detailedErrors);
5964
auto aspnetCoreEnvironmentEnabled = equals_ignore_case(L"Development", aspnetCoreEnvironment);

src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ConfigurationSection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#define CS_ASPNETCORE_DETAILEDERRORS L"ASPNETCORE_DETAILEDERRORS"
3434
#define CS_ASPNETCORE_ENVIRONMENT L"ASPNETCORE_ENVIRONMENT"
3535
#define CS_DOTNET_ENVIRONMENT L"DOTNET_ENVIRONMENT"
36+
#define CS_ANCM_LAUNCHER_PATH L"ANCM_LAUNCHER_PATH"
37+
#define CS_ANCM_LAUNCHER_ARGS L"ANCM_LAUNCHER_ARGS"
3638

3739
class ConfigurationSection: NonCopyable
3840
{

src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/InProcessOptions.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "InProcessOptions.h"
55
#include "InvalidOperationException.h"
66
#include "EventLog.h"
7+
#include "Environment.h"
78

89
HRESULT InProcessOptions::Create(
910
IHttpServer& pServer,
@@ -51,6 +52,11 @@ InProcessOptions::InProcessOptions(const ConfigurationSource &configurationSourc
5152
auto const aspNetCoreSection = configurationSource.GetRequiredSection(CS_ASPNETCORE_SECTION);
5253
m_strArguments = aspNetCoreSection->GetString(CS_ASPNETCORE_PROCESS_ARGUMENTS).value_or(CS_ASPNETCORE_PROCESS_ARGUMENTS_DEFAULT);
5354
m_strProcessPath = aspNetCoreSection->GetRequiredString(CS_ASPNETCORE_PROCESS_EXE_PATH);
55+
// We prefer the environment variables for LAUNCHER_PATH and LAUNCHER_ARGS
56+
m_strProcessPath = Environment::GetEnvironmentVariableValue(CS_ANCM_LAUNCHER_PATH)
57+
.value_or(m_strProcessPath);
58+
m_strArguments = Environment::GetEnvironmentVariableValue(CS_ANCM_LAUNCHER_ARGS)
59+
.value_or(m_strArguments);
5460
m_fStdoutLogEnabled = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_STDOUT_LOG_ENABLED);
5561
m_struStdoutLogFile = aspNetCoreSection->GetRequiredString(CS_ASPNETCORE_STDOUT_LOG_FILE);
5662
m_fDisableStartUpErrorPage = aspNetCoreSection->GetRequiredBool(CS_ASPNETCORE_DISABLE_START_UP_ERROR_PAGE);

src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define ASPNETCORE_IIS_AUTH_BASIC L"basic;"
1414
#define ASPNETCORE_IIS_AUTH_ANONYMOUS L"anonymous;"
1515
#define ASPNETCORE_IIS_AUTH_NONE L"none"
16+
#define ANCM_PREFER_ENVIRONMENT_VARIABLES_ENV_STR L"ANCM_PREFER_ENVIRONMENT_VARIABLES"
1617

1718
//
1819
// The key used for hash-table lookups, consists of the port on which the http process is created.

src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/environmentvariablehelpers.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,27 @@ class ENVIRONMENT_VAR_HELPERS
7878
environmentVariables.insert_or_assign(HOSTING_STARTUP_ASSEMBLIES_ENV_STR, hostingStartupValues);
7979
}
8080

81+
auto preferEnvironmentVariablesSetting = Environment::GetEnvironmentVariableValue(ANCM_PREFER_ENVIRONMENT_VARIABLES_ENV_STR).value_or(L"false");
82+
auto preferEnvironmentVariables = equals_ignore_case(L"1", preferEnvironmentVariablesSetting) || equals_ignore_case(L"true", preferEnvironmentVariablesSetting);
83+
8184
for (auto& environmentVariable : environmentVariables)
8285
{
83-
environmentVariable.second = Environment::ExpandEnvironmentVariables(environmentVariable.second);
86+
if (preferEnvironmentVariables)
87+
{
88+
auto env = Environment::GetEnvironmentVariableValue(environmentVariable.first);
89+
if (env.has_value())
90+
{
91+
environmentVariable.second = env.value();
92+
}
93+
else
94+
{
95+
environmentVariable.second = Environment::ExpandEnvironmentVariables(environmentVariable.second);
96+
}
97+
}
98+
else
99+
{
100+
environmentVariable.second = Environment::ExpandEnvironmentVariables(environmentVariable.second);
101+
}
84102
}
85103

86104
return environmentVariables;

src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.cpp

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "environmentvariablehash.h"
88
#include "exceptions.h"
99
#include "config_utility.h"
10+
#include "Environment.h"
1011

1112
REQUESTHANDLER_CONFIG::~REQUESTHANDLER_CONFIG()
1213
{
@@ -101,6 +102,8 @@ REQUESTHANDLER_CONFIG::Populate(
101102
BSTR bstrBasicAuthSection = NULL;
102103
BSTR bstrAnonymousAuthSection = NULL;
103104
BSTR bstrAspNetCoreSection = NULL;
105+
std::optional<std::wstring> launcherPathEnv;
106+
std::optional<std::wstring> launcherArgsEnv;
104107

105108
pAdminManager = pHttpServer->GetAdminManager();
106109
try
@@ -248,12 +251,47 @@ REQUESTHANDLER_CONFIG::Populate(
248251
goto Finished;
249252
}
250253

251-
hr = GetElementStringProperty(pAspNetCoreElement,
252-
CS_ASPNETCORE_PROCESS_EXE_PATH,
253-
&m_struProcessPath);
254-
if (FAILED(hr))
254+
// We prefer the environment variables for LAUNCHER_PATH and LAUNCHER_ARGS
255+
try
255256
{
256-
goto Finished;
257+
launcherPathEnv = Environment::GetEnvironmentVariableValue(CS_ANCM_LAUNCHER_PATH);
258+
launcherArgsEnv = Environment::GetEnvironmentVariableValue(CS_ANCM_LAUNCHER_ARGS);
259+
}
260+
catch(...)
261+
{
262+
FINISHED_IF_FAILED(E_FAIL);
263+
}
264+
265+
if (launcherPathEnv.has_value())
266+
{
267+
hr = m_struProcessPath.Copy(launcherPathEnv.value().c_str());
268+
FINISHED_IF_FAILED(hr);
269+
}
270+
else
271+
{
272+
hr = GetElementStringProperty(pAspNetCoreElement,
273+
CS_ASPNETCORE_PROCESS_EXE_PATH,
274+
&m_struProcessPath);
275+
if (FAILED(hr))
276+
{
277+
goto Finished;
278+
}
279+
}
280+
281+
if (launcherArgsEnv.has_value())
282+
{
283+
hr = m_struArguments.Copy(launcherArgsEnv.value().c_str());
284+
FINISHED_IF_FAILED(hr);
285+
}
286+
else
287+
{
288+
hr = GetElementStringProperty(pAspNetCoreElement,
289+
CS_ASPNETCORE_PROCESS_ARGUMENTS,
290+
&m_struArguments);
291+
if (FAILED(hr))
292+
{
293+
goto Finished;
294+
}
257295
}
258296

259297
hr = GetElementStringProperty(pAspNetCoreElement,
@@ -281,14 +319,6 @@ REQUESTHANDLER_CONFIG::Populate(
281319
goto Finished;
282320
}
283321

284-
hr = GetElementStringProperty(pAspNetCoreElement,
285-
CS_ASPNETCORE_PROCESS_ARGUMENTS,
286-
&m_struArguments);
287-
if (FAILED(hr))
288-
{
289-
goto Finished;
290-
}
291-
292322
hr = GetElementDWORDProperty(pAspNetCoreElement,
293323
CS_ASPNETCORE_RAPID_FAILS_PER_MINUTE,
294324
&m_dwRapidFailsPerMinute);

src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/EnvironmentVariableTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,22 @@ private async Task WebConfigExpandsVariables(HostingModel hostingModel)
126126
deploymentParameters.WebConfigBasedEnvironmentVariables["OtherVariable"] = "%TestVariable%;Hello";
127127
Assert.Equal("World;Hello", await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=OtherVariable"));
128128
}
129+
130+
[ConditionalTheory]
131+
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
132+
[RequiresNewHandler]
133+
[RequiresNewShim]
134+
[InlineData(HostingModel.InProcess)]
135+
[InlineData(HostingModel.OutOfProcess)]
136+
public async Task PreferEnvironmentVariablesOverWebConfigWhenConfigured(HostingModel hostingModel)
137+
{
138+
var deploymentParameters = Fixture.GetBaseDeploymentParameters(hostingModel);
139+
140+
var environment = "Development";
141+
deploymentParameters.EnvironmentVariables["ANCM_PREFER_ENVIRONMENT_VARIABLES"] = "true";
142+
deploymentParameters.EnvironmentVariables["ASPNETCORE_ENVIRONMENT"] = environment;
143+
deploymentParameters.WebConfigBasedEnvironmentVariables.Add("ASPNETCORE_ENVIRONMENT", "Debug");
144+
Assert.Equal(environment, await GetStringAsync(deploymentParameters, "/GetEnvironmentVariable?name=ASPNETCORE_ENVIRONMENT"));
145+
}
129146
}
130147
}

src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,39 @@ public async Task StackOverflowCanBeSetBySettingLargerStackViaHandlerSetting()
875875
Assert.True(result.IsSuccessStatusCode);
876876
}
877877

878+
[ConditionalTheory]
879+
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
880+
[RequiresNewShim]
881+
[RequiresNewHandler]
882+
[InlineData(HostingModel.InProcess)]
883+
[InlineData(HostingModel.OutOfProcess)]
884+
public async Task EnvironmentVariableForLauncherPathIsPreferred(HostingModel hostingModel)
885+
{
886+
var deploymentParameters = Fixture.GetBaseDeploymentParameters(hostingModel);
887+
888+
deploymentParameters.EnvironmentVariables["ANCM_LAUNCHER_PATH"] = _dotnetLocation;
889+
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("processPath", "nope"));
890+
891+
await StartAsync(deploymentParameters);
892+
}
893+
894+
[ConditionalTheory]
895+
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
896+
[RequiresNewShim]
897+
[RequiresNewHandler]
898+
[InlineData(HostingModel.InProcess)]
899+
[InlineData(HostingModel.OutOfProcess)]
900+
public async Task EnvironmentVariableForLauncherArgsIsPreferred(HostingModel hostingModel)
901+
{
902+
var deploymentParameters = Fixture.GetBaseDeploymentParameters(hostingModel);
903+
using var publishedApp = await deploymentParameters.ApplicationPublisher.Publish(deploymentParameters, LoggerFactory.CreateLogger("test"));
904+
905+
deploymentParameters.EnvironmentVariables["ANCM_LAUNCHER_ARGS"] = Path.ChangeExtension(Path.Combine(publishedApp.Path, deploymentParameters.ApplicationPublisher.ApplicationPath), ".dll");
906+
deploymentParameters.WebConfigActionList.Add(WebConfigHelpers.AddOrModifyAspNetCoreSection("arguments", "nope"));
907+
908+
await StartAsync(deploymentParameters);
909+
}
910+
878911
private static void VerifyDotnetRuntimeEventLog(IISDeploymentResult deploymentResult)
879912
{
880913
var entries = GetEventLogsFromDotnetRuntime(deploymentResult);

src/Servers/IIS/IIS/test/IIS.Shared.FunctionalTests/RequiresIISAttribute.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ static RequiresIISAttribute()
6161

6262
var ancmConfigPath = Path.Combine(Environment.SystemDirectory, "inetsrv", "config", "schema", "aspnetcore_schema.xml");
6363

64+
if (!File.Exists(ancmConfigPath))
65+
{
66+
ancmConfigPath = Path.Combine(Environment.SystemDirectory, "inetsrv", "config", "schema", "aspnetcore_schema_v2.xml");
67+
}
68+
6469
if (!File.Exists(ancmConfigPath) && !SkipInVSTSAttribute.RunningInVSTS)
6570
{
6671
_skipReasonStatic = "IIS Schema is not installed.";

0 commit comments

Comments
 (0)