[ResourceBase]: Add Microsoft DSC support - #54
Conversation
WalkthroughResourceBase now supports typed test and set results, what-if prediction, deletion, export, existence tracking, and runtime JSON schema generation. Unit and integration tests cover these operations through a new in-memory DSC resource fixture. ChangesResourceBase DSC support
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant DSCAdapter
participant DscBaseTestResource
participant ResourceBase
participant InMemoryStore
DSCAdapter->>DscBaseTestResource: Invoke DSC operation
DscBaseTestResource->>ResourceBase: Call lifecycle helper
ResourceBase->>InMemoryStore: Read or update state
ResourceBase-->>DscBaseTestResource: Return typed result
DscBaseTestResource-->>DSCAdapter: Return operation response
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@gaelcolas - after trying out v0.119.1 of Sampler locally, the build succeeded. Looks like there have been some breaking changes from v0.120.0 onwards? |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (10)
tests/Unit/Private/New-DscResultTuple.Tests.ps1 (1)
105-112: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert against the localized string.
The test hardcodes the English error text. Build the expected message from
$script:localizedDataso a change of the string does not silently break the intent of the test.♻️ Proposed change
Context 'When the number of types does not match the number of values' { It 'Should throw the correct error' { InModuleScope -ScriptBlock { - { New-DscResultTuple -Type @([System.String]) -Value @('MyValue', 'MySecondValue') } | - Should -Throw -ExpectedMessage '*does not match the number of values*' + Set-StrictMode -Version 1.0 + + $mockExpectedMessage = $script:localizedData.NewDscResultTuple_CountMismatch -f 1, 2 + + { New-DscResultTuple -Type @([System.String]) -Value @('MyValue', 'MySecondValue') } | + Should -Throw -ExpectedMessage ('*{0}*' -f $mockExpectedMessage) } } }As per path instructions: "Test with localized strings: Use
InModuleScope -ScriptBlock { $script:localizedData.Key }".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Unit/Private/New-DscResultTuple.Tests.ps1` around lines 105 - 112, Update the “When the number of types does not match the number of values” test for New-DscResultTuple to obtain the expected message from $script:localizedData inside InModuleScope, then assert the thrown error against that localized value instead of hardcoding English text.Source: Path instructions
tests/Integration/ResourceBase.Integration.Tests.ps1 (2)
199-200: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse one
Describeblock per file.The file now contains two
Describeblocks. Move thedsc.exetests into aContextblock insideDescribe 'ResourceBase'and keep the tag and the skip condition on thatContext.♻️ Proposed structure change
-Describe 'ResourceBase with dsc.exe' -Tag 'RequiresDsc' -Skip:$script:skipDscExe { - Context 'When invoking operations through the DSC PowerShell adapter' { + Context 'When invoking operations through the DSC PowerShell adapter' -Tag 'RequiresDsc' -Skip:$script:skipDscExe {As per path instructions: "One
Describeblock per file matching the tested entity name".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Integration/ResourceBase.Integration.Tests.ps1` around lines 199 - 200, Consolidate the dsc.exe test suite into the existing Describe 'ResourceBase' block instead of declaring a second Describe. Wrap these tests in a Context that retains the RequiresDsc tag and skip:$script:skipDscExe condition, while preserving the existing test behavior.Source: Path instructions
96-166: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNote the order dependency between the contexts.
The
Export(),Set(), andDelete()contexts share one in-memory store. TheExport()test expects two instances, and theDelete()test removesInstance1. A change of test order, or execution of a singleContext, then fails. Reset the fixture state in aBeforeEachorBeforeAllblock perContextto make each context independent.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Integration/ResourceBase.Integration.Tests.ps1` around lines 96 - 166, Reset the shared in-memory fixture before each relevant context so the tests under Export(), Set(), and Delete() start from the expected initial state independently. Add the setup to the appropriate BeforeEach or BeforeAll blocks, using the existing fixture initialization mechanism, while preserving each context’s current assertions and behavior.source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1 (1)
1-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing
.INPUTSsection in the comment-based help of the new private functions. All three new functions declare.OUTPUTSbut omit.INPUTS. None of them accept pipeline input, so each help block must declareNone..
source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1#L1-L22: add an.INPUTSsection withNone.before.OUTPUTS.source/Private/ConvertTo-DscResourceJsonSchema.ps1#L1-L22: add an.INPUTSsection withNone.before.OUTPUTS.source/Private/New-DscResultTuple.ps1#L1-L39: add an.INPUTSsection withNone.before.OUTPUTS.As per path instructions: "INPUTS: List each pipeline‑accepted type as inline code with a 1‑line description. ... If there are no inputs, specify
None.."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1` around lines 1 - 22, Update the comment-based help for ConvertTo-JsonSchemaTypeDefinition in source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1#L1-L22, ConvertTo-DscResourceJsonSchema in source/Private/ConvertTo-DscResourceJsonSchema.ps1#L1-L22, and New-DscResultTuple in source/Private/New-DscResultTuple.ps1#L1-L39 by adding an .INPUTS section containing None. immediately before each .OUTPUTS section.Source: Path instructions
source/Private/New-DscResultTuple.ps1 (1)
57-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
$PSCmdlet.ThrowTerminatingError()instead ofthrow.The guidelines require terminating errors from functions to use
$PSCmdlet.ThrowTerminatingError()withNew-ErrorRecordandNew-Exception. Also check the localized key name against the patternVerb_FunctionName_Action;NewDscResultTuple_CountMismatchmisses the separator after the verb.♻️ Proposed error handling change
if ($Type.Count -ne $Value.Count) { - throw ($script:localizedData.NewDscResultTuple_CountMismatch -f $Type.Count, $Value.Count) + $errorMessage = $script:localizedData.New_DscResultTuple_CountMismatch -f $Type.Count, $Value.Count + + $PSCmdlet.ThrowTerminatingError( + (New-ErrorRecord -Message $errorMessage -ErrorId 'NDRT0001' -ErrorCategory 'InvalidArgument' -TargetObject $Type) + ) }If you rename the key, update
source/en-US/DscResource.Base.strings.psd1and the assertion intests/Unit/Private/New-DscResultTuple.Tests.ps1.As per path instructions: "Use
$PSCmdlet.ThrowTerminatingError()for terminating errors (except for classes), use relevant error category, in try-catch include exception with localized message" and "Format:Verb_FunctionName_Action(underscore separators)".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@source/Private/New-DscResultTuple.ps1` around lines 57 - 60, Replace the direct throw in New-DscResultTuple with $PSCmdlet.ThrowTerminatingError(), constructing the error through New-Exception and New-ErrorRecord with the appropriate error category. Rename the localized key to follow the Verb_FunctionName_Action pattern, then update its definition in DscResource.Base.strings.psd1 and the corresponding assertion in New-DscResultTuple.Tests.ps1.Source: Path instructions
tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1 (1)
120-234: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winGroup the
Itblocks inContextblocks.All
Itblocks sit directly underDescribe. AddContextblocks per scenario, for example aContext 'When converting a class-based DSC resource type'block that wraps the schema document tests, and separateContextblocks for the property conversion scenarios.As per path instructions: "Each scenario = separate
Contextblock" and "Contextdescriptions start with 'When'".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1` around lines 120 - 234, Group the direct child tests in the ConvertTo-DscResourceJsonSchema Describe block into separate Context blocks, with each scenario in its own Context and every Context description starting with “When”. Use a class-based resource Context for the schema document keyword tests and separate “When” Contexts for each property conversion, inheritance, exclusion, and description scenario; keep the existing It assertions unchanged.Source: Path instructions
tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1 (1)
60-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing
Set-StrictMode -Version 1.0in the newInModuleScopeunit tests. All three new unit test files call the private function insideInModuleScopewithout strict mode. Add the statement immediately before each invocation.
tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1#L60-L64: addSet-StrictMode -Version 1.0before eachConvertTo-JsonSchemaTypeDefinitioncall in everyInModuleScopeblock.tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1#L121-L125: addSet-StrictMode -Version 1.0before eachConvertTo-DscResourceJsonSchemacall in everyInModuleScopeblock.tests/Unit/Private/New-DscResultTuple.Tests.ps1#L48-L59: addSet-StrictMode -Version 1.0before eachNew-DscResultTuplecall in everyInModuleScopeblock.As per path instructions: "In
InModuleScopetests, addSet-StrictMode -Version 1.0immediately before invoking the tested function".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1` around lines 60 - 64, All new InModuleScope unit tests must enable strict mode immediately before invoking the tested private function. In tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1 lines 60-64, add Set-StrictMode -Version 1.0 before every ConvertTo-JsonSchemaTypeDefinition call; apply the same change before every ConvertTo-DscResourceJsonSchema call in tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1 lines 121-125 and every New-DscResultTuple call in tests/Unit/Private/New-DscResultTuple.Tests.ps1 lines 48-59.Source: Path instructions
source/Classes/010.ResourceBase.ps1 (1)
356-359: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winNew
ResourceBasemethods usethrowfor terminating errors. The class guidelines requireNew-*Exceptioncommands for terminating errors in classes. Both new methods raise errors withthrow.
source/Classes/010.ResourceBase.ps1#L356-L359: replacethrowinDeleteInstance()withNew-InvalidOperationException(orNew-NotImplementedException) using the localizedDeleteInstanceNotSupportedmessage.source/Classes/010.ResourceBase.ps1#L375-L378: replacethrowinExportInstances()withNew-NotImplementedExceptionusing the localizedExportInstancesMethodNotImplementedmessage.As per coding guidelines: "Do not use
throwfor terminating errors, useNew-*Exceptioncommands (never for functions)".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@source/Classes/010.ResourceBase.ps1` around lines 356 - 359, Replace the terminating throw in ResourceBase.DeleteInstance() at source/Classes/010.ResourceBase.ps1:356-359 with New-InvalidOperationException or New-NotImplementedException, preserving the localized DeleteInstanceNotSupported message. Also replace the terminating throw in ResourceBase.ExportInstances() at source/Classes/010.ResourceBase.ps1:375-378 with New-NotImplementedException using the localized ExportInstancesMethodNotImplemented message.Source: Path instructions
tests/Unit/Classes/ResourceBase.Tests.ps1 (2)
1786-1811: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winWrap the
Itblocks in aContextblock.The
Itblocks sit directly in theDescribeblock. The tests guidelines require a separateContextblock per scenario, and the description must start with 'When'. TheGetInstanceJsonSchema()Describeat Lines 2116-2149 has the same structure.As per coding guidelines: "Each scenario = separate
Contextblock" and "Contextdescriptions start with 'When'".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Unit/Classes/ResourceBase.Tests.ps1` around lines 1786 - 1811, Wrap the three `It` blocks testing `GetPredictedState` in a dedicated `Context` whose description starts with “When”, keeping each assertion-focused test within that context. Apply the same structure to the `GetInstanceJsonSchema()` `Describe` block, using a separate “When” context for its scenario tests.Source: Path instructions
1969-1973: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAssert against the localized strings.
Both assertions use hardcoded message fragments. Read the message through
$script:localizedDataso a message change does not silently break the intent of the test.As per coding guidelines: "Test with localized strings: Use
InModuleScope -ScriptBlock { $script:localizedData.Key }".Also applies to: 1992-1994
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/Unit/Classes/ResourceBase.Tests.ps1` around lines 1969 - 1973, Update the error assertions in the tests around DeleteInstance and the additional assertion near the referenced range to use the expected message fragments from $script:localizedData inside InModuleScope, rather than hardcoded localized text. Preserve the existing wildcard matching and exception behavior while referencing the appropriate localization keys.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@source/en-US/ResourceBase.strings.psd1`:
- Line 18: Update the DeleteInstanceNotSupported resource string to state that
delete is unsupported when the resource lacks both the _exist and Ensure
properties, while preserving the existing DeleteInstance() override guidance and
error code.
In `@source/Private/New-DscResultTuple.ps1`:
- Around line 62-64: Add an arity validation guard before constructing
$closedTupleType in New-DscResultTuple, rejecting $Type.Count values above 8
with the existing localized count-mismatch/validation error. Preserve the
current generic tuple creation flow for supported arities from 1 through 8.
In `@tests/Integration/ResourceBase.Integration.Tests.ps1`:
- Around line 29-35: Update the PSModulePath setup near $script:fixturePath to
also prepend the built module’s output\RequiredModules directory before
importing DscResourceBaseTestResource. Preserve the existing Fixtures path and
ordering, and ensure both paths are included in $env:PSModulePath for child
processes such as dsc.exe.
In `@tests/Unit/Classes/ResourceBase.Tests.ps1`:
- Around line 2116-2122: Update the test for
$mockResourceBaseType::InstanceJsonSchema() to invoke ConvertFrom-Json directly
with -ErrorAction 'Stop', removing the surrounding Should -Not -Throw assertion
while retaining validation of the returned JSON.
---
Nitpick comments:
In `@source/Classes/010.ResourceBase.ps1`:
- Around line 356-359: Replace the terminating throw in
ResourceBase.DeleteInstance() at source/Classes/010.ResourceBase.ps1:356-359
with New-InvalidOperationException or New-NotImplementedException, preserving
the localized DeleteInstanceNotSupported message. Also replace the terminating
throw in ResourceBase.ExportInstances() at
source/Classes/010.ResourceBase.ps1:375-378 with New-NotImplementedException
using the localized ExportInstancesMethodNotImplemented message.
In `@source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1`:
- Around line 1-22: Update the comment-based help for
ConvertTo-JsonSchemaTypeDefinition in
source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1#L1-L22,
ConvertTo-DscResourceJsonSchema in
source/Private/ConvertTo-DscResourceJsonSchema.ps1#L1-L22, and
New-DscResultTuple in source/Private/New-DscResultTuple.ps1#L1-L39 by adding an
.INPUTS section containing None. immediately before each .OUTPUTS section.
In `@source/Private/New-DscResultTuple.ps1`:
- Around line 57-60: Replace the direct throw in New-DscResultTuple with
$PSCmdlet.ThrowTerminatingError(), constructing the error through New-Exception
and New-ErrorRecord with the appropriate error category. Rename the localized
key to follow the Verb_FunctionName_Action pattern, then update its definition
in DscResource.Base.strings.psd1 and the corresponding assertion in
New-DscResultTuple.Tests.ps1.
In `@tests/Integration/ResourceBase.Integration.Tests.ps1`:
- Around line 199-200: Consolidate the dsc.exe test suite into the existing
Describe 'ResourceBase' block instead of declaring a second Describe. Wrap these
tests in a Context that retains the RequiresDsc tag and skip:$script:skipDscExe
condition, while preserving the existing test behavior.
- Around line 96-166: Reset the shared in-memory fixture before each relevant
context so the tests under Export(), Set(), and Delete() start from the expected
initial state independently. Add the setup to the appropriate BeforeEach or
BeforeAll blocks, using the existing fixture initialization mechanism, while
preserving each context’s current assertions and behavior.
In `@tests/Unit/Classes/ResourceBase.Tests.ps1`:
- Around line 1786-1811: Wrap the three `It` blocks testing `GetPredictedState`
in a dedicated `Context` whose description starts with “When”, keeping each
assertion-focused test within that context. Apply the same structure to the
`GetInstanceJsonSchema()` `Describe` block, using a separate “When” context for
its scenario tests.
- Around line 1969-1973: Update the error assertions in the tests around
DeleteInstance and the additional assertion near the referenced range to use the
expected message fragments from $script:localizedData inside InModuleScope,
rather than hardcoded localized text. Preserve the existing wildcard matching
and exception behavior while referencing the appropriate localization keys.
In `@tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1`:
- Around line 120-234: Group the direct child tests in the
ConvertTo-DscResourceJsonSchema Describe block into separate Context blocks,
with each scenario in its own Context and every Context description starting
with “When”. Use a class-based resource Context for the schema document keyword
tests and separate “When” Contexts for each property conversion, inheritance,
exclusion, and description scenario; keep the existing It assertions unchanged.
In `@tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1`:
- Around line 60-64: All new InModuleScope unit tests must enable strict mode
immediately before invoking the tested private function. In
tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1 lines 60-64, add
Set-StrictMode -Version 1.0 before every ConvertTo-JsonSchemaTypeDefinition
call; apply the same change before every ConvertTo-DscResourceJsonSchema call in
tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1 lines 121-125 and
every New-DscResultTuple call in tests/Unit/Private/New-DscResultTuple.Tests.ps1
lines 48-59.
In `@tests/Unit/Private/New-DscResultTuple.Tests.ps1`:
- Around line 105-112: Update the “When the number of types does not match the
number of values” test for New-DscResultTuple to obtain the expected message
from $script:localizedData inside InModuleScope, then assert the thrown error
against that localized value instead of hardcoding English text.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3f2f5c96-0497-4c8c-9d56-3931cf453935
📒 Files selected for processing (15)
CHANGELOG.mdsource/Classes/010.ResourceBase.ps1source/Private/ConvertTo-DscResourceJsonSchema.ps1source/Private/ConvertTo-JsonSchemaTypeDefinition.ps1source/Private/New-DscResultTuple.ps1source/en-US/DscResource.Base.strings.psd1source/en-US/ResourceBase.strings.psd1tests/Integration/Fixtures/DscResourceBaseTestResource/DscResourceBaseTestResource.psd1tests/Integration/Fixtures/DscResourceBaseTestResource/DscResourceBaseTestResource.psm1tests/Integration/Fixtures/DscResourceBaseTestResource/en-US/DscBaseTestResource.strings.psd1tests/Integration/ResourceBase.Integration.Tests.ps1tests/Unit/Classes/ResourceBase.Tests.ps1tests/Unit/Private/ConvertTo-DscResourceJsonSchema.Tests.ps1tests/Unit/Private/ConvertTo-JsonSchemaTypeDefinition.Tests.ps1tests/Unit/Private/New-DscResultTuple.Tests.ps1
| $openTupleType = [System.Type] ('System.Tuple`{0}' -f $Type.Count) | ||
|
|
||
| $closedTupleType = $openTupleType.MakeGenericType($Type) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Does casting the string "System.Tuple2" to [System.Type] in PowerShell resolve the open generic type, and what arities does System.Tuple define?`
💡 Result:
Casting a string like "System.Tuple2" to [System.Type] in PowerShell does not resolve it into a fully constructed (closed) generic type, but rather provides a reference to the open generic type definition [1]. In PowerShell, an open generic type requires the use of the.MakeGenericType method to bind specific type arguments and create a usable, closed type [2][1]. Alternatively, you can use the syntax [System.Tuple[type1, type2]] to directly specify the closed type, provided the syntax is supported by your version of PowerShell [2][3][4]. Regarding arities, the System.Tuple class defines support for tuples ranging from 1 to 8 elements (octuples) [5]. Specifically, the.NET Framework provides the following generic classes: - System.Tuple<T1> (1-tuple) - System.Tuple<T1, T2> (2-tuple) - System.Tuple<T1, T2, T3> (3-tuple) - System.Tuple<T1, T2, T3, T4> (4-tuple) - System.Tuple<T1, T2, T3, T4, T5> (5-tuple) - System.Tuple<T1, T2, T3, T4, T5, T6> (6-tuple) - System.Tuple<T1, T2, T3, T4, T5, T6, T7> (7-tuple) - System.Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> (8 or more elements) [5][6] To create tuples with nine or more components, you use the 8-arity version (System.Tuple8) and nest additional System.Tuple objects within the Rest property [5][6].
Citations:
- 1: https://www.leeholmes.com/creating-generic-types-in-powershell/
- 2: Typename does not parse: [system.tuple[string[],string[]]] PowerShell/PowerShell#9639
- 3: https://wiki.hoelee.com/content/stackoverflow.com_en_all_2023-11/questions/73119025/tuple-nuances-in-powershell
- 4: https://stackoverflow.com/questions/73119025/tuple-nuances-in-powershell
- 5: https://learn.microsoft.com/en-us/dotnet/api/system.tuple?view=net-10.0
- 6: https://learn.microsoft.com/en-us/dotnet/api/system.tuple-8?view=net-9.0
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'Files matching New-DscResultTuple:\n'
fd -a 'New-DscResultTuple\.ps1$' . || true
file="$(fd 'New-DscResultTuple\.ps1$' . | head -n 1)"
if [ -n "${file:-}" ]; then
printf '\nOutline:\n'
ast-grep outline "$file" || true
printf '\nRelevant content:\n'
cat -n "$file"
fi
printf '\nSearch for New-DscResultTuple usages:\n'
rg -n "New-DscResultTuple|DscResultTuple|Get-DscResultTuple|Set-DscResultTuple|Test-DscResultTuple" . -g '*.ps1' -g '*.psm1' || trueRepository: dsccommunity/DscResource.Base
Length of output: 5312
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf 'PowerShell/System.Tuple arity probe:\n'
which pwsh || true
if command -v pwsh >/dev/null 2>&1; then
pwsh -NoProfile -Command '
try {
$openTupleType = [System.Type] ("System.Tuple`{0}" -f 9)
$closedTupleType = $openTupleType.MakeGenericType([string], [int], [bool], [object], [object], [object], [object], [object], [object])
"closed9=$closedTupleType"
} catch {
"closed9_error=$($_.Exception.GetType().FullName): $($_.TargetObject.ToString() -join `"")"
}
try {
$openTupleType = [System.Type] ("System.Tuple`{0}" -f 8)
$closedTupleType = $openTupleType.MakeGenericType([string], [int], [bool], [object], [object], [object], [object], [object])
"closed8=$closedTupleType"
} catch {
"closed8_error=$($_.Exception.GetType().FullName): $($_.TargetObject.ToString() -join `"")"
}
try {
$openTupleType = [System.Type] ("System.Tuple`{0}" -f 1)
$closedTupleType = $openTupleType.MakeGenericType([string])
"closed1=$closedTupleType"
} catch {
"closed1_error=$($_.Exception.GetType().FullName): $($_.TargetObject.ToString() -join `"`")"
}
'
else
printf 'pwsh not available in environment.\n'
fi
printf '\nLocalized string key exists check:\n'
rg -n "NewDscResultTuple_|New-DscResultTuple" source/en-US source/ -g '*.strings.psd1' -g '*.ps1' || trueRepository: dsccommunity/DscResource.Base
Length of output: 978
🏁 Script executed:
#!/bin/bash
set -u
printf 'PowerShell/System.Tuple arity and error-name probe:\n'
which pwsh || true
if command -v pwsh >/dev/null 2>&1; then
pwsh -NoProfile -Command '
function TryTuple($arity) {
$name = ("System.Tuple`{0}" -f $arity)
Write-Verbose ("Name={0}" -f $name)
$openTupleType = [System.Type] $name
$types = 1..$arity | ForEach-Object { [string] }
$closedTupleType = $openTupleType.MakeGenericType($types)
return $closedTupleType.FullName
}
foreach ($arity in @(1,2,8,9)) {
try {
$result = TryTuple $arity -ErrorAction Stop
Write-Host "$arity=OK $result"
} catch {
$ex = $_.Exception
$tr = $_.TargetObject
$trStr = if ($tr -gt 0 -and $tr -lt 256) { $tr.ToString("X63") } else { "" }
Write-Host "$arity=ERROR $($ex.GetType().FullName) $ex.Message TargetId=$trStr"
}
}
' -ErrorAction Stop
else
printf 'pwsh not available in environment.\n'
fi
printf '\nLocalized string key exists check:\n'
rg -n "NewDscResultTuple_|New-DscResultTuple" source/en-US source/tests -g '*.strings.psd1' -g '*.ps1' || true
printf '\nCall sites with arity literals:\n'
ruby -e 'STDIN.read.scan(/\[New-DscResultTuple -Type\s+@?\(?\s*\[([^,\]]+)\s*(?:,[^,\]]+)+\s*([^\)]+)\s*]/m) { |types,l| puts "TYPES=#{types.count + 1}" }' <<'PS' > /tmp/dsc_call_extraction.txt 2>/tmp/dsc_call_extraction.err || true
cat /tmp/dsc_call_extraction.txt 2>/dev/null || true
cat /tmp/dsc_call_extraction.err >/dev/null 2>&1 || true
rg -n "New-DscResultTuple\s+-Type" source tests -g '*.ps1' -g '*.psm1' || trueRepository: dsccommunity/DscResource.Base
Length of output: 6279
🏁 Script executed:
#!/usr/bin/env bash
set -u
printf 'PowerShell/System.Tuple arity probe (robust):\n'
command -v pwsh >/dev/null 2>&1 && {
pwsh -NoProfile -Command '
function TryTuple($arity) {
$name = ("System.Tuple`{0}" -f $arity)
try {
$openTupleType = $null
$openTupleType = [System.Type] $name
$types = 1..$arity | ForEach-Object { [string] }
$closedTupleType = $openTupleType.MakeGenericType($types)
return ("OK:{0}" -f $closedTupleType.FullName)
} catch {
$msg = $_.Exception.Message.Insert(0, "{0}:" -f $arity)
return "FAIL:$msg"
}
}
1, 2, 8, 9 | ForEach-Object { TryTuple $_ }
'
} || printf 'pwsh not available\n'
printf '\nFile and localized key context:\n'
for f in $(fd 'New-DscResultTuple\.ps1$|DscResource\.Base\.strings\.psd1$' .); do
printf '\n--- %s ---\n' "$f"
wc -l "$f"
rg -n "New-DscResultTuple|Tuples are invariant|Arity|tuple" "$f" || true
done
rg -n "New-DscResultTuple\s+-Type" . -g '*.ps1' -g '*.psm1' || trueRepository: dsccommunity/DscResource.Base
Length of output: 3620
Add a tuple arity limit guard.
System.Tuple supports 1 to 8 elements. If $Type has more than 8 types, MakeGenericType() returns null and CreateInstance() then throws an unclear error. Emit the localized count-mismatch/validation error for this case instead of throwing the .NET reflection error.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@source/Private/New-DscResultTuple.ps1` around lines 62 - 64, Add an arity
validation guard before constructing $closedTupleType in New-DscResultTuple,
rejecting $Type.Count values above 8 with the existing localized
count-mismatch/validation error. Preserve the current generic tuple creation
flow for supported arities from 1 through 8.
johlju
left a comment
There was a problem hiding this comment.
this doesn't look like it would break existing functionality. Just a small comment.
| $openTupleType = [System.Type] ('System.Tuple`{0}' -f $Type.Count) | ||
|
|
||
| $closedTupleType = $openTupleType.MakeGenericType($Type) |
|
Not sure why the build breaks, something change in new Sampler release maybe? |
Pull Request (PR) description
Adds DSC v3 (Microsoft DSC) support to
ResourceBase. New hidden helpermethods (
GetTestResult(),GetSetResult(),DeleteInstance(),ExportInstances(),GetInstanceJsonSchema()) let a derived classparticipate in Microsoft DSC semantics by declaring one-liner static methods.
These are added as per the resource contract RFC while remaining compatible with PSDSC v1/v2.
This Pull Request (PR) fixes the following issues
n/a
Task list
file CHANGELOG.md. Entry should say what was changed and how that
affects users (if applicable), and reference the issue being resolved
(if applicable).
DSC Community Testing Guidelines.
This change is