Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/DependencyManagement/DependencyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ public DependencyManager(
IInstalledDependenciesLocator installedDependenciesLocator = null,
IDependencySnapshotInstaller installer = null,
INewerDependencySnapshotDetector newerSnapshotDetector = null,
IBackgroundDependencySnapshotMaintainer maintainer = null)
IBackgroundDependencySnapshotMaintainer maintainer = null,
ILogger logger = null)
{
_storage = storage ?? new DependencyManagerStorage(GetFunctionAppRootPath(requestMetadataDirectory));
_installedDependenciesLocator = installedDependenciesLocator ?? new InstalledDependenciesLocator(_storage);
_installer = installer ?? new DependencySnapshotInstaller(
moduleProvider ?? new PowerShellGalleryModuleProvider(),
moduleProvider ?? new PowerShellGalleryModuleProvider(logger),
_storage,
new PowerShellModuleSnapshotComparer(),
new PowerShellModuleSnapshotLogger());
Expand Down
35 changes: 32 additions & 3 deletions src/DependencyManagement/PowerShellGalleryModuleProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.DependencyManagement

using Microsoft.Azure.Functions.PowerShellWorker.PowerShell;
using Microsoft.Azure.Functions.PowerShellWorker.Utility;
using LogLevel = Microsoft.Azure.WebJobs.Script.Grpc.Messages.RpcLog.Types.Level;

internal class PowerShellGalleryModuleProvider : IModuleProvider
{
private readonly ILogger _logger;

private readonly IPowerShellGallerySearchInvoker _searchInvoker;

public PowerShellGalleryModuleProvider(IPowerShellGallerySearchInvoker searchInvoker = null)
public PowerShellGalleryModuleProvider(ILogger logger, IPowerShellGallerySearchInvoker searchInvoker = null)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_searchInvoker = searchInvoker ?? new PowerShellGallerySearchInvoker();
}

Expand Down Expand Up @@ -87,8 +91,18 @@ public void SaveModule(PowerShell pwsh, string moduleName, string version, strin
.AddParameter("AllowPrerelease", Utils.BoxedTrue)
.AddParameter("Path", path)
.AddParameter("Force", Utils.BoxedTrue)
.AddParameter("ErrorAction", "Stop")
.InvokeAndClearCommands();
.AddParameter("ErrorAction", "Stop");

try
{
pwsh.Invoke();
}
finally
{
LogSaveModuleErrorsAndWarnings(pwsh, moduleName, version);
pwsh.Streams.ClearStreams();
pwsh.Commands.Clear();
}
}

/// <summary>
Expand All @@ -104,6 +118,21 @@ public void Cleanup(PowerShell pwsh)
.InvokeAndClearCommands();
}

private void LogSaveModuleErrorsAndWarnings(PowerShell pwsh, string moduleName, string version)
{
var prefix = $"Save-Module('{moduleName}', '{version}'): ";

foreach (var item in pwsh.Streams.Error)
{
_logger.Log(isUserOnlyLog: false, LogLevel.Error, $"{prefix}{item.Exception.Message}");
}

foreach (var item in pwsh.Streams.Warning)
{
_logger.Log(isUserOnlyLog: false, LogLevel.Warning, $"{prefix}{item.Message}");
}
}

private static Version GetLatestVersion(
XmlNode root, XmlNamespaceManager namespaceManager, string expectedVersionStart, Version latestVersion)
{
Expand Down
2 changes: 1 addition & 1 deletion src/RequestProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ internal StreamingMessage ProcessFunctionLoadRequest(StreamingMessage request)
var rpcLogger = new RpcLogger(_msgStream);
rpcLogger.SetContext(request.RequestId, null);

_dependencyManager = new DependencyManager(request.FunctionLoadRequest.Metadata.Directory);
_dependencyManager = new DependencyManager(request.FunctionLoadRequest.Metadata.Directory, logger: rpcLogger);
var managedDependenciesPath = _dependencyManager.Initialize(request, rpcLogger);

// Setup the FunctionApp root path and module path.
Expand Down
10 changes: 5 additions & 5 deletions test/Unit/DependencyManagement/DependencyManagementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public void TestManagedDependencyBasicRequirements()
var functionLoadRequest = GetFuncLoadRequest(functionFolderPath, true);

// Create DependencyManager and process the requirements.psd1 file at the function app root.
using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory))
using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory, logger: _testLogger))
{
var currentDependenciesPath = dependencyManager.Initialize(_testLogger);

Expand Down Expand Up @@ -132,7 +132,7 @@ public void TestManagedDependencyEmptyHashtableRequirement()
var functionLoadRequest = GetFuncLoadRequest(functionFolderPath, true);

// Create DependencyManager and process the requirements.psd1 file at the function app root.
using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory))
using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory, logger: _testLogger))
{
var currentDependenciesPath = dependencyManager.Initialize(_testLogger);

Expand All @@ -153,7 +153,7 @@ public void TestManagedDependencyNoHashtableRequirementShouldThrow()
var functionFolderPath = Path.Combine(_dependencyManagementDirectory, requirementsDirectoryName, "FunctionDirectory");
var functionLoadRequest = GetFuncLoadRequest(functionFolderPath, true);

using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory))
using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory, logger: _testLogger))
{
// Trying to set the functionApp dependencies should throw since requirements.psd1 is not a hash table.
var exception = Assert.Throws<DependencyInstallationException>(
Expand All @@ -172,7 +172,7 @@ public void TestManagedDependencyInvalidRequirementsFormatShouldThrow()
var functionFolderPath = Path.Combine(_dependencyManagementDirectory, requirementsDirectoryName, "FunctionDirectory");
var functionLoadRequest = GetFuncLoadRequest(functionFolderPath, true);

using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory))
using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory, logger: _testLogger))
{
// Trying to set the functionApp dependencies should throw since the module version
// in requirements.psd1 is not in a valid format.
Expand All @@ -193,7 +193,7 @@ public void TestManagedDependencyNoRequirementsFileShouldThrow()
var functionFolderPath = Path.Combine(_dependencyManagementDirectory, requirementsDirectoryName, "FunctionDirectory");
var functionLoadRequest = GetFuncLoadRequest(functionFolderPath, true);

using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory))
using (var dependencyManager = new DependencyManager(functionLoadRequest.Metadata.Directory, logger: _testLogger))
{
// Trying to set the functionApp dependencies should throw since no
// requirements.psd1 is found at the function app root.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,27 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.Test.DependencyManagement
using Xunit;

using PowerShellWorker.DependencyManagement;
using PowerShellWorker.Utility;

public class PowerShellGalleryModuleProviderTests
{
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();

private readonly Mock<IPowerShellGallerySearchInvoker> _mockSearchInvoker =
new Mock<IPowerShellGallerySearchInvoker>(MockBehavior.Strict);

private PowerShellGalleryModuleProvider _moduleProvider;

public PowerShellGalleryModuleProviderTests()
{
_moduleProvider = new PowerShellGalleryModuleProvider(_mockLogger.Object, _mockSearchInvoker.Object);
}

[Fact]
public void ReturnsNullIfSearchInvokerReturnsNull()
{
_mockSearchInvoker.Setup(_ => _.Invoke(It.IsAny<Uri>())).Returns(default(Stream));
var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
Assert.Null(actualVersion);
}

Expand All @@ -43,8 +52,7 @@ public void ReturnsSingleVersion()
using (var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(ResponseText)))
{
_mockSearchInvoker.Setup(_ => _.Invoke(It.IsAny<Uri>())).Returns(responseStream);
var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
Assert.Equal("1.2.3.4", actualVersion);
}
}
Expand Down Expand Up @@ -82,8 +90,7 @@ public void FindsLatestVersionRegardlessOfResponseOrder()
using (var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(ResponseText)))
{
_mockSearchInvoker.Setup(_ => _.Invoke(It.IsAny<Uri>())).Returns(responseStream);
var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
Assert.Equal("1.2.3.6", actualVersion);
}
}
Expand Down Expand Up @@ -121,8 +128,7 @@ public void IgnoresPrereleaseVersions()
using (var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(ResponseText)))
{
_mockSearchInvoker.Setup(_ => _.Invoke(It.IsAny<Uri>())).Returns(responseStream);
var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
Assert.Equal("1.2.3.5", actualVersion);
}
}
Expand Down Expand Up @@ -166,8 +172,7 @@ public void IgnoresNotMatchingMajorVersions()
using (var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(ResponseText)))
{
_mockSearchInvoker.Setup(_ => _.Invoke(It.IsAny<Uri>())).Returns(responseStream);
var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
Assert.Equal("1.2.3.6", actualVersion);
}
}
Expand Down Expand Up @@ -207,8 +212,7 @@ public void ComparesVersionsCorrectly(string lowerVersion, string higherVersion)
using (var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(responseText)))
{
_mockSearchInvoker.Setup(_ => _.Invoke(It.IsAny<Uri>())).Returns(responseStream);
var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "0");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "0");
Assert.Equal(higherVersion, actualVersion);
}
}
Expand All @@ -228,8 +232,7 @@ public void ReturnsNullIfNoVersionFound()
using (var responseStream = new MemoryStream(Encoding.UTF8.GetBytes(ResponseText)))
{
_mockSearchInvoker.Setup(_ => _.Invoke(It.IsAny<Uri>())).Returns(responseStream);
var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
Assert.Null(actualVersion);
}
}
Expand Down Expand Up @@ -315,8 +318,7 @@ public void FindsLatestVersionAcrossMultiplePages()
_mockSearchInvoker.Setup(_ => _.Invoke(new Uri("https://NextLink2")))
.Returns(responseStream3);

var moduleProvider = new PowerShellGalleryModuleProvider(_mockSearchInvoker.Object);
var actualVersion = moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
var actualVersion = _moduleProvider.GetLatestPublishedModuleVersion("ModuleName", "1");
Assert.Equal("1.2.3.6", actualVersion);
}
}
Expand Down