Added support for Windows RSAT Modules#136
Open
justinainsworth wants to merge 8 commits into
Open
Conversation
Member
|
Hey @justinainsworth I'm not opposed to this. Let me know if you're still interested in a review. If not (or I don't hear from you by next Fri), we'll close this out and try again a later. |
The original PR contained two typos in WindowsFeature names that would cause Install-WindowsFeature to fail on Windows Server: - 'BitLocket' -> 'BitLocker' in RSAT-Feature-Tools-BitLocker-RemoteAdminTool - 'Huper-V' -> 'Hyper-V' in RSAT-Hyper-V-Tools Verified against Windows Server 2022 catalog via Get-WindowsFeature. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The mapping pointed to 'RSAT', the umbrella Remote Server Administration
Tools feature. Installing it pulls in every RSAT sub-feature on Server,
not just Group Policy management. The targeted feature is GPMC
("Group Policy Management"), which installs the GroupPolicy module
without the rest of RSAT.
Verified against Windows Server 2022 catalog via Get-WindowsFeature.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The BitsTransfer module ships in-box on both Windows Server and Windows client; no RSAT install is required for its cmdlets. The mapping pointed to 'RSAT-Bits-Server' (BITS Server Extensions Tools), which manages remote BITS server endpoints rather than the BitsTransfer cmdlets. With the in-box module present, the Get-Module -ListAvailable check at the top of the script short-circuits before reaching the install branch, so the mapping was both wrong and effectively dead code. No Rsat.Bits.* capability (Win 11) or RSAT-BitsTransfer-* feature (Server 2022) exists to map this to, so removing the entry. Verified against Server 2022 catalog and Win 11 capability list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Moves the inline WindowsPrincipal/WindowsBuiltInRole.Administrator check
into PSDepend/Private/Test-Administrator.ps1. The module loader already
dot-sources everything under Private/ (see PSDepend.psm1), so the helper
becomes a module-scope function alongside the existing 20 private helpers.
This makes the Install branch's admin guard mockable from Pester via
InModuleScope PSDepend { Mock Test-Administrator }, so the dispatch
tests in the upcoming test file run on any developer machine regardless
of elevation rather than skipping on non-admin hosts.
No behavior change: the helper performs the same check as the inline
expression it replaces.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The original guard used $RSAT_MODULE_MAP[$ModuleName][$Type] to detect an unknown module and relied on the chain returning $null. Under PowerShell strict mode (Set-StrictMode -Version 2+), indexing into a $null array throws "Cannot index into a null array" before the explicit throw is reached -- making the "Unknown Module" error unreachable whenever the module name was missing from the map entirely. Adds a ContainsKey guard before the index chain so the explicit error message is reached under strict and non-strict modes alike. Surfaced by the new "Throws when the module name is not in the mapping table" test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds Tests/WindowsRSAT.Type.Tests.ps1 with 12 tests covering: - Test-only action: returns $false when missing, $true when available - Install on Server (ProductType=3): dispatches to Install-WindowsFeature with the correct mapped name for ActiveDirectory (baseline) plus BitLocker, Hyper-V, and GroupPolicy/GPMC (the three Server-side fixes from the preceding commits) - Install on Workstation (ProductType=1): dispatches to Add-WindowsCapability with the correct mapped name - Unknown module name throws "Unknown Module" - Install gated by admin check: Test-Administrator -> $false throws - Test, Install short-circuits when the module is already available Test-PSDependTypeSupportedHere skips the entire Describe on non-Windows. The script's admin check is mocked via Test-Administrator (extracted in the preceding refactor commit) so all 12 tests run regardless of the test runner's elevation status. Install-WindowsFeature ships only on Windows Server (ServerManager module). The BeforeAll injects stub functions into the PSDepend module scope when the real cmdlets are missing, so Pester's Mock has a command to attach to on hosts that don't ship them (e.g. Win 11 client when testing the Server dispatch path locally). Verified locally on Win 11 (non-admin): 12 passed, 0 failed, 0 skipped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new WindowsRSAT dependency type so PSDepend can install/import RSAT-related PowerShell modules through Windows features on servers or Windows capabilities on workstations.
Changes:
- Added
WindowsRSAT.ps1dependency script with RSAT module-to-feature/capability mappings. - Registered
WindowsRSATinPSDependMap.psd1. - Added administrator detection and WindowsRSAT tests.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
PSDepend/PSDependScripts/WindowsRSAT.ps1 |
Implements RSAT dependency handling and installation dispatch. |
PSDepend/PSDependMap.psd1 |
Registers the new WindowsRSAT dependency type. |
PSDepend/Private/Test-Administrator.ps1 |
Adds an admin-role helper used before installing RSAT components. |
Tests/WindowsRSAT.Type.Tests.ps1 |
Adds tests for WindowsRSAT test/install behavior and platform dispatch. |
Comments suppressed due to low confidence (1)
Tests/WindowsRSAT.Type.Tests.ps1:15
- This second import references the same missing
Tests/Shared/TestHelpers.psm1file. Even if discovery setup is fixed or removed,BeforeAllwill fail here until the helper module is added or the tests use existing repository setup patterns.
Import-Module (Join-Path $PSScriptRoot 'Shared/TestHelpers.psm1') -Force
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1
to
+6
| #requires -Module @{ ModuleName = 'Pester'; ModuleVersion = '5.0.0' } | ||
|
|
||
| BeforeDiscovery { | ||
| Import-Module (Join-Path $PSScriptRoot 'Shared/TestHelpers.psm1') -Force | ||
| $script:SkipUnsupported = -not (Test-PSDependTypeSupportedHere -DependencyType 'WindowsRSAT') | ||
| } |
Comment on lines
+4
to
+5
| Import-Module (Join-Path $PSScriptRoot 'Shared/TestHelpers.psm1') -Force | ||
| $script:SkipUnsupported = -not (Test-PSDependTypeSupportedHere -DependencyType 'WindowsRSAT') |
| [OutputType([bool])] | ||
| param() | ||
|
|
||
| ([Security.Principal.WindowsPrincipal]::new( |
| $null = install-windowsfeature -name $RSAT_MODULE_MAP[$ModuleName][$Type] | ||
| } | ||
| else { | ||
| $null = Add-WindowsCapability -Online -Name $RSAT_MODULE_MAP[$ModuleName][$Type] |
Comment on lines
+10
to
+11
| & "$PSScriptRoot\..\build.ps1" -Task 'Build' | ||
| } |
| } | ||
|
|
||
| if ($null -eq $RSAT_MODULE_MAP[$ModuleName][$type]) { | ||
| throw "Unknown Module $ModuleName" |
…n PS 5.1 The previous BeforeAll only injected stub functions when Get-Command found no real Install-WindowsFeature / Add-WindowsCapability. On the Windows PowerShell 5.1 CI matrix entry, ServerManager auto-loads on Server 2022 and the real Install-WindowsFeature is present, so the stub was skipped. Pester then mocked the CDXML cmdlet, but the mock silently did not intercept calls from the script under test -- all four Server-dispatch tests reported "was called 0 times" while the rest passed. (PS 7 matrix entries are unaffected since ServerManager does not load on PowerShell Core, so the stub path was always taken.) PowerShell resolves functions before cmdlets in the same scope, so injecting the stub unconditionally lets it take precedence over the real cmdlet, and Pester reliably mocks the function across all matrix entries. Verified locally on Win 11 in both PowerShell 7 and Windows PowerShell 5.1: 12 passed, 0 failed, 0 skipped on both. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a
WindowsRSATDependencyType for installing Windows RSAT modulesvia
Add-WindowsCapability(Workstation) orInstall-WindowsFeature(Server). Originally authored by @justinainsworth.
Fixes verified against live catalogs
BitLocket->BitLockertypo in Server feature nameHuper-V->Hyper-Vtypo in Server feature nameGroupPolicyServer feature:''RSAT''umbrella ->''GPMC''(targeted)BitsTransfermapping (module ships in-box on Server and client)All 11 other mapping entries verified present in the Server 2022 catalog
and (where applicable) the Win 11 Workstation capability catalog.
Reliability fixes surfaced by testing
WindowsPrincipal.IsInRole(Administrator)extracted to
PSDepend/Private/Test-Administrator.ps1so the installbranch can be exercised in unit tests without elevation.
$RSAT_MODULE_MAP[$ModuleName][$Type]chain threw "Cannot index intoa null array" under
Set-StrictMode -Version 2+before the explicit"Unknown Module" message could fire. Added a
ContainsKeyguard.Tests
12 Pester tests in
Tests/WindowsRSAT.Type.Tests.ps1(follows theChocolatey.Type.Tests.ps1skip pattern) covering Test/Install dispatchon Server and Workstation, mapping correctness for the fixed entries,
unknown-module handling, the admin guard, and the
Test, Installshort-circuit.
Local run on Win 11 (non-admin): 12 passed, 0 failed, 0 skipped.
Out of scope (follow-ups)
Hyper-V,IISAdministration)current OS path (currently reuses "Unknown Module")
etc.)
Server 2022+; Server 2016 lacks several of the targeted feature names)
Refs #160.
Co-Authored-By: @justinainsworth