Skip to content
5 changes: 5 additions & 0 deletions src/DependencyManagement/DependencyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ internal string Initialize(ILogger logger)
return null;
}

if (WorkerEnvironment.IsLinuxConsumptionOnLegion())
{
throw new NotSupportedException(PowerShellWorkerStrings.ManagedDependenciesIsNotSupportedOnLegion);
}

_currentSnapshotPath = _installedDependenciesLocator.GetPathWithAcceptableDependencyVersionsInstalled()
?? _storage.CreateNewSnapshotPath();

Expand Down
16 changes: 1 addition & 15 deletions src/DependencyManagement/ManagedDependenciesPathDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.DependencyManagement
{
internal static class ManagedDependenciesPathDetector
{
// Environment variables to help figure out if we are running in Azure.
private const string AzureWebsiteInstanceId = "WEBSITE_INSTANCE_ID";
private const string ContainerName = "CONTAINER_NAME";

private const string HomeDriveName = "HOME";
private const string DataFolderName = "data";

Expand All @@ -31,7 +27,7 @@ internal static class ManagedDependenciesPathDetector
public static string GetManagedDependenciesPath(string functionAppRootPath)
{
// If we are running in Azure App Service or Linux Consumption use the 'HOME\data' path.
if (IsAppService() || IsLinuxConsumption())
if (WorkerEnvironment.IsAppService() || WorkerEnvironment.IsLinuxConsumption())
{
var homeDriveVariable = Environment.GetEnvironmentVariable(HomeDriveName);
if (string.IsNullOrEmpty(homeDriveVariable))
Expand All @@ -48,15 +44,5 @@ public static string GetManagedDependenciesPath(string functionAppRootPath)
string appDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.DoNotVerify);
return Path.Combine(appDataFolder, AzureFunctionsFolderName, functionAppName, ManagedDependenciesFolderName);
}

private static bool IsAppService()
{
return !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(AzureWebsiteInstanceId));
}

private static bool IsLinuxConsumption()
{
return !IsAppService() && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(ContainerName));
}
}
}
36 changes: 36 additions & 0 deletions src/DependencyManagement/WorkerEnvironment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.Azure.Functions.PowerShellWorker.DependencyManagement
{
/// <summary>
/// Hold information about the environment.
/// </summary>
internal static class WorkerEnvironment
{
// Environment variables to help figure out if we are running in Azure.
private const string AzureWebsiteInstanceId = "WEBSITE_INSTANCE_ID";
private const string ContainerName = "CONTAINER_NAME";
private const string LegionServiceHost = "LEGION_SERVICE_HOST";

public static bool IsAppService()
{
return !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(AzureWebsiteInstanceId));
}

public static bool IsLinuxConsumption()
{
return !IsAppService() && !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(ContainerName));
}

public static bool IsLinuxConsumptionOnLegion()
{
return !IsAppService() &&
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(ContainerName)) &&
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(LegionServiceHost));
}
}
}
3 changes: 3 additions & 0 deletions src/resources/PowerShellWorkerStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -376,4 +376,7 @@
<data name="UtilizingExternalDurableSDK" xml:space="preserve">
<value>Utilizing external Durable Functions SDK: '{0}'.</value>
</data>
<data name="ManagedDependenciesIsNotSupportedOnLegion" xml:space="preserve">
<value>Managed Dependencies is not supported in Linux Consumption on Legion. Please remove all module references from requirements.psd1 and include the function app dependencies with the function app content. For more information, please see https://aka.ms/functions-powershell-include-modules.</value>
</data>
</root>
66 changes: 66 additions & 0 deletions test/Unit/DependencyManagement/DependencyManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,72 @@ public void Initialize_ReturnsNewSnapshotPath_WhenNoAcceptableDependencyVersions
}
}

[Fact]
public void Initialize_Throws_WhenDependenciesAreDefinedInRequirementsPsd1_OnLegion()
{
const string ContainerName = "CONTAINER_NAME";
const string LegionServiceHost = "LEGION_SERVICE_HOST";
const string AzureWebsiteInstanceId = "WEBSITE_INSTANCE_ID";

try
{
Environment.SetEnvironmentVariable(AzureWebsiteInstanceId, null);
Environment.SetEnvironmentVariable(ContainerName, "MY_CONTAINER_NAME");
Environment.SetEnvironmentVariable(LegionServiceHost, "MY_LEGION_SERVICE_HOST");

_mockStorage.Setup(_ => _.GetDependencies()).Returns(GetAnyNonEmptyDependencyManifestEntries());

using (var dependencyManager = CreateDependencyManagerWithMocks())
{
var caughtException = Assert.Throws<DependencyInstallationException>(
() => dependencyManager.Initialize(_mockLogger.Object));

Assert.Contains("Managed Dependencies is not supported in Linux Consumption on Legion.", caughtException.Message);
Assert.Contains("https://aka.ms/functions-powershell-include-modules", caughtException.Message);
}
}

finally
{
Environment.SetEnvironmentVariable(ContainerName, null);
Environment.SetEnvironmentVariable(LegionServiceHost, null);
}
}

[Fact]
public void Initialize_NoDependenciesOnRequirementsPsd1_OnLegion_DoesNotThrow()
{
const string ContainerName = "CONTAINER_NAME";
const string LegionServiceHost = "LEGION_SERVICE_HOST";
const string AzureWebsiteInstanceId = "WEBSITE_INSTANCE_ID";

try
{
Environment.SetEnvironmentVariable(AzureWebsiteInstanceId, null);
Environment.SetEnvironmentVariable(ContainerName, "MY_CONTAINER_NAME");
Environment.SetEnvironmentVariable(LegionServiceHost, "MY_LEGION_SERVICE_HOST");

_mockStorage.Setup(_ => _.GetDependencies()).Returns(new DependencyManifestEntry[0]);

using (var dependencyManager = CreateDependencyManagerWithMocks())
{
var dependenciesPath = dependencyManager.Initialize(_mockLogger.Object);

Assert.Null(dependenciesPath);
VerifyMessageLogged(LogLevel.Warning, PowerShellWorkerStrings.FunctionAppDoesNotHaveRequiredModulesToInstall, expectedIsUserLog: true);

_mockBackgroundDependencySnapshotMaintainer.VerifyNoOtherCalls();
_mockNewerDependencySnapshotDetector.VerifyNoOtherCalls();
}
}

finally
{
Environment.SetEnvironmentVariable(ContainerName, null);
Environment.SetEnvironmentVariable(LegionServiceHost, null);
}
}

[Fact]
public void Initialize_ReturnsExistingSnapshotPath_WhenAcceptableDependencyVersionsAlreadyInstalled()
{
Expand Down