Skip to content

Commit 54a9b1a

Browse files
committed
fix: Ensure full refresh on cache cold start
1 parent d5eac6d commit 54a9b1a

File tree

1 file changed

+41
-31
lines changed

1 file changed

+41
-31
lines changed

powershell-adapter/psDscAdapter/win_psDscAdapter.psm1

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ function Invoke-DscCacheRefresh {
5353
)
5454

5555
$refreshCache = $false
56-
56+
$namedModules = [System.Collections.Generic.List[Object]]::new()
5757
$cacheFilePath = Join-Path $env:LocalAppData "dsc\WindowsPSAdapterCache.json"
5858

5959
if (Test-Path $cacheFilePath) {
@@ -83,18 +83,17 @@ function Invoke-DscCacheRefresh {
8383
$diff = $hs_cache
8484

8585
"PSModulePath diff '$diff'" | Write-DscTrace
86+
# TODO: Optimise for named module refresh
8687
if ($diff.Count -gt 0) {
8788
$refreshCache = $true
88-
# Get all resources
89-
$Module = $null
9089
}
9190

9291
if (-not $refreshCache) {
9392
"Checking cache for stale entries" | Write-DscTrace
9493

9594
foreach ($cacheEntry in $dscResourceCacheEntries) {
9695

97-
$cacheEntry.LastWriteTimes.PSObject.Properties | ForEach-Object {
96+
foreach ($_ in $cacheEntry.LastWriteTimes.PSObject.Properties) {
9897

9998
if (Test-Path $_.Name) {
10099
$file_LastWriteTime = (Get-Item $_.Name).LastWriteTimeUtc
@@ -118,8 +117,19 @@ function Invoke-DscCacheRefresh {
118117
}
119118
}
120119

121-
if ($refreshCache) { break }
120+
if ($refreshCache) {
121+
$namedModules.Add($cacheEntry.DscResourceInfo.ModuleName)
122+
$refreshCache = $false
123+
}
124+
}
125+
}
126+
if ($namedModules.Count -gt 0) {
127+
$refreshCache = $true
128+
if ($null -ne $Module) {
129+
$namedModules.AddRange(@($Module))
122130
}
131+
$namedModules = $namedModules | Sort-Object -Unique
132+
"Module list: $($namedModules -join ', ')" | Write-DscTrace
123133
}
124134
}
125135
}
@@ -133,32 +143,32 @@ function Invoke-DscCacheRefresh {
133143
'Constructing Get-DscResource cache' | Write-DscTrace
134144

135145
# create a list object to store cache of Get-DscResource
136-
[dscResourceCacheEntry[]]$dscResourceCacheEntries = [System.Collections.Generic.List[Object]]::new()
146+
$dscResourceCacheEntries = [System.Collections.Generic.List[dscResourceCacheEntry]]::new()
137147

138148
# improve by performance by having the option to only get details for named modules
139149
# workaround for File and SignatureValidation resources that ship in Windows
140-
if ($null -ne $module -and 'PSDesiredStateConfiguration' -ne $module) {
141-
if ($module.gettype().name -eq 'string') {
142-
$module = @($module)
143-
}
150+
if ($namedModules.Count -gt 0) {
144151
$DscResources = [System.Collections.Generic.List[Object]]::new()
145152
$Modules = [System.Collections.Generic.List[Object]]::new()
146153
$filteredResources = @()
147-
foreach ($m in $module) {
148-
$DscResources += Get-DscResource -Module $m
149-
$Modules += Get-Module -Name $m -ListAvailable
150-
151-
# Grab all DSC resources to filter out of the cache
152-
$filteredResources += $dscResources | Where-Object -Property ModuleName -NE $null | ForEach-Object { [System.String]::Concat($_.ModuleName, '/', $_.Name) }
154+
foreach ($m in $namedModules) {
155+
$DscResources.AddRange(@(Get-DscResource -Module $m))
156+
$Modules.AddRange(@(Get-Module -Name $m -ListAvailable))
153157
}
154158

159+
if ('PSDesiredStateConfiguration' -in $namedModules -and $PSVersionTable.PSVersion.Major -le 5 ) {
160+
# the resources in Windows should only load in Windows PowerShell
161+
# workaround: the binary modules don't have a module name, so we have to special case File and SignatureValidation resources that ship in Windows
162+
$DscResources.AddRange(@(Get-DscResource | Where-Object -Property ParentPath -eq "$env:windir\system32\Configuration\BaseRegistration"))
163+
$filteredResources = @(
164+
'PSDesiredStateConfiguration/File'
165+
'PSDesiredStateConfiguration/SignatureValidation'
166+
)
167+
}
168+
# Grab all DSC resources to filter out of the cache
169+
$filteredResources += $dscResources | Where-Object -Property ModuleName -NE $null | ForEach-Object { [System.String]::Concat($_.ModuleName, '/', $_.Name) }
155170
# Exclude the one module that was passed in as a parameter
156-
$existingDscResourceCacheEntries = $cache.ResourceCache | Where-Object -Property Type -NotIn $filteredResources
157-
}
158-
elseif ('PSDesiredStateConfiguration' -eq $module -and $PSVersionTable.PSVersion.Major -le 5 ) {
159-
# the resources in Windows should only load in Windows PowerShell
160-
# workaround: the binary modules don't have a module name, so we have to special case File and SignatureValidation resources that ship in Windows
161-
$DscResources = Get-DscResource | Where-Object { $_.modulename -eq 'PSDesiredStateConfiguration' -or ( $_.modulename -eq $null -and $_.parentpath -like "$env:windir\System32\Configuration\*" ) }
171+
$existingDscResourceCacheEntries = @($cache.ResourceCache | Where-Object -Property Type -NotIn $filteredResources)
162172
}
163173
else {
164174
# if no module is specified, get all resources
@@ -237,26 +247,26 @@ function Invoke-DscCacheRefresh {
237247
$lastWriteTimes.Add($_.FullName, $_.LastWriteTime)
238248
}
239249

240-
$dscResourceCacheEntries += [dscResourceCacheEntry]@{
250+
$dscResourceCacheEntries.Add([dscResourceCacheEntry]@{
241251
Type = "$moduleName/$($dscResource.Name)"
242252
DscResourceInfo = $DscResourceInfo
243253
LastWriteTimes = $lastWriteTimes
254+
})
255+
}
256+
257+
if ($namedModules.Count -gt 0) {
258+
# Make sure all resource cache entries are returned
259+
foreach ($entry in $existingDscResourceCacheEntries) {
260+
$dscResourceCacheEntries.Add([dscResourceCacheEntry]$entry)
244261
}
245262
}
246263

247264
[dscResourceCache]$cache = [dscResourceCache]::new()
248-
$cache.ResourceCache = $dscResourceCacheEntries
265+
$cache.ResourceCache = $dscResourceCacheEntries.ToArray()
249266
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | % { Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue }
250267
$cache.PSModulePaths = $m.FullName
251268
$cache.CacheSchemaVersion = $script:CurrentCacheSchemaVersion
252269

253-
if ($existingDscResourceCacheEntries) {
254-
$cache.ResourceCache += $existingDscResourceCacheEntries
255-
256-
# Make sure all resource cache entries are returned
257-
$dscResourceCacheEntries = $cache.ResourceCache
258-
}
259-
260270
# save cache for future use
261271
# TODO: replace this with a high-performance serializer
262272
"Saving Get-DscResource cache to '$cacheFilePath'" | Write-DscTrace

0 commit comments

Comments
 (0)