Skip to content

Commit 74849e1

Browse files
authored
fix(psresourcelist): Get operation filters out resources on installed version (#1998)
1 parent d09a72f commit 74849e1

2 files changed

Lines changed: 116 additions & 30 deletions

File tree

‎src/dsc/psresourceget.ps1‎

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -342,33 +342,38 @@ function GetPSResourceList {
342342
)
343343
}
344344

345-
$resourcesExist = @()
346-
347-
foreach ($resource in $allPSResources) {
348-
foreach ($inputResource in $inputResources) {
349-
if ($resource.Name -eq $inputResource.Name) {
350-
Write-Trace -message "Found matching resource for input: $($inputResource.Name). Checking version constraints. Input version: $($inputResource.Version), Resource version: $($resource.Version)" -level debug
351-
if ($inputResource.Version) {
352-
# Use the NuGet.Versioning package if available, otherwise do a simple comparison
353-
try {
354-
if (SatisfiesVersion -version $resource.Version -versionRange $inputResource.Version) {
355-
$resourcesExist += $resource
356-
}
357-
}
358-
catch {
359-
Write-Trace -message "Error checking version constraints for resource: $($inputResource.Name). Error details: $($_.Exception.Message)" -level debug
360-
# Fallback: simple string comparison (not full NuGet range support)
361-
if ($resource.Version.ToString() -eq $inputResource.Version) {
362-
$resourcesExist += $resource
363-
}
364-
}
365-
}
345+
$resolvedResources = @()
346+
347+
foreach ($inputResource in $inputResources) {
348+
$matchingResources = $allPSResources | Where-Object { $_.Name -eq $inputResource.Name }
349+
350+
if ($matchingResources) {
351+
$preferred = $null
352+
if ($inputResource.Version) {
353+
$preferred = $matchingResources | Where-Object {
354+
try { SatisfiesVersion -version $_.Version -versionRange $inputResource.Version } catch { $false }
355+
} | Select-Object -First 1
356+
} else {
357+
$preferred = $matchingResources | Select-Object -First 1
358+
}
359+
360+
if ($preferred) {
361+
Write-Trace -message "Resource '$($inputResource.Name)' version '$($preferred.Version)' satisfies requested range '$($inputResource.Version)'." -level debug
362+
$resolvedResources += $preferred
363+
} else {
364+
# Installed but doesn't satisfy the version range - report actual installed version with _exist = false
365+
$fallback = $matchingResources | Select-Object -First 1
366+
Write-Trace -message "Resource '$($inputResource.Name)' installed at '$($fallback.Version)' does not satisfy requested range '$($inputResource.Version)'. Reporting _exist = false." -level debug
367+
$fallback._exist = $false
368+
$resolvedResources += $fallback
366369
}
370+
} else {
371+
Write-Trace -message "Resource '$($inputResource.Name)' is not installed. Reporting _exist = false." -level debug
372+
$resolvedResources += [PSResource]::new($inputResource.Name)
367373
}
368374
}
369375

370-
## For get operation we only need the first resource that exists, which is always the latest for currentUser
371-
PopulatePSResourceListObjectByRepository -resourcesExist $resourcesExist -inputResources $inputResources -repositoryName $inputPSResourceList.RepositoryName -trustedRepository $inputPSResourceList.trustedRepository
376+
PopulatePSResourceListObjectByRepository -resourcesExist $resolvedResources -inputResources $inputResources -repositoryName $inputPSResourceList.RepositoryName -trustedRepository $inputPSResourceList.trustedRepository
372377
}
373378

374379
function GetOperation {
@@ -771,13 +776,20 @@ function PopulatePSResourceListObjectByRepository {
771776
}
772777
else {
773778
$resources += $resourcesExist | ForEach-Object {
774-
[PSResource]::new(
775-
$_.Name,
776-
$_.Version.PreRelease ? $_.Version.ToString() + "-" + $_.PreRelease : $_.Version.ToString(),
777-
$_.Scope,
778-
$_.RepositoryName,
779-
$_.PreRelease ? $true : $false
780-
)
779+
$srcExist = $_._exist
780+
$r = if ($_.version) {
781+
[PSResource]::new(
782+
$_.Name,
783+
$_.Version.ToString(),
784+
$_.Scope,
785+
$_.RepositoryName,
786+
$_.PreRelease ? $true : $false
787+
)
788+
} else {
789+
[PSResource]::new($_.Name)
790+
}
791+
$r._exist = $srcExist
792+
$r
781793
}
782794
}
783795

‎test/DscResource/PSResourceGetDSCResource.Tests.ps1‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,16 @@ Describe "PSResourceList Resource Tests" -Tags 'CI' {
221221
return
222222
}
223223

224+
# Remove test modules installed through DSC so they do not leak into later runs.
225+
foreach ($moduleToRemove in @($script:testModuleName, $script:testModuleName2)) {
226+
$cleanupInput = @{
227+
repositoryName = $script:localRepo
228+
trustedRepository = $true
229+
resources = @(@{ name = $moduleToRemove; _exist = $false })
230+
} | ConvertTo-Json -Depth 5
231+
$null = & $script:dscExe resource set --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $cleanupInput -o json 2>&1
232+
}
233+
224234
# Clean up the test repository
225235
Get-RevertPSResourceRepositoryFile
226236
}
@@ -370,6 +380,70 @@ Describe "PSResourceList Resource Tests" -Tags 'CI' {
370380
$testResult = & $script:dscExe resource test --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $resourceInput -o json | ConvertFrom-Json
371381
$testResult.inDesiredState | Should -BeFalse
372382
}
383+
384+
It 'Get returns actual installed version with _exist false when installed version does not satisfy requested version' {
385+
# Install 1.0.0 but request 5.0.0 - get should report _exist = false (requested version absent)
386+
$removeAllInput = @{
387+
repositoryName = $script:localRepo
388+
trustedRepository = $true
389+
resources = @(@{ name = $script:testModuleName; _exist = $false })
390+
} | ConvertTo-Json -Depth 5
391+
$null = & $script:dscExe resource set --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $removeAllInput -o json
392+
393+
$installOldInput = @{
394+
repositoryName = $script:localRepo
395+
trustedRepository = $true
396+
resources = @(@{ name = $script:testModuleName; version = '1.0.0' })
397+
} | ConvertTo-Json -Depth 5
398+
$null = & $script:dscExe resource set --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $installOldInput -o json
399+
400+
$psResourceListParams = @{
401+
repositoryName = $script:localRepo
402+
resources = @(
403+
@{
404+
name = $script:testModuleName
405+
version = '5.0.0'
406+
}
407+
)
408+
}
409+
410+
$resourceInput = $psResourceListParams | ConvertTo-Json -Depth 5
411+
$getResult = & $script:dscExe resource get --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $resourceInput -o json | ConvertFrom-Json
412+
$getResult.actualState.resources.Count | Should -Be 1
413+
$getResult.actualState.resources[0].name | Should -BeExactly $script:testModuleName
414+
$getResult.actualState.resources[0].version | Should -BeExactly '1.0.0'
415+
$getResult.actualState.resources[0]._exist | Should -BeFalse
416+
}
417+
418+
It 'Get prefers installed version that satisfies requested version range when multiple versions are installed' {
419+
# Install both 1.0.0 and 5.0.0 but request 5.0.0 - get should prefer the satisfying version (5.0.0).
420+
# Setup goes through DSC for the same reason as the previous test.
421+
foreach ($setupVersion in @('1.0.0', '5.0.0')) {
422+
$installInput = @{
423+
repositoryName = $script:localRepo
424+
trustedRepository = $true
425+
resources = @(@{ name = $script:testModuleName; version = $setupVersion })
426+
} | ConvertTo-Json -Depth 5
427+
$null = & $script:dscExe resource set --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $installInput -o json
428+
}
429+
430+
$psResourceListParams = @{
431+
repositoryName = $script:localRepo
432+
resources = @(
433+
@{
434+
name = $script:testModuleName
435+
version = '5.0.0'
436+
}
437+
)
438+
}
439+
440+
$resourceInput = $psResourceListParams | ConvertTo-Json -Depth 5
441+
$getResult = & $script:dscExe resource get --resource Microsoft.PowerShell.PSResourceGet/PSResourceList --input $resourceInput -o json | ConvertFrom-Json
442+
$getResult.actualState.resources.Count | Should -Be 1
443+
$getResult.actualState.resources[0].name | Should -BeExactly $script:testModuleName
444+
$getResult.actualState.resources[0].version | Should -BeExactly '5.0.0'
445+
$getResult.actualState.resources[0]._exist | Should -BeTrue
446+
}
373447
}
374448

375449
Describe 'E2E tests for Repository resource' -Tags 'CI' {

0 commit comments

Comments
 (0)