diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f4b366a8b..5b2b32e4f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -177,6 +177,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added public command `Install-SqlDscFailoverCluster` to install SQL Server in a failover cluster configuration. Extracted from `Install-SqlDscServer` InstallFailoverCluster parameter set. +- Added public command `Restart-SqlDscRSService` to restart the Windows service + for SQL Server Reporting Services or Power BI Report Server. Supports waiting + for dependent services, configurable wait time, and accepts pipeline input + from `Get-SqlDscRSConfiguration`. +- Added public command `Test-SqlDscRSInitialized` to test whether a Reporting + Services instance is initialized by checking the `IsInitialized` property of + the configuration CIM instance + ([issue #2014](https://github.com/dsccommunity/SqlServerDsc/issues/2014)). +- Added public command `Initialize-SqlDscRS` to initialize Reporting Services + by calling the `InitializeReportServer` CIM method. Used to complete initial + configuration after database and URL setup + ([issue #2014](https://github.com/dsccommunity/SqlServerDsc/issues/2014)). ### Changed @@ -210,6 +222,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([issue #2017](https://github.com/dsccommunity/SqlServerDsc/issues/2017)) ([issue #2019](https://github.com/dsccommunity/SqlServerDsc/issues/2019)) ([issue #2021](https://github.com/dsccommunity/SqlServerDsc/issues/2021)). + - Refactored to use the public command `Restart-SqlDscRSService` for restarting + the Reporting Services Windows service instead of calling the private + function `Restart-ReportingServicesService` directly. + - Refactored to use the public commands `Test-SqlDscRSInitialized` and + `Initialize-SqlDscRS` for checking and performing Reporting Services + initialization instead of accessing the `IsInitialized` property and + calling the CIM method directly + ([issue #2014](https://github.com/dsccommunity/SqlServerDsc/issues/2014)). - `Assert-SetupActionProperties` - Refactored to use the command `Get-FileVersion` from the DscResource.Common module instead of the private function `Get-FileVersionInformation` diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a0dd77bba4..122febc092 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -552,6 +552,11 @@ stages: 'tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscRSUrlReservation.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscRSDatabaseConnection.Integration.Tests.ps1' + 'tests/Integration/Commands/Restart-SqlDscRSService.Integration.Tests.ps1' + 'tests/Integration/Commands/Request-SqlDscRSDatabaseUpgradeScript.Integration.Tests.ps1' + 'tests/Integration/Commands/Test-SqlDscRSInitialized.Integration.Tests.ps1' + # Group 4 + 'tests/Integration/Commands/Initialize-SqlDscRS.Integration.Tests.ps1' # Group 8 'tests/Integration/Commands/Repair-SqlDscReportingService.Integration.Tests.ps1' # Group 9 @@ -631,6 +636,10 @@ stages: 'tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscRSUrlReservation.Integration.Tests.ps1' 'tests/Integration/Commands/Set-SqlDscRSDatabaseConnection.Integration.Tests.ps1' + 'tests/Integration/Commands/Restart-SqlDscRSService.Integration.Tests.ps1' + 'tests/Integration/Commands/Test-SqlDscRSInitialized.Integration.Tests.ps1' + # Group 4 + 'tests/Integration/Commands/Initialize-SqlDscRS.Integration.Tests.ps1' # Group 8 'tests/Integration/Commands/Repair-SqlDscPowerBIReportServer.Integration.Tests.ps1' # Group 9 diff --git a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 index 8b0d8b5a7e..b63d72fb43 100644 --- a/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 +++ b/source/DSCResources/DSC_SqlRS/DSC_SqlRS.psm1 @@ -80,7 +80,7 @@ function Get-TargetResource $getTargetResourceResult.DatabaseInstanceName = 'MSSQLSERVER' } - $isInitialized = $rsConfiguration.IsInitialized + $isInitialized = $rsConfiguration | Test-SqlDscRSInitialized [System.Boolean] $getTargetResourceResult.IsInitialized = $isInitialized @@ -348,7 +348,7 @@ function Set-TargetResource $language = $wmiOperatingSystem.OSLanguage $restartReportingService = $false - if (-not $rsConfiguration.IsInitialized) + if (-not ($rsConfiguration | Test-SqlDscRSInitialized)) { Write-Verbose -Message "Initializing Reporting Services on $DatabaseServerName\$DatabaseInstanceName." @@ -456,7 +456,7 @@ function Set-TargetResource #> Write-Verbose -Message $script:localizedData.RestartToFinishInitialization - Restart-ReportingServicesService -ServiceName $reportingServicesServiceName -WaitTime 30 + Restart-SqlDscRSService -ServiceName $reportingServicesServiceName -WaitTime 30 -Force <# Wait for the service to be fully ready after restart before attempting @@ -481,7 +481,7 @@ function Set-TargetResource InitializeReportServer will fail on SQL Server Standard and lower editions. #> - if (-not $rsConfiguration.IsInitialized) + if (-not ($rsConfiguration | Test-SqlDscRSInitialized)) { 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 '$($rsConfiguration.InstallationID)'." @@ -498,15 +498,7 @@ function Set-TargetResource $restartReportingService = $true - $invokeRsCimMethodParameters = @{ - CimInstance = $rsConfiguration - MethodName = 'InitializeReportServer' - Arguments = @{ - InstallationId = $rsConfiguration.InstallationID - } - } - - Invoke-RsCimMethod @invokeRsCimMethodParameters -ErrorAction 'Stop' + $rsConfiguration | Initialize-SqlDscRS -Force -ErrorAction 'Stop' } else { @@ -646,7 +638,7 @@ function Set-TargetResource elseif ( $restartReportingService -and (-not $SuppressRestart) ) { Write-Verbose -Message $script:localizedData.Restart - Restart-ReportingServicesService -ServiceName $reportingServicesServiceName -WaitTime 30 + Restart-SqlDscRSService -ServiceName $reportingServicesServiceName -WaitTime 30 -Force <# Wait for the service to be fully ready after restart before attempting @@ -850,81 +842,3 @@ function Test-TargetResource $result } - -<# - .SYNOPSIS - A wrapper for Invoke-CimMethod to be able to handle errors in one place. - - .PARAMETER CimInstance - The CIM instance object that contains the method to call. - - .PARAMETER MethodName - The method to call in the CIM Instance object. - - .PARAMETER Arguments - The arguments that should be -#> -function Invoke-RsCimMethod -{ - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('AvoidThrowOutsideOfTry', '', Justification = 'Because the code throws based on an prior expression')] - [CmdletBinding()] - [OutputType([Microsoft.Management.Infrastructure.CimMethodResult])] - param - ( - - [Parameter(Mandatory = $true)] - [Microsoft.Management.Infrastructure.CimInstance] - $CimInstance, - - [Parameter(Mandatory = $true)] - [System.String] - $MethodName, - - [Parameter()] - [System.Collections.Hashtable] - $Arguments - ) - - $invokeCimMethodParameters = @{ - MethodName = $MethodName - ErrorAction = 'Stop' - } - - if ($PSBoundParameters.ContainsKey('Arguments')) - { - $invokeCimMethodParameters['Arguments'] = $Arguments - } - - $invokeCimMethodResult = $CimInstance | Invoke-CimMethod @invokeCimMethodParameters - - <# - Successfully calling the method returns $invokeCimMethodResult.HRESULT -eq 0. - If an general error occur in the Invoke-CimMethod, like calling a method - that does not exist, returns $null in $invokeCimMethodResult. - - cSpell: ignore HRESULT - #> - if ($invokeCimMethodResult -and $invokeCimMethodResult.HRESULT -ne 0) - { - if ($invokeCimMethodResult | Get-Member -Name 'ExtendedErrors') - { - <# - The returned object property ExtendedErrors is an array - so that needs to be concatenated. - #> - $errorMessage = $invokeCimMethodResult.ExtendedErrors -join ';' - } - else - { - $errorMessage = $invokeCimMethodResult.Error - } - - throw 'Method {0}() failed with an error. Error: {1} (HRESULT:{2})' -f @( - $MethodName - $errorMessage - $invokeCimMethodResult.HRESULT - ) - } - - return $invokeCimMethodResult -} diff --git a/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psd1 b/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psd1 index 6f72c36323..bce357efab 100644 --- a/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psd1 +++ b/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psd1 @@ -31,7 +31,6 @@ 'Connect-SQLAnalysis' 'Get-SqlInstanceMajorVersion' 'Restart-SqlService' - 'Restart-ReportingServicesService' 'Update-AvailabilityGroupReplica' 'Test-LoginEffectivePermissions' 'Test-AvailabilityReplicaSeedingModeAutomatic' diff --git a/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 b/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 index 1b0cd94e8e..aeee920338 100644 --- a/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 +++ b/source/Modules/SqlServerDsc.Common/SqlServerDsc.Common.psm1 @@ -1128,64 +1128,6 @@ function Restart-SqlClusterService } } -<# - .SYNOPSIS - Restarts a Reporting Services instance and associated services - - .PARAMETER ServiceName - Name of the service to be restarted. - - .PARAMETER WaitTime - Number of seconds to wait between service stop and service start. - Default value is 0 seconds. -#> -function Restart-ReportingServicesService -{ - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $ServiceName, - - [Parameter()] - [System.UInt16] - $WaitTime = 0 - ) - - Write-Verbose -Message ($script:localizedData.GetServiceInformation -f $ServiceName) -Verbose - $reportingServicesService = Get-Service -Name $ServiceName - - <# - Get all dependent services that are running. - There are scenarios where an automatic service is stopped and should - not be restarted automatically. - #> - $dependentService = $reportingServicesService.DependentServices | Where-Object -FilterScript { - $_.Status -eq 'Running' - } - - Write-Verbose -Message ($script:localizedData.RestartService -f $reportingServicesService.DisplayName) -Verbose - - Write-Verbose -Message ($script:localizedData.StoppingService -f $reportingServicesService.DisplayName) -Verbose - $reportingServicesService | Stop-Service -Force - - if ($WaitTime -ne 0) - { - Write-Verbose -Message ($script:localizedData.WaitServiceRestart -f $WaitTime, $reportingServicesService.DisplayName) -Verbose - Start-Sleep -Seconds $WaitTime - } - - Write-Verbose -Message ($script:localizedData.StartingService -f $reportingServicesService.DisplayName) -Verbose - $reportingServicesService | Start-Service - - # Start dependent services - $dependentService | ForEach-Object -Process { - Write-Verbose -Message ($script:localizedData.StartingDependentService -f $_.DisplayName) -Verbose - $_ | Start-Service - } -} - <# .SYNOPSIS Executes the alter method on an Availability Group Replica object. diff --git a/source/Modules/SqlServerDsc.Common/en-US/SqlServerDsc.Common.strings.psd1 b/source/Modules/SqlServerDsc.Common/en-US/SqlServerDsc.Common.strings.psd1 index 558e95261d..6e1199905f 100644 --- a/source/Modules/SqlServerDsc.Common/en-US/SqlServerDsc.Common.strings.psd1 +++ b/source/Modules/SqlServerDsc.Common/en-US/SqlServerDsc.Common.strings.psd1 @@ -24,9 +24,6 @@ ConvertFrom-StringData @' BringSqlServerAgentClusterResourcesOnline = Bringing the SQL Server Agent resource online. (SQLCOMMON0036) GetServiceInformation = Getting information about service '{0}'. (SQLCOMMON0037) RestartService = '{0}' service is restarting. (SQLCOMMON0038) - StoppingService = '{0}' service is stopping. (SQLCOMMON0039) - StartingService = '{0}' service is starting. (SQLCOMMON0040) - WaitServiceRestart = Waiting {0} seconds before starting service '{1}'. (SQLCOMMON0041) StartingDependentService = Starting service '{0}'. (SQLCOMMON0042) WaitingInstanceTimeout = Waiting for instance {0}\\{1} to report status online, with a timeout value of {2} seconds. (SQLCOMMON0043) FailedToConnectToInstanceTimeout = Failed to connect to the instance {0}\\{1} within the timeout period of {2} seconds. (SQLCOMMON0044) diff --git a/source/Modules/SqlServerDsc.Common/sv-SE/SqlServerDsc.Common.strings.psd1 b/source/Modules/SqlServerDsc.Common/sv-SE/SqlServerDsc.Common.strings.psd1 index 819b92a81a..e60b46ca86 100644 --- a/source/Modules/SqlServerDsc.Common/sv-SE/SqlServerDsc.Common.strings.psd1 +++ b/source/Modules/SqlServerDsc.Common/sv-SE/SqlServerDsc.Common.strings.psd1 @@ -30,9 +30,6 @@ ConvertFrom-StringData @' BringSqlServerAgentClusterResourcesOnline = Tar SQL Server Agent resurser online. (SQLCOMMON0036) GetServiceInformation = Hämtar information om SQL Server-tjänst '{0}'. (SQLCOMMON0037) RestartService = '{0}' service is restarting. (SQLCOMMON0038) - StoppingService = '{0}' service is stopping. (SQLCOMMON0039) - StartingService = '{0}' service is starting. (SQLCOMMON0040) - WaitServiceRestart = Waiting {0} seconds before starting service '{1}'. (SQLCOMMON0041) StartingDependentService = Startar tjänst {0} (SQLCOMMON0042) WaitingInstanceTimeout = Waiting for instance {0}\\{1} to report status online, with a timeout value of {2} seconds. (SQLCOMMON0043) FailedToConnectToInstanceTimeout = Failed to connect to the instance {0}\\{1} within the timeout period of {2} seconds. (SQLCOMMON0044) diff --git a/source/Public/Get-SqlDscRSConfiguration.ps1 b/source/Public/Get-SqlDscRSConfiguration.ps1 index f5fa2da1c5..2af9d80b3b 100644 --- a/source/Public/Get-SqlDscRSConfiguration.ps1 +++ b/source/Public/Get-SqlDscRSConfiguration.ps1 @@ -51,7 +51,6 @@ #> function Get-SqlDscRSConfiguration { - # cSpell: ignore PBIRS [CmdletBinding()] [OutputType([Microsoft.Management.Infrastructure.CimInstance])] param diff --git a/source/Public/Get-SqlDscRSPackage.ps1 b/source/Public/Get-SqlDscRSPackage.ps1 index 72e772499f..175e2e4ee5 100644 --- a/source/Public/Get-SqlDscRSPackage.ps1 +++ b/source/Public/Get-SqlDscRSPackage.ps1 @@ -46,7 +46,6 @@ #> function Get-SqlDscRSPackage { - # cSpell: ignore PBIRS [CmdletBinding()] [OutputType([System.Diagnostics.FileVersionInfo])] param diff --git a/source/Public/Get-SqlDscRSSetupConfiguration.ps1 b/source/Public/Get-SqlDscRSSetupConfiguration.ps1 index 8cdee6500a..45bec31711 100644 --- a/source/Public/Get-SqlDscRSSetupConfiguration.ps1 +++ b/source/Public/Get-SqlDscRSSetupConfiguration.ps1 @@ -49,7 +49,6 @@ #> function Get-SqlDscRSSetupConfiguration { - # cSpell: ignore PBIRS [CmdletBinding()] [OutputType([PSCustomObject[]])] param diff --git a/source/Public/Get-SqlDscRSUrlReservation.ps1 b/source/Public/Get-SqlDscRSUrlReservation.ps1 index ff50ef88e3..8530af5b1b 100644 --- a/source/Public/Get-SqlDscRSUrlReservation.ps1 +++ b/source/Public/Get-SqlDscRSUrlReservation.ps1 @@ -50,7 +50,6 @@ #> function Get-SqlDscRSUrlReservation { - # cSpell: ignore PBIRS [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')] [CmdletBinding()] [OutputType([Microsoft.Management.Infrastructure.CimMethodResult])] diff --git a/source/Public/Initialize-SqlDscRS.ps1 b/source/Public/Initialize-SqlDscRS.ps1 new file mode 100644 index 0000000000..2edc32245f --- /dev/null +++ b/source/Public/Initialize-SqlDscRS.ps1 @@ -0,0 +1,135 @@ +<# + .SYNOPSIS + Initializes SQL Server Reporting Services. + + .DESCRIPTION + Initializes SQL Server Reporting Services or Power BI Report Server + by calling the `InitializeReportServer` method on the + `MSReportServer_ConfigurationSetting` CIM instance. + + This command initializes the report server with the current + configuration settings. The report server must have a database + connection configured before initialization. + + The configuration CIM instance can be obtained using the + `Get-SqlDscRSConfiguration` command and passed via the pipeline. + + .PARAMETER Configuration + Specifies the `MSReportServer_ConfigurationSetting` CIM instance for + the Reporting Services instance. This can be obtained using the + `Get-SqlDscRSConfiguration` command. This parameter accepts pipeline + input. + + .PARAMETER PassThru + If specified, returns the configuration CIM instance after + initialization. + + .PARAMETER Force + If specified, suppresses the confirmation prompt. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Initialize-SqlDscRS + + Initializes the Reporting Services instance 'SSRS'. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Initialize-SqlDscRS -Force + + Initializes the Reporting Services instance without confirmation. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Initialize-SqlDscRS -PassThru + + Initializes the Reporting Services instance and returns the + configuration CIM instance. + + .INPUTS + `Microsoft.Management.Infrastructure.CimInstance` + + Accepts MSReportServer_ConfigurationSetting CIM instance via pipeline. + + .OUTPUTS + None. By default, this command does not generate any output. + + .OUTPUTS + `Microsoft.Management.Infrastructure.CimInstance` + + When PassThru is specified, returns the MSReportServer_ConfigurationSetting + CIM instance. + + .NOTES + The report server database must be configured before calling this + command. Use `Set-SqlDscRSDatabaseConnection` to configure the + database connection first. + + The Reporting Services service may need to be restarted after + initialization. + + .LINK + https://docs.microsoft.com/en-us/sql/reporting-services/wmi-provider-library-reference/configurationsetting-method-initializereportserver +#> +function Initialize-SqlDscRS +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')] + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] + [OutputType([System.Object])] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [System.Object] + $Configuration, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) + + process + { + if ($Force.IsPresent -and -not $Confirm) + { + $ConfirmPreference = 'None' + } + + $instanceName = $Configuration.InstanceName + + Write-Verbose -Message ($script:localizedData.Initialize_SqlDscRS_Initializing -f $instanceName) + + $descriptionMessage = $script:localizedData.Initialize_SqlDscRS_ShouldProcessDescription -f $instanceName + $confirmationMessage = $script:localizedData.Initialize_SqlDscRS_ShouldProcessConfirmation -f $instanceName + $captionMessage = $script:localizedData.Initialize_SqlDscRS_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage)) + { + $invokeRsCimMethodParameters = @{ + CimInstance = $Configuration + MethodName = 'InitializeReportServer' + Arguments = @{ + InstallationId = $Configuration.InstallationID + } + } + + try + { + $null = Invoke-RsCimMethod @invokeRsCimMethodParameters -ErrorAction 'Stop' + } + catch + { + $errorMessage = $script:localizedData.Initialize_SqlDscRS_FailedToInitialize -f $instanceName, $_.Exception.Message + + $errorRecord = New-ErrorRecord -Exception (New-InvalidOperationException -Message $errorMessage -PassThru) -ErrorId 'ISRS0001' -ErrorCategory 'InvalidOperation' -TargetObject $Configuration + + $PSCmdlet.ThrowTerminatingError($errorRecord) + } + } + + if ($PassThru.IsPresent) + { + return $Configuration + } + } +} diff --git a/source/Public/Request-SqlDscRSDatabaseRightsScript.ps1 b/source/Public/Request-SqlDscRSDatabaseRightsScript.ps1 index 2267e8cdc9..c7118a950d 100644 --- a/source/Public/Request-SqlDscRSDatabaseRightsScript.ps1 +++ b/source/Public/Request-SqlDscRSDatabaseRightsScript.ps1 @@ -83,7 +83,6 @@ #> function Request-SqlDscRSDatabaseRightsScript { - # cSpell: ignore PBIRS [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')] [CmdletBinding()] [OutputType([System.String])] diff --git a/source/Public/Request-SqlDscRSDatabaseUpgradeScript.ps1 b/source/Public/Request-SqlDscRSDatabaseUpgradeScript.ps1 new file mode 100644 index 0000000000..7394db2050 --- /dev/null +++ b/source/Public/Request-SqlDscRSDatabaseUpgradeScript.ps1 @@ -0,0 +1,96 @@ +<# + .SYNOPSIS + Gets the database upgrade script for SQL Server Reporting Services. + + .DESCRIPTION + Gets the database upgrade script for SQL Server Reporting Services or + Power BI Report Server by calling the `GenerateDatabaseUpgradeScript` + method on the `MSReportServer_ConfigurationSetting` CIM instance. + + This command generates a Transact-SQL script that can be used to + upgrade the report server database schema to match the current + Reporting Services version. This is useful during upgrade scenarios. + + The configuration CIM instance can be obtained using the + `Get-SqlDscRSConfiguration` command and passed via the pipeline. + + .PARAMETER Configuration + Specifies the `MSReportServer_ConfigurationSetting` CIM instance for + the Reporting Services instance. This can be obtained using the + `Get-SqlDscRSConfiguration` command. This parameter accepts pipeline + input. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Request-SqlDscRSDatabaseUpgradeScript + + Gets the database upgrade script for the Reporting Services instance. + + .EXAMPLE + $config = Get-SqlDscRSConfiguration -InstanceName 'SSRS' + $script = Request-SqlDscRSDatabaseUpgradeScript -Configuration $config + Invoke-Sqlcmd -ServerInstance 'localhost' -Database 'ReportServer' -Query $script + + Gets the upgrade script and executes it against the database. + + .INPUTS + `Microsoft.Management.Infrastructure.CimInstance` + + Accepts MSReportServer_ConfigurationSetting CIM instance via pipeline. + + .OUTPUTS + `System.String` + + Returns the Transact-SQL script for upgrading the database. + + .NOTES + Review the generated script before executing it against a production + database. Always back up the database before performing upgrades. + + .LINK + https://docs.microsoft.com/en-us/sql/reporting-services/wmi-provider-library-reference/configurationsetting-method-generatedatabaseupgradescript +#> +function Request-SqlDscRSDatabaseUpgradeScript +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')] + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [System.Object] + $Configuration + ) + + process + { + $instanceName = $Configuration.InstanceName + $databaseName = $Configuration.DatabaseName + $serverVersion = $Configuration.Version + + Write-Verbose -Message ($script:localizedData.Request_SqlDscRSDatabaseUpgradeScript_Generating -f $instanceName) + + $invokeRsCimMethodParameters = @{ + CimInstance = $Configuration + MethodName = 'GenerateDatabaseUpgradeScript' + Arguments = @{ + DatabaseName = $databaseName + ServerVersion = $serverVersion + } + } + + try + { + $result = Invoke-RsCimMethod @invokeRsCimMethodParameters -ErrorAction 'Stop' + + return $result.Script + } + catch + { + $errorMessage = $script:localizedData.Request_SqlDscRSDatabaseUpgradeScript_FailedToGenerate -f $instanceName, $_.Exception.Message + + $errorRecord = New-ErrorRecord -Exception (New-InvalidOperationException -Message $errorMessage -ErrorRecord $_ -PassThru) -ErrorId 'RSRSDBUS0001' -ErrorCategory 'InvalidOperation' -TargetObject $Configuration + + $PSCmdlet.ThrowTerminatingError($errorRecord) + } + } +} diff --git a/source/Public/Restart-SqlDscRSService.ps1 b/source/Public/Restart-SqlDscRSService.ps1 new file mode 100644 index 0000000000..231a330d25 --- /dev/null +++ b/source/Public/Restart-SqlDscRSService.ps1 @@ -0,0 +1,181 @@ +<# + .SYNOPSIS + Restarts a SQL Server Reporting Services instance. + + .DESCRIPTION + Restarts a SQL Server Reporting Services or Power BI Report Server + Windows service. This command stops the service, optionally waits for + a specified time, then starts the service again. It also restarts any + dependent services that were running before the restart. + + The command can be used in two ways: + - With a configuration CIM instance from `Get-SqlDscRSConfiguration` + - With a service name directly + + .PARAMETER Configuration + Specifies the `MSReportServer_ConfigurationSetting` CIM instance for + the Reporting Services instance. This can be obtained using the + `Get-SqlDscRSConfiguration` command. This parameter accepts pipeline + input. + + .PARAMETER ServiceName + Specifies the name of the Reporting Services Windows service to restart. + This parameter is used when the service name is known and a configuration + object is not available. + + .PARAMETER WaitTime + Specifies the number of seconds to wait after stopping the service + before starting it again. This can be useful to allow the service to + fully release resources before restarting. Default value is 0 seconds. + + .PARAMETER Force + If specified, suppresses the confirmation prompt. + + .PARAMETER PassThru + If specified, returns the configuration CIM instance after restarting + the service. Only applicable when using the Configuration parameter. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Restart-SqlDscRSService + + Restarts the Reporting Services instance 'SSRS'. + + .EXAMPLE + Restart-SqlDscRSService -ServiceName 'SQLServerReportingServices' + + Restarts the Reporting Services service by name. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Restart-SqlDscRSService -WaitTime 30 + + Restarts the Reporting Services instance and waits 30 seconds between + stopping and starting the service. + + .EXAMPLE + Restart-SqlDscRSService -ServiceName 'SQLServerReportingServices' -Force + + Restarts the service without confirmation. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Restart-SqlDscRSService -PassThru + + Restarts the service and returns the configuration CIM instance. + + .INPUTS + `Microsoft.Management.Infrastructure.CimInstance` + + Accepts MSReportServer_ConfigurationSetting CIM instance via pipeline. + + .OUTPUTS + None. By default, this command does not generate any output. + + .OUTPUTS + `Microsoft.Management.Infrastructure.CimInstance` + + When PassThru is specified and using Configuration parameter, returns + the MSReportServer_ConfigurationSetting CIM instance. + + .NOTES + Dependent services that were running before the restart will be + automatically restarted after the main service starts. + + .LINK + https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/restart-service +#> +function Restart-SqlDscRSService +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')] + [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium', DefaultParameterSetName = 'ByServiceName')] + [OutputType([System.Object])] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ByConfiguration')] + [System.Object] + $Configuration, + + [Parameter(Mandatory = $true, ParameterSetName = 'ByServiceName')] + [System.String] + $ServiceName, + + [Parameter()] + [System.UInt16] + $WaitTime = 0, + + [Parameter(ParameterSetName = 'ByConfiguration')] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Force + ) + + process + { + if ($Force.IsPresent -and -not $Confirm) + { + $ConfirmPreference = 'None' + } + + $targetServiceName = $ServiceName + + if ($PSCmdlet.ParameterSetName -eq 'ByConfiguration') + { + $targetServiceName = $Configuration.ServiceName + } + + Write-Verbose -Message ($script:localizedData.Restart_SqlDscRSService_GettingService -f $targetServiceName) + + try + { + $reportingServicesService = Get-Service -Name $targetServiceName -ErrorAction Stop + } + catch + { + $errorMessage = $script:localizedData.Restart_SqlDscRSService_ServiceNotFound -f $targetServiceName, $_.Exception.Message + + Write-Error -Message $errorMessage -Category ObjectNotFound -ErrorId 'RSRSRS0001' -TargetObject $targetServiceName + + return + } + + <# + Get all dependent services that are running. + There are scenarios where an automatic service is stopped and should + not be restarted automatically. + #> + $dependentService = $reportingServicesService.DependentServices | Where-Object -FilterScript { + $_.Status -eq 'Running' + } + + $descriptionMessage = $script:localizedData.Restart_SqlDscRSService_ShouldProcessDescription -f $reportingServicesService.DisplayName + $confirmationMessage = $script:localizedData.Restart_SqlDscRSService_ShouldProcessConfirmation -f $reportingServicesService.DisplayName + $captionMessage = $script:localizedData.Restart_SqlDscRSService_ShouldProcessCaption + + if ($PSCmdlet.ShouldProcess($descriptionMessage, $confirmationMessage, $captionMessage)) + { + $reportingServicesService | Stop-Service -Force + + if ($WaitTime -ne 0) + { + Write-Debug -Message ($script:localizedData.Restart_SqlDscRSService_WaitingBeforeStart -f $WaitTime, $reportingServicesService.DisplayName) + + Start-Sleep -Seconds $WaitTime + } + + $reportingServicesService | Start-Service + + # Start dependent services + $dependentService | ForEach-Object -Process { + Write-Debug -Message ($script:localizedData.Restart_SqlDscRSService_StartingDependentService -f $_.DisplayName) + + $_ | Start-Service + } + } + + if ($PassThru.IsPresent -and $PSCmdlet.ParameterSetName -eq 'ByConfiguration') + { + return $Configuration + } + } +} diff --git a/source/Public/Set-SqlDscRSDatabaseConnection.ps1 b/source/Public/Set-SqlDscRSDatabaseConnection.ps1 index c2f439438a..71add0203f 100644 --- a/source/Public/Set-SqlDscRSDatabaseConnection.ps1 +++ b/source/Public/Set-SqlDscRSDatabaseConnection.ps1 @@ -103,7 +103,6 @@ #> function Set-SqlDscRSDatabaseConnection { - # cSpell: ignore PBIRS [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([System.Object])] diff --git a/source/Public/Test-SqlDscRSInitialized.ps1 b/source/Public/Test-SqlDscRSInitialized.ps1 new file mode 100644 index 0000000000..3b136967f3 --- /dev/null +++ b/source/Public/Test-SqlDscRSInitialized.ps1 @@ -0,0 +1,86 @@ +<# + .SYNOPSIS + Tests if SQL Server Reporting Services is initialized. + + .DESCRIPTION + Tests if SQL Server Reporting Services or Power BI Report Server + is initialized by checking the `IsInitialized` property on the + `MSReportServer_ConfigurationSetting` CIM instance. + + A Reporting Services instance is considered initialized when: + - The report server database is configured + - The encryption keys are set up + - The service is ready to serve reports + + The configuration CIM instance can be obtained using the + `Get-SqlDscRSConfiguration` command and passed via the pipeline. + + .PARAMETER Configuration + Specifies the `MSReportServer_ConfigurationSetting` CIM instance for + the Reporting Services instance. This can be obtained using the + `Get-SqlDscRSConfiguration` command. This parameter accepts pipeline + input. + + .EXAMPLE + Get-SqlDscRSConfiguration -InstanceName 'SSRS' | Test-SqlDscRSInitialized + + Returns $true if the Reporting Services instance 'SSRS' is initialized. + + .EXAMPLE + $config = Get-SqlDscRSConfiguration -InstanceName 'SSRS' + if (Test-SqlDscRSInitialized -Configuration $config) { + Write-Information -MessageData 'Reporting Services is initialized' -InformationAction Continue + } + + Tests if Reporting Services is initialized and performs an action. + + .INPUTS + `Microsoft.Management.Infrastructure.CimInstance` + + Accepts MSReportServer_ConfigurationSetting CIM instance via pipeline. + + .OUTPUTS + `System.Boolean` + + Returns $true if the Reporting Services instance is initialized, + $false otherwise. + + .NOTES + This is a convenience wrapper around checking the `IsInitialized` + property of the configuration CIM instance. + + .LINK + https://docs.microsoft.com/en-us/sql/reporting-services/wmi-provider-library-reference/msreportserver-configurationsetting-properties +#> +function Test-SqlDscRSInitialized +{ + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the examples use pipeline input the rule cannot validate.')] + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [System.Object] + $Configuration + ) + + process + { + $instanceName = $Configuration.InstanceName + + Write-Verbose -Message ($script:localizedData.Test_SqlDscRSInitialized_Testing -f $instanceName) + + $isInitialized = $Configuration.IsInitialized + + if ($isInitialized) + { + Write-Verbose -Message ($script:localizedData.Test_SqlDscRSInitialized_IsInitialized -f $instanceName) + } + else + { + Write-Verbose -Message ($script:localizedData.Test_SqlDscRSInitialized_NotInitialized -f $instanceName) + } + + return $isInitialized + } +} diff --git a/source/Public/Test-SqlDscRSInstalled.ps1 b/source/Public/Test-SqlDscRSInstalled.ps1 index 0dc3727e3c..a348f19fee 100644 --- a/source/Public/Test-SqlDscRSInstalled.ps1 +++ b/source/Public/Test-SqlDscRSInstalled.ps1 @@ -35,7 +35,6 @@ #> function Test-SqlDscRSInstalled { - # cSpell: ignore PBIRS [CmdletBinding()] [OutputType([System.Boolean])] param diff --git a/source/en-US/SqlServerDsc.strings.psd1 b/source/en-US/SqlServerDsc.strings.psd1 index a577168d1a..3827785521 100644 --- a/source/en-US/SqlServerDsc.strings.psd1 +++ b/source/en-US/SqlServerDsc.strings.psd1 @@ -787,4 +787,31 @@ ConvertFrom-StringData @' Set_SqlDscRSDatabaseConnection_ShouldProcessCaption = Set report server database connection for Reporting Services instance Set_SqlDscRSDatabaseConnection_FailedToSet = Failed to set report server database connection for Reporting Services instance '{0}'. {1} (SSRSDC0001) Set_SqlDscRSDatabaseConnection_CredentialRequired = The Credential parameter is required when Type is '{0}'. (SSRSDC0002) + + ## Restart-SqlDscRSService + Restart_SqlDscRSService_GettingService = Getting service information for '{0}'. + Restart_SqlDscRSService_ServiceNotFound = Failed to get service '{0}'. {1} (RSRSRS0001) + Restart_SqlDscRSService_ShouldProcessDescription = Restarting Reporting Services service '{0}'. + Restart_SqlDscRSService_ShouldProcessConfirmation = Are you sure you want to restart the Reporting Services service '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + Restart_SqlDscRSService_ShouldProcessCaption = Restart Reporting Services service + Restart_SqlDscRSService_WaitingBeforeStart = Waiting {0} seconds before starting service '{1}'. + Restart_SqlDscRSService_StartingDependentService = Starting dependent service '{0}'. + + ## Test-SqlDscRSInitialized + Test_SqlDscRSInitialized_Testing = Testing if Reporting Services instance '{0}' is initialized. + Test_SqlDscRSInitialized_IsInitialized = Reporting Services instance '{0}' is initialized. + Test_SqlDscRSInitialized_NotInitialized = Reporting Services instance '{0}' is not initialized. + + ## Initialize-SqlDscRS + Initialize_SqlDscRS_Initializing = Initializing Reporting Services instance '{0}'. + Initialize_SqlDscRS_ShouldProcessDescription = Initializing Reporting Services instance '{0}'. + Initialize_SqlDscRS_ShouldProcessConfirmation = Are you sure you want to initialize Reporting Services instance '{0}'? + # This string shall not end with full stop (.) since it is used as a title of ShouldProcess messages. + Initialize_SqlDscRS_ShouldProcessCaption = Initialize Reporting Services instance + Initialize_SqlDscRS_FailedToInitialize = Failed to initialize Reporting Services instance '{0}'. {1} (ISRS0001) + + ## Request-SqlDscRSDatabaseUpgradeScript + Request_SqlDscRSDatabaseUpgradeScript_Generating = Generating database upgrade script for Reporting Services instance '{0}'. + Request_SqlDscRSDatabaseUpgradeScript_FailedToGenerate = Failed to generate database upgrade script for Reporting Services instance '{0}'. {1} (RSRSDBUS0001) '@ diff --git a/tests/Integration/Commands/Add-SqlDscRSUrlReservation.Integration.Tests.ps1 b/tests/Integration/Commands/Add-SqlDscRSUrlReservation.Integration.Tests.ps1 index 0584e78dfe..1dd541cb6b 100644 --- a/tests/Integration/Commands/Add-SqlDscRSUrlReservation.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Add-SqlDscRSUrlReservation.Integration.Tests.ps1 @@ -192,7 +192,6 @@ Describe 'Add-SqlDscRSUrlReservation' { } Context 'When adding URL reservation for Power BI Report Server' -Tag @('Integration_PowerBI') { - # cSpell: ignore PBIRS BeforeAll { $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' -ErrorAction 'Stop' diff --git a/tests/Integration/Commands/Enable-SqlDscRsSecureConnection.Integration.Tests.ps1 b/tests/Integration/Commands/Enable-SqlDscRsSecureConnection.Integration.Tests.ps1 index ae2f14e872..6bcd47cca3 100644 --- a/tests/Integration/Commands/Enable-SqlDscRsSecureConnection.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Enable-SqlDscRsSecureConnection.Integration.Tests.ps1 @@ -156,7 +156,6 @@ Describe 'Enable-SqlDscRsSecureConnection' { } Context 'When enabling secure connection for Power BI Report Server' -Tag @('Integration_PowerBI') { - # cSpell: ignore PBIRS BeforeAll { $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' $script:originalLevel = $script:configuration.SecureConnectionLevel diff --git a/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 index eb64576204..8ead182259 100644 --- a/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscInstalledInstance.Integration.Tests.ps1 @@ -49,7 +49,6 @@ Describe 'Get-SqlDscInstalledInstance' { } Context 'When getting a specific SQL Server instance by name' -Tag @('Integration_PowerBI') { - # cSpell: ignore PBIRS It 'Should return the specified instance when it exists' { $result = Get-SqlDscInstalledInstance -InstanceName 'PBIRS' diff --git a/tests/Integration/Commands/Get-SqlDscRSConfiguration.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscRSConfiguration.Integration.Tests.ps1 index 972eeab693..caa16ae45c 100644 --- a/tests/Integration/Commands/Get-SqlDscRSConfiguration.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscRSConfiguration.Integration.Tests.ps1 @@ -66,7 +66,6 @@ Describe 'Get-SqlDscRSConfiguration' { } Context 'When getting the configuration CIM instance for Power BI Report Server' -Tag @('Integration_PowerBI') { - # cSpell: ignore PBIRS It 'Should return the configuration CIM instance for PBIRS instance' { $result = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' diff --git a/tests/Integration/Commands/Get-SqlDscRSPackage.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscRSPackage.Integration.Tests.ps1 index 01692c81cd..ee06006e16 100644 --- a/tests/Integration/Commands/Get-SqlDscRSPackage.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscRSPackage.Integration.Tests.ps1 @@ -54,7 +54,6 @@ Describe 'Get-SqlDscRSPackage' { } } - # cSpell: ignore PBIRS Context 'When getting package information for Power BI Report Server' -Tag @('Integration_PowerBI') { BeforeAll { $script:temporaryFolder = Get-TemporaryFolder diff --git a/tests/Integration/Commands/Get-SqlDscRSUrlReservation.Integration.Tests.ps1 b/tests/Integration/Commands/Get-SqlDscRSUrlReservation.Integration.Tests.ps1 index 6a806e2d14..93cd2e666d 100644 --- a/tests/Integration/Commands/Get-SqlDscRSUrlReservation.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Get-SqlDscRSUrlReservation.Integration.Tests.ps1 @@ -135,7 +135,6 @@ Describe 'Get-SqlDscRSUrlReservation' { } Context 'When getting URL reservations for Power BI Report Server' -Tag @('Integration_PowerBI') { - # cSpell: ignore PBIRS BeforeAll { $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' -ErrorAction 'Stop' } diff --git a/tests/Integration/Commands/Initialize-SqlDscRS.Integration.Tests.ps1 b/tests/Integration/Commands/Initialize-SqlDscRS.Integration.Tests.ps1 new file mode 100644 index 0000000000..91e1a54fb9 --- /dev/null +++ b/tests/Integration/Commands/Initialize-SqlDscRS.Integration.Tests.ps1 @@ -0,0 +1,133 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + # Do not use -Force. Doing so, or unloading the module in AfterAll, causes + # PowerShell class types to get new identities, breaking type comparisons. + Import-Module -Name $script:moduleName -ErrorAction 'Stop' +} + +<# + .NOTES + Initialize-SqlDscRS is a complex command that initializes a Reporting Services + instance. This test is designed to be run in a CI environment where the + instance may already be initialized. The test verifies the command can be + called without throwing, even if initialization is already complete. +#> +Describe 'Initialize-SqlDscRS' { + Context 'When initializing SQL Server 2017 Reporting Services' -Tag @('Integration_SQL2017_RS') { + BeforeAll { + $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + + # Check if already initialized + $script:isInitialized = $script:configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + } + + It 'Should return initialization status' { + $script:isInitialized | Should -BeOfType [System.Boolean] + } + + It 'Should initialize or return already initialized' -Skip:$script:isInitialized { + # Only run initialization if not already initialized + $script:configuration | Initialize-SqlDscRS -Force -ErrorAction 'Stop' + } + + It 'Should return configuration when using PassThru on initialized instance' -Skip:(-not $script:isInitialized) { + # Re-initialize (should be idempotent) + $result = $script:configuration | Initialize-SqlDscRS -Force -PassThru -ErrorAction 'Stop' + + $result | Should -Not -BeNullOrEmpty + $result.InstanceName | Should -Be 'SSRS' + } + } + + Context 'When initializing SQL Server 2019 Reporting Services' -Tag @('Integration_SQL2019_RS') { + BeforeAll { + $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $script:isInitialized = $script:configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + } + + It 'Should return initialization status' { + $script:isInitialized | Should -BeOfType [System.Boolean] + } + + It 'Should initialize or return already initialized' -Skip:$script:isInitialized { + $script:configuration | Initialize-SqlDscRS -Force -ErrorAction 'Stop' + } + + It 'Should return configuration when using PassThru on initialized instance' -Skip:(-not $script:isInitialized) { + $result = $script:configuration | Initialize-SqlDscRS -Force -PassThru -ErrorAction 'Stop' + + $result | Should -Not -BeNullOrEmpty + $result.InstanceName | Should -Be 'SSRS' + } + } + + Context 'When initializing SQL Server 2022 Reporting Services' -Tag @('Integration_SQL2022_RS') { + BeforeAll { + $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $script:isInitialized = $script:configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + } + + It 'Should return initialization status' { + $script:isInitialized | Should -BeOfType [System.Boolean] + } + + It 'Should initialize or return already initialized' -Skip:$script:isInitialized { + $script:configuration | Initialize-SqlDscRS -Force -ErrorAction 'Stop' + } + + It 'Should return configuration when using PassThru on initialized instance' -Skip:(-not $script:isInitialized) { + $result = $script:configuration | Initialize-SqlDscRS -Force -PassThru -ErrorAction 'Stop' + + $result | Should -Not -BeNullOrEmpty + $result.InstanceName | Should -Be 'SSRS' + } + } + + Context 'When initializing Power BI Report Server' -Tag @('Integration_PowerBI') { + BeforeAll { + $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' -ErrorAction 'Stop' + $script:isInitialized = $script:configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + } + + It 'Should return initialization status' { + $script:isInitialized | Should -BeOfType [System.Boolean] + } + + It 'Should initialize or return already initialized' -Skip:$script:isInitialized { + $script:configuration | Initialize-SqlDscRS -Force -ErrorAction 'Stop' + } + + It 'Should return configuration when using PassThru on initialized instance' -Skip:(-not $script:isInitialized) { + $result = $script:configuration | Initialize-SqlDscRS -Force -PassThru -ErrorAction 'Stop' + + $result | Should -Not -BeNullOrEmpty + $result.InstanceName | Should -Be 'PBIRS' + } + } +} diff --git a/tests/Integration/Commands/Install-SqlDscPowerBIReportServer.Integration.Tests.ps1 b/tests/Integration/Commands/Install-SqlDscPowerBIReportServer.Integration.Tests.ps1 index 03e0dc5339..8885e0f4c0 100644 --- a/tests/Integration/Commands/Install-SqlDscPowerBIReportServer.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Install-SqlDscPowerBIReportServer.Integration.Tests.ps1 @@ -42,7 +42,6 @@ Describe 'Install-SqlDscPowerBIReportServer' -Tag @('Integration_PowerBI') { } Context 'When installing Power BI Report Server' { - # cSpell: ignore PBIRS It 'Should run the command without throwing' { # Set splatting parameters for Install-SqlDscPowerBIReportServer $installSqlDscBIReportServerParameters = @{ diff --git a/tests/Integration/Commands/Prerequisites.RSDB.Integration.Tests.ps1 b/tests/Integration/Commands/Prerequisites.RSDB.Integration.Tests.ps1 index 13308ce48d..1b7981619f 100644 --- a/tests/Integration/Commands/Prerequisites.RSDB.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Prerequisites.RSDB.Integration.Tests.ps1 @@ -39,7 +39,7 @@ Describe 'Prerequisites - RSDB SQL Server Instance' -Tag @('Integration_SQL2017_ $computerName = Get-ComputerName } - Context 'Install SQL Server Database Engine instance RSDB for Reporting Services database' { + Context 'When installing SQL Server Database Engine instance RSDB for Reporting Services database' { It 'Should install the RSDB instance without throwing' { <# Install a minimal SQL Server Database Engine instance named RSDB diff --git a/tests/Integration/Commands/README.md b/tests/Integration/Commands/README.md index b4e28f4e60..20de193ee9 100644 --- a/tests/Integration/Commands/README.md +++ b/tests/Integration/Commands/README.md @@ -175,6 +175,9 @@ Get-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscReportingService), 0 (Prerequi Add-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscReportingService), 0 (Prerequisites) | SSRS | - Remove-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscReportingService), 0 (Prerequisites) | SSRS | - Set-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscReportingService), 0 (Prerequisites) | SSRS | - +Restart-SqlDscRSService | 3 | 1 (Install-SqlDscReportingService), 0 (Prerequisites) | SSRS | - +Test-SqlDscRSInitialized | 3 | 1 (Install-SqlDscReportingService), 0 (Prerequisites) | SSRS | - +Initialize-SqlDscRS | 4 | 3 (Set-SqlDscRSDatabaseConnection), 1 (Install-SqlDscReportingService), 0 (Prerequisites) | SSRS | - Set-SqlDscRSDatabaseConnection | 3 | 2 (Request-SqlDscRSDatabaseScript, Request-SqlDscRSDatabaseRightsScript), 1 (Install-SqlDscReportingService), 0 (Prerequisites, Prerequisites.RSDB) | SSRS, RSDB | ReportServer, ReportServerTempDB databases Repair-SqlDscReportingService | 8 | 1 (Install-SqlDscReportingService) | SSRS | - Uninstall-SqlDscReportingService | 9 | 8 (Repair-SqlDscReportingService) | - | - @@ -205,6 +208,9 @@ Get-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscPowerBIReportServer), 0 (Prere Add-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscPowerBIReportServer), 0 (Prerequisites) | PBIRS | - Remove-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscPowerBIReportServer), 0 (Prerequisites) | PBIRS | - Set-SqlDscRSUrlReservation | 3 | 1 (Install-SqlDscPowerBIReportServer), 0 (Prerequisites) | PBIRS | - +Restart-SqlDscRSService | 3 | 1 (Install-SqlDscPowerBIReportServer), 0 (Prerequisites) | PBIRS | - +Test-SqlDscRSInitialized | 3 | 1 (Install-SqlDscPowerBIReportServer), 0 (Prerequisites) | PBIRS | - +Initialize-SqlDscRS | 4 | 3 (Set-SqlDscRSDatabaseConnection), 1 (Install-SqlDscPowerBIReportServer), 0 (Prerequisites) | PBIRS | - Set-SqlDscRSDatabaseConnection | 3 | 2 (Request-SqlDscRSDatabaseScript, Request-SqlDscRSDatabaseRightsScript), 1 (Install-SqlDscPowerBIReportServer), 0 (Prerequisites, Prerequisites.RSDB) | PBIRS, RSDB | ReportServer, ReportServerTempDB databases Repair-SqlDscPowerBIReportServer | 8 | 1 (Install-SqlDscPowerBIReportServer) | PBIRS | - Uninstall-SqlDscPowerBIReportServer | 9 | 8 (Repair-SqlDscPowerBIReportServer) | - | - diff --git a/tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1 b/tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1 index 16fa1d0d25..73fbd5d60e 100644 --- a/tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Remove-SqlDscRSUrlReservation.Integration.Tests.ps1 @@ -177,7 +177,6 @@ Describe 'Remove-SqlDscRSUrlReservation' { } Context 'When removing URL reservation for Power BI Report Server' -Tag @('Integration_PowerBI') { - # cSpell: ignore PBIRS BeforeAll { $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' diff --git a/tests/Integration/Commands/Request-SqlDscRSDatabaseRightsScript.Integration.Tests.ps1 b/tests/Integration/Commands/Request-SqlDscRSDatabaseRightsScript.Integration.Tests.ps1 index 082d0424a9..3b387743a2 100644 --- a/tests/Integration/Commands/Request-SqlDscRSDatabaseRightsScript.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Request-SqlDscRSDatabaseRightsScript.Integration.Tests.ps1 @@ -44,7 +44,7 @@ Describe 'Request-SqlDscRSDatabaseRightsScript' { } It 'Should generate the database rights script without throwing' { - { $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } | Should -Not -Throw + $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { @@ -66,7 +66,7 @@ Describe 'Request-SqlDscRSDatabaseRightsScript' { } It 'Should generate the database rights script without throwing' { - { $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } | Should -Not -Throw + $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { @@ -87,7 +87,7 @@ Describe 'Request-SqlDscRSDatabaseRightsScript' { } It 'Should generate the database rights script without throwing' { - { $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } | Should -Not -Throw + $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { @@ -108,7 +108,7 @@ Describe 'Request-SqlDscRSDatabaseRightsScript' { } It 'Should generate the database rights script without throwing' { - { $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } | Should -Not -Throw + $script:rightsScript = $script:configuration | Request-SqlDscRSDatabaseRightsScript -DatabaseName 'ReportServer' -UserName $script:serviceAccount -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { diff --git a/tests/Integration/Commands/Request-SqlDscRSDatabaseScript.Integration.Tests.ps1 b/tests/Integration/Commands/Request-SqlDscRSDatabaseScript.Integration.Tests.ps1 index 3a59bcc252..9eec9eb6e0 100644 --- a/tests/Integration/Commands/Request-SqlDscRSDatabaseScript.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Request-SqlDscRSDatabaseScript.Integration.Tests.ps1 @@ -32,7 +32,7 @@ BeforeAll { } Describe 'Request-SqlDscRSDatabaseScript' { - Context 'When generating database creation script for SQL Server Reporting Services' -Tag @('Integration_SQL2017_RS') { + Context 'When generating database creation script for SQL Server 2017 Reporting Services' -Tag @('Integration_SQL2017_RS') { BeforeAll { <# Ensure the Reporting Services service is running before running @@ -52,7 +52,7 @@ Describe 'Request-SqlDscRSDatabaseScript' { } It 'Should generate the database creation script without throwing' { - { $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } | Should -Not -Throw + $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { @@ -81,7 +81,7 @@ Describe 'Request-SqlDscRSDatabaseScript' { } It 'Should generate the database creation script without throwing' { - { $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } | Should -Not -Throw + $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { @@ -110,7 +110,7 @@ Describe 'Request-SqlDscRSDatabaseScript' { } It 'Should generate the database creation script without throwing' { - { $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } | Should -Not -Throw + $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { @@ -139,7 +139,7 @@ Describe 'Request-SqlDscRSDatabaseScript' { } It 'Should generate the database creation script without throwing' { - { $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } | Should -Not -Throw + $script:databaseScript = $script:configuration | Request-SqlDscRSDatabaseScript -DatabaseName 'ReportServer' -ErrorAction 'Stop' } It 'Should return a string containing T-SQL' { diff --git a/tests/Integration/Commands/Request-SqlDscRSDatabaseUpgradeScript.Integration.Tests.ps1 b/tests/Integration/Commands/Request-SqlDscRSDatabaseUpgradeScript.Integration.Tests.ps1 new file mode 100644 index 0000000000..7a2e28f2b9 --- /dev/null +++ b/tests/Integration/Commands/Request-SqlDscRSDatabaseUpgradeScript.Integration.Tests.ps1 @@ -0,0 +1,74 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + # Do not use -Force. Doing so, or unloading the module in AfterAll, causes + # PowerShell class types to get new identities, breaking type comparisons. + Import-Module -Name $script:moduleName -ErrorAction 'Stop' +} + +Describe 'Request-SqlDscRSDatabaseUpgradeScript' { + Context 'When requesting database upgrade script for SQL Server 2017 Reporting Services' -Tag @('Integration_SQL2017_RS') { + It 'Should return database upgrade script or empty result' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + + $result = $configuration | Request-SqlDscRSDatabaseUpgradeScript -ErrorAction 'Stop' + + $result | Should -BeOfType ([System.String]) + } + } + + Context 'When requesting database upgrade script for SQL Server 2019 Reporting Services' -Tag @('Integration_SQL2019_RS') { + It 'Should return database upgrade script or empty result' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + + $result = $configuration | Request-SqlDscRSDatabaseUpgradeScript -ErrorAction 'Stop' + + $result | Should -BeOfType ([System.String]) + } + } + + Context 'When requesting database upgrade script for SQL Server 2022 Reporting Services' -Tag @('Integration_SQL2022_RS') { + It 'Should return database upgrade script or empty result' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + + $result = $configuration | Request-SqlDscRSDatabaseUpgradeScript -ErrorAction 'Stop' + + $result | Should -BeOfType ([System.String]) + } + } + + Context 'When requesting database upgrade script for Power BI Report Server' -Tag @('Integration_PowerBI') { + It 'Should return database upgrade script or empty result' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' -ErrorAction 'Stop' + + $result = $configuration | Request-SqlDscRSDatabaseUpgradeScript -ErrorAction 'Stop' + + $result | Should -BeOfType ([System.String]) + } + } +} diff --git a/tests/Integration/Commands/Restart-SqlDscRSService.Integration.Tests.ps1 b/tests/Integration/Commands/Restart-SqlDscRSService.Integration.Tests.ps1 new file mode 100644 index 0000000000..1037805875 --- /dev/null +++ b/tests/Integration/Commands/Restart-SqlDscRSService.Integration.Tests.ps1 @@ -0,0 +1,62 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + # Do not use -Force. Doing so, or unloading the module in AfterAll, causes + # PowerShell class types to get new identities, breaking type comparisons. + Import-Module -Name $script:moduleName -ErrorAction 'Stop' +} + +Describe 'Restart-SqlDscRSService' { + Context 'When restarting SQL Server 2017 Reporting Services' -Tag @('Integration_SQL2017_RS') { + It 'Should restart the service without error' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $configuration | Restart-SqlDscRSService -Force -ErrorAction 'Stop' + } + } + + Context 'When restarting SQL Server 2019 Reporting Services' -Tag @('Integration_SQL2019_RS') { + It 'Should restart the service without error' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $configuration | Restart-SqlDscRSService -Force -ErrorAction 'Stop' + } + } + + Context 'When restarting SQL Server 2022 Reporting Services' -Tag @('Integration_SQL2022_RS') { + It 'Should restart the service without error' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $configuration | Restart-SqlDscRSService -Force -ErrorAction 'Stop' + } + } + + Context 'When restarting Power BI Report Server' -Tag @('Integration_PowerBI') { + It 'Should restart the service without error' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' -ErrorAction 'Stop' + $configuration | Restart-SqlDscRSService -Force -ErrorAction 'Stop' + } + } +} diff --git a/tests/Integration/Commands/Set-SqlDscRSVirtualDirectory.Integration.Tests.ps1 b/tests/Integration/Commands/Set-SqlDscRSVirtualDirectory.Integration.Tests.ps1 index c66f6103fe..a4e277ce4f 100644 --- a/tests/Integration/Commands/Set-SqlDscRSVirtualDirectory.Integration.Tests.ps1 +++ b/tests/Integration/Commands/Set-SqlDscRSVirtualDirectory.Integration.Tests.ps1 @@ -99,7 +99,6 @@ Describe 'Set-SqlDscRSVirtualDirectory' { } Context 'When setting virtual directory for Power BI Report Server' -Tag @('Integration_PowerBI') { - # cSpell: ignore PBIRS BeforeAll { $script:configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' -ErrorAction 'Stop' } diff --git a/tests/Integration/Commands/Test-SqlDscRSInitialized.Integration.Tests.ps1 b/tests/Integration/Commands/Test-SqlDscRSInitialized.Integration.Tests.ps1 new file mode 100644 index 0000000000..055bd945e0 --- /dev/null +++ b/tests/Integration/Commands/Test-SqlDscRSInitialized.Integration.Tests.ps1 @@ -0,0 +1,66 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + # Do not use -Force. Doing so, or unloading the module in AfterAll, causes + # PowerShell class types to get new identities, breaking type comparisons. + Import-Module -Name $script:moduleName -ErrorAction 'Stop' +} + +Describe 'Test-SqlDscRSInitialized' { + Context 'When testing if SQL Server 2017 Reporting Services is initialized' -Tag @('Integration_SQL2017_RS') { + It 'Should return initialization status' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $result = $configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + $result | Should -BeOfType [System.Boolean] + } + } + + Context 'When testing if SQL Server 2019 Reporting Services is initialized' -Tag @('Integration_SQL2019_RS') { + It 'Should return initialization status' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $result = $configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + $result | Should -BeOfType [System.Boolean] + } + } + + Context 'When testing if SQL Server 2022 Reporting Services is initialized' -Tag @('Integration_SQL2022_RS') { + It 'Should return initialization status' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'SSRS' -ErrorAction 'Stop' + $result = $configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + $result | Should -BeOfType [System.Boolean] + } + } + + Context 'When testing if Power BI Report Server is initialized' -Tag @('Integration_PowerBI') { + It 'Should return initialization status' { + $configuration = Get-SqlDscRSConfiguration -InstanceName 'PBIRS' -ErrorAction 'Stop' + $result = $configuration | Test-SqlDscRSInitialized -ErrorAction 'Stop' + $result | Should -BeOfType [System.Boolean] + } + } +} diff --git a/tests/Unit/DSC_SqlRS.Tests.ps1 b/tests/Unit/DSC_SqlRS.Tests.ps1 index f17c9bc30b..b957ed35e9 100644 --- a/tests/Unit/DSC_SqlRS.Tests.ps1 +++ b/tests/Unit/DSC_SqlRS.Tests.ps1 @@ -400,19 +400,6 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { return } - - # Inject a stub in the module scope to support testing cross-plattform - function script:Invoke-CimMethod - { - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ParameterBlockParameterAttribute', '', Justification='The stub cannot use [Parameter()].')] - param - ( - $MethodName, - $Arguments - ) - - return - } } $mockNamedInstanceName = 'INSTANCE' @@ -430,10 +417,6 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { $mockVirtualDirectoryReportServerName = 'ReportServer_SQL2016' $mockReportingServicesServiceName = 'SQLServerReportingServices' - $mockInvokeCimMethod = { - throw 'Should not call Invoke-CimMethod directly, should call the wrapper Invoke-RsCimMethod.' - } - $mockInvokeRsCimMethod_ListReservedUrls = { return New-Object -TypeName Object | Add-Member -MemberType ScriptProperty -Name 'Application' -Value { @@ -505,23 +488,17 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Mock -CommandName Get-SqlDscRSUrlReservation -MockWith $mockInvokeRsCimMethod_ListReservedUrls - <# - This is mocked here so that no calls are made to it directly, - or if any mock of Invoke-RsCimMethod are wrong. - #> - Mock -CommandName Invoke-CimMethod -MockWith $mockInvokeCimMethod - Mock -CommandName Import-SqlDscPreferredModule Mock -CommandName Invoke-SqlDscQuery Mock -CommandName Enable-SqlDscRsSecureConnection Mock -CommandName Disable-SqlDscRsSecureConnection - Mock -CommandName Restart-ReportingServicesService + Mock -CommandName Restart-SqlDscRSService Mock -CommandName Start-Sleep Mock -CommandName Set-SqlDscRSVirtualDirectory Mock -CommandName Add-SqlDscRSUrlReservation Mock -CommandName Remove-SqlDscRSUrlReservation Mock -CommandName Set-SqlDscRSUrlReservation - Mock -CommandName Invoke-RsCimMethod + Mock -CommandName Initialize-SqlDscRS Mock -CommandName Request-SqlDscRSDatabaseScript -MockWith { return 'select * from something' } @@ -530,12 +507,6 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { } Mock -CommandName Set-SqlDscRSDatabaseConnection - <# - This is mocked here so that no calls are made to it directly, - or if any mock of Invoke-RsCimMethod are wrong. - #> - Mock -CommandName Invoke-CimMethod -MockWith $mockInvokeCimMethod - $mockDynamicReportServerApplicationName = $mockReportServerApplicationName $mockDynamicReportsApplicationName = $mockReportsApplicationName $mockDynamicReportsApplicationUrlString = $mockReportsApplicationUrl @@ -545,19 +516,6 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { $script:mockNamedInstanceName = 'INSTANCE' $script:mockReportingServicesDatabaseServerName = 'SERVER' $script:mockReportingServicesDatabaseNamedInstanceName = $mockNamedInstanceName - - # Inject a stub in the module scope to support testing cross-plattform - function script:Invoke-CimMethod - { - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ParameterBlockParameterAttribute', '', Justification='The stub cannot use [Parameter()].')] - param - ( - $MethodName, - $Arguments - ) - - return - } } } @@ -612,13 +570,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Enable-SqlDscRsSecureConnection -Exactly -Times 1 -Scope It - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'RemoveURL' - } -Exactly -Times 0 -Scope It - - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'InitializeReportServer' - } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Initialize-SqlDscRS -Exactly -Times 1 -Scope It Should -Invoke -CommandName Set-SqlDscRSDatabaseConnection -Exactly -Times 1 -Scope It @@ -644,7 +596,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It Should -Invoke -CommandName Invoke-SqlDscQuery -Exactly -Times 2 -Scope It - Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 2 -Scope It + Should -Invoke -CommandName Restart-SqlDscRSService -Exactly -Times 2 -Scope It } Context 'When there is no Reporting Services instance after Set-TargetResource has been called' { @@ -862,9 +814,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { $Application -eq $mockReportsApplicationName } -Exactly -Times 1 -Scope It - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'InitializeReportServer' - } -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Initialize-SqlDscRS -Exactly -Times 0 -Scope It Should -Invoke -CommandName Set-SqlDscRSDatabaseConnection -Exactly -Times 0 -Scope It @@ -890,7 +840,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It Should -Invoke -CommandName Invoke-SqlDscQuery -Exactly -Times 0 -Scope It - Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Restart-SqlDscRSService -Exactly -Times 1 -Scope It } } @@ -960,9 +910,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { $Application -eq $mockReportsApplicationName } -Exactly -Times 1 -Scope It - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'InitializeReportServer' - } -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Initialize-SqlDscRS -Exactly -Times 0 -Scope It Should -Invoke -CommandName Set-SqlDscRSDatabaseConnection -Exactly -Times 0 -Scope It @@ -988,7 +936,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It Should -Invoke -CommandName Invoke-SqlDscQuery -Exactly -Times 0 -Scope It - Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Restart-SqlDscRSService -Exactly -Times 0 -Scope It } } @@ -1038,13 +986,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { It 'Should configure Reporting Service without throwing an error' { $null = Set-TargetResource @defaultParameters - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'RemoveURL' - } -Exactly -Times 0 -Scope It - - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'InitializeReportServer' - } -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Initialize-SqlDscRS -Exactly -Times 1 -Scope It Should -Invoke -CommandName Set-SqlDscRSDatabaseConnection -Exactly -Times 1 -Scope It @@ -1070,7 +1012,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It Should -Invoke -CommandName Invoke-SqlDscQuery -Exactly -Times 2 -Scope It - Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 2 -Scope It + Should -Invoke -CommandName Restart-SqlDscRSService -Exactly -Times 2 -Scope It Should -Invoke -CommandName Invoke-SqlDscQuery -ParameterFilter { $PesterBoundParameters.Keys -notcontains 'Encrypt' @@ -1149,13 +1091,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Enable-SqlDscRsSecureConnection -Exactly -Times 0 -Scope It Should -Invoke -CommandName Disable-SqlDscRsSecureConnection -Exactly -Times 0 -Scope It - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'RemoveURL' - } -Exactly -Times 0 -Scope It - - Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { - $MethodName -eq 'InitializeReportServer' - } -Exactly -Times 0 -Scope It + Should -Invoke -CommandName Initialize-SqlDscRS -Exactly -Times 0 -Scope It Should -Invoke -CommandName Set-SqlDscRSDatabaseConnection -Exactly -Times 1 -Scope It @@ -1181,7 +1117,7 @@ Describe 'SqlRS\Set-TargetResource' -Tag 'Set' { Should -Invoke -CommandName Get-CimInstance -Exactly -Times 1 -Scope It Should -Invoke -CommandName Invoke-SqlDscQuery -Exactly -Times 2 -Scope It - Should -Invoke -CommandName Restart-ReportingServicesService -Exactly -Times 1 -Scope It + Should -Invoke -CommandName Restart-SqlDscRSService -Exactly -Times 1 -Scope It } } } @@ -1441,139 +1377,3 @@ Describe 'SqlRS\Test-TargetResource' -Tag 'Test' { } } } - -Describe 'SqlRS\Invoke-RsCimMethod' -Tag 'Helper' { - BeforeAll { - InModuleScope -ScriptBlock { - $script:mockCimInstance = New-Object -TypeName Microsoft.Management.Infrastructure.CimInstance -ArgumentList @( - 'MSReportServer_ConfigurationSetting' - 'root/Microsoft/SQLServer/ReportServer/RS_SQL2016/v13/Admin' - ) - - # Inject a stub in the module scope to support testing cross-plattform - function script:Invoke-CimMethod - { - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ParameterBlockParameterAttribute', '', Justification='The stub cannot use [Parameter()].')] - param - ( - $MethodName, - $Arguments - ) - - return - } - } - } - - Context 'When calling a method that execute successfully' { - BeforeAll { - Mock -CommandName Invoke-CimMethod -MockWith { - return @{ - HRESULT = 0 # cSpell: disable-line - } - } - } - - Context 'When calling Invoke-CimMethod without arguments' { - It 'Should call Invoke-CimMethod without throwing an error' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $invokeRsCimMethodParameters = @{ - CimInstance = $mockCimInstance - MethodName = 'AnyMethod' - } - - $resultTestTargetResource = Invoke-RsCimMethod @invokeRsCimMethodParameters - $resultTestTargetResource.HRESULT | Should -Be 0 # cSpell: disable-line - } - - Should -Invoke -CommandName Invoke-CimMethod -ParameterFilter { - $MethodName -eq 'AnyMethod' -and $Arguments -eq $null - } -Exactly -Times 1 - } - } - - Context 'When calling Invoke-CimMethod with arguments' { - It 'Should call Invoke-CimMethod without throwing an error' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $invokeRsCimMethodParameters = @{ - CimInstance = $mockCimInstance - MethodName = 'AnyMethod' - Arguments = @{ - Argument1 = 'ArgumentValue1' - } - } - - $resultTestTargetResource = Invoke-RsCimMethod @invokeRsCimMethodParameters - $resultTestTargetResource.HRESULT | Should -Be 0 # cSpell: disable-line - } - - Should -Invoke -CommandName Invoke-CimMethod -ParameterFilter { - $MethodName -eq 'AnyMethod' -and $Arguments.Argument1 -eq 'ArgumentValue1' - } -Exactly -Times 1 - } - } - } - - Context 'When calling a method that fails with an error' { - Context 'When Invoke-CimMethod fails and returns an object with a Error property' { - BeforeAll { - Mock -CommandName Invoke-CimMethod -MockWith { - return @{ - HRESULT = 1 # cSpell: disable-line - Error = 'Something went wrong' - } - } - } - - It 'Should call Invoke-CimMethod and throw the correct error' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $invokeRsCimMethodParameters = @{ - CimInstance = $mockCimInstance - MethodName = 'AnyMethod' - } - - # cSpell: disable-next - { Invoke-RsCimMethod @invokeRsCimMethodParameters } | Should -Throw 'Method AnyMethod() failed with an error. Error: Something went wrong (HRESULT:1)' - } - - Should -Invoke -CommandName Invoke-CimMethod -ParameterFilter { - $MethodName -eq 'AnyMethod' - } -Exactly -Times 1 - } - } - - Context 'When Invoke-CimMethod fails and returns an object with a ExtendedErrors property' { - BeforeAll { - Mock -CommandName Invoke-CimMethod -MockWith { - return New-Object -TypeName Object | - Add-Member -MemberType NoteProperty -Name 'HRESULT' -Value 1 -PassThru | # cSpell: disable-line - Add-Member -MemberType NoteProperty -Name 'ExtendedErrors' -Value @('Something went wrong', 'Another thing went wrong') -PassThru -Force - } - } - - It 'Should call Invoke-CimMethod and throw the correct error' { - InModuleScope -ScriptBlock { - Set-StrictMode -Version 1.0 - - $invokeRsCimMethodParameters = @{ - CimInstance = $mockCimInstance - MethodName = 'AnyMethod' - } - - # cSpell: disable-next - { Invoke-RsCimMethod @invokeRsCimMethodParameters } | Should -Throw 'Method AnyMethod() failed with an error. Error: Something went wrong;Another thing went wrong (HRESULT:1)' - } - - Should -Invoke -CommandName Invoke-CimMethod -ParameterFilter { - $MethodName -eq 'AnyMethod' - } -Exactly -Times 1 - } - } - } -} diff --git a/tests/Unit/Private/Get-HResultMessage.Tests.ps1 b/tests/Unit/Private/Get-HResultMessage.Tests.ps1 index 66238d4985..c659b75e96 100644 --- a/tests/Unit/Private/Get-HResultMessage.Tests.ps1 +++ b/tests/Unit/Private/Get-HResultMessage.Tests.ps1 @@ -38,7 +38,7 @@ BeforeAll { } AfterAll { - $env:SqlServerDscCI = $null + Remove-Item -Path 'env:SqlServerDscCI' -ErrorAction 'SilentlyContinue' $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') $PSDefaultParameterValues.Remove('Mock:ModuleName') diff --git a/tests/Unit/Public/Initialize-SqlDscRS.Tests.ps1 b/tests/Unit/Public/Initialize-SqlDscRS.Tests.ps1 new file mode 100644 index 0000000000..24c0bc719f --- /dev/null +++ b/tests/Unit/Public/Initialize-SqlDscRS.Tests.ps1 @@ -0,0 +1,177 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:moduleName -ErrorAction 'Stop' + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Initialize-SqlDscRS' { + Context 'When validating parameter sets' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + ExpectedParameterSetName = '__AllParameterSets' + ExpectedParameters = '[-Configuration] [-PassThru] [-Force] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Initialize-SqlDscRS').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + } + + Context 'When initializing Reporting Services successfully' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + InstallationID = '12345678-1234-1234-1234-123456789012' + } + + Mock -CommandName Invoke-RsCimMethod + } + + It 'Should initialize Reporting Services without errors' { + $mockCimInstance | Initialize-SqlDscRS -Confirm:$false + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'InitializeReportServer' -and + $Arguments.InstallationID -eq '12345678-1234-1234-1234-123456789012' + } -Exactly -Times 1 + } + + It 'Should not return anything by default' { + $result = $mockCimInstance | Initialize-SqlDscRS -Confirm:$false + + $result | Should -BeNullOrEmpty + } + } + + Context 'When initializing Reporting Services with PassThru' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + InstallationID = '12345678-1234-1234-1234-123456789012' + } + + Mock -CommandName Invoke-RsCimMethod + } + + It 'Should return the configuration CIM instance' { + $result = $mockCimInstance | Initialize-SqlDscRS -PassThru -Confirm:$false + + $result | Should -Not -BeNullOrEmpty + $result.InstanceName | Should -Be 'SSRS' + } + } + + Context 'When initializing Reporting Services with Force' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + InstallationID = '12345678-1234-1234-1234-123456789012' + } + + Mock -CommandName Invoke-RsCimMethod + } + + It 'Should initialize Reporting Services without confirmation' { + $mockCimInstance | Initialize-SqlDscRS -Force + + Should -Invoke -CommandName Invoke-RsCimMethod -Exactly -Times 1 + } + } + + Context 'When CIM method fails' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + InstallationID = '12345678-1234-1234-1234-123456789012' + } + + Mock -CommandName Invoke-RsCimMethod -MockWith { + throw 'Method InitializeReportServer() failed with an error.' + } + } + + It 'Should throw a terminating error' { + { $mockCimInstance | Initialize-SqlDscRS -Confirm:$false } | Should -Throw -ErrorId 'ISRS0001,Initialize-SqlDscRS' + } + } + + Context 'When using WhatIf' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + InstallationID = '12345678-1234-1234-1234-123456789012' + } + + Mock -CommandName Invoke-RsCimMethod + } + + It 'Should not call Invoke-RsCimMethod' { + $mockCimInstance | Initialize-SqlDscRS -WhatIf + + Should -Invoke -CommandName Invoke-RsCimMethod -Exactly -Times 0 + } + } + + Context 'When passing configuration as parameter' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + InstallationID = '12345678-1234-1234-1234-123456789012' + } + + Mock -CommandName Invoke-RsCimMethod + } + + It 'Should initialize Reporting Services' { + Initialize-SqlDscRS -Configuration $mockCimInstance -Confirm:$false + + Should -Invoke -CommandName Invoke-RsCimMethod -Exactly -Times 1 + } + } +} diff --git a/tests/Unit/Public/Request-SqlDscRSDatabaseUpgradeScript.Tests.ps1 b/tests/Unit/Public/Request-SqlDscRSDatabaseUpgradeScript.Tests.ps1 new file mode 100644 index 0000000000..b6cf066b74 --- /dev/null +++ b/tests/Unit/Public/Request-SqlDscRSDatabaseUpgradeScript.Tests.ps1 @@ -0,0 +1,186 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:moduleName -ErrorAction 'Stop' + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Request-SqlDscRSDatabaseUpgradeScript' { + Context 'When validating parameter sets' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + ExpectedParameterSetName = '__AllParameterSets' + ExpectedParameters = '[-Configuration] []' + } + ) { + $result = (Get-Command -Name 'Request-SqlDscRSDatabaseUpgradeScript').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + } + + Context 'When validating the Configuration parameter attributes' { + BeforeAll { + $commandMetadata = Get-Command -Name 'Request-SqlDscRSDatabaseUpgradeScript' + $configurationParameter = $commandMetadata.Parameters['Configuration'] + } + + It 'Should have ValueFromPipeline set to True' { + $configurationParameter.Attributes.ValueFromPipeline | Should -Contain $true + } + + It 'Should have Mandatory set to True' { + $configurationParameter.Attributes.Mandatory | Should -Contain $true + } + + It 'Should have the expected parameter type' { + $configurationParameter.ParameterType.Name | Should -Be 'Object' + } + } + + Context 'When generating database upgrade script successfully' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + DatabaseName = 'ReportServer' + Version = '15.0.2000.5' + } + + $mockScript = @" +-- Upgrade script for ReportServer database +ALTER TABLE dbo.Catalog ADD NewColumn nvarchar(100) NULL; +GO +"@ + + Mock -CommandName Invoke-RsCimMethod -MockWith { + return @{ + Script = $mockScript + } + } + } + + It 'Should return the database upgrade script' { + $result = $mockCimInstance | Request-SqlDscRSDatabaseUpgradeScript + + $result | Should -Not -BeNullOrEmpty + $result | Should -BeLike '*Upgrade script*' + $result | Should -BeLike '*ALTER TABLE*' + + Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { + $MethodName -eq 'GenerateDatabaseUpgradeScript' -and + $Arguments.DatabaseName -eq 'ReportServer' -and + $Arguments.ServerVersion -eq '15.0.2000.5' + } -Exactly -Times 1 + } + } + + Context 'When no upgrade is needed' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + DatabaseName = 'ReportServer' + Version = '15.0.2000.5' + } + + Mock -CommandName Invoke-RsCimMethod -MockWith { + return @{ + Script = '' + } + } + } + + It 'Should return an empty script' { + $result = $mockCimInstance | Request-SqlDscRSDatabaseUpgradeScript + + $result | Should -BeNullOrEmpty + + Should -Invoke -CommandName Invoke-RsCimMethod -Exactly -Times 1 + } + } + + Context 'When CIM method fails' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + DatabaseName = 'ReportServer' + Version = '15.0.2000.5' + } + + Mock -CommandName Invoke-RsCimMethod -MockWith { + throw 'Method GenerateDatabaseUpgradeScript() failed with an error.' + } + } + + It 'Should throw a terminating error' { + { $mockCimInstance | Request-SqlDscRSDatabaseUpgradeScript } | Should -Throw -ErrorId 'RSRSDBUS0001,Request-SqlDscRSDatabaseUpgradeScript' + } + } + + Context 'When passing configuration as parameter' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + DatabaseName = 'ReportServer' + Version = '15.0.2000.5' + } + + Mock -CommandName Invoke-RsCimMethod -MockWith { + return @{ + Script = '-- Upgrade script' + } + } + } + + It 'Should generate database upgrade script' { + $result = Request-SqlDscRSDatabaseUpgradeScript -Configuration $mockCimInstance + + $result | Should -Not -BeNullOrEmpty + + Should -Invoke -CommandName Invoke-RsCimMethod -Exactly -Times 1 + } + } +} diff --git a/tests/Unit/Public/Restart-SqlDscRSService.Tests.ps1 b/tests/Unit/Public/Restart-SqlDscRSService.Tests.ps1 new file mode 100644 index 0000000000..7200fbda56 --- /dev/null +++ b/tests/Unit/Public/Restart-SqlDscRSService.Tests.ps1 @@ -0,0 +1,344 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:moduleName -ErrorAction 'Stop' + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName + + # Create stub for Get-Service in module scope for cross-platform testing + InModuleScope -ScriptBlock { + # Inject a stub in the module scope to support testing cross-platform + function script:Get-Service + { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ParameterBlockParameterAttribute', '', Justification='The stub cannot use [Parameter()].')] + param + ( + $Name, + $ErrorAction + ) + + throw 'Stub function Get-Service was called' + } + + function script:Stop-Service + { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ParameterBlockParameterAttribute', '', Justification='The stub cannot use [Parameter()].')] + param + ( + [Parameter(ValueFromPipeline = $true)] + $InputObject, + [Switch] + $Force + ) + + throw 'Stub function Stop-Service was called' + } + + function script:Start-Service + { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('DscResource.AnalyzerRules\Measure-ParameterBlockParameterAttribute', '', Justification='The stub cannot use [Parameter()].')] + param + ( + [Parameter(ValueFromPipeline = $true)] + $InputObject + ) + + throw 'Stub function Start-Service was called' + } + } +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Restart-SqlDscRSService' { + Context 'When validating parameter sets' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + ExpectedParameterSetName = 'ByServiceName' + ExpectedParameters = '-ServiceName [-WaitTime ] [-Force] [-WhatIf] [-Confirm] []' + } + @{ + ExpectedParameterSetName = 'ByConfiguration' + ExpectedParameters = '-Configuration [-WaitTime ] [-PassThru] [-Force] [-WhatIf] [-Confirm] []' + } + ) { + $result = (Get-Command -Name 'Restart-SqlDscRSService').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + } + + Context 'When restarting service using ServiceName parameter' { + BeforeAll { + $mockServiceName = 'SQLServerReportingServices' + + Mock -CommandName Get-Service -MockWith { + return [PSCustomObject] @{ + Name = $mockServiceName + DisplayName = 'SQL Server Reporting Services' + Status = 'Running' + DependentServices = @() + } + } + + Mock -CommandName Stop-Service + Mock -CommandName Start-Service + Mock -CommandName Start-Sleep + } + + It 'Should restart the service without errors' { + { Restart-SqlDscRSService -ServiceName $mockServiceName -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Get-Service -ParameterFilter { + $Name -eq $mockServiceName + } -Exactly -Times 1 + + Should -Invoke -CommandName Stop-Service -Exactly -Times 1 + Should -Invoke -CommandName Start-Service -Exactly -Times 1 + } + + It 'Should not return anything by default' { + $result = Restart-SqlDscRSService -ServiceName $mockServiceName -Confirm:$false + + $result | Should -BeNullOrEmpty + } + + It 'Should not wait when WaitTime is 0' { + Restart-SqlDscRSService -ServiceName $mockServiceName -WaitTime 0 -Confirm:$false + + Should -Invoke -CommandName Start-Sleep -Exactly -Times 0 + } + + It 'Should wait when WaitTime is specified' { + Restart-SqlDscRSService -ServiceName $mockServiceName -WaitTime 30 -Confirm:$false + + Should -Invoke -CommandName Start-Sleep -ParameterFilter { + $Seconds -eq 30 + } -Exactly -Times 1 + } + } + + Context 'When restarting service using Configuration parameter' { + BeforeAll { + $mockServiceName = 'SQLServerReportingServices' + + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + ServiceName = $mockServiceName + } + + Mock -CommandName Get-Service -MockWith { + return [PSCustomObject] @{ + Name = $mockServiceName + DisplayName = 'SQL Server Reporting Services' + Status = 'Running' + DependentServices = @() + } + } + + Mock -CommandName Stop-Service + Mock -CommandName Start-Service + } + + It 'Should restart the service using the ServiceName from configuration' { + { $mockCimInstance | Restart-SqlDscRSService -Confirm:$false } | Should -Not -Throw + + Should -Invoke -CommandName Get-Service -ParameterFilter { + $Name -eq $mockServiceName + } -Exactly -Times 1 + + Should -Invoke -CommandName Stop-Service -Exactly -Times 1 + Should -Invoke -CommandName Start-Service -Exactly -Times 1 + } + + It 'Should not return anything by default' { + $result = $mockCimInstance | Restart-SqlDscRSService -Confirm:$false + + $result | Should -BeNullOrEmpty + } + } + + Context 'When using PassThru with Configuration parameter' { + BeforeAll { + $mockServiceName = 'SQLServerReportingServices' + + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + ServiceName = $mockServiceName + } + + Mock -CommandName Get-Service -MockWith { + return [PSCustomObject] @{ + Name = $mockServiceName + DisplayName = 'SQL Server Reporting Services' + Status = 'Running' + DependentServices = @() + } + } + + Mock -CommandName Stop-Service + Mock -CommandName Start-Service + } + + It 'Should return the configuration CIM instance' { + $result = $mockCimInstance | Restart-SqlDscRSService -PassThru -Confirm:$false + + $result | Should -Not -BeNullOrEmpty + $result.InstanceName | Should -Be 'SSRS' + $result.ServiceName | Should -Be $mockServiceName + } + } + + Context 'When using Force' { + BeforeAll { + $mockServiceName = 'SQLServerReportingServices' + + Mock -CommandName Get-Service -MockWith { + return [PSCustomObject] @{ + Name = $mockServiceName + DisplayName = 'SQL Server Reporting Services' + Status = 'Running' + DependentServices = @() + } + } + + Mock -CommandName Stop-Service + Mock -CommandName Start-Service + } + + It 'Should restart service without confirmation' { + { Restart-SqlDscRSService -ServiceName $mockServiceName -Force } | Should -Not -Throw + + Should -Invoke -CommandName Stop-Service -Exactly -Times 1 + Should -Invoke -CommandName Start-Service -Exactly -Times 1 + } + } + + Context 'When there are dependent services' { + BeforeAll { + $mockServiceName = 'SQLServerReportingServices' + + $mockDependentService = [PSCustomObject] @{ + Name = 'DependentService' + DisplayName = 'Dependent Service' + Status = 'Running' + } + + Mock -CommandName Get-Service -MockWith { + return [PSCustomObject] @{ + Name = $mockServiceName + DisplayName = 'SQL Server Reporting Services' + Status = 'Running' + DependentServices = @($mockDependentService) + } + } + + Mock -CommandName Stop-Service + Mock -CommandName Start-Service + } + + It 'Should restart the main service and dependent services' { + { Restart-SqlDscRSService -ServiceName $mockServiceName -Confirm:$false } | Should -Not -Throw + + # Main service restart + dependent service restart + Should -Invoke -CommandName Start-Service -Exactly -Times 2 + } + } + + Context 'When dependent service is not running' { + BeforeAll { + $mockServiceName = 'SQLServerReportingServices' + + $mockDependentService = [PSCustomObject] @{ + Name = 'DependentService' + DisplayName = 'Dependent Service' + Status = 'Stopped' + } + + Mock -CommandName Get-Service -MockWith { + return [PSCustomObject] @{ + Name = $mockServiceName + DisplayName = 'SQL Server Reporting Services' + Status = 'Running' + DependentServices = @($mockDependentService) + } + } + + Mock -CommandName Stop-Service + Mock -CommandName Start-Service + } + + It 'Should not restart stopped dependent services' { + { Restart-SqlDscRSService -ServiceName $mockServiceName -Confirm:$false } | Should -Not -Throw + + # Only main service restart, not the stopped dependent service + Should -Invoke -CommandName Start-Service -Exactly -Times 1 + } + } + + Context 'When using WhatIf' { + BeforeAll { + $mockServiceName = 'SQLServerReportingServices' + + Mock -CommandName Get-Service -MockWith { + return [PSCustomObject] @{ + Name = $mockServiceName + DisplayName = 'SQL Server Reporting Services' + Status = 'Running' + DependentServices = @() + } + } + + Mock -CommandName Stop-Service + Mock -CommandName Start-Service + } + + It 'Should not call Stop-Service or Start-Service' { + Restart-SqlDscRSService -ServiceName $mockServiceName -WhatIf + + Should -Invoke -CommandName Stop-Service -Exactly -Times 0 + Should -Invoke -CommandName Start-Service -Exactly -Times 0 + } + } +} diff --git a/tests/Unit/Public/Set-SqlDscRSDatabaseConnection.Tests.ps1 b/tests/Unit/Public/Set-SqlDscRSDatabaseConnection.Tests.ps1 index 2f247db58b..d9ff52f357 100644 --- a/tests/Unit/Public/Set-SqlDscRSDatabaseConnection.Tests.ps1 +++ b/tests/Unit/Public/Set-SqlDscRSDatabaseConnection.Tests.ps1 @@ -73,7 +73,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should set database connection without errors' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Confirm:$false } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { $MethodName -eq 'SetDatabaseConnection' -and @@ -119,7 +119,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should set database connection without confirmation' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Force } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Force Should -Invoke -CommandName Invoke-RsCimMethod -Exactly -Times 1 } @@ -140,7 +140,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should use the Windows credentials type (0)' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Type 'Windows' -Credential $mockCredential -Confirm:$false } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Type 'Windows' -Credential $mockCredential -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { $Arguments.CredentialsType -eq 0 -and @@ -165,7 +165,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should use the SqlServer credentials type (1)' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Type 'SqlServer' -Credential $mockCredential -Confirm:$false } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Type 'SqlServer' -Credential $mockCredential -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { $Arguments.CredentialsType -eq 1 -and @@ -185,7 +185,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should use the ServiceAccount credentials type (2)' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Type 'ServiceAccount' -Confirm:$false } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer' -Type 'ServiceAccount' -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { $Arguments.CredentialsType -eq 2 -and @@ -265,7 +265,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should set database connection' { - { Set-SqlDscRSDatabaseConnection -Configuration $mockCimInstance -ServerName 'localhost' -DatabaseName 'ReportServer' -Confirm:$false } | Should -Not -Throw + Set-SqlDscRSDatabaseConnection -Configuration $mockCimInstance -ServerName 'localhost' -DatabaseName 'ReportServer' -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -Exactly -Times 1 } @@ -281,7 +281,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should pass the correct server name format when InstanceName is specified' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'SqlServer01' -InstanceName 'MSSQLSERVER' -DatabaseName 'ReportServer' -Confirm:$false } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'SqlServer01' -InstanceName 'MSSQLSERVER' -DatabaseName 'ReportServer' -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { $Arguments.Server -eq 'SqlServer01\MSSQLSERVER' @@ -289,7 +289,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should pass only the server name when InstanceName is not specified' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'SqlServer01' -DatabaseName 'ReportServer' -Confirm:$false } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'SqlServer01' -DatabaseName 'ReportServer' -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { $Arguments.Server -eq 'SqlServer01' @@ -307,7 +307,7 @@ Describe 'Set-SqlDscRSDatabaseConnection' { } It 'Should pass the correct database name' { - { $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer$SSRS' -Confirm:$false } | Should -Not -Throw + $mockCimInstance | Set-SqlDscRSDatabaseConnection -ServerName 'localhost' -DatabaseName 'ReportServer$SSRS' -Confirm:$false Should -Invoke -CommandName Invoke-RsCimMethod -ParameterFilter { $Arguments.DatabaseName -eq 'ReportServer$SSRS' diff --git a/tests/Unit/Public/Test-SqlDscRSInitialized.Tests.ps1 b/tests/Unit/Public/Test-SqlDscRSInitialized.Tests.ps1 new file mode 100644 index 0000000000..5d7c3885f3 --- /dev/null +++ b/tests/Unit/Public/Test-SqlDscRSInitialized.Tests.ps1 @@ -0,0 +1,110 @@ +[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Suppressing this rule because Script Analyzer does not understand Pester syntax.')] +param () + +BeforeDiscovery { + try + { + if (-not (Get-Module -Name 'DscResource.Test')) + { + # Assumes dependencies have been resolved, so if this module is not available, run 'noop' task. + if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable)) + { + # Redirect all streams to $null, except the error stream (stream 2) + & "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null + } + + # If the dependencies have not been resolved, this will throw an error. + Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop' + } + } + catch [System.IO.FileNotFoundException] + { + throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks noop" first.' + } +} + +BeforeAll { + $script:moduleName = 'SqlServerDsc' + + $env:SqlServerDscCI = $true + + Import-Module -Name $script:moduleName -ErrorAction 'Stop' + + $PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName + $PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName +} + +AfterAll { + $PSDefaultParameterValues.Remove('InModuleScope:ModuleName') + $PSDefaultParameterValues.Remove('Mock:ModuleName') + $PSDefaultParameterValues.Remove('Should:ModuleName') + + Remove-Item -Path 'env:SqlServerDscCI' +} + +Describe 'Test-SqlDscRSInitialized' { + Context 'When validating parameter sets' { + It 'Should have the correct parameters in parameter set ' -ForEach @( + @{ + ExpectedParameterSetName = '__AllParameterSets' + ExpectedParameters = '[-Configuration] []' + } + ) { + $result = (Get-Command -Name 'Test-SqlDscRSInitialized').ParameterSets | + Where-Object -FilterScript { $_.Name -eq $ExpectedParameterSetName } | + Select-Object -Property @( + @{ Name = 'ParameterSetName'; Expression = { $_.Name } }, + @{ Name = 'ParameterListAsString'; Expression = { $_.ToString() } } + ) + + $result.ParameterSetName | Should -Be $ExpectedParameterSetName + $result.ParameterListAsString | Should -Be $ExpectedParameters + } + } + + Context 'When Reporting Services is initialized' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + IsInitialized = $true + } + } + + It 'Should return $true' { + $result = $mockCimInstance | Test-SqlDscRSInitialized + + $result | Should -BeTrue + } + } + + Context 'When Reporting Services is not initialized' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + IsInitialized = $false + } + } + + It 'Should return $false' { + $result = $mockCimInstance | Test-SqlDscRSInitialized + + $result | Should -BeFalse + } + } + + Context 'When passing configuration as parameter' { + BeforeAll { + $mockCimInstance = [PSCustomObject] @{ + InstanceName = 'SSRS' + IsInitialized = $true + } + } + + It 'Should return the initialization status' { + $result = Test-SqlDscRSInitialized -Configuration $mockCimInstance + + $result | Should -BeTrue + } + } +} diff --git a/tests/Unit/SqlServerDsc.Common.Tests.ps1 b/tests/Unit/SqlServerDsc.Common.Tests.ps1 index 731367c432..9ab45e7959 100644 --- a/tests/Unit/SqlServerDsc.Common.Tests.ps1 +++ b/tests/Unit/SqlServerDsc.Common.Tests.ps1 @@ -2876,110 +2876,6 @@ Describe 'SqlServerDsc.Common\Test-ClusterPermissions' -Tag 'TestClusterPermissi } } -Describe 'SqlServerDsc.Common\Restart-ReportingServicesService' -Tag 'RestartReportingServicesService' { - BeforeAll { - $mockGetService = { - return @{ - Name = $mockDynamicServiceName - DisplayName = $mockDynamicServiceDisplayName - DependentServices = @( - @{ - Name = $mockDynamicDependedServiceName - Status = 'Running' - DependentServices = @() - } - ) - } - } - - InModuleScope -ScriptBlock { - # Stubs for cross-platform testing. - function script:Get-Service - { - [CmdletBinding()] - param - ( - [Parameter()] - [System.String] - $Name - ) - - throw '{0}: StubNotImplemented' -f $MyInvocation.MyCommand - } - - function script:Stop-Service - { - throw '{0}: StubNotImplemented' -f $MyInvocation.MyCommand - } - - function script:Start-Service - { - throw '{0}: StubNotImplemented' -f $MyInvocation.MyCommand - } - } - } - - AfterAll { - InModuleScope -ScriptBlock { - Remove-Item -Path 'function:/Start-Service' - Remove-Item -Path 'function:/Stop-Service' - Remove-Item -Path 'function:/Get-Service' - } - } - - Context 'When restarting a Report Services service name is supplied' { - BeforeAll { - $mockServiceName = 'ReportServer' - $mockDependedServiceName = 'DependentService' - - $mockDynamicServiceName = $mockServiceName - $mockDynamicDependedServiceName = $mockDependedServiceName - $mockDynamicServiceDisplayName = 'Reporting Services (MSSQLSERVER)' - - Mock -CommandName Stop-Service - Mock -CommandName Start-Service - Mock -CommandName Get-Service -MockWith $mockGetService - } - - It 'Should restart the service and dependent service' { - $null = Restart-ReportingServicesService -ServiceName 'ReportServer' - - Should -Invoke -CommandName Get-Service -ParameterFilter { - $Name -eq $mockServiceName - } -Scope It -Exactly -Times 1 - Should -Invoke -CommandName Stop-Service -Scope It -Exactly -Times 1 - Should -Invoke -CommandName Start-Service -Scope It -Exactly -Times 2 - } - } - - Context 'When restarting a Report Services service with wait timer' { - BeforeAll { - $mockServiceName = 'ReportServer' - $mockDependedServiceName = 'DependentService' - - $mockDynamicServiceName = $mockServiceName - $mockDynamicDependedServiceName = $mockDependedServiceName - $mockDynamicServiceDisplayName = 'Reporting Services (MSSQLSERVER)' - - Mock -CommandName Start-Sleep - Mock -CommandName Stop-Service - Mock -CommandName Start-Service - Mock -CommandName Get-Service -MockWith $mockGetService - } - - It 'Should restart the service and dependent service with wait time' { - $null = Restart-ReportingServicesService -ServiceName 'ReportServer' -WaitTime 1 - - Should -Invoke -CommandName Get-Service -ParameterFilter { - $Name -eq $mockServiceName - } -Scope It -Exactly -Times 1 - Should -Invoke -CommandName Stop-Service -Scope It -Exactly -Times 1 - Should -Invoke -CommandName Start-Service -Scope It -Exactly -Times 2 - Should -Invoke -CommandName Start-Sleep -Scope It -Exactly -Times 1 - } - } -} - Describe 'SqlServerDsc.Common\Test-ActiveNode' -Tag 'TestActiveNode' { BeforeAll { $mockServerObject = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server