Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Processor improvements #3101

Merged
merged 3 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion src/AppInstallerSharedLib/Public/AppInstallerErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
#define WINGET_CONFIG_ERROR_UNIT_INVOKE_GET ((HRESULT)0x8A15C104)
#define WINGET_CONFIG_ERROR_UNIT_INVOKE_TEST ((HRESULT)0x8A15C105)
#define WINGET_CONFIG_ERROR_UNIT_INVOKE_SET ((HRESULT)0x8A15C106)

#define WINGET_CONFIG_ERRROR_UNIT_MODULE_CONFLICT ((HRESULT)0x8A15C107)
msftrubengu marked this conversation as resolved.
Show resolved Hide resolved

namespace AppInstaller
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ namespace Microsoft.Management.Configuration.Processor.DscModule
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using Microsoft.Management.Configuration.Processor.DscResourcesInfo;
using Microsoft.Management.Configuration.Processor.Exceptions;
using Microsoft.Management.Configuration.Processor.Extensions;
using Microsoft.Management.Configuration.Processor.Helpers;
using Microsoft.PowerShell.Commands;
using Windows.Foundation.Collections;
Expand Down Expand Up @@ -54,51 +52,26 @@ public DscModuleV2()
public string InvokeDscResourceCmd { get; } = Commands.InvokeDscResource;

/// <inheritdoc/>
public IReadOnlyList<DscResourceInfoInternal> GetAllDscResources(Runspace runspace)
public IReadOnlyList<DscResourceInfoInternal> GetAllDscResources(PowerShell pwsh)
{
var result = new List<DscResourceInfoInternal>();

using PowerShell pwsh = PowerShell.Create(runspace);
var resources = pwsh.AddCommand(this.GetDscResourceCmd)
.InvokeAndStopOnError();

return this.ConvertToDscResourceInfoInternal(resources);
return this.GetDscResources(pwsh, null, null);
}

/// <inheritdoc/>
public IReadOnlyList<DscResourceInfoInternal> GetDscResourcesInModule(
Runspace runspace,
PowerShell pwsh,
ModuleSpecification moduleSpecification)
{
var result = new List<DscResourceInfoInternal>();

using PowerShell pwsh = PowerShell.Create(runspace);

var resources = pwsh.AddCommand(this.GetDscResourceCmd)
.AddParameter(Parameters.Module, moduleSpecification)
.InvokeAndStopOnError();

return this.ConvertToDscResourceInfoInternal(resources);
return this.GetDscResources(pwsh, null, moduleSpecification);
}

/// <inheritdoc/>
public DscResourceInfoInternal? GetDscResource(
Runspace runspace,
PowerShell pwsh,
string name,
ModuleSpecification? moduleSpecification)
{
using PowerShell pwsh = PowerShell.Create(runspace);
pwsh.AddCommand(this.GetDscResourceCmd)
.AddParameter(Parameters.Name, name);

if (moduleSpecification is not null)
{
pwsh.AddParameter(Parameters.Module, moduleSpecification);
}

var resources = pwsh.InvokeAndStopOnError();

var dscResourceInfos = this.ConvertToDscResourceInfoInternal(resources);
var dscResourceInfos = this.GetDscResources(pwsh, name, moduleSpecification);

if (dscResourceInfos.Count == 0)
{
Expand All @@ -114,17 +87,15 @@ public IReadOnlyList<DscResourceInfoInternal> GetDscResourcesInModule(

/// <inheritdoc/>
public ValueSet InvokeGetResource(
Runspace runspace,
PowerShell pwsh,
ValueSet settings,
string name,
ModuleSpecification? moduleSpecification)
{
using PowerShell pwsh = PowerShell.Create(runspace);

var getResult = pwsh.AddCommand(this.InvokeDscResourceCmd)
.AddParameters(PrepareInvokeParameters(name, settings, moduleSpecification))
.AddParameter(Parameters.Method, DscMethods.Get)
.InvokeAndStopOnError()
.Invoke()
.FirstOrDefault();

if (getResult is null)
Expand All @@ -151,19 +122,17 @@ public ValueSet InvokeGetResource(

/// <inheritdoc/>
public bool InvokeTestResource(
Runspace runspace,
PowerShell pwsh,
ValueSet settings,
string name,
ModuleSpecification? moduleSpecification)
{
using PowerShell pwsh = PowerShell.Create(runspace);

// Returned type is InvokeDscResourceTestResult which is a PowerShell classed defined
// in PSDesiredStateConfiguration.psm1.
dynamic? testResult = pwsh.AddCommand(this.InvokeDscResourceCmd)
.AddParameters(PrepareInvokeParameters(name, settings, moduleSpecification))
.AddParameter(Parameters.Method, DscMethods.Test)
.InvokeAndStopOnError()
.Invoke()
.FirstOrDefault();

if (testResult is null ||
Expand All @@ -177,19 +146,17 @@ public bool InvokeTestResource(

/// <inheritdoc/>
public bool InvokeSetResource(
Runspace runspace,
PowerShell pwsh,
ValueSet settings,
string name,
ModuleSpecification? moduleSpecification)
{
using PowerShell pwsh = PowerShell.Create(runspace);

// Returned type is InvokeDscResourceSetResult which is a PowerShell classed defined
// in PSDesiredStateConfiguration.psm1.
dynamic? setResult = pwsh.AddCommand(this.InvokeDscResourceCmd)
.AddParameters(PrepareInvokeParameters(name, settings, moduleSpecification))
.AddParameter(Parameters.Method, DscMethods.Set)
.InvokeAndStopOnError()
.Invoke()
.FirstOrDefault();

if (setResult is null ||
Expand Down Expand Up @@ -226,6 +193,40 @@ private static Dictionary<string, object> PrepareInvokeParameters(
return parameters;
}

private IReadOnlyList<DscResourceInfoInternal> GetDscResources(
PowerShell pwsh,
string? name,
ModuleSpecification? moduleSpecification)
{
pwsh.AddCommand(this.GetDscResourceCmd);

if (name is not null)
{
pwsh.AddParameter(Parameters.Name, name);
}

if (moduleSpecification is not null)
{
pwsh.AddParameter(Parameters.Module, moduleSpecification);
}

try
{
var resources = pwsh.Invoke();
return this.ConvertToDscResourceInfoInternal(resources);
}
catch (RuntimeException e)
{
// Detect easily this.
if (e.ErrorRecord.FullyQualifiedErrorId == "ExceptionWhenSetting,GetResourceFromKeyword")
{
throw new GetDscResourceModuleConflict(name, moduleSpecification, e);
}

throw;
}
}

private List<DscResourceInfoInternal> ConvertToDscResourceInfoInternal(Collection<PSObject> psObjects)
{
var result = new List<DscResourceInfoInternal>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace Microsoft.Management.Configuration.Processor.DscModule
{
using System.Collections.Generic;
using System.Management.Automation.Runspaces;
using System.Management.Automation;
using Microsoft.Management.Configuration.Processor.DscResourcesInfo;
using Microsoft.PowerShell.Commands;
using Windows.Foundation.Collections;
Expand Down Expand Up @@ -35,55 +35,55 @@ internal interface IDscModule
/// <summary>
/// Gets all DSC resource.
/// </summary>
/// <param name="runspace">PowerShell Runspace.</param>
/// <param name="pwsh">PowerShell.</param>
/// <returns>A list with the DSC resource.</returns>
IReadOnlyList<DscResourceInfoInternal> GetAllDscResources(Runspace runspace);
IReadOnlyList<DscResourceInfoInternal> GetAllDscResources(PowerShell pwsh);

/// <summary>
/// Gets all resources in a module.
/// </summary>
/// <param name="runspace">PowerShell Runspace.</param>
/// <param name="pwsh">PowerShell.</param>
/// <param name="moduleSpecification">Module specification.</param>
/// <returns>List of resources of that module and version.</returns>
IReadOnlyList<DscResourceInfoInternal> GetDscResourcesInModule(Runspace runspace, ModuleSpecification moduleSpecification);
IReadOnlyList<DscResourceInfoInternal> GetDscResourcesInModule(PowerShell pwsh, ModuleSpecification moduleSpecification);

/// <summary>
/// Gets a DSC Resource.
/// </summary>
/// <param name="runspace">PowerShell Runspace.</param>
/// <param name="pwsh">PowerShell.</param>
/// <param name="name">Name.</param>
/// <param name="moduleSpecification">Module specification.</param>
/// <returns>DSC Resource from that module and version.</returns>
DscResourceInfoInternal? GetDscResource(Runspace runspace, string name, ModuleSpecification? moduleSpecification);
DscResourceInfoInternal? GetDscResource(PowerShell pwsh, string name, ModuleSpecification? moduleSpecification);

/// <summary>
/// Calls Invoke-DscResource -Method Get from this module.
/// </summary>
/// <param name="runspace">PowerShell Runspace.</param>
/// <param name="pwsh">PowerShell.</param>
/// <param name="settings">Settings.</param>
/// <param name="name">Name.</param>
/// <param name="moduleSpecification">Module specification.</param>
/// <returns>Properties of resource.</returns>
ValueSet InvokeGetResource(Runspace runspace, ValueSet settings, string name, ModuleSpecification? moduleSpecification);
ValueSet InvokeGetResource(PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification);

/// <summary>
/// Calls Invoke-DscResource -Method Test from this module.
/// </summary>
/// <param name="runspace">PowerShell Runspace.</param>
/// <param name="pwsh">PowerShell.</param>
/// <param name="settings">Settings.</param>
/// <param name="name">Name.</param>
/// <param name="moduleSpecification">Module specification.</param>
/// <returns>Is in desired state.</returns>
bool InvokeTestResource(Runspace runspace, ValueSet settings, string name, ModuleSpecification? moduleSpecification);
bool InvokeTestResource(PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification);

/// <summary>
/// Calls Invoke-DscResource -Method Set from this module.
/// </summary>
/// <param name="runspace">PowerShell Runspace.</param>
/// <param name="pwsh">PowerShell.</param>
/// <param name="settings">Settings.</param>
/// <param name="name">Name.</param>
/// <param name="moduleSpecification">Module specification.</param>
/// <returns>If a reboot is required.</returns>
bool InvokeSetResource(Runspace runspace, ValueSet settings, string name, ModuleSpecification? moduleSpecification);
bool InvokeSetResource(PowerShell pwsh, ValueSet settings, string name, ModuleSpecification? moduleSpecification);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,10 @@ internal static class ErrorCodes
/// Internal error calling Invoke-DscResource Set.
/// </summary>
internal const int WinGetConfigUnitInvokeSet = unchecked((int)0x8A15C106);

/// <summary>
/// Internal error calling Get-DscResource. More than one module found with the same version.
/// </summary>
internal const int WinGetConfigUnitModuleConflict = unchecked((int)0x8A15C107);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// -----------------------------------------------------------------------------
// <copyright file="GetDscResourceModuleConflict.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------------

namespace Microsoft.Management.Configuration.Processor.Exceptions
{
using System;
using System.Management.Automation;
using Microsoft.PowerShell.Commands;

/// <summary>
/// A call to Get-DscResource failed because at least two modules with the same version where found in the module path.
/// If you are getting this verify the module path.
/// </summary>
internal class GetDscResourceModuleConflict : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="GetDscResourceModuleConflict"/> class.
/// </summary>
/// <param name="resourceName">Resource name.</param>
/// <param name="module">Optional module.</param>
/// <param name="inner">The original runtime exception thrown.</param>
public GetDscResourceModuleConflict(string? resourceName, ModuleSpecification? module, RuntimeException inner)
: base($"Multiple modules with same version in module path: {resourceName?.ToString() ?? "<no resource>"} [{module?.ToString() ?? "<no module>"}]", inner)
{
this.HResult = ErrorCodes.WinGetConfigUnitModuleConflict;
this.ResourceName = resourceName;
this.Module = module;
}

/// <summary>
/// Gets the resource name.
/// </summary>
public string? ResourceName { get; }

/// <summary>
/// Gets the module, if any.
/// </summary>
public ModuleSpecification? Module { get; }
}
}
Loading