From 9b1497db18ce8a326330a579bb7b244690ceb8e3 Mon Sep 17 00:00:00 2001 From: Andrew <anmenaga@microsoft.com> Date: Fri, 12 Jul 2024 10:47:09 -0700 Subject: [PATCH 1/3] handle case of multiple modules with same name --- .../psDscAdapter/psDscAdapter.psm1 | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 index 53d7dda4..997dd333 100644 --- a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -$script:CurrentCacheSchemaVersion = 1 +$script:CurrentCacheSchemaVersion = 2 function Write-DscTrace { param( @@ -42,7 +42,6 @@ function Get-DSCResourceModules if($null -ne $containsDSCResource) { $dscModulePsd1List.Add($psd1) | Out-Null - break } } } @@ -107,7 +106,9 @@ function FindAndParseResourceDefinitions [CmdletBinding(HelpUri = '')] param( [Parameter(Mandatory = $true)] - [string]$filePath + [string]$filePath, + [Parameter(Mandatory = $true)] + [string]$moduleVersion ) if (-not (Test-Path $filePath)) @@ -155,6 +156,7 @@ function FindAndParseResourceDefinitions #TODO: ModuleName, Version and ParentPath should be taken from psd1 contents $DscResourceInfo.ModuleName = [System.IO.Path]::GetFileNameWithoutExtension($filePath) $DscResourceInfo.ParentPath = [System.IO.Path]::GetDirectoryName($filePath) + $DscResourceInfo.Version = $moduleVersion $DscResourceInfo.Properties = [System.Collections.Generic.List[DscResourcePropertyInfo]]::new() Add-AstMembers $typeDefinitions $typeDefinitionAst $DscResourceInfo.Properties @@ -194,7 +196,7 @@ function LoadPowerShellClassResourcesFromModule $scriptPath = $moduleInfo.Path; } - $Resources = FindAndParseResourceDefinitions $scriptPath + $Resources = FindAndParseResourceDefinitions $scriptPath $moduleInfo.Version if ($moduleInfo.NestedModules) { @@ -309,11 +311,23 @@ function Invoke-DscCacheRefresh { $dscResourceModulePsd1s = Get-DSCResourceModules if($null -ne $dscResourceModulePsd1s) { $modules = Get-Module -ListAvailable -Name ($dscResourceModulePsd1s) + $processedModuleNames = @{} foreach ($mod in $modules) { - [System.Collections.Generic.List[DscResourceInfo]]$r = LoadPowerShellClassResourcesFromModule -moduleInfo $mod - if ($r) { - $DscResources.AddRange($r) + if (-not ($processedModuleNames.ContainsKey($mod.Name))) { + $processedModuleNames.Add($mod.Name, $true) + + # from several modules with the same name select the one with the highest version + $selectedMod = $modules | Where-Object Name -EQ $mod.Name + if ($selectedMod.Count -gt 1) { + "Found $($selectedMod.Count) modules with name '$($mod.Name)'" | Write-DscTrace -Operation Trace + $selectedMod = $selectedMod | Sort-Object -Property Version -Descending | Select-Object -First 1 + } + + [System.Collections.Generic.List[DscResourceInfo]]$r = LoadPowerShellClassResourcesFromModule -moduleInfo $selectedMod + if ($r) { + $DscResources.AddRange($r) + } } } } From 21a5bed18e6fa3a3da8cc1ceff11137cd7461a6d Mon Sep 17 00:00:00 2001 From: Andrew <anmenaga@microsoft.com> Date: Fri, 12 Jul 2024 15:18:16 -0700 Subject: [PATCH 2/3] added test --- .../Tests/powershellgroup.resource.tests.ps1 | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 b/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 index 74856cfc..2367f31a 100644 --- a/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 +++ b/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 @@ -128,4 +128,53 @@ Describe 'PowerShell adapter resource tests' { $t = $resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'} $t.properties | Should -Contain "BaseProperty" } + + It 'Verify highest module version is loaded' { + + $srcPath = Join-Path $PSScriptRoot 'TestClassResource' + $pathRoot1 = Join-Path $TestDrive 'A' + $pathRoot2 = Join-Path $TestDrive 'B' + $path1 = Join-Path $pathRoot1 'TestClassResource' '0.0.1' + $path2 = Join-Path $pathRoot1 'TestClassResource' '0.0.2' + $path3 = Join-Path $pathRoot2 'TestClassResource' '0.0.3' + $path4 = Join-Path $pathRoot2 'TestClassResource' '0.0.4' + + New-Item -ItemType Directory -Force -Path $path1 | Out-Null + New-Item -ItemType Directory -Force -Path $path2 | Out-Null + New-Item -ItemType Directory -Force -Path $path3 | Out-Null + New-Item -ItemType Directory -Force -Path $path4 | Out-Null + + $files = Get-ChildItem -Recurse -File -Path $srcPath + $files | Copy-Item -Destination $path1 + $files | Copy-Item -Destination $path2 + $files | Copy-Item -Destination $path3 + $files | Copy-Item -Destination $path4 + + $filePath = Join-Path $path1 'TestClassResource.psd1' + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.1`'") | Set-Content $filePath + $filePath = Join-Path $path2 'TestClassResource.psd1' + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.2`'") | Set-Content $filePath + $filePath = Join-Path $path3 'TestClassResource.psd1' + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.3`'") | Set-Content $filePath + $filePath = Join-Path $path4 'TestClassResource.psd1' + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.4`'") | Set-Content $filePath + + + $oldPath = $env:PSModulePath + try { + $env:PSModulePath += [System.IO.Path]::PathSeparator + $pathRoot1 + $env:PSModulePath += [System.IO.Path]::PathSeparator + $pathRoot2 + + $r = dsc resource list '*' -a Microsoft.DSC/PowerShell + $LASTEXITCODE | Should -Be 0 + $resources = $r | ConvertFrom-Json + $r = @($resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'}) + $r.Count | Should -Be 1 + $r[0].Version | Should -Be '0.0.4' + } + finally { + $env:PSModulePath = $oldPath + } + + } } From aa0448308853a78a3ed6b2ce4e1b49e8e4796c4a Mon Sep 17 00:00:00 2001 From: Andrew <anmenaga@microsoft.com> Date: Fri, 12 Jul 2024 22:53:59 -0700 Subject: [PATCH 3/3] updated test --- .../Tests/powershellgroup.resource.tests.ps1 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 b/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 index b336952c..3864799f 100644 --- a/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 +++ b/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 @@ -134,10 +134,10 @@ Describe 'PowerShell adapter resource tests' { $srcPath = Join-Path $PSScriptRoot 'TestClassResource' $pathRoot1 = Join-Path $TestDrive 'A' $pathRoot2 = Join-Path $TestDrive 'B' - $path1 = Join-Path $pathRoot1 'TestClassResource' '0.0.1' - $path2 = Join-Path $pathRoot1 'TestClassResource' '0.0.2' - $path3 = Join-Path $pathRoot2 'TestClassResource' '0.0.3' - $path4 = Join-Path $pathRoot2 'TestClassResource' '0.0.4' + $path1 = Join-Path $pathRoot1 'TestClassResource' '1.0' + $path2 = Join-Path $pathRoot1 'TestClassResource' '1.1' + $path3 = Join-Path $pathRoot2 'TestClassResource' '2.0' + $path4 = Join-Path $pathRoot2 'TestClassResource' '2.0.1' New-Item -ItemType Directory -Force -Path $path1 | Out-Null New-Item -ItemType Directory -Force -Path $path2 | Out-Null @@ -151,13 +151,13 @@ Describe 'PowerShell adapter resource tests' { $files | Copy-Item -Destination $path4 $filePath = Join-Path $path1 'TestClassResource.psd1' - (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.1`'") | Set-Content $filePath + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'1.0`'") | Set-Content $filePath $filePath = Join-Path $path2 'TestClassResource.psd1' - (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.2`'") | Set-Content $filePath + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'1.1`'") | Set-Content $filePath $filePath = Join-Path $path3 'TestClassResource.psd1' - (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.3`'") | Set-Content $filePath + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'2.0`'") | Set-Content $filePath $filePath = Join-Path $path4 'TestClassResource.psd1' - (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'0.0.4`'") | Set-Content $filePath + (Get-Content -Raw $filePath).Replace("ModuleVersion = `'0.0.1`'", "ModuleVersion = `'2.0.1`'") | Set-Content $filePath $oldPath = $env:PSModulePath @@ -170,7 +170,7 @@ Describe 'PowerShell adapter resource tests' { $resources = $r | ConvertFrom-Json $r = @($resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'}) $r.Count | Should -Be 1 - $r[0].Version | Should -Be '0.0.4' + $r[0].Version | Should -Be '2.0.1' } finally { $env:PSModulePath = $oldPath