From 64facd74ee44cbb71aa8027a367fb84f4b46bf95 Mon Sep 17 00:00:00 2001 From: "G.Reijn" Date: Mon, 16 Dec 2024 12:03:45 +0100 Subject: [PATCH] Implement export WinGetPackage DSC resource --- .../Microsoft.WinGet.DSC.psd1 | 34 ++++++------ .../Microsoft.WinGet.DSC.psm1 | 52 ++++++++++++++----- .../tests/Microsoft.WinGet.DSC.Tests.ps1 | 33 ++++++++---- 3 files changed, 79 insertions(+), 40 deletions(-) diff --git a/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psd1 b/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psd1 index fcbe96f023..f854bc1bbe 100644 --- a/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psd1 +++ b/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psd1 @@ -7,31 +7,31 @@ @{ # Script module or binary module file associated with this manifest. - RootModule = 'Microsoft.WinGet.DSC.psm1' + RootModule = 'Microsoft.WinGet.DSC.psm1' # Version number of this module. - ModuleVersion = '0.0.1' + ModuleVersion = '0.0.1' # Supported PSEditions CompatiblePSEditions = 'Core' # ID used to uniquely identify this module - GUID = '8c9326eb-595a-40eb-8696-b289e8085cad' + GUID = '8c9326eb-595a-40eb-8696-b289e8085cad' # Author of this module - Author = 'Microsoft Corporation' + Author = 'Microsoft Corporation' # Company or vendor of this module - CompanyName = 'Microsoft Corporation' + CompanyName = 'Microsoft Corporation' # Copyright statement for this module - Copyright = '(c) Microsoft Corporation. All rights reserved.' + Copyright = '(c) Microsoft Corporation. All rights reserved.' # Description of the functionality provided by this module - Description = 'PowerShell Module with DSC resources related to WinGet configurations' + Description = 'PowerShell Module with DSC resources related to WinGet configurations' # Minimum version of the PowerShell engine required by this module - PowerShellVersion = '7.2' + PowerShellVersion = '7.2' # Name of the PowerShell host required by this module # PowerShellHostName = '' @@ -49,7 +49,7 @@ # ProcessorArchitecture = '' # Modules that must be imported into the global environment prior to importing this module - RequiredModules = @('Microsoft.WinGet.Client') + RequiredModules = @('Microsoft.WinGet.Client') # Assemblies that must be loaded prior to importing this module # RequiredAssemblies = @() @@ -94,37 +94,39 @@ # FileList = @() # 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 = @{ + PrivateData = @{ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. - Tags = @( + Tags = @( 'PSEdition_Core', 'Windows', 'WindowsPackageManager' ) # A URL to the license for this module. - # LicenseUri = '' + LicenseUri = 'https://github.com/microsoft/winget-cli/blob/master/LICENSE' # A URL to the main website for this project. - ProjectUri = 'https://github.com/microsoft/winget-cli' + ProjectUri = 'https://github.com/microsoft/winget-cli' # A URL to an icon representing this module. - IconUri = 'https://aka.ms/winget-icon' + IconUri = 'https://aka.ms/winget-icon' # ReleaseNotes of this module # ReleaseNotes = '' # Prerelease string of this module - Prerelease = 'alpha' + Prerelease = 'alpha' # Flag to indicate whether the module requires explicit user acceptance for install/update/save # RequireLicenseAcceptance = $false # External dependent modules of this module # ExternalModuleDependencies = @() + + DscCapabilities = ('Get', 'Set', 'Test', 'Export') } # End of PSData hashtable @@ -136,5 +138,5 @@ # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # DefaultCommandPrefix = '' - } +} \ No newline at end of file diff --git a/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psm1 b/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psm1 index 96938c707a..04052fc941 100644 --- a/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psm1 +++ b/src/PowerShell/Microsoft.WinGet.DSC/Microsoft.WinGet.DSC.psm1 @@ -79,7 +79,7 @@ class WinGetUserSettings { $userSettings = Get-WinGetUserSetting $result = @{ - SID = '' + SID = '' Settings = $userSettings } return $result @@ -135,7 +135,7 @@ class WinGetAdminSettings # Get admin setting values. $result = @{ - SID = '' + SID = '' Settings = $settingsJson.adminSettings } return $result @@ -216,10 +216,12 @@ class WinGetSource $currentSource = $null - try { + try + { $currentSource = Get-WinGetSource -Name $this.Name } - catch { + catch + { } $result = [WinGetSource]::new() @@ -295,7 +297,7 @@ class WinGetSource if ($addSource) { $hashArgs = @{ - Name = $this.Name + Name = $this.Name Argument = $this.Argument } @@ -396,11 +398,13 @@ class WinGetPackageManager if ($this.UseLatest) { $hashArgs.Add("Latest", $true) - } elseif ($this.UseLatestPreRelease) + } + elseif ($this.UseLatestPreRelease) { $hashArgs.Add("Latest", $true) $hashArgs.Add("IncludePrerelease", $true) - } elseif (-not [string]::IsNullOrWhiteSpace($this.Version)) + } + elseif (-not [string]::IsNullOrWhiteSpace($this.Version)) { $hashArgs.Add("Version", $this.Version) } @@ -426,11 +430,13 @@ class WinGetPackageManager if ($this.UseLatest) { $hashArgs.Add("Latest", $true) - } elseif ($this.UseLatestPreRelease) + } + elseif ($this.UseLatestPreRelease) { $hashArgs.Add("Latest", $true) $hashArgs.Add("IncludePrerelease", $true) - } elseif (-not [string]::IsNullOrWhiteSpace($this.Version)) + } + elseif (-not [string]::IsNullOrWhiteSpace($this.Version)) { $hashArgs.Add("Version", $this.Version) } @@ -482,7 +488,7 @@ class WinGetPackage $result = [WinGetPackage]::new() $hashArgs = @{ - Id = $this.Id + Id = $this.Id MatchOption = $this.MatchOption } @@ -523,9 +529,9 @@ class WinGetPackage if (-not $this.TestAgainstCurrent($currentPackage)) { $hashArgs = @{ - Id = $this.Id + Id = $this.Id MatchOption = $this.MatchOption - Mode = $this.InstallMode + Mode = $this.InstallMode } if ($this.Ensure -eq [WinGetEnsure]::Present) @@ -553,7 +559,7 @@ class WinGetPackage $this.TryUpdate($hashArgs) break } - {'Greater' -or 'Unknown'} + { 'Greater' -or 'Unknown' } { # The installed package has a greater version or unknown. Uninstall and install. $this.Uninstall() @@ -579,6 +585,26 @@ class WinGetPackage } } } + + static [WinGetPackage[]] Export() + { + $packages = Get-WingetPackage + $out = [List[WinGetPackage]]::new() + foreach ($package in $packages) + { + $in = [WinGetPackage]@{ + Ensure = [WinGetEnsure]::Present + Id = $package.Id + Source = $package.Source + Version = $package.InstalledVersion + UseLatest = -not $package.IsUpdateAvailable + } + + $out.Add($in) + } + + return $out + } [bool] hidden TestAgainstCurrent([WinGetPackage]$currentPackage) { diff --git a/src/PowerShell/tests/Microsoft.WinGet.DSC.Tests.ps1 b/src/PowerShell/tests/Microsoft.WinGet.DSC.Tests.ps1 index 0dc01f6dd8..6d2b15f5b3 100644 --- a/src/PowerShell/tests/Microsoft.WinGet.DSC.Tests.ps1 +++ b/src/PowerShell/tests/Microsoft.WinGet.DSC.Tests.ps1 @@ -8,13 +8,16 @@ 'Invoke-Pester' should be called in an admin PowerShell window. #> +# TODO: Might need using statement for export + BeforeAll { Install-Module -Name PSDesiredStateConfiguration -Force -SkipPublisherCheck Import-Module Microsoft.WinGet.Client Import-Module Microsoft.WinGet.DSC # Helper function for calling Invoke-DscResource on the Microsoft.WinGet.DSC module. - function InvokeWinGetDSC() { + function InvokeWinGetDSC() + { param ( [Parameter()] [string]$Name, @@ -30,12 +33,12 @@ BeforeAll { } } -Describe 'List available DSC resources'{ - It 'Shows DSC Resources'{ +Describe 'List available DSC resources' { + It 'Shows DSC Resources' { $expectedDSCResources = "WinGetAdminSettings", "WinGetPackage", "WinGetPackageManager", "WinGetSource", "WinGetUserSettings" $availableDSCResources = (Get-DscResource -Module Microsoft.WinGet.DSC).Name $availableDSCResources.length | Should -Be 5 - $availableDSCResources | Where-Object {$expectedDSCResources -notcontains $_} | Should -BeNullOrEmpty -ErrorAction Stop + $availableDSCResources | Where-Object { $expectedDSCResources -notcontains $_ } | Should -BeNullOrEmpty -ErrorAction Stop } } @@ -45,9 +48,9 @@ Describe 'WinGetAdminSettings' { $initialAdminSettings = (Get-WinGetSetting).adminSettings $adminSettingsHash = @{ BypassCertificatePinningForMicrosoftStore = !$initialAdminSettings.BypassCertificatePinningForMicrosoftStore; - InstallerHashOverride = !$initialAdminSettings.InstallerHashOverride; - LocalManifestFiles = !$initialAdminSettings.LocalManifestFiles; - LocalArchiveMalwareScanOverride = !$initialAdminSettings.LocalArchiveMalwareScanOverride; + InstallerHashOverride = !$initialAdminSettings.InstallerHashOverride; + LocalManifestFiles = !$initialAdminSettings.LocalManifestFiles; + LocalArchiveMalwareScanOverride = !$initialAdminSettings.LocalArchiveMalwareScanOverride; } } @@ -103,7 +106,7 @@ Describe 'WinGetUserSettings' { $userSettingsHash = @{ experimentalFeatures = @{ directMSI = $true }; - installBehavior = @{ Preferences = @{ Scope = 'User' }} + installBehavior = @{ Preferences = @{ Scope = 'User' } } } } @@ -143,7 +146,7 @@ Describe 'WinGetSource' { } It 'Test WinGet source' { - $result = InvokeWinGetDSC -Name WinGetSource -Method Test -Property @{ Ensure='Present'; Name = $testSourceName; Argument = $testSourceArg; Type = $testSourceType } + $result = InvokeWinGetDSC -Name WinGetSource -Method Test -Property @{ Ensure = 'Present'; Name = $testSourceName; Argument = $testSourceArg; Type = $testSourceType } $result.InDesiredState | Should -Be $false } @@ -205,7 +208,15 @@ Describe 'WinGetPackage' { $result.Ensure | Should -Be 'Present' $result.UseLatest | Should -Be $true $result.Version | Should -Not -Be $testPackageVersion - } + } + + It 'Export WinGetPackage(s)' { + $result = [WinGetPackage]::Export() + + # Verify if export contains at least 1 package + $result | Should -not -BeNullOrEmpty + $result.Count | Should -BeGreaterThan 0 + } It 'Uninstall WinGetPackage' { InvokeWinGetDSC -Name WinGetPackage -Method Set -Property @{ Id = $testPackageId; UseLatest = $true } @@ -221,7 +232,7 @@ Describe 'WinGetPackage' { } AfterAll { - InvokeWinGetDSC -Name WinGetPackage -Method Set -Property @{ Ensure = 'Absent'; Id = $testPackageId} + InvokeWinGetDSC -Name WinGetPackage -Method Set -Property @{ Ensure = 'Absent'; Id = $testPackageId } } }