diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b9197c74a..4a98f188a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,6 +130,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- `DSC_SqlRS` + - Fixed intermittent initialization failures on resource-constrained systems + (particularly Windows Server 2025 in CI) by adding an optional `RestartTimeout` + parameter that allows specifying a wait period (in seconds) after service + restart to allow Reporting Services to fully initialize before attempting + to get configuration data or run initialization methods. The timeout is applied + both after the initial service restart and before calling `InitializeReportServer()` + if needed, giving the WMI provider sufficient time to be ready. When not specified, + no additional wait time is applied, maintaining backward compatibility. - `New-SqlDscAudit` - Fixed parameter validation to prevent the `ReserveDiskSpace` parameter from being used with the `FileWithMaxFiles` parameter set (when only `MaximumFiles` diff --git a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 index b29ae3afe7..0614d502a5 100644 --- a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 +++ b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 @@ -180,6 +180,12 @@ function Get-TargetResource settings change. If this parameter is set to $true, Reporting Services will not be restarted, even after initialization. + .PARAMETER RestartTimeout + The number of seconds to wait after restarting Reporting Services before + continuing with configuration. This is useful on resource-constrained + systems where the service may take longer to fully initialize. If not + specified, no additional wait time is applied after service restart. + .PARAMETER Encrypt Specifies how encryption should be enforced. There are currently no difference between using `Mandatory` or `Strict`. @@ -263,6 +269,10 @@ function Set-TargetResource [System.Boolean] $SuppressRestart, + [Parameter()] + [System.UInt32] + $RestartTimeout, + [Parameter()] [ValidateSet('Mandatory', 'Optional', 'Strict')] [System.String] @@ -526,6 +536,18 @@ function Set-TargetResource Restart-ReportingServicesService -InstanceName $InstanceName -WaitTime 30 + <# + Wait for the service to be fully ready after restart before attempting + to get reporting services data or initialize. This is especially important + on resource-constrained systems where the service may take longer to + fully initialize (e.g., Windows Server 2025 in CI environments). + #> + if ($PSBoundParameters.ContainsKey('RestartTimeout')) + { + Write-Verbose -Message ($script:localizedData.WaitingForServiceReady -f $RestartTimeout) + Start-Sleep -Seconds $RestartTimeout + } + $restartReportingService = $false $reportingServicesData = Get-ReportingServicesData -InstanceName $InstanceName @@ -540,6 +562,17 @@ function Set-TargetResource { Write-Verbose -Message "Did not help restarting the Reporting Services service, running the CIM method to initialize report server on $DatabaseServerName\$DatabaseInstanceName for instance ID '$($reportingServicesData.Configuration.InstallationID)'." + <# + Add an additional wait before calling InitializeReportServer to give + the WMI provider more time to be fully ready. This is especially + important on resource-constrained systems. + #> + if ($PSBoundParameters.ContainsKey('RestartTimeout')) + { + Write-Verbose -Message ($script:localizedData.WaitingForServiceReady -f $RestartTimeout) + Start-Sleep -Seconds $RestartTimeout + } + $restartReportingService = $true $invokeRsCimMethodParameters = @{ @@ -804,6 +837,17 @@ function Set-TargetResource { Write-Verbose -Message $script:localizedData.Restart Restart-ReportingServicesService -InstanceName $InstanceName -WaitTime 30 + + <# + Wait for the service to be fully ready after restart before attempting + to test the configuration. This is especially important on resource-constrained + systems where the service may take longer to fully initialize. + #> + if ($PSBoundParameters.ContainsKey('RestartTimeout')) + { + Write-Verbose -Message ($script:localizedData.WaitingForServiceReady -f $RestartTimeout) + Start-Sleep -Seconds $RestartTimeout + } } } @@ -851,6 +895,9 @@ function Set-TargetResource settings change. If this parameter is set to $true, Reporting Services will not be restarted, even after initialization. + .PARAMETER RestartTimeout + Not used in Test-TargetResource. + .PARAMETER Encrypt Specifies how encryption should be enforced. There are currently no difference between using `Mandatory` or `Strict`. @@ -898,6 +945,10 @@ function Test-TargetResource [System.Boolean] $SuppressRestart, + [Parameter()] + [System.UInt32] + $RestartTimeout, + [Parameter()] [ValidateSet('Mandatory', 'Optional', 'Strict')] [System.String] diff --git a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof index c4d7fdc3a4..deb876cfc5 100644 --- a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof +++ b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.schema.mof @@ -10,6 +10,7 @@ class DSC_SqlRS : OMI_BaseResource [Write, Description("_Report Manager_ or _Report Web App_ URL reservations. Optional. If not specified, `'http://+:80'` URL reservation will be used.")] String ReportsReservedUrl[]; [Write, Description("If connections to the _Reporting Services_ must use SSL. If this parameter is not assigned a value, the default is that _Reporting Services_ does not use SSL.")] Boolean UseSsl; [Write, Description("_Reporting Services_ need to be restarted after initialization or settings change. If this parameter is set to `$true`, _Reporting Services_ will not be restarted, even after initialization.")] Boolean SuppressRestart; + [Write, Description("The number of seconds to wait after restarting _Reporting Services_ before continuing with configuration. This is useful on resource-constrained systems where the service may take longer to fully initialize. If not specified, no additional wait time is applied after service restart.")] UInt32 RestartTimeout; [Write, Description("Specifies how encryption should be enforced when using command `Invoke-SqlCmd`. When not specified, the default value is `Mandatory`."), ValueMap{"Mandatory","Optional","Strict"}, Values{"Mandatory","Optional","Strict"}] String Encrypt; [Read, Description("Returns if the _Reporting Services_ instance initialized or not.")] Boolean IsInitialized; }; diff --git a/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 b/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 index 07dd9a79e5..ed937fa250 100644 --- a/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 +++ b/source/DSCResources/DSC_SqlRS/en-US/DSC_SqlRS.strings.psd1 @@ -5,4 +5,5 @@ ConvertFrom-StringData @' ReportingServicesNotFound = SQL Reporting Services instance '{0}' does not exist. GetConfiguration = Get the current reporting services configuration for the instance '{0}'. RestartToFinishInitialization = Restarting Reporting Services to finish initialization. + WaitingForServiceReady = Waiting {0} seconds for Reporting Services to be fully ready after restart. (DSC_SQLRS0001) '@ diff --git a/tests/Integration/Resources/DSC_SqlRS.config.ps1 b/tests/Integration/Resources/DSC_SqlRS.config.ps1 index 18d6f8cdfe..17ce501c89 100644 --- a/tests/Integration/Resources/DSC_SqlRS.config.ps1 +++ b/tests/Integration/Resources/DSC_SqlRS.config.ps1 @@ -187,6 +187,12 @@ Configuration DSC_SqlRS_ConfigureReportingServices_Config ReportServerReservedUrl = @('http://+:80') + <# + Adding a restart timeout to help with intermittent failures + on resource-constrained CI systems (especially Windows Server 2025). + #> + RestartTimeout = 30 + PsDscRunAsCredential = New-Object ` -TypeName System.Management.Automation.PSCredential ` -ArgumentList @( diff --git a/tests/Integration/Resources/DSC_SqlRS_Default.config.ps1 b/tests/Integration/Resources/DSC_SqlRS_Default.config.ps1 index 77e8884beb..a801ed074c 100644 --- a/tests/Integration/Resources/DSC_SqlRS_Default.config.ps1 +++ b/tests/Integration/Resources/DSC_SqlRS_Default.config.ps1 @@ -185,6 +185,12 @@ Configuration DSC_SqlRS_ConfigureReportingServices_Config DatabaseInstanceName = $Node.DatabaseInstanceName Encrypt = 'Optional' + <# + Adding a restart timeout to help with intermittent failures + on resource-constrained CI systems (especially Windows Server 2025). + #> + RestartTimeout = 30 + PsDscRunAsCredential = New-Object ` -TypeName System.Management.Automation.PSCredential ` -ArgumentList @( diff --git a/tests/Unit/DSC_SqlRS.Tests.ps1 b/tests/Unit/DSC_SqlRS.Tests.ps1 index eacfddc53b..f1a4e3c5e0 100644 --- a/tests/Unit/DSC_SqlRS.Tests.ps1 +++ b/tests/Unit/DSC_SqlRS.Tests.ps1 @@ -513,6 +513,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Mock -CommandName Import-SqlDscPreferredModule Mock -CommandName Invoke-SqlDscQuery Mock -CommandName Restart-ReportingServicesService + Mock -CommandName Start-Sleep Mock -CommandName Invoke-RsCimMethod Mock -CommandName Invoke-RsCimMethod -MockWith $mockInvokeRsCimMethod_GenerateDatabaseCreationScript -ParameterFilter { $MethodName -eq 'GenerateDatabaseCreationScript'