Skip to content

Commit 83efbc3

Browse files
authored
Merge pull request #468 from anmenaga/pscacheupdates
PSAdapter cache updates
2 parents 75c80d5 + 84f03ea commit 83efbc3

File tree

4 files changed

+138
-45
lines changed

4 files changed

+138
-45
lines changed

powershell-adapter/Tests/powershellgroup.resource.tests.ps1

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,44 @@ Describe 'PowerShell adapter resource tests' {
8282
$res.actualState.result| % {$_.Name | Should -Not -BeNullOrEmpty}
8383
}
8484

85+
It 'Verify that ClearCache works in PSAdapter' {
86+
# generate the cache
87+
$null = dsc resource list '*' -a Microsoft.DSC/PowerShell
88+
# call the ClearCache operation
89+
$scriptPath = Join-Path $PSScriptRoot '..' 'psDscAdapter' 'powershell.resource.ps1'
90+
$null = & $scriptPath -Operation ClearCache
91+
# verify that PSAdapter does not find the cache
92+
dsc -l debug resource list '*' -a Microsoft.DSC/PowerShell 2> $TestDrive/tracing.txt
93+
$LASTEXITCODE | Should -Be 0
94+
"$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'Cache file not found'
95+
}
96+
97+
It 'Verify that a new PS Cache version results in cache rebuid' {
98+
# generate the cache
99+
$null = dsc resource list '*' -a Microsoft.DSC/PowerShell
100+
# update the version in the cache file
101+
$cacheFilePath = if ($IsWindows) {
102+
# PS 6+ on Windows
103+
Join-Path $env:LocalAppData "dsc\PSAdapterCache.json"
104+
} else {
105+
# either WinPS or PS 6+ on Linux/Mac
106+
if ($PSVersionTable.PSVersion.Major -le 5) {
107+
Join-Path $env:LocalAppData "dsc\WindowsPSAdapterCache.json"
108+
} else {
109+
Join-Path $env:HOME ".dsc" "PSAdapterCache.json"
110+
}
111+
}
112+
$cache = Get-Content -Raw $cacheFilePath | ConvertFrom-Json
113+
$cache.CacheSchemaVersion = 0
114+
$jsonCache = $cache | ConvertTo-Json -Depth 90
115+
New-Item -Force -Path $cacheFilePath -Value $jsonCache -Type File | Out-Null
116+
117+
# verify that a new PS Cache version results in cache rebuid
118+
dsc -l debug resource list '*' -a Microsoft.DSC/PowerShell 2> $TestDrive/tracing.txt
119+
$LASTEXITCODE | Should -Be 0
120+
"$TestDrive/tracing.txt" | Should -FileContentMatchExactly 'Incompatible version of cache in file'
121+
}
122+
85123
It 'Verify inheritance works in class-based resources' {
86124

87125
$r = dsc resource list '*' -a Microsoft.DSC/PowerShell

powershell-adapter/psDscAdapter/powershell.resource.ps1

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[CmdletBinding()]
44
param(
55
[Parameter(Mandatory = $true, Position = 0, HelpMessage = 'Operation to perform. Choose from List, Get, Set, Test, Export, Validate.')]
6-
[ValidateSet('List', 'Get', 'Set', 'Test', 'Export', 'Validate')]
6+
[ValidateSet('List', 'Get', 'Set', 'Test', 'Export', 'Validate', 'ClearCache')]
77
[string]$Operation,
88
[Parameter(Mandatory = $false, Position = 1, ValueFromPipeline = $true, HelpMessage = 'Configuration or resource input in JSON format.')]
99
[string]$jsonInput = '@{}'
@@ -27,6 +27,24 @@ function Write-DscTrace {
2727
'PSPath=' + $PSHome | Write-DscTrace
2828
'PSModulePath=' + $env:PSModulePath | Write-DscTrace
2929

30+
if ($Operation -eq 'ClearCache') {
31+
$cacheFilePath = if ($IsWindows) {
32+
# PS 6+ on Windows
33+
Join-Path $env:LocalAppData "dsc\PSAdapterCache.json"
34+
} else {
35+
# either WinPS or PS 6+ on Linux/Mac
36+
if ($PSVersionTable.PSVersion.Major -le 5) {
37+
Join-Path $env:LocalAppData "dsc\WindowsPSAdapterCache.json"
38+
} else {
39+
Join-Path $env:HOME ".dsc" "PSAdapterCache.json"
40+
}
41+
}
42+
43+
'Deleting cache file ' + $cacheFilePath | Write-DscTrace
44+
Remove-Item -Force -ea SilentlyContinue -Path $cacheFilePath
45+
exit 0
46+
}
47+
3048
if ('Validate' -ne $Operation) {
3149
# write $jsonInput to STDERR for debugging
3250
$trace = @{'Debug' = 'jsonInput=' + $jsonInput } | ConvertTo-Json -Compress

powershell-adapter/psDscAdapter/psDscAdapter.psm1

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT License.
33

4+
$script:CurrentCacheSchemaVersion = 1
5+
46
function Write-DscTrace {
57
param(
68
[Parameter(Mandatory = $false)]
@@ -242,47 +244,53 @@ function Invoke-DscCacheRefresh {
242244
"Reading from Get-DscResource cache file $cacheFilePath" | Write-DscTrace
243245

244246
$cache = Get-Content -Raw $cacheFilePath | ConvertFrom-Json
245-
$dscResourceCacheEntries = $cache.ResourceCache
246247

247-
if ($dscResourceCacheEntries.Count -eq 0) {
248-
# if there is nothing in the cache file - refresh cache
248+
if ($cache.CacheSchemaVersion -ne $script:CurrentCacheSchemaVersion) {
249249
$refreshCache = $true
250+
"Incompatible version of cache in file '"+$cache.CacheSchemaVersion+"' (expected '"+$script:CurrentCacheSchemaVersion+"')" | Write-DscTrace
251+
} else {
252+
$dscResourceCacheEntries = $cache.ResourceCache
250253

251-
"Filtered DscResourceCache cache is empty" | Write-DscTrace
252-
}
253-
else
254-
{
255-
"Checking cache for stale entries" | Write-DscTrace
254+
if ($dscResourceCacheEntries.Count -eq 0) {
255+
# if there is nothing in the cache file - refresh cache
256+
$refreshCache = $true
256257

257-
foreach ($cacheEntry in $dscResourceCacheEntries) {
258-
#"Checking cache entry '$($cacheEntry.Type) $($cacheEntry.LastWriteTimes)'" | Write-DscTrace -Operation Trace
258+
"Filtered DscResourceCache cache is empty" | Write-DscTrace
259+
}
260+
else
261+
{
262+
"Checking cache for stale entries" | Write-DscTrace
259263

260-
$cacheEntry.LastWriteTimes.PSObject.Properties | ForEach-Object {
261-
262-
if (-not ((Get-Item $_.Name).LastWriteTime.Equals([DateTime]$_.Value)))
263-
{
264-
"Detected stale cache entry '$($_.Name)'" | Write-DscTrace
265-
$refreshCache = $true
266-
break
264+
foreach ($cacheEntry in $dscResourceCacheEntries) {
265+
#"Checking cache entry '$($cacheEntry.Type) $($cacheEntry.LastWriteTimes)'" | Write-DscTrace -Operation Trace
266+
267+
$cacheEntry.LastWriteTimes.PSObject.Properties | ForEach-Object {
268+
269+
if (-not ((Get-Item $_.Name).LastWriteTime.Equals([DateTime]$_.Value)))
270+
{
271+
"Detected stale cache entry '$($_.Name)'" | Write-DscTrace
272+
$refreshCache = $true
273+
break
274+
}
267275
}
268-
}
269276

270-
if ($refreshCache) {break}
271-
}
277+
if ($refreshCache) {break}
278+
}
272279

273-
"Checking cache for stale PSModulePath" | Write-DscTrace
280+
"Checking cache for stale PSModulePath" | Write-DscTrace
274281

275-
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | %{Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue}
282+
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | %{Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue}
276283

277-
$hs_cache = [System.Collections.Generic.HashSet[string]]($cache.PSModulePaths)
278-
$hs_live = [System.Collections.Generic.HashSet[string]]($m.FullName)
279-
$hs_cache.SymmetricExceptWith($hs_live)
280-
$diff = $hs_cache
284+
$hs_cache = [System.Collections.Generic.HashSet[string]]($cache.PSModulePaths)
285+
$hs_live = [System.Collections.Generic.HashSet[string]]($m.FullName)
286+
$hs_cache.SymmetricExceptWith($hs_live)
287+
$diff = $hs_cache
281288

282-
"PSModulePath diff '$diff'" | Write-DscTrace
289+
"PSModulePath diff '$diff'" | Write-DscTrace
283290

284-
if ($diff.Count -gt 0) {
285-
$refreshCache = $true
291+
if ($diff.Count -gt 0) {
292+
$refreshCache = $true
293+
}
286294
}
287295
}
288296
}
@@ -330,6 +338,7 @@ function Invoke-DscCacheRefresh {
330338
$cache.ResourceCache = $dscResourceCacheEntries
331339
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | %{Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue}
332340
$cache.PSModulePaths = $m.FullName
341+
$cache.CacheSchemaVersion = $script:CurrentCacheSchemaVersion
333342

334343
# save cache for future use
335344
# TODO: replace this with a high-performance serializer
@@ -494,6 +503,7 @@ class dscResourceCacheEntry {
494503
}
495504

496505
class dscResourceCache {
506+
[int] $CacheSchemaVersion
497507
[string[]] $PSModulePaths
498508
[dscResourceCacheEntry[]] $ResourceCache
499509
}

powershell-adapter/psDscAdapter/win_psDscAdapter.psm1

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT License.
33

4+
$script:CurrentCacheSchemaVersion = 1
5+
46
function Write-DscTrace {
57
param(
68
[Parameter(Mandatory = $false)]
@@ -68,13 +70,16 @@ function Invoke-DscCacheRefresh {
6870
"Reading from Get-DscResource cache file $cacheFilePath" | Write-DscTrace
6971

7072
$cache = Get-Content -Raw $cacheFilePath | ConvertFrom-Json
71-
$dscResourceCacheEntries = $cache.ResourceCache
72-
73-
if ($dscResourceCacheEntries.Count -eq 0) {
74-
# if there is nothing in the cache file - refresh cache
73+
if ($cache.CacheSchemaVersion -ne $script:CurrentCacheSchemaVersion) {
7574
$refreshCache = $true
75+
"Incompartible version of cache in file '"+$cache.CacheSchemaVersion+"' (expected '"+$script:CurrentCacheSchemaVersion+"')" | Write-DscTrace
76+
} else {
77+
$dscResourceCacheEntries = $cache.ResourceCache
7678

77-
"Filtered DscResourceCache cache is empty" | Write-DscTrace
79+
if ($dscResourceCacheEntries.Count -eq 0) {
80+
# if there is nothing in the cache file - refresh cache
81+
$refreshCache = $true
82+
"Filtered DscResourceCache cache is empty" | Write-DscTrace
7883
}
7984
else
8085
{
@@ -93,22 +98,42 @@ function Invoke-DscCacheRefresh {
9398
}
9499
}
95100

96-
if ($refreshCache) {break}
101+
"Filtered DscResourceCache cache is empty" | Write-DscTrace
97102
}
103+
else
104+
{
105+
"Checking cache for stale entries" | Write-DscTrace
98106

99-
"Checking cache for stale PSModulePath" | Write-DscTrace
107+
foreach ($cacheEntry in $dscResourceCacheEntries) {
108+
"Checking cache entry '$($cacheEntry.Type) $($cacheEntry.LastWriteTimes)'" | Write-DscTrace -Operation Trace
100109

101-
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | %{Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue}
110+
$cacheEntry.LastWriteTimes.PSObject.Properties | ForEach-Object {
111+
112+
if (-not ((Get-Item $_.Name).LastWriteTime.Equals([DateTime]$_.Value)))
113+
{
114+
"Detected stale cache entry '$($_.Name)'" | Write-DscTrace
115+
$refreshCache = $true
116+
break
117+
}
118+
}
102119

103-
$hs_cache = [System.Collections.Generic.HashSet[string]]($cache.PSModulePaths)
104-
$hs_live = [System.Collections.Generic.HashSet[string]]($m.FullName)
105-
$hs_cache.SymmetricExceptWith($hs_live)
106-
$diff = $hs_cache
120+
if ($refreshCache) {break}
121+
}
107122

108-
"PSModulePath diff '$diff'" | Write-DscTrace
123+
"Checking cache for stale PSModulePath" | Write-DscTrace
109124

110-
if ($diff.Count -gt 0) {
111-
$refreshCache = $true
125+
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | %{Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue}
126+
127+
$hs_cache = [System.Collections.Generic.HashSet[string]]($cache.PSModulePaths)
128+
$hs_live = [System.Collections.Generic.HashSet[string]]($m.FullName)
129+
$hs_cache.SymmetricExceptWith($hs_live)
130+
$diff = $hs_cache
131+
132+
"PSModulePath diff '$diff'" | Write-DscTrace
133+
134+
if ($diff.Count -gt 0) {
135+
$refreshCache = $true
136+
}
112137
}
113138
}
114139
}
@@ -223,6 +248,7 @@ function Invoke-DscCacheRefresh {
223248
$cache.ResourceCache = $dscResourceCacheEntries
224249
$m = $env:PSModulePath -split [IO.Path]::PathSeparator | %{Get-ChildItem -Directory -Path $_ -Depth 1 -ea SilentlyContinue}
225250
$cache.PSModulePaths = $m.FullName
251+
$cache.CacheSchemaVersion = $script:CurrentCacheSchemaVersion
226252

227253
# save cache for future use
228254
# TODO: replace this with a high-performance serializer
@@ -472,6 +498,7 @@ class dscResourceCacheEntry {
472498
}
473499

474500
class dscResourceCache {
501+
[int] $CacheSchemaVersion
475502
[string[]] $PSModulePaths
476503
[dscResourceCacheEntry[]] $ResourceCache
477504
}

0 commit comments

Comments
 (0)