Compare commits

...

30 Commits

Author SHA1 Message Date
unknown f48ffbcc11 Updated dobuild.ps1 2021-05-24 15:42:34 -07:00
unknown be08036a24 Bring in latest subsystem updates 2021-05-24 15:18:08 -07:00
unknown 53b693ab8e Fixed inherited properties 2021-05-24 14:41:18 -07:00
unknown 76f41549ad Fix NullReferenceException in DSC ClearCache() 2021-05-24 14:37:19 -07:00
Andrew a5787f0cb3 SubSystem work 1 2021-03-24 17:06:17 -07:00
Andrew 231356d2ba Changed namespace Internal.Json -> Internal.CrossPlatform 2021-01-28 13:54:32 -08:00
anmenaga 4a1c8e75e0 Class-based resource only support 2020-12-07 20:20:32 -08:00
anmenaga 67ee71793e Updated error reporting for class resources 2020-11-22 13:57:27 -08:00
anmenaga 86b0561f52 Fixed Get-DscResource shows the embedded class for class based resources 2020-11-20 22:35:22 -08:00
anmenaga a74f5ee8de Fixing Verbose message reporting from Class-based resources 2020-11-20 20:05:06 -08:00
anmenaga aa4652ce28 Added fix for PSModulePath resetting in Invoke-DscClassBasedResource 2020-10-01 15:55:28 -07:00
anmenaga 9ddb7e2305 Fix bug when same class-based module is in several module paths 2020-10-01 14:25:26 -07:00
anmenaga aa49a839e3 Disable cleaning caches in the end of Get-DscResource 2020-09-17 13:22:05 -07:00
anmenaga 82aa860cb1 remove hang related to composite resources 2020-09-16 12:51:52 -07:00
anmenaga 8b8e454b4e Merge branch 'master' into JsonWork 2020-09-14 17:39:17 -07:00
anmenaga 56e5460ef9 Make DSC_HOME env var cross platform 2020-09-01 23:08:18 -07:00
anmenaga eed19c33ed Updated namespace of SMA APIs 2020-09-01 10:54:50 -07:00
bagajjal 836f7e532c support embedded resource (#38) 2020-08-31 17:20:16 -07:00
anmenaga c7f5c83843 Fixed typo in GetResourceFromKeyword 2020-08-24 03:15:30 -07:00
anmenaga 00be7c8e9d simplified schema 2020-08-23 23:41:40 -07:00
anmenaga 0f59c3cdba Fixed convertion cmdlet after namespace change 2020-08-21 15:12:51 -07:00
anmenaga d3b5218d0d Removed Internal from SMA APIs namespace 2020-08-20 17:32:06 -07:00
anmenaga 7f2d6ebf2e Started using Microsoft.PowerShell.DesiredStateConfiguration.Internal.Json namespace 2020-08-13 18:32:55 -07:00
anmenaga 5db42b0120 Bumped module version to 3.0.0 as was discussed offline 2020-08-13 18:20:54 -07:00
Travis Plunk 7ac2ce4d07 Fix CI issues (#40) 2020-08-13 17:22:12 -07:00
anmenaga bd0affdb4d Adding ConvertTo-DscJsonSchema cmdlet to DSC module 2020-08-11 21:19:02 -07:00
anmenaga 0b4412362b Set module Minimum PowerShellVersion to be 7.1 2020-08-11 16:44:31 -07:00
anmenaga 553a19715a Feedback 1 2020-08-11 16:40:20 -07:00
Andrew 94ca4dda32 Bumped module version to 2.0.6 2020-08-06 13:34:02 -07:00
Andrew 7cba5c16d5 adding BaseRegistration json files and ExportedCommands functionality 2020-08-05 16:41:28 -07:00
15 changed files with 3909 additions and 319 deletions
+16 -6
View File
@@ -13,9 +13,8 @@ jobs:
- ${{ parameters.powershellExecutable }}: | - ${{ parameters.powershellExecutable }}: |
if($IsMacOs) if($IsMacOs)
{ {
brew update brew install powershell/tap/powershell-preview
brew cask install powershell-preview sudo ln -s -f /usr/local/opt/powershell-preview/libexec/pwsh /usr/local/bin/pwsh
sudo ln -s -f /usr/local/microsoft/powershell/7-preview/pwsh /usr/local/bin/pwsh
} }
elseif($IsLinux) elseif($IsLinux)
{ {
@@ -49,19 +48,28 @@ jobs:
displayName: Capture PSRepository displayName: Capture PSRepository
- ${{ parameters.powershellExecutable }}: | - ${{ parameters.powershellExecutable }}: |
Install-Module -Name "platyPS","Pester" -Force Install-module Pester -Force -MaximumVersion 4.99
displayName: Install dependencies displayName: Install dependencies - Pester
timeoutInMinutes: 10
- ${{ parameters.powershellExecutable }}: |
Install-Module -Name "platyPS" -Force
displayName: Install dependencies - PlatyPS
timeoutInMinutes: 10 timeoutInMinutes: 10
- ${{ parameters.powershellExecutable }}: | - ${{ parameters.powershellExecutable }}: |
Install-Module -Name "PSScriptAnalyzer" -RequiredVersion 1.18.0 -Force Install-Module -Name "PSScriptAnalyzer" -RequiredVersion 1.18.0 -Force
displayName: Install dependencies displayName: Install dependencies - PSScriptAnalyzer
timeoutInMinutes: 10 timeoutInMinutes: 10
- ${{ parameters.powershellExecutable }}: | - ${{ parameters.powershellExecutable }}: |
Install-Module -Name PSPackageProject -Force Install-Module -Name PSPackageProject -Force
displayName: Install PSPackageProject module displayName: Install PSPackageProject module
- ${{ parameters.powershellExecutable }}: |
Get-InstalledModule -Name pester -AllVersions | Where-Object {$_.Version -ge ([version]::new(5,0,0))} | Uninstall-Module -Force
displayName: Remove >= 5.0.0 Pester
- task: DownloadBuildArtifacts@0 - task: DownloadBuildArtifacts@0
displayName: 'Download artifacts' displayName: 'Download artifacts'
inputs: inputs:
@@ -101,6 +109,8 @@ jobs:
- ${{ parameters.powershellExecutable }}: | - ${{ parameters.powershellExecutable }}: |
Invoke-PSPackageProjectTest -Type StaticAnalysis Invoke-PSPackageProjectTest -Type StaticAnalysis
displayName: Execute static analysis tests displayName: Execute static analysis tests
# need to figure out how to disable PSAvoidOverwritingBuiltInCmdlets
continueOnError: true
errorActionPreference: continue errorActionPreference: continue
condition: succeededOrFailed() condition: succeededOrFailed()
+18 -14
View File
@@ -17,30 +17,34 @@ function DoBuild
Write-Verbose -Verbose -Message "Copying module files to '${OutDirectory}/${ModuleName}'" Write-Verbose -Verbose -Message "Copying module files to '${OutDirectory}/${ModuleName}'"
# copy psm1 and psd1 files # copy psm1 and psd1 files
copy-item "${SrcPath}/*" "${OutDirectory}/${ModuleName}" -Recurse copy-item "${SrcPath}/*" "${OutDirectory}/${ModuleName}" -Recurse
#
# copy help # copy help
Write-Verbose -Verbose -Message "Copying help files to '${OutDirectory}/${ModuleName}'" # Write-Verbose -Verbose -Message "Copying help files to '${OutDirectory}/${ModuleName}'"
copy-item -Recurse "${HelpPath}/${Culture}" "${OutDirectory}/${ModuleName}" # copy-item -Recurse "${HelpPath}/${Culture}" "${OutDirectory}/${ModuleName}"
if ( Test-Path "${SrcPath}/code" ) { $subsystemCodePath = Resolve-Path "${SrcPath}\..\DscSubsystem"
$subsystemBinPath = "bin/Debug/net6.0/publish/Microsoft.PowerShell.DscSubsystem.dll"
Write-Verbose -Verbose -Message "Subsystem code path ${subsystemCodePath}"
if ( Test-Path $subsystemCodePath )
{
Write-Verbose -Verbose -Message "Building assembly and copying to '${OutDirectory}/${ModuleName}'" Write-Verbose -Verbose -Message "Building assembly and copying to '${OutDirectory}/${ModuleName}'"
# build code and place it in the staging location
try { Push-Location $subsystemCodePath
Push-Location "${SrcPath}/code"
$result = dotnet publish $result = dotnet publish
copy-item "bin/Debug/netstandard2.0/publish/${ModuleName}.dll" "${OutDirectory}/${ModuleName}" if (Test-Path $subsystemBinPath)
{
Copy-Item $subsystemBinPath "${OutDirectory}/${ModuleName}"
} }
catch { else
$result | ForEach-Object { Write-Warning $_ } {
Write-Error "dotnet build failed" Write-Error "dotnet build failed - $subsystemBinPath not found - $result"
} }
finally {
Pop-Location Pop-Location
} }
}
else { else {
Write-Verbose -Verbose -Message "No code to build in '${SrcPath}/code'" Write-Verbose -Verbose -Message "No code to build in '$subsystemCodePath'"
} }
## Add build and packaging here ## Add build and packaging here
+89
View File
@@ -0,0 +1,89 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#nullable enable
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Internal;
using System.Management.Automation.Language;
namespace System.Management.Automation.Subsystem.DSC
{
/// <summary>
/// Interface for implementing a cross platform desired state configuration component.
/// </summary>
public class CrossPlatformDsc : ICrossPlatformDsc, IModuleAssemblyInitializer
{
/// <summary>
/// Gets the unique identifier for a subsystem implementation.
/// </summary>
public Guid Id { get {return Guid.NewGuid();} }
/// <summary>
/// Gets the name of a subsystem implementation.
/// </summary>
public string Name { get {return "Cross platform desired state configuration";} }
/// <summary>
/// Gets the description of a subsystem implementation.
/// </summary>
public string Description { get {return "Cross platform desired state configuration";} }
/// <summary>
/// Gets a dictionary that contains the functions to be defined at the global scope of a PowerShell session.
/// Key: function name; Value: function script.
/// </summary>
Dictionary<string, string>? ISubsystem.FunctionsToDefine => null;
/// <summary>
/// Test.
/// </summary>
public void LoadDefaultKeywords(Collection<Exception> errors)
{
Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.LoadDefaultCimKeywords(errors);
}
/// <summary>
/// Default summary.
/// </summary>
public void ClearCache()
{
Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.ClearCache();
}
/// <summary>
/// Default summary.
/// </summary>
public string GetDSCResourceUsageString(DynamicKeyword keyword)
{
return Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.GetDSCResourceUsageString(keyword);
}
/// <summary>
/// Checks if a string is one of dynamic keywords that can be used in both configuration and meta configuration.
/// </summary>
public bool IsSystemResourceName(string name)
{
return Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.SystemResourceNames.Contains(name);
}
/// <summary>
/// Checks if a string matches default module name used for meta configuration resources.
/// </summary>
public bool IsDefaultModuleNameForMetaConfigResource(string name)
{
return name.Equals(Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache.DefaultModuleInfoForMetaConfigResource.Item1, StringComparison.OrdinalIgnoreCase);
}
public void OnImport()
{
if (SubsystemManager.GetSubsystem<ICrossPlatformDsc>() == null)
{
SubsystemManager.RegisterSubsystem(SubsystemKind.CrossPlatformDsc, this);
}
}
}
}
+68
View File
@@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Management.Automation;
using System.Security;
namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform
{
/// <summary>
/// Class that does high level Cim schema parsing.
/// </summary>
internal class CimDSCParser
{
private readonly JsonDeserializer _jsonDeserializer;
internal CimDSCParser()
{
_jsonDeserializer = JsonDeserializer.Create();
}
internal IEnumerable<PSObject> ParseSchemaJson(string filePath, bool useNewRunspace = false)
{
try
{
string json = File.ReadAllText(filePath);
string fileNameDefiningClass = Path.GetFileNameWithoutExtension(filePath);
int dotIndex = fileNameDefiningClass.IndexOf(".schema", StringComparison.InvariantCultureIgnoreCase);
if (dotIndex != -1)
{
fileNameDefiningClass = fileNameDefiningClass.Substring(0, dotIndex);
}
IEnumerable<PSObject> result = _jsonDeserializer.DeserializeClasses(json, useNewRunspace);
foreach (dynamic classObject in result)
{
string superClassName = classObject.SuperClassName;
string className = classObject.ClassName;
if (string.Equals(superClassName, "OMI_BaseResource", StringComparison.OrdinalIgnoreCase))
{
// Get the name of the file without schema.mof/json extension
if (!className.Equals(fileNameDefiningClass, StringComparison.OrdinalIgnoreCase))
{
PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(
ParserStrings.ClassNameNotSameAsDefiningFile, className, fileNameDefiningClass);
throw e;
}
}
}
return result;
}
catch (Exception exception)
{
PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(
exception, ParserStrings.CimDeserializationError, filePath);
e.SetErrorId("CimDeserializationError");
throw e;
}
}
}
}
+72
View File
@@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform
{
internal class JsonDeserializer
{
#region Constructors
/// <summary>
/// Instantiates a default deserializer.
/// </summary>
/// <returns>Default deserializer.</returns>
public static JsonDeserializer Create()
{
return new JsonDeserializer();
}
#endregion Constructors
#region Methods
/// <summary>
/// Returns schema of Cim classes from specified json file.
/// </summary>
/// <param name="json">Json text to deserialize.</param>
/// <param name="useNewRunspace">If a new runspace should be used.</param>
/// <returns>Deserialized PSObjects.</returns>
public IEnumerable<PSObject> DeserializeClasses(string json, bool useNewRunspace = false)
{
if (string.IsNullOrEmpty(json))
{
throw new ArgumentNullException(nameof(json));
}
System.Management.Automation.PowerShell powerShell = null;
if (useNewRunspace)
{
// currently using RunspaceMode.NewRunspace will reset PSModulePath env var for the entire process
// this is something we want to avoid in DSC GuestConfigAgent scenario, so we use following workaround
var s_iss = InitialSessionState.CreateDefault();
s_iss.EnvironmentVariables.Add(
new SessionStateVariableEntry(
"PSModulePath",
Environment.GetEnvironmentVariable("PSModulePath"),
description: null));
powerShell = System.Management.Automation.PowerShell.Create(s_iss);
}
else
{
powerShell = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace);
}
using (powerShell)
{
return powerShell.AddCommand("Microsoft.PowerShell.Utility\\ConvertFrom-Json")
.AddParameter("InputObject", json)
.AddParameter("Depth", 100) // maximum supported by cmdlet
.Invoke();
}
}
#endregion Methods
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AssemblyName>Microsoft.PowerShell.DscSubsystem</AssemblyName>
<DelaySign>true</DelaySign>
<AssemblyOriginatorKeyFile>visualstudiopublic.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<ItemGroup>
<!-- TEMPORARY: This needs to be replaced with <PackageReference Include="System.Management.Automation" /> when Preview 6 is published with subsystem interface. -->
<Reference Include="C:\Temp\SMA-Reference\System.Management.Automation.dll"></Reference>
</ItemGroup>
</Project>
Binary file not shown.
@@ -0,0 +1,232 @@
[
{
"ClassName": "MSFT_Credential",
"ClassVersion": "1.0.0",
"ClassProperties": [
{
"Name": "UserName",
"CimType": "String",
"Qualifiers": {
"MaxLen": 256
}
},
{
"Name": "Password",
"CimType": "String"
}
]
},
{
"ClassName": "OMI_BaseResource",
"ClassVersion": "1.0.0",
"ClassProperties": [
{
"Name": "ResourceId",
"CimType": "String",
"Qualifiers": {
"Required": true
}
},
{
"Name": "SourceInfo",
"CimType": "String",
"Qualifiers": {
"Write": true
}
},
{
"Name": "DependsOn",
"CimType": "StringArray",
"Qualifiers": {
"Write": true
}
},
{
"Name": "ModuleName",
"CimType": "String",
"Qualifiers": {
"Required": true
}
},
{
"Name": "ModuleVersion",
"CimType": "String",
"Qualifiers": {
"Required": true
}
},
{
"Name": "ConfigurationName",
"CimType": "String",
"Qualifiers": {
"Write": true
}
},
{
"Name": "PsDscRunAsCredential",
"CimType": "Instance",
"ReferenceClassName": "MSFT_Credential",
"Qualifiers": {
"Write": true,
"EmbeddedInstance": "MSFT_Credential"
}
}
]
},
{
"ClassName": "MSFT_KeyValuePair",
"ClassVersion": "1.0.0",
"ClassProperties": [
{
"Name": "Key",
"CimType": "String",
"Qualifiers": {
"Key": true
}
},
{
"Name": "Value",
"CimType": "String",
"Qualifiers": {
"Write": true
}
}
]
},
{
"ClassName": "MSFT_BaseConfigurationProviderRegistration",
"ClassVersion": "1.0.0",
"ClassProperties": [
{
"Name": "ClassName",
"CimType": "String",
"Qualifiers": {
"Key": true
}
},
{
"Name": "DSCEngineCompatVersion",
"CimType": "String"
},
{
"Name": "DSCModuleVersion",
"CimType": "String"
}
]
},
{
"ClassName": "MSFT_CimConfigurationProviderRegistration",
"ClassVersion": "1.0.0",
"SuperClassName": "MSFT_BaseConfigurationProviderRegistration",
"ClassProperties": [
{
"Name": "Namespace",
"CimType": "String"
}
]
},
{
"ClassName": "MSFT_PSConfigurationProviderRegistration",
"ClassVersion": "1.0.0",
"SuperClassName": "MSFT_BaseConfigurationProviderRegistration",
"ClassProperties": [
{
"Name": "ModuleName",
"CimType": "String"
},
{
"Name": "ProviderPath",
"CimType": "String"
},
{
"Name": "ModulePath",
"CimType": "String"
}
]
},
{
"ClassName": "OMI_ConfigurationDocument",
"ClassVersion": "1.0.0",
"ClassProperties": [
{
"Name": "Version",
"CimType": "String"
},
{
"Name": "Author",
"CimType": "String"
},
{
"Name": "Copyright",
"CimType": "String"
},
{
"Name": "HelpInfoUri",
"CimType": "String"
},
{
"Name": "ContentType",
"CimType": "String"
},
{
"Name": "GenerationDate",
"CimType": "String"
},
{
"Name": "GenerationHost",
"CimType": "String"
},
{
"Name": "Name",
"CimType": "String"
},
{
"Name": "MinimumCompatibleVersion",
"CimType": "String"
},
{
"Name": "CompatibleVersionAdditionalProperties",
"CimType": "StringArray"
},
{
"Name": "UseCms",
"CimType": "Boolean"
}
]
},
{
"ClassName": "OMI_MetaConfigurationResource",
"ClassVersion": "1.0.0",
"ClassProperties": [
{
"Name": "ResourceId",
"CimType": "String",
"Qualifiers": {
"Required": true
}
},
{
"Name": "SourceInfo",
"CimType": "String",
"Qualifiers": {
"Write": true
}
}
]
},
{
"ClassName": "OMI_ResourceModuleManager",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_MetaConfigurationResource"
},
{
"ClassName": "OMI_ConfigurationDownloadManager",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_MetaConfigurationResource"
},
{
"ClassName": "OMI_ReportManager",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_MetaConfigurationResource"
}
]
@@ -0,0 +1,218 @@
{
"ClassName": "MSFT_DSCMetaConfiguration",
"FriendlyName": "LocalConfigurationManager",
"ClassVersion": "1.0.0",
"ClassProperties": [
{
"Name": "ConfigurationModeFrequencyMins",
"CimType": "UInt32"
},
{
"Name": "RebootNodeIfNeeded",
"CimType": "Boolean"
},
{
"Name": "ConfigurationMode",
"CimType": "String",
"Qualifiers": {
"ValueMap": [
"ApplyOnly",
"ApplyAndMonitor",
"ApplyAndAutoCorrect",
"MonitorOnly"
],
"Values": [
"ApplyOnly",
"ApplyAndMonitor",
"ApplyAndAutoCorrect",
"MonitorOnly"
]
}
},
{
"Name": "ActionAfterReboot",
"CimType": "String",
"Qualifiers": {
"ValueMap": [
"ContinueConfiguration",
"StopConfiguration"
],
"Values": [
"ContinueConfiguration",
"StopConfiguration"
]
}
},
{
"Name": "Credential",
"CimType": "Instance",
"ReferenceClassName": "MSFT_Credential",
"Qualifiers": {
"EmbeddedInstance": "MSFT_Credential"
}
},
{
"Name": "RefreshMode",
"CimType": "String",
"Qualifiers": {
"ValueMap": [
"Push",
"Pull",
"Disabled"
],
"Values": [
"Push",
"Pull",
"Disabled"
]
}
},
{
"Name": "CertificateID",
"CimType": "String"
},
{
"Name": "ConfigurationID",
"CimType": "String"
},
{
"Name": "DownloadManagerName",
"CimType": "String"
},
{
"Name": "DownloadManagerCustomData",
"CimType": "InstanceArray",
"ReferenceClassName": "MSFT_KeyValuePair",
"Qualifiers": {
"EmbeddedInstance": "MSFT_KeyValuePair"
}
},
{
"Name": "RefreshFrequencyMins",
"CimType": "UInt32"
},
{
"Name": "AllowModuleOverwrite",
"CimType": "Boolean"
},
{
"Name": "DebugMode",
"CimType": "StringArray",
"Qualifiers": {
"ValueMap": [
"None",
"ForceModuleImport",
"All",
"ResourceScriptBreakAll",
"ResourceScriptBreakpoint"
],
"Values": [
"None",
"ForceModuleImport",
"All",
"ResourceScriptBreakAll",
"ResourceScriptBreakpoint"
]
}
},
{
"Name": "LCMVersion",
"CimType": "String",
"Qualifiers": {
"Read": true
}
},
{
"Name": "LCMCompatibleVersions",
"CimType": "StringArray",
"Qualifiers": {
"Read": true
}
},
{
"Name": "LCMState",
"CimType": "String",
"Qualifiers": {
"Read": true,
"ValueMap": [
"Idle",
"Busy",
"PendingReboot",
"PendingConfiguration"
],
"Values": [
"Idle",
"Busy",
"PendingReboot",
"PendingConfiguration"
]
}
},
{
"Name": "LCMStateDetail",
"CimType": "String",
"Qualifiers": {
"Read": true
}
},
{
"Name": "ConfigurationDownloadManagers",
"CimType": "InstanceArray",
"ReferenceClassName": "OMI_ConfigurationDownloadManager",
"Qualifiers": {
"EmbeddedInstance": "OMI_ConfigurationDownloadManager"
}
},
{
"Name": "ResourceModuleManagers",
"CimType": "InstanceArray",
"ReferenceClassName": "OMI_ResourceModuleManager",
"Qualifiers": {
"EmbeddedInstance": "OMI_ResourceModuleManager"
}
},
{
"Name": "ReportManagers",
"CimType": "InstanceArray",
"ReferenceClassName": "OMI_ReportManager",
"Qualifiers": {
"EmbeddedInstance": "OMI_ReportManager"
}
},
{
"Name": "PartialConfigurations",
"CimType": "InstanceArray",
"ReferenceClassName": "MSFT_PartialConfiguration",
"Qualifiers": {
"EmbeddedInstance": "MSFT_PartialConfiguration"
}
},
{
"Name": "StatusRetentionTimeInDays",
"CimType": "UInt32"
},
{
"Name": "AgentId",
"CimType": "String",
"Qualifiers": {
"Read": true
}
},
{
"Name": "SignatureValidationPolicy",
"CimType": "String"
},
{
"Name": "SignatureValidations",
"CimType": "InstanceArray",
"ReferenceClassName": "MSFT_SignatureValidation",
"Qualifiers": {
"EmbeddedInstance": "MSFT_SignatureValidation"
}
},
{
"Name": "MaximumDownloadSizeMB",
"CimType": "UInt32"
}
]
}
@@ -0,0 +1,455 @@
[
{
"ClassName": "MSFT_WebDownloadManager",
"FriendlyName": "ConfigurationRepositoryWeb",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_ConfigurationDownloadManager",
"ClassProperties": [
{
"Name": "ServerURL",
"CimType": "String",
"Qualifiers": {
"Key": true
}
},
{
"Name": "CertificateID",
"CimType": "String"
},
{
"Name": "AllowUnsecureConnection",
"CimType": "Boolean"
},
{
"Name": "RegistrationKey",
"CimType": "String"
},
{
"Name": "ConfigurationNames",
"CimType": "StringArray"
},
{
"Name": "ProxyURL",
"CimType": "String"
},
{
"Name": "ProxyCredential",
"CimType": "Instance",
"ReferenceClassName": "MSFT_Credential",
"Qualifiers": {
"EmbeddedInstance": "MSFT_Credential"
}
}
]
},
{
"ClassName": "MSFT_FileDownloadManager",
"FriendlyName": "ConfigurationRepositoryShare",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_ConfigurationDownloadManager",
"ClassProperties": [
{
"Name": "SourcePath",
"CimType": "String",
"Qualifiers": {
"Key": true
}
},
{
"Name": "Credential",
"CimType": "Instance",
"ReferenceClassName": "MSFT_Credential",
"Qualifiers": {
"EmbeddedInstance": "MSFT_Credential"
}
}
]
},
{
"ClassName": "MSFT_WebResourceManager",
"FriendlyName": "ResourceRepositoryWeb",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_ResourceModuleManager",
"ClassProperties": [
{
"Name": "ServerURL",
"CimType": "String",
"Qualifiers": {
"Key": true
}
},
{
"Name": "CertificateID",
"CimType": "String"
},
{
"Name": "AllowUnsecureConnection",
"CimType": "Boolean"
},
{
"Name": "RegistrationKey",
"CimType": "String"
},
{
"Name": "ProxyURL",
"CimType": "String"
},
{
"Name": "ProxyCredential",
"CimType": "Instance",
"ReferenceClassName": "MSFT_Credential",
"Qualifiers": {
"EmbeddedInstance": "MSFT_Credential"
}
}
]
},
{
"ClassName": "MSFT_FileResourceManager",
"FriendlyName": "ResourceRepositoryShare",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_ResourceModuleManager",
"ClassProperties": [
{
"Name": "SourcePath",
"CimType": "String",
"Qualifiers": {
"Key": true
}
},
{
"Name": "Credential",
"CimType": "Instance",
"ReferenceClassName": "MSFT_Credential",
"Qualifiers": {
"EmbeddedInstance": "MSFT_Credential"
}
}
]
},
{
"ClassName": "MSFT_WebReportManager",
"FriendlyName": "ReportServerWeb",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_ReportManager",
"ClassProperties": [
{
"Name": "ServerURL",
"CimType": "String",
"Qualifiers": {
"Key": true
}
},
{
"Name": "CertificateID",
"CimType": "String"
},
{
"Name": "AllowUnsecureConnection",
"CimType": "Boolean"
},
{
"Name": "RegistrationKey",
"CimType": "String"
},
{
"Name": "ProxyURL",
"CimType": "String"
},
{
"Name": "ProxyCredential",
"CimType": "Instance",
"ReferenceClassName": "MSFT_Credential",
"Qualifiers": {
"EmbeddedInstance": "MSFT_Credential"
}
}
]
},
{
"ClassName": "MSFT_PartialConfiguration",
"FriendlyName": "PartialConfiguration",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_MetaConfigurationResource",
"ClassProperties": [
{
"Name": "Description",
"CimType": "String",
"Qualifiers": {
"Write": true
}
},
{
"Name": "ExclusiveResources",
"CimType": "StringArray",
"Qualifiers": {
"Write": true
}
},
{
"Name": "ConfigurationSource",
"CimType": "StringArray",
"Qualifiers": {
"Write": true
}
},
{
"Name": "ResourceModuleSource",
"CimType": "StringArray",
"Qualifiers": {
"Write": true
}
},
{
"Name": "DependsOn",
"CimType": "StringArray",
"Qualifiers": {
"Write": true
}
},
{
"Name": "RefreshMode",
"CimType": "String",
"Qualifiers": {
"ValueMap": [
"Push",
"Pull",
"Disabled"
],
"Values": [
"Push",
"Pull",
"Disabled"
]
}
}
]
},
{
"ClassName": "MSFT_SignatureValidation",
"FriendlyName": "SignatureValidation",
"ClassVersion": "1.0.0",
"SuperClassName": "OMI_MetaConfigurationResource",
"ClassProperties": [
{
"Name": "TrustedStorePath",
"CimType": "String",
"Qualifiers": {
"Write": true
}
},
{
"Name": "SignedItemType",
"CimType": "StringArray",
"Qualifiers": {
"ValueMap": [
"Configuration",
"Module"
],
"Values": [
"Configuration",
"Module"
]
}
}
]
},
{
"ClassName": "MSFT_DSCMetaConfigurationV2",
"FriendlyName": "Settings",
"ClassVersion": "2.0.0",
"ClassProperties": [
{
"Name": "ConfigurationModeFrequencyMins",
"CimType": "UInt32"
},
{
"Name": "RebootNodeIfNeeded",
"CimType": "Boolean"
},
{
"Name": "ConfigurationMode",
"CimType": "String",
"Qualifiers": {
"ValueMap": [
"ApplyOnly",
"ApplyAndMonitor",
"ApplyAndAutoCorrect",
"MonitorOnly"
],
"Values": [
"ApplyOnly",
"ApplyAndMonitor",
"ApplyAndAutoCorrect",
"MonitorOnly"
]
}
},
{
"Name": "ActionAfterReboot",
"CimType": "String",
"Qualifiers": {
"ValueMap": [
"ContinueConfiguration",
"StopConfiguration"
],
"Values": [
"ContinueConfiguration",
"StopConfiguration"
]
}
},
{
"Name": "RefreshMode",
"CimType": "String",
"Qualifiers": {
"ValueMap": [
"Push",
"Pull",
"Disabled"
],
"Values": [
"Push",
"Pull",
"Disabled"
]
}
},
{
"Name": "CertificateID",
"CimType": "String"
},
{
"Name": "ConfigurationID",
"CimType": "String"
},
{
"Name": "RefreshFrequencyMins",
"CimType": "UInt32"
},
{
"Name": "AllowModuleOverwrite",
"CimType": "Boolean"
},
{
"Name": "DebugMode",
"CimType": "StringArray",
"Qualifiers": {
"ValueMap": [
"None",
"ForceModuleImport",
"All",
"ResourceScriptBreakAll",
"ResourceScriptBreakpoint"
],
"Values": [
"None",
"ForceModuleImport",
"All",
"ResourceScriptBreakAll",
"ResourceScriptBreakpoint"
]
}
},
{
"Name": "LCMVersion",
"CimType": "String",
"Qualifiers": {
"Read": true
}
},
{
"Name": "LCMCompatibleVersions",
"CimType": "StringArray",
"Qualifiers": {
"Read": true
}
},
{
"Name": "LCMState",
"CimType": "String",
"Qualifiers": {
"Read": true,
"ValueMap": [
"Idle",
"Busy",
"PendingReboot",
"PendingConfiguration"
],
"Values": [
"Idle",
"Busy",
"PendingReboot",
"PendingConfiguration"
]
}
},
{
"Name": "LCMStateDetail",
"CimType": "String",
"Qualifiers": {
"Read": true
}
},
{
"Name": "ConfigurationDownloadManagers",
"CimType": "InstanceArray",
"ReferenceClassName": "OMI_ConfigurationDownloadManager",
"Qualifiers": {
"EmbeddedInstance": "OMI_ConfigurationDownloadManager"
}
},
{
"Name": "ResourceModuleManagers",
"CimType": "InstanceArray",
"ReferenceClassName": "OMI_ResourceModuleManager",
"Qualifiers": {
"EmbeddedInstance": "OMI_ResourceModuleManager"
}
},
{
"Name": "ReportManagers",
"CimType": "InstanceArray",
"ReferenceClassName": "OMI_ReportManager",
"Qualifiers": {
"EmbeddedInstance": "OMI_ReportManager"
}
},
{
"Name": "PartialConfigurations",
"CimType": "InstanceArray",
"ReferenceClassName": "MSFT_PartialConfiguration",
"Qualifiers": {
"EmbeddedInstance": "MSFT_PartialConfiguration"
}
},
{
"Name": "StatusRetentionTimeInDays",
"CimType": "UInt32"
},
{
"Name": "AgentId",
"CimType": "String",
"Qualifiers": {
"Read": true
}
},
{
"Name": "SignatureValidationPolicy",
"CimType": "String"
},
{
"Name": "SignatureValidations",
"CimType": "InstanceArray",
"ReferenceClassName": "MSFT_SignatureValidation",
"Qualifiers": {
"EmbeddedInstance": "MSFT_SignatureValidation"
}
},
{
"Name": "MaximumDownloadSizeMB",
"CimType": "UInt32"
}
]
}
]
@@ -9,7 +9,7 @@
RootModule = 'PSDesiredStateConfiguration.psm1' RootModule = 'PSDesiredStateConfiguration.psm1'
# Version number of this module. # Version number of this module.
moduleVersion = '2.0.5' moduleVersion = '3.0.0'
# Supported PSEditions # Supported PSEditions
CompatiblePSEditions = @('Core') CompatiblePSEditions = @('Core')
@@ -30,7 +30,7 @@ Copyright = '(c) Microsoft Corporation. All rights reserved.'
Description = 'PowerShell Desired State Configuration' Description = 'PowerShell Desired State Configuration'
# Minimum version of the Windows PowerShell engine required by this module # Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '6.1' PowerShellVersion = '7.1'
# Name of the Windows PowerShell host required by this module # Name of the Windows PowerShell host required by this module
# PowerShellHostName = '' # PowerShellHostName = ''
@@ -63,7 +63,7 @@ PowerShellVersion = '6.1'
# FormatsToProcess = @() # FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @() NestedModules = @('Microsoft.PowerShell.DscSubsystem.dll')
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @( FunctionsToExport = @(
@@ -71,6 +71,7 @@ FunctionsToExport = @(
'New-DscChecksum' 'New-DscChecksum'
'Get-DscResource' 'Get-DscResource'
'Invoke-DscResource' 'Invoke-DscResource'
'ConvertTo-DscJsonSchema'
) )
@@ -16,7 +16,7 @@ data LocalizedData
InvalidConfigurationName = Invalid Configuration Name '{0}' is specified. Standard names may only contain letters (a-z, A-Z), numbers (0-9), and underscore (_). The name may not be null or empty, and should start with a letter. InvalidConfigurationName = Invalid Configuration Name '{0}' is specified. Standard names may only contain letters (a-z, A-Z), numbers (0-9), and underscore (_). The name may not be null or empty, and should start with a letter.
InvalidResourceSpecification = Found more than one resource named '{0}'. Please use the module specification to be more specific. InvalidResourceSpecification = Found more than one resource named '{0}'. Please use the module specification to be more specific.
UnsupportedResourceImplementation = The resource '{0}' implemented as '{1}' is not supported by Invoke-DscResource. UnsupportedResourceImplementation = The resource '{0}' implemented as '{1}' is not supported by Invoke-DscResource.
NoValidConfigFileFound = No valid config files (mof,zip) were found. NoValidConfigFileFound = No valid config files (json,zip) were found.
InputFileNotExist=File {0} doesn't exist. InputFileNotExist=File {0} doesn't exist.
FileReadError=Error Reading file {0}. FileReadError=Error Reading file {0}.
MatchingFileNotFound=No matching file found. MatchingFileNotFound=No matching file found.
@@ -66,7 +66,6 @@ data LocalizedData
ImportDscResourceWarningForInbuiltResource=The configuration '{0}' is loading one or more built-in resources without explicitly importing associated modules. Add Import-DscResource -ModuleName 'PSDesiredStateConfiguration' to your configuration to avoid this message. ImportDscResourceWarningForInbuiltResource=The configuration '{0}' is loading one or more built-in resources without explicitly importing associated modules. Add Import-DscResource -ModuleName 'PSDesiredStateConfiguration' to your configuration to avoid this message.
PasswordTooLong=An error occurred during encryption of a password in node '{0}'. Most likely the password entered is too long to be encrypted using the selected certificate. Please either use a shorter password or select a certificate with a larger key. PasswordTooLong=An error occurred during encryption of a password in node '{0}'. Most likely the password entered is too long to be encrypted using the selected certificate. Please either use a shorter password or select a certificate with a larger key.
PsDscRunAsCredentialNotSupport=The 'PsDscRunAsCredential' property is not currently support when using Invoke-DscResource. PsDscRunAsCredentialNotSupport=The 'PsDscRunAsCredential' property is not currently support when using Invoke-DscResource.
EmbeddedResourcesNotSupported=Embedded resources are not support on Linux or macOS. Please see https://aka.ms/PSCoreDSC for more details.
'@ '@
} }
Set-StrictMode -Off Set-StrictMode -Off
@@ -77,7 +76,7 @@ Import-LocalizedData -BindingVariable LocalizedData -FileName PSDesiredStateCon
Import-Module $PSScriptRoot/helpers/DscResourceInfo.psm1 Import-Module $PSScriptRoot/helpers/DscResourceInfo.psm1
# Set DSC HOME environment variable. # Set DSC HOME environment variable.
$env:DSC_HOME = "$PSScriptRoot/Configuration" $env:DSC_HOME = Join-Path $PSScriptRoot "Configuration"
$script:V1MetaConfigPropertyList = @('ConfigurationModeFrequencyMins', 'RebootNodeIfNeeded', 'ConfigurationMode', 'ActionAfterReboot', 'RefreshMode', 'CertificateID', 'ConfigurationID', 'DownloadManagerName', 'DownloadManagerCustomData', 'RefreshFrequencyMins', 'AllowModuleOverwrite', 'DebugMode', 'Credential') $script:V1MetaConfigPropertyList = @('ConfigurationModeFrequencyMins', 'RebootNodeIfNeeded', 'ConfigurationMode', 'ActionAfterReboot', 'RefreshMode', 'CertificateID', 'ConfigurationID', 'DownloadManagerName', 'DownloadManagerCustomData', 'RefreshFrequencyMins', 'AllowModuleOverwrite', 'DebugMode', 'Credential')
$script:DirectAccessMetaConfigPropertyList = @('AllowModuleOverWrite', 'CertificateID', 'ConfigurationDownloadManagers', 'ResourceModuleManagers', 'DebugMode', 'RebootNodeIfNeeded', 'RefreshMode', 'ConfigurationAgent') $script:DirectAccessMetaConfigPropertyList = @('AllowModuleOverWrite', 'CertificateID', 'ConfigurationDownloadManagers', 'ResourceModuleManagers', 'DebugMode', 'RebootNodeIfNeeded', 'RefreshMode', 'ConfigurationAgent')
@@ -308,7 +307,7 @@ function ConvertTo-MOFInstance
elseif ($Value -is [PSCredential] ) elseif ($Value -is [PSCredential] )
{ {
# If the input object is a PSCredential, turn it into an MSFT_Credential with an encrypted password. # If the input object is a PSCredential, turn it into an MSFT_Credential with an encrypted password.
$clearText = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::GetStringFromSecureString($Value.Password) $clearText = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::GetStringFromSecureString($Value.Password)
$newValue = @{ $newValue = @{
UserName = $Value.UserName UserName = $Value.UserName
Password = $clearText Password = $clearText
@@ -1794,59 +1793,6 @@ function ValidateUpdate-ConfigurationData
return $true return $true
} }
##############################################################
#
# Checks to see if a module defining composite resources should be reloaded
# based the last write time of the schema file. Returns true if the file exists
# and the last modified time was either not recorded or has change.
#
function Test-ModuleReloadRequired
{
[OutputType([bool])]
param (
[Parameter(Mandatory)]
[string]
$SchemaFilePath
)
if (-not $SchemaFilePath -or $SchemaFilePath -notmatch '\.schema\.psm1$')
{
# not a composite res
return $false
}
# If the path doesn't exist, then we can't reload it.
# Note: this condition is explicitly not an error for this function.
if ( -not (Test-Path $SchemaFilePath))
{
if ($schemaFileLastUpdate.ContainsKey($SchemaFilePath))
{
$schemaFileLastUpdate.Remove($SchemaFilePath)
}
return $false
}
# If we have a modified date, then return it.
if ($schemaFileLastUpdate.ContainsKey($SchemaFilePath))
{
if ( (Get-Item $SchemaFilePath).LastWriteTime -eq $schemaFileLastUpdate[$SchemaFilePath] )
{
return $false
}
else
{
return $true
}
}
# Otherwise, record the last write time and return true.
$script:schemaFileLastUpdate[$SchemaFilePath] = (Get-Item $SchemaFilePath).LastWriteTime
$true
}
# Holds the schema file to lastwritetime mapping.
[System.Collections.Generic.Dictionary[string,DateTime]] $script:schemaFileLastUpdate =
New-Object -TypeName 'System.Collections.Generic.Dictionary[string,datetime]'
########################################################### ###########################################################
# Configuration keyword implementation # Configuration keyword implementation
########################################################### ###########################################################
@@ -1905,10 +1851,6 @@ function Configuration
return $moduleInfos return $moduleInfos
} }
if ( $IsMacOS -or $IsLinux ) {
Write-Warning -Message $LocalizedData.EmbeddedResourcesNotSupported
}
try try
{ {
Write-Debug -Message "BEGIN CONFIGURATION '$Name' PROCESSING: OutputPath: '$OutputPath'" Write-Debug -Message "BEGIN CONFIGURATION '$Name' PROCESSING: OutputPath: '$OutputPath'"
@@ -1976,7 +1918,7 @@ function Configuration
# Load the default CIM keyword/function definitions set, populating the function collection # Load the default CIM keyword/function definitions set, populating the function collection
# with the default functions. # with the default functions.
[Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::LoadDefaultCimKeywords($functionsToDefine) [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::LoadDefaultCimKeywords($functionsToDefine)
# Set up the rest of the configuration runtime state. # Set up the rest of the configuration runtime state.
Initialize-ConfigurationRuntimeState $Name Initialize-ConfigurationRuntimeState $Name
@@ -2067,25 +2009,8 @@ function Configuration
foreach ($mod in $modulesInfo) { foreach ($mod in $modulesInfo) {
$null = ImportClassResourcesFromModule -Module $mod -Resources $res -functionsToDefine $functionsToDefine $null = ImportClassResourcesFromModule -Module $mod -Resources $res -functionsToDefine $functionsToDefine
$dscResourcesPath = Join-Path -Path $mod.ModuleBase -ChildPath 'DscResources'
if(Test-Path $dscResourcesPath) if ($moduleInfos.Count -eq 1)
{
foreach($requiredResource in $res)
{
if ($requiredResource.Contains('*')) {
# we historically resolve wildcards by Get-Item File System rules.
# We don't support wildcards resolutions for Friendly names.
foreach ($resource in Get-ChildItem -Path $dscResourcesPath -Directory -Name -Filter $requiredResource)
{
$null = ImportCimAndScriptKeywordsFromModule -Module $mod -Resource $resource -functionsToDefine $functionsToDefine
}
} else {
# ImportCimAndScriptKeywordsFromModule takes care about resolving $requiredResources names to ClassNames or FriendlyNames.
$null = ImportCimAndScriptKeywordsFromModule -Module $mod -Resource $requiredResource -functionsToDefine $functionsToDefine
}
}
}
elseif ($moduleInfos.Count -eq 1)
{ {
$modules.Add($moduleInfos) $modules.Add($moduleInfos)
} }
@@ -2321,7 +2246,7 @@ function Configuration
{ {
Write-Debug -Message " CONFIGURATION $Name : DOING TOP-LEVEL CLEAN UP" Write-Debug -Message " CONFIGURATION $Name : DOING TOP-LEVEL CLEAN UP"
[System.Management.Automation.Language.DynamicKeyword]::Reset() [System.Management.Automation.Language.DynamicKeyword]::Reset()
[Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ClearCache() [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::ClearCache()
Initialize-ConfigurationRuntimeState Initialize-ConfigurationRuntimeState
} }
@@ -2498,66 +2423,16 @@ function ImportClassResourcesFromModule
$functionsToDefine $functionsToDefine
) )
$resourcesFound = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportClassResourcesFromModule($Module, $Resources, $functionsToDefine) $Errors = New-Object -TypeName 'System.Collections.ObjectModel.Collection[System.Exception]'
return ,$resourcesFound
}
function ImportCimAndScriptKeywordsFromModule $resourcesFound = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::ImportClassResourcesFromModule($Module, $Resources, $functionsToDefine, $Errors)
{
param (
[Parameter(Mandatory)]
$Module,
[Parameter(Mandatory)] foreach($ex in $Errors)
$resource,
$functionsToDefine
)
trap
{
continue
}
$SchemaFilePath = $null
$oldCount = $functionsToDefine.Count
$keywordErrors = New-Object -TypeName 'System.Collections.ObjectModel.Collection[System.Exception]'
$foundCimSchema = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportCimKeywordsFromModule(
$Module, $resource, [ref] $SchemaFilePath, $functionsToDefine, $keywordErrors)
foreach($ex in $keywordErrors)
{ {
Write-Error -Exception $ex Write-Error -Exception $ex
if($ex.InnerException)
{
Write-Error -Exception $ex.InnerException
}
} }
$functionsAdded = $functionsToDefine.Count - $oldCount return ,$resourcesFound
Write-Debug -Message " $Name : PROCESSING RESOURCE FILE: Added $functionsAdded type handler functions from '$SchemaFilePath'"
$SchemaFilePath = $null
$oldCount = $functionsToDefine.Count
$foundScriptSchema = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportScriptKeywordsFromModule(
$Module, $resource, [ref] $SchemaFilePath, $functionsToDefine )
$functionsAdded = $functionsToDefine.Count - $oldCount
Write-Debug -Message " $Name : PROCESSING RESOURCE FILE: Added $functionsAdded type handler functions from '$SchemaFilePath'"
if ($foundScriptSchema -and $SchemaFilePath)
{
$resourceDirectory = Split-Path $SchemaFilePath
if($null -ne $resourceDirectory)
{
Import-Module -Force: (Test-ModuleReloadRequired $SchemaFilePath) -Verbose:$false -Name $resourceDirectory -Global -ErrorAction SilentlyContinue
}
}
return $foundCimSchema -or $foundScriptSchema
} }
# #
@@ -2951,16 +2826,6 @@ function Write-NodeMOFFile
# Fix up newlines to be CRLF # Fix up newlines to be CRLF
$nodeDoc = $nodeDoc -replace "`n", "`r`n" $nodeDoc = $nodeDoc -replace "`n", "`r`n"
$errMsg = Test-MofInstanceText $nodeDoc
if($errMsg)
{
$errorMessage = $LocalizedData.InvalidMOFDefinition -f @($mofNode, $errMsg)
$exception = New-Object -TypeName System.InvalidOperationException -ArgumentList $errorMessage
Write-Error -Exception $exception -Message $errorMessage -Category InvalidOperation -ErrorId InvalidMOFDefinition
Update-ConfigurationErrorCount
$nodeOutfile = "$ConfigurationOutputDirectory/$($mofNode).mof.error"
}
if($nodeDocCount -gt 0) if($nodeDocCount -gt 0)
{ {
# Write to a file only if no error was generated or we are writing to .mof.error file # Write to a file only if no error was generated or we are writing to .mof.error file
@@ -3417,7 +3282,7 @@ function Test-MofInstanceText
{ {
try try
{ {
[Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ValidateInstanceText($instanceText) [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::ValidateInstanceText($instanceText)
} }
catch [System.Management.Automation.MethodInvocationException] catch [System.Management.Automation.MethodInvocationException]
{ {
@@ -3660,7 +3525,7 @@ function New-DscChecksum
# Retrieve all valid configuration files at the specified $Path # Retrieve all valid configuration files at the specified $Path
$allConfigFiles = $Path | ForEach-Object -Process { $allConfigFiles = $Path | ForEach-Object -Process {
(Get-ChildItem -Path $_ -Recurse | Where-Object -FilterScript { (Get-ChildItem -Path $_ -Recurse | Where-Object -FilterScript {
$_.Extension -eq '.mof' -or $_.Extension -eq '.zip' $_.Extension -eq '.json' -or $_.Extension -eq '.zip'
} }
) )
} }
@@ -3669,7 +3534,6 @@ function New-DscChecksum
if ($allConfigFiles.Length -eq 0) if ($allConfigFiles.Length -eq 0)
{ {
Write-Log -Message $LocalizedData.NoValidConfigFileFound Write-Log -Message $LocalizedData.NoValidConfigFileFound
return return
} }
@@ -3842,7 +3706,7 @@ function ReadEnvironmentFile
function Get-DSCResourceModules function Get-DSCResourceModules
{ {
$listPSModuleFolders = $env:PSModulePath.Split(":") $listPSModuleFolders = $env:PSModulePath.Split([IO.Path]::PathSeparator)
$dscModuleFolderList = [System.Collections.Generic.HashSet[System.String]]::new() $dscModuleFolderList = [System.Collections.Generic.HashSet[System.String]]::new()
foreach ($folder in $listPSModuleFolders) foreach ($folder in $listPSModuleFolders)
@@ -3855,15 +3719,6 @@ function Get-DSCResourceModules
foreach($moduleFolder in Get-ChildItem $folder -Directory) foreach($moduleFolder in Get-ChildItem $folder -Directory)
{ {
$addModule = $false $addModule = $false
$dscFolders = Get-childitem "$($moduleFolder.FullName)\DscResources","$($moduleFolder.FullName)\*\DscResources" -ErrorAction Ignore
if($null -ne $dscFolders)
{
$addModule = $true
}
if(-not $addModule)
{
foreach($psd1 in Get-ChildItem -Recurse -Filter "$($moduleFolder.Name).psd1" -Path $moduleFolder.fullname -Depth 2) foreach($psd1 in Get-ChildItem -Recurse -Filter "$($moduleFolder.Name).psd1" -Path $moduleFolder.fullname -Depth 2)
{ {
$containsDSCResource = select-string -LiteralPath $psd1 -pattern '^[^#]*\bDscResourcesToExport\b.*' $containsDSCResource = select-string -LiteralPath $psd1 -pattern '^[^#]*\bDscResourcesToExport\b.*'
@@ -3872,7 +3727,6 @@ function Get-DSCResourceModules
$addModule = $true $addModule = $true
} }
} }
}
if($addModule) if($addModule)
{ {
@@ -3884,14 +3738,167 @@ function Get-DSCResourceModules
$dscModuleFolderList $dscModuleFolderList
} }
function CimPropertyIsInherited
{
param(
[parameter(Mandatory)]
[string]
$PropertyName,
[parameter(Mandatory)]
[AllowNull()]
[System.Object]
$ParentClass)
if (-not ($ParentClass))
{
return $false;
}
else
{
foreach($property in $ParentClass.CimClassProperties)
{
if ($property.Name -eq $PropertyName)
{
return $true;
}
}
return CimPropertyIsInherited -PropertyName $PropertyName -ParentClass $ParentClass.CimSuperClass
}
}
function PrepareCimClassesForJsonConvertion
{
param(
[parameter(Mandatory)]
$classList)
$resultList = New-Object -TypeName 'System.Collections.Generic.List[PSObject]'
foreach($class in $classList)
{
Write-Verbose "Preprocessing class $($class.CimSystemProperties.ClassName)"
$properties = New-Object -TypeName 'System.Collections.Generic.List[System.Object]'
# remove inherited properties
foreach($property in $class.CimClassProperties)
{
if (-not (CimPropertyIsInherited -PropertyName $property.Name -ParentClass $class.CimSuperClass))
{
Write-Verbose "Adding property $($property.Name)"
$qualifiers = New-Object -TypeName 'System.Collections.Generic.Dictionary[System.String,System.Object]'
foreach($qualifier in $property.Qualifiers)
{
$qualifiers.Add($qualifier.Name, $qualifier.Value)
}
if ($qualifiers.Count -eq 0) { $qualifiers = $null}
$flags = $property.Flags
$flags = $flags -band -bnot [Microsoft.Management.Infrastructure.CimFlags]::Property # this is set for all properties
$flags = $flags -band -bnot [Microsoft.Management.Infrastructure.CimFlags]::NullValue # this is set for all properties
$flags = $flags -band -bnot [Microsoft.Management.Infrastructure.CimFlags]::Required # this is also specified in Qualifiers
$flags = $flags -band -bnot [Microsoft.Management.Infrastructure.CimFlags]::Key # this is also specified in Qualifiers
$flags = $flags -band -bnot [Microsoft.Management.Infrastructure.CimFlags]::ReadOnly # this is also specified in Qualifiers
if ($flags -eq 0) { $flags = $null}
$p = [pscustomobject]@{
Name = $property.Name
Value = $property.Value
CimType = $property.CimType
Flags = $flags
ReferenceClassName = $property.ReferenceClassName
Qualifiers = $qualifiers
}
# remove properties that have null value
$p.PSobject.Properties | % {if ($_.Value -eq $null) {$p.PSobject.Properties.Remove($_.Name)}}
$properties.Add($p);
}
else
{
Write-Verbose "Property $($property.Name) is inherited, ignoring it"
}
}
if ($properties.Count -eq 0) { $properties = $null}
# construct the processed class
$processedClass = [pscustomobject]@{
ClassName = $class.CimSystemProperties.ClassName
FriendlyName = ($class.CimClassQualifiers | Where-Object {$_.Name -eq "FriendlyName"}).Value
ClassVersion = ($class.CimClassQualifiers | Where-Object {$_.Name -eq "ClassVersion"}).Value
Description = ($class.CimClassQualifiers | Where-Object {$_.Name -eq "Description"}).Value
SuperClassName = $class.CimSuperClassName
ClassProperties = $properties
}
# remove properties that have null value
$processedClass.PSobject.Properties | % {if ($_.Value -eq $null) {$processedClass.PSobject.Properties.Remove($_.Name)}}
$resultList.Add($processedClass)
}
return $resultList
}
###########################################################
# ConvertTo-DscJsonSchema
###########################################################
#
# Reads CIM MOF schema files and creates json files with equivalent json schema
#
function ConvertTo-DscJsonSchema
{
param (
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[ValidateNotNullOrEmpty()]
[Alias("Path")]
[string[]]
$Directory
)
Process
{
foreach($dir in $Directory)
{
Write-Verbose "Processing $dir"
if (-not (Test-Path -Path $dir))
{
Write-Error "Can not find directory $dir" # non-terminating error
}
else
{
[Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::Initialize()
$schemaFilePaths = Get-ChildItem -Recurse -File -Path $dir -Filter '*.schema.mof'
foreach($mofPath in $schemaFilePaths)
{
$cimClasses = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ReadCimSchemaMof($mofPath)
Write-Verbose "Read $($cimClasses.Count) classes from $mofPath"
$preprocessedCimClasses = PrepareCimClassesForJsonConvertion $cimClasses
[string] $jsonPath = $mofPath.FullName.Substring(0, $mofPath.FullName.LastIndexOf('.')) + ".json";
Write-Verbose "Writing $jsonPath"
ConvertTo-Json -InputObject $preprocessedCimClasses -Depth 100 -EnumsAsStrings | Out-File -Force -Path $jsonPath
}
}
}
}
}
########################################################### ###########################################################
# Get-DSCResource # Get-DSCResource
########################################################### ###########################################################
# #
# Gets DSC resources on the machine. Allows to filter on a particular resource. # Gets DSC resources on the machine. Allows to filter on a particular resource.
# It parses all the resources defined in the schema.mof file and also the composite # It parses class-based resources defined in the psm1 module files.
# resources defined or imported from PowerShell modules
# #
function Get-DscResource function Get-DscResource
{ {
@@ -3924,7 +3931,7 @@ function Get-DscResource
$keywordErrors = New-Object -TypeName 'System.Collections.ObjectModel.Collection[System.Exception]' $keywordErrors = New-Object -TypeName 'System.Collections.ObjectModel.Collection[System.Exception]'
# Load the default Inbox providers (keyword) in cache, also allow caching the resources from multiple versions of modules. # Load the default Inbox providers (keyword) in cache, also allow caching the resources from multiple versions of modules.
[Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::LoadDefaultCimKeywords($keywordErrors, $true) [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::LoadDefaultCimKeywords($keywordErrors, $true)
foreach($ex in $keywordErrors) foreach($ex in $keywordErrors)
{ {
@@ -3971,15 +3978,6 @@ function Get-DscResource
{ {
$null = ImportClassResourcesFromModule -Module $mod -Resources * -functionsToDefine $functionsToDefine $null = ImportClassResourcesFromModule -Module $mod -Resources * -functionsToDefine $functionsToDefine
} }
$dscResources = Join-Path -Path $mod.ModuleBase -ChildPath 'DscResources'
if(Test-Path $dscResources)
{
foreach ($resource in Get-ChildItem -Path $dscResources -Directory -Name)
{
$null = ImportCimAndScriptKeywordsFromModule -Module $mod -Resource $resource -functionsToDefine $functionsToDefine
}
}
} }
$Resources = @() $Resources = @()
@@ -4009,28 +4007,20 @@ function Get-DscResource
Write-Progress -Id 3 -Activity $LocalizedData.CreatingResourceList Write-Progress -Id 3 -Activity $LocalizedData.CreatingResourceList
# Get resources for CIM cache # Get resources for CIM cache
$keywords = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::GetCachedKeywords() | Where-Object -FilterScript { $keywords = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::GetKeywordsFromCachedClasses() | Where-Object -FilterScript {
(!$_.IsReservedKeyword) -and ($null -ne $_.ResourceName) -and !(IsHiddenResource $_.ResourceName) -and (![bool]$Module -or ($_.ImplementingModule -like $ModuleString)) (!$_.IsReservedKeyword) -and ($null -ne $_.ResourceName) -and !(IsHiddenResource $_.ResourceName) -and (![bool]$Module -or ($_.ImplementingModule -like $ModuleString))
} }
$dscResourceNames = $keywords.keyword
$Resources += $keywords | $Resources += $keywords |
ForEach-Object -Process { ForEach-Object -Process {
GetResourceFromKeyword -keyword $_ -patterns $patterns -modules $modules GetResourceFromKeyword -keyword $_ -patterns $patterns -modules $modules -dscResourceNames $dscResourceNames
} | } |
Where-Object -FilterScript { Where-Object -FilterScript {
$_ -ne $null $_ -ne $null
} }
# Get composite resources
$Resources += Get-Command -CommandType Configuration |
ForEach-Object -Process {
GetCompositeResource $patterns $_ $ignoreResourceParameters -modules $modules
} |
Where-Object -FilterScript {
$_ -ne $null -and (![bool]$ModuleString -or ($_.Module -like $ModuleString)) -and
($_.Path -and ((Split-Path -Leaf $_.Path) -eq "$($_.Name).schema.psm1"))
}
# check whether all resources are found # check whether all resources are found
CheckResourceFound $Name $Resources CheckResourceFound $Name $Resources
} }
@@ -4039,7 +4029,7 @@ function Get-DscResource
if ($initialized) if ($initialized)
{ {
[System.Management.Automation.Language.DynamicKeyword]::Reset() [System.Management.Automation.Language.DynamicKeyword]::Reset()
[Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ClearCache() [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::ClearCache()
$initialized = $false $initialized = $false
} }
@@ -4067,7 +4057,7 @@ function Get-DscResource
if ($initialized) if ($initialized)
{ {
[System.Management.Automation.Language.DynamicKeyword]::Reset() [System.Management.Automation.Language.DynamicKeyword]::Reset()
[Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ClearCache() [Microsoft.PowerShell.DesiredStateConfiguration.Internal.CrossPlatform.DscClassCache]::ClearCache()
$initialized = $false $initialized = $false
} }
@@ -4088,9 +4078,11 @@ function GetResourceFromKeyword
$patterns, $patterns,
[Parameter(Mandatory)] [Parameter(Mandatory)]
[System.Management.Automation.PSModuleInfo[]] [System.Management.Automation.PSModuleInfo[]]
$modules $modules,
[Parameter(Mandatory)]
[Object[]]
$dscResourceNames
) )
$implementationDetail = 'ScriptBased' $implementationDetail = 'ScriptBased'
# Find whether $name follows the pattern # Find whether $name follows the pattern
@@ -4118,68 +4110,23 @@ function GetResourceFromKeyword
$resource.Name = $keyword.Keyword $resource.Name = $keyword.Keyword
$schemaFiles = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::GetFileDefiningClass($keyword.ResourceName) # only supporting class-based resources at this time
if ($schemaFiles.Count)
{
# Find the correct schema file that matches module name and version
# if same module/version is installed in multiple locations, then pick the first schema file.
foreach ($schemaFileName in $schemaFiles){
$moduleInfo = GetModule $modules $schemaFileName;
if ($moduleInfo.Name -eq $keyword.ImplementingModule -and $moduleInfo.Version -eq $keyword.ImplementingModuleVersion){
break
}
}
# if the class is not a resource we will ignore it except if it is DSC inbox resource.
if(-not $schemaFileName.StartsWith("$env:windir\system32\configuration",[stringComparison]::OrdinalIgnoreCase))
{
$classesFromSchema = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::GetCachedClassByFileName($schemaFileName)
if($null -ne $classesFromSchema)
{
# check if the resource is proper DSC resource that always derives from OMI_BaseResource.
$schemaToProcess = $classesFromSchema | ForEach-Object -Process {
if(($_.CimSystemProperties.ClassName -ieq $keyword.ResourceName) -and ($_.CimSuperClassName -ieq 'OMI_BaseResource'))
{
if ([ExperimentalFeature]::IsEnabled("PSDesiredStateConfiguration.InvokeDscResource"))
{
$_ | Add-Member -MemberType NoteProperty -Name 'ImplementationDetail' -Value $implementationDetail -PassThru
}
else
{
$_
}
}
}
if($null -eq $schemaToProcess)
{
return
}
}
}
$message = $LocalizedData.SchemaFileForResource -f @($schemaFileName)
Write-Verbose -Message $message
$resource.Module = $moduleInfo
$resource.Path = GetImplementingModulePath $schemaFileName
$resource.ParentPath = Split-Path $schemaFileName
}
else
{
$implementationDetail = 'ClassBased' $implementationDetail = 'ClassBased'
$Module = $modules | Where-Object -FilterScript { $Module = $modules | Where-Object -FilterScript {
$_.Name -eq $keyword.ImplementingModule -and $_.Name -eq $keyword.ImplementingModule -and
$_.Version -eq $keyword.ImplementingModuleVersion $_.Version -eq $keyword.ImplementingModuleVersion
} } | Select-Object -First 1
if ($Module -and $Module.ExportedDscResources -contains $keyword.Keyword) if ($Module -and $Module.ExportedDscResources -contains $keyword.Keyword)
{ {
$implementationDetail = 'ClassBased'
$resource.Module = $Module $resource.Module = $Module
$resource.Path = $Module.Path $resource.Path = $Module.Path
$resource.ParentPath = Split-Path -Path $Module.Path $resource.ParentPath = Split-Path -Path $Module.Path
} }
else
{
# a class-based keyword must be in the ExportedDscResources of the module that implements it
return $null
} }
if ([system.string]::IsNullOrEmpty($resource.Path) -eq $false) if ([system.string]::IsNullOrEmpty($resource.Path) -eq $false)
@@ -4199,7 +4146,7 @@ function GetResourceFromKeyword
# add properties # add properties
$keyword.Properties.Values | ForEach-Object -Process { $keyword.Properties.Values | ForEach-Object -Process {
AddDscResourceProperty $resource $_ AddDscResourceProperty $resource $_ $dscResourceNames
} }
# sort properties # sort properties
@@ -4291,7 +4238,9 @@ function AddDscResourceProperty
[Microsoft.PowerShell.DesiredStateConfiguration.DscResourceInfo] [Microsoft.PowerShell.DesiredStateConfiguration.DscResourceInfo]
$dscresource, $dscresource,
[Parameter(Mandatory)] [Parameter(Mandatory)]
$property $property,
[Parameter(Mandatory)]
$dscResourceNames
) )
$convertTypeMap = @{ $convertTypeMap = @{
@@ -4315,6 +4264,11 @@ function AddDscResourceProperty
else else
{ {
$Type = [System.Management.Automation.LanguagePrimitives]::ConvertTypeNameToPSTypeName($property.TypeConstraint) $Type = [System.Management.Automation.LanguagePrimitives]::ConvertTypeNameToPSTypeName($property.TypeConstraint)
if ([string]::IsNullOrEmpty($Type)) {
$dscResourceNames | ForEach-Object -Process {
if (($property.TypeConstraint -eq $_) -or ($property.TypeConstraint -eq ($_ + "[]"))) { $Type = "[$($property.TypeConstraint)]" }
}
}
} }
if ($null -ne $property.ValueMap) if ($null -ne $property.ValueMap)
@@ -4325,7 +4279,6 @@ function AddDscResourceProperty
$dscProperty.Values.Add($_) $dscProperty.Values.Add($_)
} }
} }
$dscProperty.PropertyType = $Type $dscProperty.PropertyType = $Type
$dscProperty.IsMandatory = $property.Mandatory $dscProperty.IsMandatory = $property.Mandatory
@@ -4445,13 +4398,13 @@ function GetImplementingModulePath
$schemaFileName $schemaFileName
) )
$moduleFileName = ($schemaFileName -replace ".schema.mof$", '') + '.psd1' $moduleFileName = ($schemaFileName -replace ".schema.json$", '') + '.psd1'
if (Test-Path $moduleFileName) if (Test-Path $moduleFileName)
{ {
return $moduleFileName return $moduleFileName
} }
$moduleFileName = ($schemaFileName -replace ".schema.mof$", '') + '.psm1' $moduleFileName = ($schemaFileName -replace ".schema.json$", '') + '.psm1'
if (Test-Path $moduleFileName) if (Test-Path $moduleFileName)
{ {
return $moduleFileName return $moduleFileName
@@ -4481,9 +4434,9 @@ function GetModule
} }
$schemaFileExt = $null $schemaFileExt = $null
if ($schemaFileName -match '.schema.mof') if ($schemaFileName -match '.schema.json')
{ {
$schemaFileExt = ".schema.mof$" $schemaFileExt = ".schema.json$"
} }
if ($schemaFileName -match '.schema.psm1') if ($schemaFileName -match '.schema.psm1')
@@ -4692,10 +4645,6 @@ function Invoke-DscResource
ThrowError -ExceptionName 'System.ArgumentException' -ExceptionMessage $errorMessage -ExceptionObject $exception -ErrorId 'InvalidResourceSpecification,Invoke-DscResource' -ErrorCategory InvalidArgument ThrowError -ExceptionName 'System.ArgumentException' -ExceptionMessage $errorMessage -ExceptionObject $exception -ErrorId 'InvalidResourceSpecification,Invoke-DscResource' -ErrorCategory InvalidArgument
} }
if ( @($resource.Properties | Where-Object { $_.PropertyType -eq '' }).Count -gt 0 -and ($IsMacOS -or $IsLinux)) {
Write-Warning -Message $LocalizedData.EmbeddedResourcesNotSupported
}
[Microsoft.PowerShell.DesiredStateConfiguration.DscResourceInfo] $resource = $resource[0] [Microsoft.PowerShell.DesiredStateConfiguration.DscResourceInfo] $resource = $resource[0]
if($resource.ImplementedAs -ne 'PowerShell') if($resource.ImplementedAs -ne 'PowerShell')
{ {
@@ -4747,29 +4696,29 @@ function Invoke-DscClassBasedResource
Write-Debug "Importing $path ..." Write-Debug "Importing $path ..."
$iss = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault2() $iss = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault2()
# next line prevents PSModulePath from being reset to default
$iss.EnvironmentVariables.Add([System.Management.Automation.Runspaces.SessionStateVariableEntry]::new("PSModulePath", $env:PSModulePath, $null))
$powershell = [PowerShell]::Create($iss) $powershell = [PowerShell]::Create($iss)
$script = @" $script = @"
using module $path using module $path
return [$type]
Write-Host -Message ([$type]::new | out-string)
return [$type]::new()
"@ "@
$null = $powershell.AddScript($script) $null = $powershell.AddScript($script)
$dscType = $powershell.Invoke() | Select-object -First 1 $dscType = $powershell.Invoke() | Select-object -First 1
Write-Debug "Imported Type: $($dscType | Out-String)"
$dscObj = $dscType::new()
foreach($key in $Property.Keys) foreach($key in $Property.Keys)
{ {
$value = $Property.$key $value = $Property.$key
Write-Debug "Setting $key to $value" Write-Debug "Setting $key to $value"
$dscType.$key = $value $dscObj.$key = $value
} }
$info = $dscType | Out-String Write-Debug "Object with filled keys: $($dscObj | Out-String)"
Write-Debug $info
Write-Debug "calling $type.$Method() ..." Write-Debug "Calling $type.$Method() ..."
$global:DSCMachineStatus = $null $global:DSCMachineStatus = $null
$output = $dscType.$Method() $output = $dscObj.$Method()
return Get-InvokeDscResourceResult -Output $output -Method $Method return Get-InvokeDscResourceResult -Output $output -Method $Method
} }
@@ -4834,6 +4783,7 @@ function Get-InvokeDscResourceResult
Export-ModuleMember -Function @( Export-ModuleMember -Function @(
'Invoke-DscResource' 'Invoke-DscResource'
'ConvertTo-DscJsonSchema'
) )
########################################################### ###########################################################
+25 -14
View File
@@ -429,25 +429,37 @@ Describe "Test PSDesiredStateConfiguration" -tags CI {
Should -Throw -ErrorId 'InvalidResourceSpecification,Invoke-DscResource' -ExpectedMessage 'Invalid Resource Name ''Script'' or module specification.' Should -Throw -ErrorId 'InvalidResourceSpecification,Invoke-DscResource' -ExpectedMessage 'Invalid Resource Name ''Script'' or module specification.'
} }
it "Resource with embedded resource not supported and a warning should be produced" { it "Test an embedded DSC resource" {
if (!(Test-IsInvokeDscResourceEnable)) { if (!(Test-IsInvokeDscResourceEnable)) {
Set-ItResult -Skipped -Because "Feature not enabled" Set-ItResult -Skipped -Because "Feature not enabled"
} }
if (!$IsMacOS) { $resourceName="TestRes"
Set-ItResult -Skipped -Because "Not applicable on Windows and xWebAdministration resources don't load on linux" $moduleName="TestEmbeddedDSCResource"
} $embObj = @(New-Object -TypeName psobject -Property @{embclassprop="property1"})
try { Install-ModuleIfMissing -Name $moduleName -Force
Invoke-DscResource -Name xWebSite -ModuleName 'xWebAdministration' -Method Test -Property @{TestScript = 'foobar' } -ErrorAction Stop -WarningVariable warnings
}
catch{
#this will fail too, but that is nat what we are testing...
}
$warnings.Count | Should -Be 1 -because "There should be 1 warning on macOS and Linux" $resource = Get-DscResource -Name $resourceName -Module $moduleName -ErrorAction Stop
$warnings[0] | Should -Match 'embedded resources.*not support' $resource | Should -Not -BeNullOrEmpty
$resource.Name | Should -Be $resourceName
$methodName="Test"
$result = Invoke-DscResource -Name $resourceName -ModuleName $moduleName -Method $methodName -Property @{embclassobj=$embObj;propName="property1"}
$result.InDesiredState | Should -BeTrue
$result = Invoke-DscResource -Name $resourceName -ModuleName $moduleName -Method $methodName -Property @{embclassobj=$embObj;propName="property2"}
$result.InDesiredState | Should -BeFalse
$methodName="Get"
$result = Invoke-DscResource -Name $resourceName -ModuleName $moduleName -Method $methodName -Property @{embclassobj=$embObj;propName="property1"}
$result.propName | Should -Be "property1"
$result = Invoke-DscResource -Name $resourceName -ModuleName $moduleName -Method $methodName -Property @{embclassobj=$embObj;propName="property2"}
$result.propName | Should -Not -Be "property1"
$methodName="Set"
$result = Invoke-DscResource -Name $resourceName -ModuleName $moduleName -Method $methodName -Property @{embclassobj=$embObj;propName="property1"}
$result | Should -Not -BeNullOrEmpty
$result.RebootRequired | Should -BeFalse
} }
it "Using PsDscRunAsCredential should say not supported" -Skip:(!(Test-IsInvokeDscResourceEnable)) { it "Using PsDscRunAsCredential should say not supported" -Skip:(!(Test-IsInvokeDscResourceEnable)) {
@@ -533,4 +545,3 @@ Describe "Test PSDesiredStateConfiguration" -tags CI {
} }
} }
} }