Skip to content

Commit 35dabc9

Browse files
authored
Merge pull request #787 from haodeon/fix/diff-get-all
fix: win_psDscAdapter targeted module cache refreshes
2 parents e0a71a8 + cf7574e commit 35dabc9

File tree

1 file changed

+64
-62
lines changed

1 file changed

+64
-62
lines changed

powershell-adapter/psDscAdapter/win_psDscAdapter.psm1

Lines changed: 64 additions & 62 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) {
@@ -73,51 +73,53 @@ function Invoke-DscCacheRefresh {
7373
"Filtered DscResourceCache cache is empty" | Write-DscTrace
7474
}
7575
else {
76-
"Checking cache for stale entries" | Write-DscTrace
76+
"Checking cache for stale PSModulePath" | Write-DscTrace
77+
78+
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | ForEach-Object { Get-ChildItem -Directory -Path $_ -Depth 1 -ErrorAction Ignore }
79+
80+
$hs_cache = [System.Collections.Generic.HashSet[string]]($cache.PSModulePaths)
81+
$hs_live = [System.Collections.Generic.HashSet[string]]($m.FullName)
82+
$hs_cache.SymmetricExceptWith($hs_live)
83+
$diff = $hs_cache
84+
85+
"PSModulePath diff '$diff'" | Write-DscTrace
86+
# TODO: Optimise for named module refresh
87+
if ($diff.Count -gt 0) {
88+
$refreshCache = $true
89+
}
7790

78-
foreach ($cacheEntry in $dscResourceCacheEntries) {
91+
if (-not $refreshCache) {
92+
"Checking cache for stale entries" | Write-DscTrace
7993

80-
$cacheEntry.LastWriteTimes.PSObject.Properties | ForEach-Object {
94+
foreach ($cacheEntry in $dscResourceCacheEntries) {
8195

82-
if (Test-Path $_.Name) {
83-
$file_LastWriteTime = (Get-Item $_.Name).LastWriteTimeUtc
84-
# Truncate DateTime to seconds
85-
$file_LastWriteTime = $file_LastWriteTime.AddTicks( - ($file_LastWriteTime.Ticks % [TimeSpan]::TicksPerSecond));
96+
foreach ($_ in $cacheEntry.LastWriteTimes.PSObject.Properties) {
8697

87-
$cache_LastWriteTime = [DateTime]$_.Value
88-
# Truncate DateTime to seconds
89-
$cache_LastWriteTime = $cache_LastWriteTime.AddTicks( - ($cache_LastWriteTime.Ticks % [TimeSpan]::TicksPerSecond));
98+
if (Test-Path $_.Name) {
99+
$file_LastWriteTime = (Get-Item $_.Name).LastWriteTime.ToFileTime()
100+
$cache_LastWriteTime = [long]$_.Value
90101

91-
if (-not ($file_LastWriteTime.Equals($cache_LastWriteTime))) {
92-
"Detected stale cache entry '$($_.Name)'" | Write-DscTrace
93-
$refreshCache = $true
102+
if ($file_LastWriteTime -ne $cache_LastWriteTime) {
103+
"Detected stale cache entry '$($_.Name)'" | Write-DscTrace
104+
$namedModules.Add($cacheEntry.DscResourceInfo.ModuleName)
105+
break
106+
}
107+
}
108+
else {
109+
"Detected non-existent cache entry '$($_.Name)'" | Write-DscTrace
110+
$namedModules.Add($cacheEntry.DscResourceInfo.ModuleName)
94111
break
95112
}
96113
}
97-
else {
98-
"Detected non-existent cache entry '$($_.Name)'" | Write-DscTrace
99-
$refreshCache = $true
100-
break
101-
}
102114
}
103-
104-
if ($refreshCache) { break }
105115
}
106-
107-
if (-not $refreshCache) {
108-
"Checking cache for stale PSModulePath" | Write-DscTrace
109-
110-
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | % { Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue }
111-
112-
$hs_cache = [System.Collections.Generic.HashSet[string]]($cache.PSModulePaths)
113-
$hs_live = [System.Collections.Generic.HashSet[string]]($m.FullName)
114-
$hs_cache.SymmetricExceptWith($hs_live)
115-
$diff = $hs_cache
116-
117-
"PSModulePath diff '$diff'" | Write-DscTrace
118-
if ($diff.Count -gt 0) {
119-
$refreshCache = $true
116+
if ($namedModules.Count -gt 0) {
117+
$refreshCache = $true
118+
if ($null -ne $Module) {
119+
$namedModules.AddRange(@($Module))
120120
}
121+
$namedModules = $namedModules | Sort-Object -Unique
122+
"Module list: $($namedModules -join ', ')" | Write-DscTrace
121123
}
122124
}
123125
}
@@ -131,32 +133,32 @@ function Invoke-DscCacheRefresh {
131133
'Constructing Get-DscResource cache' | Write-DscTrace
132134

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

136138
# improve by performance by having the option to only get details for named modules
137139
# workaround for File and SignatureValidation resources that ship in Windows
138-
if ($null -ne $module -and 'PSDesiredStateConfiguration' -ne $module) {
139-
if ($module.gettype().name -eq 'string') {
140-
$module = @($module)
141-
}
140+
if ($namedModules.Count -gt 0) {
142141
$DscResources = [System.Collections.Generic.List[Object]]::new()
143142
$Modules = [System.Collections.Generic.List[Object]]::new()
144143
$filteredResources = @()
145-
foreach ($m in $module) {
146-
$DscResources += Get-DscResource -Module $m
147-
$Modules += Get-Module -Name $m -ListAvailable
148-
149-
# Grab all DSC resources to filter out of the cache
150-
$filteredResources += $dscResources | Where-Object -Property ModuleName -NE $null | ForEach-Object { [System.String]::Concat($_.ModuleName, '/', $_.Name) }
144+
foreach ($m in $namedModules) {
145+
$DscResources.AddRange(@(Get-DscResource -Module $m))
146+
$Modules.AddRange(@(Get-Module -Name $m -ListAvailable))
151147
}
152148

149+
if ('PSDesiredStateConfiguration' -in $namedModules -and $PSVersionTable.PSVersion.Major -le 5 ) {
150+
# the resources in Windows should only load in Windows PowerShell
151+
# workaround: the binary modules don't have a module name, so we have to special case File and SignatureValidation resources that ship in Windows
152+
$DscResources.AddRange(@(Get-DscResource | Where-Object -Property ParentPath -eq "$env:windir\system32\Configuration\BaseRegistration"))
153+
$filteredResources = @(
154+
'PSDesiredStateConfiguration/File'
155+
'PSDesiredStateConfiguration/SignatureValidation'
156+
)
157+
}
158+
# Grab all DSC resources to filter out of the cache
159+
$filteredResources += $dscResources | Where-Object -Property ModuleName -NE $null | ForEach-Object { [System.String]::Concat($_.ModuleName, '/', $_.Name) }
153160
# Exclude the one module that was passed in as a parameter
154-
$existingDscResourceCacheEntries = $cache.ResourceCache | Where-Object -Property Type -NotIn $filteredResources
155-
}
156-
elseif ('PSDesiredStateConfiguration' -eq $module -and $PSVersionTable.PSVersion.Major -le 5 ) {
157-
# the resources in Windows should only load in Windows PowerShell
158-
# workaround: the binary modules don't have a module name, so we have to special case File and SignatureValidation resources that ship in Windows
159-
$DscResources = Get-DscResource | Where-Object { $_.modulename -eq 'PSDesiredStateConfiguration' -or ( $_.modulename -eq $null -and $_.parentpath -like "$env:windir\System32\Configuration\*" ) }
161+
$existingDscResourceCacheEntries = @($cache.ResourceCache | Where-Object -Property Type -NotIn $filteredResources)
160162
}
161163
else {
162164
# if no module is specified, get all resources
@@ -232,29 +234,29 @@ function Invoke-DscCacheRefresh {
232234
# fill in resource files (and their last-write-times) that will be used for up-do-date checks
233235
$lastWriteTimes = @{}
234236
Get-ChildItem -Recurse -File -Path $dscResource.ParentPath -Include "*.ps1", "*.psd1", "*.psm1", "*.mof" -ea Ignore | % {
235-
$lastWriteTimes.Add($_.FullName, $_.LastWriteTime)
237+
$lastWriteTimes.Add($_.FullName, $_.LastWriteTime.ToFileTime())
236238
}
237239

238-
$dscResourceCacheEntries += [dscResourceCacheEntry]@{
240+
$dscResourceCacheEntries.Add([dscResourceCacheEntry]@{
239241
Type = "$moduleName/$($dscResource.Name)"
240242
DscResourceInfo = $DscResourceInfo
241243
LastWriteTimes = $lastWriteTimes
244+
})
245+
}
246+
247+
if ($namedModules.Count -gt 0) {
248+
# Make sure all resource cache entries are returned
249+
foreach ($entry in $existingDscResourceCacheEntries) {
250+
$dscResourceCacheEntries.Add([dscResourceCacheEntry]$entry)
242251
}
243252
}
244253

245254
[dscResourceCache]$cache = [dscResourceCache]::new()
246-
$cache.ResourceCache = $dscResourceCacheEntries
255+
$cache.ResourceCache = $dscResourceCacheEntries.ToArray()
247256
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | % { Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue }
248257
$cache.PSModulePaths = $m.FullName
249258
$cache.CacheSchemaVersion = $script:CurrentCacheSchemaVersion
250259

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

0 commit comments

Comments
 (0)