diff --git a/.vscode/settings.json b/.vscode/settings.json index 24bf5814..93224251 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,6 +12,7 @@ "./y2j/Cargo.toml" ], "rust-analyzer.showUnlinkedFileNotification": true, + "powershell.codeFormatting.preset": "OTBS", "json.schemas": [ { "fileMatch": ["**/*.dsc.resource.json"], diff --git a/powershell-adapter/Tests/TestClassNoVersion/TestClassNoVersion.psd1 b/powershell-adapter/Tests/TestClassNoVersion/TestClassNoVersion.psd1 new file mode 100644 index 00000000..cbe8e12b --- /dev/null +++ b/powershell-adapter/Tests/TestClassNoVersion/TestClassNoVersion.psd1 @@ -0,0 +1,52 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'TestClassNoVersion.psm1' + + # Version number of this module. + ModuleVersion = '0.0.1' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = 'ec985d60-82f4-4d45-83e0-b6f935654350' + + # Author of this module + Author = 'Microsoft' + + # Company or vendor of this module + CompanyName = 'Microsoft Corporation' + + # Copyright statement for this module + Copyright = '(c) Microsoft. All rights reserved.' + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = @() + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = @() + + # Variables to export from this module + VariablesToExport = @() + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = @() + + # DSC resources to export from this module + DscResourcesToExport = 'TestClassNoVersion' + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + DscCapabilities = @('Get', 'Test', 'Set') + + } # End of PSData hashtable + + } # End of PrivateData hashtable +} + diff --git a/powershell-adapter/Tests/TestClassNoVersion/TestClassNoVersion.psm1 b/powershell-adapter/Tests/TestClassNoVersion/TestClassNoVersion.psm1 new file mode 100644 index 00000000..5b40b337 --- /dev/null +++ b/powershell-adapter/Tests/TestClassNoVersion/TestClassNoVersion.psm1 @@ -0,0 +1,20 @@ +[DscResource()] +class TestClassNoVersion +{ + [DscProperty(Key)] + [string] $Name + + [void] Set() + { + } + + [bool] Test() + { + return $true + } + + [TestClassNoVersion] Get() + { + return $this + } +} \ No newline at end of file diff --git a/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 b/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 index fed67da1..75f01969 100644 --- a/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 +++ b/powershell-adapter/Tests/powershellgroup.resource.tests.ps1 @@ -4,14 +4,12 @@ Describe 'PowerShell adapter resource tests' { BeforeAll { - $OldPSModulePath = $env:PSModulePath + $OldPSModulePath = $env:PSModulePath $env:PSModulePath += [System.IO.Path]::PathSeparator + $PSScriptRoot if ($IsLinux -or $IsMacOS) { $cacheFilePath = Join-Path $env:HOME ".dsc" "PSAdapterCache.json" - } - else - { + } else { $cacheFilePath = Join-Path $env:LocalAppData "dsc" "PSAdapterCache.json" } } @@ -28,7 +26,7 @@ Describe 'PowerShell adapter resource tests' { $r = dsc resource list '*' -a Microsoft.DSC/PowerShell $LASTEXITCODE | Should -Be 0 $resources = $r | ConvertFrom-Json - ($resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'}).Count | Should -Be 1 + ($resources | ? { $_.Type -in @('TestClassResource/TestClassResource', 'TestClassNoVersion/TestClassNoVersion') }).Count | Should -Be 2 } It 'Get works on class-based resource' { @@ -44,6 +42,14 @@ Describe 'PowerShell adapter resource tests' { $propertiesNames | Should -Not -Contain 'HiddenNonDscProperty' } + It 'Get works on class-based resource without sub-directory version' { + + $r = "{'Name':'TestClassNoVersion'}" | dsc resource get -r 'TestClassNoVersion/TestClassNoVersion' -f - + $LASTEXITCODE | Should -Be 0 + $res = $r | ConvertFrom-Json + $res.actualState.result.properties.Name | Should -BeExactly 'TestClassNoVersion' + } + It 'Get uses enum names on class-based resource' { $r = "{'Name':'TestClassResource1'}" | dsc resource get -r 'TestClassResource/TestClassResource' -f - @@ -66,6 +72,15 @@ Describe 'PowerShell adapter resource tests' { $propertiesNames | Should -Not -Contain 'HiddenNonDscProperty' } + It 'Test works on class-based resource without sub-directory version' { + + $r = "{'Name':'TestClassNoVersion'}" | dsc resource test -r 'TestClassNoVersion/TestClassNoVersion' -f - + $LASTEXITCODE | Should -Be 0 + $res = $r | ConvertFrom-Json + $res.actualState.result.properties.InDesiredState | Should -Be $True + $res.actualState.result.properties.InDesiredState.GetType().Name | Should -Be "Boolean" + } + It 'Set works on class-based resource' { $r = "{'Name':'TestClassResource1','Prop1':'ValueForProp1'}" | dsc resource set -r 'TestClassResource/TestClassResource' -f - @@ -74,6 +89,14 @@ Describe 'PowerShell adapter resource tests' { $res.afterState.result | Should -Not -BeNull } + It 'Set works on class-based resource without sub-directory version' { + + $r = "{'Name':'TestClassNoVersion'}" | dsc resource set -r 'TestClassNoVersion/TestClassNoVersion' -f - + $LASTEXITCODE | Should -Be 0 + $res = $r | ConvertFrom-Json + $res.afterState.result | Should -Not -BeNull + } + It 'Export works on PS class-based resource' { $r = dsc resource export -r TestClassResource/TestClassResource @@ -84,7 +107,7 @@ Describe 'PowerShell adapter resource tests' { $res.resources[0].properties.result[0].Prop1 | Should -Be "Property of object1" # verify that only properties with DscProperty attribute are returned - $res.resources[0].properties.result | %{ + $res.resources[0].properties.result | % { $propertiesNames = $_ | Get-Member -MemberType NoteProperty | % Name $propertiesNames | Should -Not -Contain 'NonDscProperty' $propertiesNames | Should -Not -Contain 'HiddenNonDscProperty' @@ -97,7 +120,7 @@ Describe 'PowerShell adapter resource tests' { $LASTEXITCODE | Should -Be 0 $res = $r | ConvertFrom-Json $res.actualState.result.count | Should -Be 5 - $res.actualState.result| % {$_.Name | Should -Not -BeNullOrEmpty} + $res.actualState.result | % { $_.Name | Should -Not -BeNullOrEmpty } } It 'Verify that ClearCache works in PSAdapter' { @@ -158,8 +181,7 @@ Describe 'PowerShell adapter resource tests' { $LASTEXITCODE | Should -Be 0 "$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'Detected non-existent cache entry' "$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'Constructing Get-DscResource cache' - } - finally { + } finally { $env:PSModulePath = $oldPath Copy-Item -Recurse -Force -Path "$PSScriptRoot/Backup/TestClassResource" -Destination "$PSScriptRoot" Remove-Item -Recurse -Force -Path "$PSScriptRoot/Backup" @@ -171,7 +193,7 @@ Describe 'PowerShell adapter resource tests' { $r = dsc resource list '*' -a Microsoft.DSC/PowerShell $LASTEXITCODE | Should -Be 0 $resources = $r | ConvertFrom-Json - $t = $resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'} + $t = $resources | ? { $_.Type -eq 'TestClassResource/TestClassResource' } $t.properties | Should -Contain "BaseProperty" } @@ -214,11 +236,10 @@ Describe 'PowerShell adapter resource tests' { $r = dsc resource list '*' -a Microsoft.DSC/PowerShell $LASTEXITCODE | Should -Be 0 $resources = $r | ConvertFrom-Json - $r = @($resources | ? {$_.Type -eq 'TestClassResource/TestClassResource'}) + $r = @($resources | ? { $_.Type -eq 'TestClassResource/TestClassResource' }) $r.Count | Should -Be 1 $r[0].Version | Should -Be '2.0.1' - } - finally { + } finally { $env:PSModulePath = $oldPath } } @@ -229,12 +250,11 @@ Describe 'PowerShell adapter resource tests' { $adapterPath = Join-Path $PSScriptRoot 'TestAdapter' $env:PATH += [System.IO.Path]::PathSeparator + $adapterPath - $r = '{TestCaseId: 1}'| dsc resource get -r 'Test/TestCase' -f - + $r = '{TestCaseId: 1}' | dsc resource get -r 'Test/TestCase' -f - $LASTEXITCODE | Should -Be 0 $resources = $r | ConvertFrom-Json $resources.actualState.result | Should -Be $True - } - finally { + } finally { $env:PATH = $oldPath } } @@ -245,13 +265,12 @@ Describe 'PowerShell adapter resource tests' { $adapterPath = Join-Path $PSScriptRoot 'TestAdapter' $env:PATH += [System.IO.Path]::PathSeparator + $adapterPath - $r = '{TestCaseId: 1}'| dsc resource set -r 'Test/TestCase' -f - + $r = '{TestCaseId: 1}' | dsc resource set -r 'Test/TestCase' -f - $LASTEXITCODE | Should -Be 0 $resources = $r | ConvertFrom-Json $resources.beforeState.result | Should -Be $True $resources.afterState.result | Should -Be $True - } - finally { + } finally { $env:PATH = $oldPath } } @@ -262,12 +281,11 @@ Describe 'PowerShell adapter resource tests' { $adapterPath = Join-Path $PSScriptRoot 'TestAdapter' $env:PATH += [System.IO.Path]::PathSeparator + $adapterPath - $r = '{TestCaseId: 1}'| dsc resource test -r 'Test/TestCase' -f - + $r = '{TestCaseId: 1}' | dsc resource test -r 'Test/TestCase' -f - $LASTEXITCODE | Should -Be 0 $resources = $r | ConvertFrom-Json $resources.actualState.result | Should -Be $True - } - finally { + } finally { $env:PATH = $oldPath } } @@ -282,8 +300,7 @@ Describe 'PowerShell adapter resource tests' { $LASTEXITCODE | Should -Be 0 $resources = $r | ConvertFrom-Json $resources.resources[0].properties.result | Should -Be $True - } - finally { + } finally { $env:PATH = $oldPath } } @@ -321,7 +338,7 @@ Describe 'PowerShell adapter resource tests' { "$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'Constructing Get-DscResource cache' # next executions following shortly after should Not rebuild the cache - 1..3 | %{ + 1..3 | % { dsc -l trace resource list -a Microsoft.DSC/PowerShell 2> $TestDrive/tracing.txt "$TestDrive/tracing.txt" | Should -Not -FileContentMatchExactly 'Constructing Get-DscResource cache' } diff --git a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 index 2aad54cc..8df88cc5 100644 --- a/powershell-adapter/psDscAdapter/psDscAdapter.psm1 +++ b/powershell-adapter/psDscAdapter/psDscAdapter.psm1 @@ -32,15 +32,17 @@ function Get-DSCResourceModules { continue } + # Partially re-used code from the original DSCv2 Get-DSCResource code + # Get-Module -ListAvailable is slow and has a bug causing incorrect reporting + $moduleFolders = Get-ChildItem $folder -Directory + if (-not $moduleFolders) { + $moduleFolders = Get-ChildItem (Split-Path $folder -Parent) | Where-Object { $_.Name -eq (Split-Path $folder -Leaf) } + } - foreach($moduleFolder in Get-ChildItem $folder -Directory) - { - $addModule = $false - foreach($psd1 in Get-ChildItem -Recurse -Filter "$($moduleFolder.Name).psd1" -Path $moduleFolder.fullname -Depth 2) - { - $containsDSCResource = select-string -LiteralPath $psd1 -pattern '^[^#]*\bDscResourcesToExport\b.*' - if($null -ne $containsDSCResource) - { + foreach ($moduleFolder in $moduleFolders) { + foreach ($psd1 in Get-ChildItem -Recurse -Filter "$($moduleFolder.Name).psd1" -Path $moduleFolder.fullname -Depth 2) { + $containsDSCResource = Select-String -LiteralPath $psd1 -Pattern '^[^#]*\bDscResourcesToExport\b.*' + if ($null -ne $containsDSCResource) { $dscModulePsd1List.Add($psd1) | Out-Null } }