diff --git a/developing/Robs-Instance.ps1 b/developing/Robs-Instance.ps1 index ce81fba5..39777bf5 100644 --- a/developing/Robs-Instance.ps1 +++ b/developing/Robs-Instance.ps1 @@ -14,6 +14,8 @@ $Checks = 'HideInstance' $Checks = 'LoginAuditFailed' $Checks = 'LoginAuditSuccessful' $Checks = 'LoginCheckPolicy' +$Checks = 'SuspectPageLimit' +$Checks = 'SupportedBuild' $Checks = 'LoginAuditSuccessful', 'LoginAuditFailed' Invoke-PerfAndValidateCheck -Checks $Checks diff --git a/source/checks/Instancev5.Tests.ps1 b/source/checks/Instancev5.Tests.ps1 index 749f4fbf..e27554e2 100644 --- a/source/checks/Instancev5.Tests.ps1 +++ b/source/checks/Instancev5.Tests.ps1 @@ -375,6 +375,29 @@ Describe "SQL Mail XPs Disabled" -Tag SQLMailXPsDisabled, Security, CIS, Low, In } } +Describe "Supported Build" -Tag SupportedBuild, DISA, High, Instance -ForEach $InstancesToTest { + $skip = ($__dbcconfig | Where-Object { $_.Name -eq 'skip.instance.SupportedBuild' }).Value + Context "Checking that build is still supported by Microsoft for <_.Name>" -Skip:$skip { + It "The build is not behind the latest build by more than <_.SupportedBuild.BuildBehind> for <_.Name>" { + $psItem.SupportedBuild.Compliant | Should -BeTrue -Because "this build $($psItem.SupportedBuild.Build) should not be behind the required build" + } + It "The build is supported by Microsoft for <_.Name>" { + $psItem.SupportedBuild.InsideMicrosoftSupport | Should -BeTrue -Because "this build $($psItem.SupportedBuild.Build) is now unsupported by Microsoft" + } + It "The build is supported by Microsoft within the warning window of <_.SupportedBuild.BuildWarning> months for <_.Name>" { + $psItem.SupportedBuild.InsideBuildWarning | Should -BeTrue -Because "this build $($psItem.SupportedBuild.Build) will be unsupported by Microsoft on $($psItem.SupportedBuild.SupportedUntil) which is less than $($psItem.SupportedBuild.BuildWarning) months away" + } + } +} + +Describe "Suspect Page Limit Nearing" -Tag SuspectPageLimit, Medium, Instance -ForEach $InstancesToTest { + $skip = ($__dbcconfig | Where-Object { $_.Name -eq 'skip.instance.suspectpagelimit' }).Value + Context "Testing if the suspect_pages table is nearing the limit of 1000 rows on on <_.Name>" { + It "The suspect_pages table in msdb shouldn't be nearing the limit of 1000 rows on on <_.Name>" -Skip:$skip { + $PSItem.SuspectPageCountResult | Should -BeTrue -Because "The suspect_pages table in msdb shouldn't be nearing the limit of 1000 rows" + } + } +} Describe "Trace Flags Expected" -Tag TraceFlagsExpected, TraceFlag, High, Instance -ForEach $InstancesToTest { $skip = ($__dbcconfig | Where-Object { $_.Name -eq 'skip.instance.TraceFlagsExpected' }).Value Context "Testing Expected Trace Flags on <_.Name>" { diff --git a/source/internal/configurations/configuration.ps1 b/source/internal/configurations/configuration.ps1 index 7c62a398..09453b0f 100644 --- a/source/internal/configurations/configuration.ps1 +++ b/source/internal/configurations/configuration.ps1 @@ -288,6 +288,7 @@ Set-PSFConfig -Module dbachecks -Name skip.instance.linkedserverconnection -Vali Set-PSFConfig -Module dbachecks -Name skip.instance.maxmemory -Validation bool -Value $false -Initialize -Description "Skip the check for max memory" Set-PSFConfig -Module dbachecks -Name skip.instance.orphanedfile -Validation bool -Value $false -Initialize -Description "Skip the check for orphaned file" Set-PSFConfig -Module dbachecks -Name skip.instance.servernamematch -Validation bool -Value $false -Initialize -Description "Skip the check for server name match" +Set-PSFConfig -Module dbachecks -Name skip.instance.supportedbuild -Validation bool -Value $false -Initialize -Description "Skip the checks for supported build" diff --git a/source/internal/functions/NewGet-AllInstanceInfo.ps1 b/source/internal/functions/NewGet-AllInstanceInfo.ps1 index f525ef8b..0f10de12 100644 --- a/source/internal/functions/NewGet-AllInstanceInfo.ps1 +++ b/source/internal/functions/NewGet-AllInstanceInfo.ps1 @@ -416,26 +416,71 @@ function NewGet-AllInstanceInfo { $Instance.SetDefaultInitFields([Microsoft.SqlServer.Management.Smo.Settings], $LoginInitFields) } + 'SuspectPageLimit' { + $sql = "Select + COUNT(file_id) as 'SuspectPageCount' + from msdb.dbo.suspect_pages" + $SuspectPageCountResult = (($Instance.Query($sql).SuspectPageCount / 1000) * 100 ) -lt ($__dbcconfig | Where-Object { $_.Name -eq 'policy.suspectpage.threshold' }).Value + } + + 'SupportedBuild' { + $BuildWarning = ($__dbcconfig | Where-Object { $_.Name -eq 'policy.build.warningwindow' }).Value + $BuildBehind = ($__dbcconfig | Where-Object { $_.Name -eq 'policy.build.behind' }).Value + $Date = Get-Date + #If $BuildBehind check against SP/CU parameter to determine validity of the build + if ($BuildBehind) { + $buildBehindResults = Test-DbaBuild -SqlInstance $Instance -SqlCredential $sqlcredential -MaxBehind $BuildBehind + $Compliant = $buildBehindResults.Compliant + + #If no $BuildBehind only check against support dates + } else { + $Compliant = $true + } + + $Results = Test-DbaBuild -SqlInstance $Instance -SqlCredential $sqlcredential -Latest + [DateTime]$SupportedUntil = Get-Date $results.SupportedUntil -Format O + $Build = $results.build + #If $BuildWarning, check for support date within the warning window + if ($BuildWarning) { + [DateTime]$expected = Get-Date ($Date).AddMonths($BuildWarning) -Format O + $SupportedUntil | Should -BeGreaterThan $expected -Because "this build $Build will be unsupported by Microsoft on $(Get-Date $SupportedUntil -Format O) which is less than $BuildWarning months away" + } else { + #If neither, check for Microsoft support date + $SupportedUntil | Should -BeGreaterThan $Date -Because "this build $Build is now unsupported by Microsoft" + } + + $SupportedBuild = [pscustomobject]@{ + BuildBehind = $BuildBehind + Compliant = $Compliant + Build = $Build + SupportedUntil = $SupportedUntil + Expected = $expected + BuildWarning = $BuildWarning + InsideBuildWarning = $SupportedUntil -gt $expected + InsideMicrosoftSupport = $SupportedUntil -gt $Date + } + } + Default { } } #build the object $testInstanceObject = [PSCustomObject]@{ - ComputerName = $Instance.ComputerName - InstanceName = $Instance.DbaInstanceName - Name = $Instance.Name - ConfigValues = $ConfigValues - VersionMajor = $Instance.VersionMajor - Configuration = if ($configurations) { $Instance.Configuration } else { $null } - Settings = $Instance.Settings - Logins = $Instance.Logins - Databases = $Instance.Databases - NumberOfLogFiles = $Instance.NumberOfLogFiles - MaxDopSettings = $MaxDopSettings - ExpectedTraceFlags = $ExpectedTraceFlags - NotExpectedTraceFlags = $NotExpectedTraceFlags - XESessions = [pscustomobject]@{ + ComputerName = $Instance.ComputerName + InstanceName = $Instance.DbaInstanceName + Name = $Instance.Name + ConfigValues = $ConfigValues + VersionMajor = $Instance.VersionMajor + Configuration = if ($configurations) { $Instance.Configuration } else { $null } + Settings = $Instance.Settings + Logins = $Instance.Logins + Databases = $Instance.Databases + NumberOfLogFiles = $Instance.NumberOfLogFiles + MaxDopSettings = $MaxDopSettings + ExpectedTraceFlags = $ExpectedTraceFlags + NotExpectedTraceFlags = $NotExpectedTraceFlags + XESessions = [pscustomobject]@{ RequiredStopped = $RequiredStopped.ForEach{ [pscustomobject]@{ Name = $Instance.Name @@ -470,23 +515,23 @@ function NewGet-AllInstanceInfo { Sessions = $Sessions Running = $RunningSessions } - ErrorLogEntries = [pscustomobject]@{ + ErrorLogEntries = [pscustomobject]@{ errorLogCount = $ErrorLogCount logWindow = $logWindow } - InstanceConnection = $InstanceConnection - BackupPathAccess = [pscustomobject]@{ + InstanceConnection = $InstanceConnection + BackupPathAccess = [pscustomobject]@{ Result = $BackupPathAccess BackupPath = $BackupPath } - LatestBuild = [PSCustomObject]@{ + LatestBuild = [PSCustomObject]@{ Compliant = $LatestBuild.Compliant } - NetworkLatency = [PSCustomObject]@{ + NetworkLatency = [PSCustomObject]@{ Latency = $Latency Threshold = $NetworkThreshold } - LinkedServerResults = if ($LinkedServerResults) { + LinkedServerResults = if ($LinkedServerResults) { $LinkedServerResults.ForEach{ [pscustomobject]@{ InstanceName = $Instance.Name @@ -505,17 +550,19 @@ function NewGet-AllInstanceInfo { Result = 'None' } } - MaxMemory = $MaxMemory - OrphanedFile = [pscustomobject]@{ + MaxMemory = $MaxMemory + OrphanedFile = [pscustomobject]@{ FileCount = $FileCount } - ServerNameMatch = [pscustomobject]@{ + ServerNameMatch = [pscustomobject]@{ configuredServerName = $ServerNameMatchconfiguredServerName netName = $ServerNameMatchnetName renamerequired = $ServerNameMatchrenamerequired } - MemoryDump = $Dump - HideInstance = $HideInstance + MemoryDump = $Dump + HideInstance = $HideInstance + SuspectPageCountResult = $SuspectPageCountResult + SupportedBuild = $SupportedBuild # TempDbConfig = [PSCustomObject]@{ # TF118EnabledCurrent = $tempDBTest[0].CurrentSetting # TF118EnabledRecommended = $tempDBTest[0].Recommended