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