tests/Unit/Config/SiteProfile.Tests.ps1
|
#Requires -Modules Pester <# .SYNOPSIS Unit Tests fuer das Standort-Profil (sqmSQLTool.site.json). .DESCRIPTION Standortspezifische Werte (Job-Namen, Freigabepfade, Monitoring-Account, ...) stehen nicht im Code, sondern in einem optionalen, nicht versionierten Standort-Profil. Geprueft wird: - Ohne Profil (oeffentliche Installation) gelten die neutralen Standardwerte. - Mit simuliertem Profil werden Detection, Config und Defaults angewendet. - Der dbatools-Fallback durchsucht die Profil-Freigaben in fester Reihenfolge: DbatoolsShareCandidates (neu) vor DbatoolsLegacyShareCandidates. - Der fruehere CheckProfile-Wert 'FiTs' wird weiter akzeptiert. - Im Code stehen keine Kundenkennungen. Profil-Tests laufen in einem eigenen PowerShell-Prozess mit einer Modulkopie im TEMP-Verzeichnis - das echte %ProgramData%\MSSQLTools wird nie beschrieben. #> BeforeAll { . "$PSScriptRoot\..\..\..\tests\TestHelpers.ps1" Import-sqmTestModule $script:PsExe = (Get-Process -Id $PID).Path # Modulkopie mit optionalem Standort-Profil anlegen, in neuem Prozess importieren und # das Ergebnis (Konfiguration, PSModulePath-Spitze, dbatools-Pfad) als JSON zurueckgeben. function Invoke-SiteProfileImport { param( [hashtable]$SiteProfile, [switch]$WithFakeDbatoolsShares ) $root = Join-Path ([IO.Path]::GetTempPath()) ("sqmSiteTest_" + [guid]::NewGuid().ToString('N')) $modDir = Join-Path $root 'sqmSQLTool' New-Item -ItemType Directory -Path $modDir -Force | Out-Null foreach ($item in @('sqmSQLTool.psm1', 'sqmSQLTool.psd1', 'Public', 'Private', 'jobs', 'Tools', 'Assets')) { $src = Join-Path $script:ModuleRoot $item if (Test-Path $src) { Copy-Item -Path $src -Destination $modDir -Recurse -Force } } $shares = @{} if ($WithFakeDbatoolsShares) { # new1 fehlt, new2 + legacy1 haben ein (Fake-)dbatools - new2 muss gewinnen foreach ($name in 'new1', 'new2', 'legacy1') { $shares[$name] = Join-Path $root "share_$name" } foreach ($name in 'new2', 'legacy1') { $fake = Join-Path $shares[$name] 'dbatools' New-Item -ItemType Directory -Path $fake -Force | Out-Null Set-Content -Path (Join-Path $fake 'dbatools.psm1') -Value "function Get-FakeDbaShare { '$name' }" } $SiteProfile['DbatoolsShareCandidates'] = @($shares['new1'], $shares['new2']) $SiteProfile['DbatoolsLegacyShareCandidates'] = @($shares['legacy1']) } if ($SiteProfile) { $SiteProfile | ConvertTo-Json -Depth 5 | Set-Content -Path (Join-Path $modDir 'sqmSQLTool.site.json') -Encoding UTF8 } $script = @" `$env:SQMSQLTOOL_SKIP_AUTO_UPDATE = '1' if ('$([bool]$WithFakeDbatoolsShares)' -eq 'True') { # Kein echtes dbatools erreichbar machen, damit der Freigabe-Fallback greift `$env:PSModulePath = (`$env:PSModulePath -split ';' | Where-Object { -not (Test-Path (Join-Path `$_ 'dbatools')) }) -join ';' } Import-Module '$modDir\sqmSQLTool.psm1' -Force -WarningAction SilentlyContinue -DisableNameChecking `$cfg = Get-sqmConfig [PSCustomObject]@{ OlaJobNameFull = `$cfg['OlaJobNameFull'] OlaJobNameBackupExcludeSync = `$cfg['OlaJobNameBackupExcludeSync'] MonitoringRegistrySubKey = `$cfg['MonitoringRegistrySubKey'] DefaultMonitoringUser = `$cfg['DefaultMonitoringUser'] CheckProfile = `$cfg['CheckProfile'] DbatoolsSharePath = `$cfg['DbatoolsSharePath'] PSModulePathHead = (`$env:PSModulePath -split ';')[0] FakeDbaShare = if (Get-Command Get-FakeDbaShare -ErrorAction SilentlyContinue) { Get-FakeDbaShare } else { `$null } } | ConvertTo-Json -Compress "@ $scriptFile = Join-Path $root 'run.ps1' Set-Content -Path $scriptFile -Value $script -Encoding UTF8 try { $out = & $script:PsExe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File $scriptFile 2>$null $json = @($out) | Where-Object { $_ -like '{*' } | Select-Object -Last 1 [PSCustomObject]@{ Result = ($json | ConvertFrom-Json); Root = $root; Shares = $shares } } finally { Remove-Item -Path $root -Recurse -Force -ErrorAction SilentlyContinue } } } AfterAll { if (Get-Module sqmSQLTool) { Remove-Module sqmSQLTool -Force } } Describe 'Standort-Profil' { It 'ohne Profil gelten die neutralen Standardwerte' { $r = (Invoke-SiteProfileImport).Result $r | Should -Not -BeNullOrEmpty $r.OlaJobNameBackupExcludeSync | Should -Be 'sqm BackupExclude - SYNC' $r.MonitoringRegistrySubKey | Should -Be 'sqmSQLTool\SystemCenter' $r.CheckProfile | Should -Be 'Auto' } It 'wendet Config an, wenn Detection.ModulePathPatterns passt (inkl. %VAR%-Expansion und FiTs-Alias)' { $siteProf = @{ Detection = @{ ModulePathPatterns = @("$([IO.Path]::GetTempPath())sqmSiteTest_*") } Defaults = @{ MonitoringRegistrySubKey = 'SiteMon\SystemCenter' } Config = @{ OlaJobNameFull = 'SITE Backup - USER_DATABASES - FULL' OlaJobNameBackupExcludeSync = 'SITE BackupExclude - SYNC' DefaultMonitoringUser = '%USERDOMAIN%\monuser' CheckProfile = 'FiTs' } } $r = (Invoke-SiteProfileImport -SiteProfile $siteProf).Result $r.OlaJobNameFull | Should -Be 'SITE Backup - USER_DATABASES - FULL' $r.OlaJobNameBackupExcludeSync | Should -Be 'SITE BackupExclude - SYNC' $r.MonitoringRegistrySubKey | Should -Be 'SiteMon\SystemCenter' $r.DefaultMonitoringUser | Should -Be "$env:USERDOMAIN\monuser" $r.CheckProfile | Should -Be 'Site' } It 'wendet Config NICHT an, wenn Detection nicht passt (Defaults gelten trotzdem)' { $siteProf = @{ Detection = @{ ModulePathPatterns = @('Q:\NoSuchDrive\*'); UserDomains = @('NO-SUCH-DOMAIN-X') } Defaults = @{ MonitoringRegistrySubKey = 'SiteMon\SystemCenter' } Config = @{ OlaJobNameFull = 'SITE Backup - USER_DATABASES - FULL' } } $r = (Invoke-SiteProfileImport -SiteProfile $siteProf).Result $r.OlaJobNameFull | Should -Not -Be 'SITE Backup - USER_DATABASES - FULL' $r.MonitoringRegistrySubKey | Should -Be 'SiteMon\SystemCenter' } It 'dbatools-Fallback: erster vorhandener neuer Pfad vor Legacy-Pfad' { $siteProf = @{ Detection = @{ ModulePathPatterns = @('Q:\NoSuchDrive\*') } } $run = Invoke-SiteProfileImport -SiteProfile $siteProf -WithFakeDbatoolsShares $run.Result.PSModulePathHead | Should -Be $run.Shares['new2'] $run.Result.FakeDbaShare | Should -Be 'new2' } } Describe 'Set-sqmConfig -CheckProfile' { It 'akzeptiert den frueheren Wert FiTs und speichert Site' { InModuleScope sqmSQLTool { $configFile = Join-Path $env:APPDATA 'MSSQLTools\config.json' $backup = if (Test-Path $configFile) { Get-Content $configFile -Raw } else { $null } $saved = $script:sqmModuleConfig['CheckProfile'] try { Set-sqmConfig -CheckProfile 'FiTs' -Confirm:$false $script:sqmModuleConfig['CheckProfile'] | Should -Be 'Site' (Get-Content $configFile -Raw | ConvertFrom-Json).CheckProfile | Should -Be 'Site' } finally { $script:sqmModuleConfig['CheckProfile'] = $saved if ($null -ne $backup) { Set-Content -Path $configFile -Value $backup -NoNewline } else { Remove-Item $configFile -Force -ErrorAction SilentlyContinue } } } } } Describe 'Keine Kundenkennungen im Code' { It 'Code-Dateien enthalten keine Kundennamen, Kundenpfade oder Kundendomaenen' { # Muster zusammengesetzt, damit diese Datei sich nicht selbst meldet $markers = @(('FI' + '-TS'), ('750' + '84'), ('\bFI' + 'TS\b'), ('OFFICE' + 'LAN'), ('izt' + '0504'), ('DWP' + '1W'), ('SUEB' + '0')) $pattern = $markers -join '|' $files = Get-ChildItem -Path $script:ModuleRoot -Recurse -File -Include '*.ps1', '*.psm1', '*.psd1', '*.cmd', '*.json' | Where-Object { $_.FullName -notmatch '\\(bin|\.git|Docs)\\' -and $_.Name -ne 'sqmSQLTool.site.json' } $hits = foreach ($f in $files) { Select-String -Path $f.FullName -Pattern $pattern -CaseSensitive | ForEach-Object { "$($f.Name):$($_.LineNumber)" } } $hits | Should -BeNullOrEmpty } } |