From d9450d6d838e832aab8decae0579b4fb044eab9a Mon Sep 17 00:00:00 2001 From: Francisco Gamino Date: Fri, 18 Mar 2022 13:15:22 -0700 Subject: [PATCH 1/3] Disable optional upgrades in PowerShell function apps (#779) * Add AutomaticUpgradesAreDisabled message * Disable optional upgrades * Update test --- .../BackgroundDependencySnapshotMaintainer.cs | 13 ++++ src/DependencyManagement/DependencyManager.cs | 13 ++++ src/resources/PowerShellWorkerStrings.resx | 3 + .../DependencyManagerTests.cs | 61 +++++++++++-------- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/DependencyManagement/BackgroundDependencySnapshotMaintainer.cs b/src/DependencyManagement/BackgroundDependencySnapshotMaintainer.cs index deba2e90..b42faacd 100644 --- a/src/DependencyManagement/BackgroundDependencySnapshotMaintainer.cs +++ b/src/DependencyManagement/BackgroundDependencySnapshotMaintainer.cs @@ -20,6 +20,9 @@ internal class BackgroundDependencySnapshotMaintainer : IBackgroundDependencySna private TimeSpan MaxBackgroundUpgradePeriod { get; } = PowerShellWorkerConfiguration.GetTimeSpan("MDMaxBackgroundUpgradePeriod") ?? TimeSpan.FromDays(7); + private bool EnableAutomaticUpgrades { get; } = + PowerShellWorkerConfiguration.GetBoolean("MDEnableAutomaticUpgrades") ?? false; + private readonly IDependencyManagerStorage _storage; private readonly IDependencySnapshotInstaller _installer; private readonly IDependencySnapshotPurger _purger; @@ -42,6 +45,16 @@ public void Start(string currentSnapshotPath, DependencyManifestEntry[] dependen _purger.SetCurrentlyUsedSnapshot(currentSnapshotPath, logger); + if (!EnableAutomaticUpgrades) + { + logger.Log( + isUserOnlyLog: false, + RpcLog.Types.Level.Warning, + PowerShellWorkerStrings.AutomaticUpgradesAreDisabled); + + return; + } + _installAndPurgeTimer = new Timer( _ => InstallAndPurgeSnapshots(PowerShell.Create, logger), state: null, diff --git a/src/DependencyManagement/DependencyManager.cs b/src/DependencyManagement/DependencyManager.cs index 28f4c59b..8862113c 100644 --- a/src/DependencyManagement/DependencyManager.cs +++ b/src/DependencyManagement/DependencyManager.cs @@ -41,6 +41,9 @@ internal class DependencyManager : IDisposable private Task _dependencyInstallationTask; + private bool EnableAutomaticUpgrades { get; } = + PowerShellWorkerConfiguration.GetBoolean("MDEnableAutomaticUpgrades") ?? false; + #endregion public DependencyManager( @@ -199,6 +202,16 @@ internal Exception InstallFunctionAppDependencies(PowerShell firstPwsh, Func Dependency snapshot '{0}' does not contain acceptable module versions. + + Automatic upgrades are disabled in PowerShell 6 function apps. To enable this functionality back, please migrate your function app to PowerShell 7. For more details, see https://aka.ms/functions-powershell-6-to-7. + \ No newline at end of file diff --git a/test/Unit/DependencyManagement/DependencyManagerTests.cs b/test/Unit/DependencyManagement/DependencyManagerTests.cs index e6249468..edd78085 100644 --- a/test/Unit/DependencyManagement/DependencyManagerTests.cs +++ b/test/Unit/DependencyManagement/DependencyManagerTests.cs @@ -163,40 +163,49 @@ public void StartDependencyInstallationIfNeeded_InstallsSnapshotInForeground_Whe [Fact] public void StartDependencyInstallationIfNeeded_InvokesBackgroundMaintainer_WhenAcceptableDependenciesAlreadyInstalled() { - _mockInstalledDependenciesLocator.Setup(_ => _.GetPathWithAcceptableDependencyVersionsInstalled()) - .Returns("AlreadyInstalled"); - _mockStorage.Setup(_ => _.GetDependencies()).Returns(GetAnyNonEmptyDependencyManifestEntries()); + try + { + Environment.SetEnvironmentVariable("MDEnableAutomaticUpgrades", "true"); - var firstPowerShellRunspace = PowerShell.Create(); - Func powerShellFactory = PowerShell.Create; + _mockInstalledDependenciesLocator.Setup(_ => _.GetPathWithAcceptableDependencyVersionsInstalled()) + .Returns("AlreadyInstalled"); + _mockStorage.Setup(_ => _.GetDependencies()).Returns(GetAnyNonEmptyDependencyManifestEntries()); - _mockStorage.Setup(_ => _.SnapshotExists("AlreadyInstalled")).Returns(true); + var firstPowerShellRunspace = PowerShell.Create(); + Func powerShellFactory = PowerShell.Create; - _mockBackgroundDependencySnapshotMaintainer.Setup( - _ => _.InstallAndPurgeSnapshots(It.IsAny>(), It.IsAny())) - .Returns("NewSnapshot"); + _mockStorage.Setup(_ => _.SnapshotExists("AlreadyInstalled")).Returns(true); - using (var dependencyManager = CreateDependencyManagerWithMocks()) - { - dependencyManager.Initialize(_mockLogger.Object); - dependencyManager.StartDependencyInstallationIfNeeded(firstPowerShellRunspace, powerShellFactory, _mockLogger.Object); - var hadToWait = dependencyManager.WaitForDependenciesAvailability(() => _mockLogger.Object); + _mockBackgroundDependencySnapshotMaintainer.Setup( + _ => _.InstallAndPurgeSnapshots(It.IsAny>(), It.IsAny())) + .Returns("NewSnapshot"); - Assert.False(hadToWait); - Assert.Equal("NewSnapshot", dependencyManager.WaitForBackgroundDependencyInstallationTaskCompletion()); + using (var dependencyManager = CreateDependencyManagerWithMocks()) + { + dependencyManager.Initialize(_mockLogger.Object); + dependencyManager.StartDependencyInstallationIfNeeded(firstPowerShellRunspace, powerShellFactory, _mockLogger.Object); + var hadToWait = dependencyManager.WaitForDependenciesAvailability(() => _mockLogger.Object); - _mockBackgroundDependencySnapshotMaintainer.Verify( - _ => _.InstallAndPurgeSnapshots(powerShellFactory, _mockLogger.Object), + Assert.False(hadToWait); + Assert.Equal("NewSnapshot", dependencyManager.WaitForBackgroundDependencyInstallationTaskCompletion()); + + _mockBackgroundDependencySnapshotMaintainer.Verify( + _ => _.InstallAndPurgeSnapshots(powerShellFactory, _mockLogger.Object), + Times.Once); + } + + _mockLogger.Verify( + _ => _.Log( + false, + LogLevel.Trace, + It.Is(message => message.Contains(PowerShellWorkerStrings.AcceptableFunctionAppDependenciesAlreadyInstalled)), + It.IsAny()), Times.Once); } - - _mockLogger.Verify( - _ => _.Log( - false, - LogLevel.Trace, - It.Is(message => message.Contains(PowerShellWorkerStrings.AcceptableFunctionAppDependenciesAlreadyInstalled)), - It.IsAny()), - Times.Once); + finally + { + Environment.SetEnvironmentVariable("MDEnableAutomaticUpgrades", null); + } } [Fact] From 0f0acf28d79dd6f149b1e9d2e514967c57ba01d8 Mon Sep 17 00:00:00 2001 From: Francisco-Gamino Date: Thu, 11 May 2023 16:14:47 -0700 Subject: [PATCH 2/3] Update upgrade guidance for PowerShell 7.0 function apps --- src/resources/PowerShellWorkerStrings.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resources/PowerShellWorkerStrings.resx b/src/resources/PowerShellWorkerStrings.resx index 1d32ed01..515207e0 100644 --- a/src/resources/PowerShellWorkerStrings.resx +++ b/src/resources/PowerShellWorkerStrings.resx @@ -353,6 +353,6 @@ Dependency snapshot '{0}' does not contain acceptable module versions. - Automatic upgrades are disabled in PowerShell 6 function apps. To enable this functionality back, please migrate your function app to PowerShell 7. For more details, see https://aka.ms/functions-powershell-6-to-7. + Automatic upgrades are disabled in PowerShell 7.0 function apps. To enable this functionality back, please migrate your function app to PowerShell 7.2. For more details, see https://aka.ms/functions-powershell-7.0-to-7.2. \ No newline at end of file From 82075f3ed761900b243ee5987a7ffff79c3be820 Mon Sep 17 00:00:00 2001 From: Francisco-Gamino Date: Mon, 15 May 2023 15:21:59 -0700 Subject: [PATCH 3/3] Add installation directory for the .Net SDK --- tools/helper.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/helper.psm1 b/tools/helper.psm1 index eef28922..0aa9f3c5 100644 --- a/tools/helper.psm1 +++ b/tools/helper.psm1 @@ -74,9 +74,9 @@ function Install-Dotnet { $version = "$majorMinorVersion.$($DotnetSDKVersionRequirements[$majorMinorVersion].DefaultPatch)" Write-Log "Installing dotnet SDK version $version" -Warning if ($IsWindowsEnv) { - & .\$installScript -Channel $Channel -Version $Version + & .\$installScript -Channel $Channel -Version $Version -InstallDir "$env:ProgramFiles/dotnet" } else { - bash ./$installScript -c $Channel -v $Version + bash ./$installScript -c $Channel -v $Version --install-dir /usr/share/dotnet } }