diff --git a/CHANGELOG.md b/CHANGELOG.md index df10cae7f8..d5e789e3e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,9 @@ - Added new resource xSQLServerAccount ([issue #706](https://github.com/PowerShell/xSQLServer/issues/706)) - Added localization support for all strings - Added examples for usage +- Changes to xSQLServerRSConfig + - Fixed so that when two Reporting Services are installed for the same major + version the resource does not throw an error ([issue #819](https://github.com/PowerShell/xSQLServer/issues/819)). ## 8.1.0.0 diff --git a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 index cbe11b8f00..1510d83c5f 100644 --- a/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 +++ b/DSCResources/MSFT_xSQLServerRSConfig/MSFT_xSQLServerRSConfig.psm1 @@ -42,6 +42,10 @@ function Get-TargetResource $sqlVersion = ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$instanceId\Setup" -Name 'Version').Version).Split('.')[0] $reportingServicesConfiguration = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$sqlVersion\Admin" + $reportingServicesConfiguration = $reportingServicesConfiguration | Where-Object -FilterScript { + $_.InstanceName -eq $InstanceName + } + if ( $reportingServicesConfiguration.DatabaseServerName.Contains('\') ) { $RSSQLServer = $reportingServicesConfiguration.DatabaseServerName.Split('\')[0] @@ -132,15 +136,18 @@ function Set-TargetResource if ( $RSSQLInstanceName -eq 'MSSQLSERVER' ) { - $reportingServicesConnnection = $RSSQLServer + $reportingServicesConnection = $RSSQLServer } else { - $reportingServicesConnnection = "$RSSQLServer\$RSSQLInstanceName" + $reportingServicesConnection = "$RSSQLServer\$RSSQLInstanceName" } $language = (Get-WMIObject -Class Win32_OperatingSystem -Namespace root/cimv2 -ErrorAction SilentlyContinue).OSLanguage $reportingServicesConfiguration = Get-WmiObject -Class MSReportServer_ConfigurationSetting -Namespace "root\Microsoft\SQLServer\ReportServer\RS_$InstanceName\v$sqlVersion\Admin" + $reportingServicesConfiguration = $reportingServicesConfiguration | Where-Object -FilterScript { + $_.InstanceName -eq $InstanceName + } if ( $reportingServicesConfiguration.VirtualDirectoryReportServer -ne $reportServerVirtualDirectoryName ) { @@ -173,9 +180,9 @@ function Set-TargetResource $reportingServicesServiceAccountUserName = (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq $reportingServicesServiceName}).StartName $reportingServicesDatabaseRightsScript = $reportingServicesConfiguration.GenerateDatabaseRightsScript($reportingServicesServiceAccountUserName, $reportingServicesDatabaseName, $false, $true) - Invoke-Sqlcmd -ServerInstance $reportingServicesConnnection -Query $reportingServicesDatabaseScript.Script - Invoke-Sqlcmd -ServerInstance $reportingServicesConnnection -Query $reportingServicesDatabaseRightsScript.Script - $null = $reportingServicesConfiguration.SetDatabaseConnection($reportingServicesConnnection, $reportingServicesDatabaseName, 2, '', '') + Invoke-Sqlcmd -ServerInstance $reportingServicesConnection -Query $reportingServicesDatabaseScript.Script + Invoke-Sqlcmd -ServerInstance $reportingServicesConnection -Query $reportingServicesDatabaseRightsScript.Script + $null = $reportingServicesConfiguration.SetDatabaseConnection($reportingServicesConnection, $reportingServicesDatabaseName, 2, '', '') $null = $reportingServicesConfiguration.InitializeReportServer($reportingServicesConfiguration.InstallationID) } diff --git a/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 b/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 index 472c40edd4..19924e25d7 100644 --- a/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 +++ b/Tests/Unit/MSFT_xSQLServerRSConfig.Tests.ps1 @@ -48,9 +48,12 @@ try } $mockGetWmiObject_ConfigurationSetting_NamedInstance = { - return New-Object Object | + return @( + ( + New-Object Object | Add-Member -MemberType NoteProperty -Name 'DatabaseServerName' -Value "$mockReportingServicesDatabaseServerName\$mockReportingServicesDatabaseNamedInstanceName" -PassThru | Add-Member -MemberType NoteProperty -Name 'IsInitialized' -Value $true -PassThru | + Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value $mockNamedInstanceName -PassThru | Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportServer' -Value '' -PassThru | Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value '' -PassThru | Add-Member -MemberType ScriptMethod -Name SetVirtualDirectory { @@ -87,14 +90,59 @@ try return $null } -PassThru -Force + ), + ( + # Array is a regression test for issue #819. + New-Object Object | + Add-Member -MemberType NoteProperty -Name 'DatabaseServerName' -Value "$mockReportingServicesDatabaseServerName\$mockReportingServicesDatabaseNamedInstanceName" -PassThru | + Add-Member -MemberType NoteProperty -Name 'IsInitialized' -Value $true -PassThru | + Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value 'DummyInstance' -PassThru -Force + ) + ) } $mockGetWmiObject_ConfigurationSetting_DefaultInstance = { - return @{ - DatabaseServerName = $mockReportingServicesDatabaseServerName - IsInitialized = $false - } - } + return New-Object Object | + Add-Member -MemberType NoteProperty -Name 'DatabaseServerName' -Value "$mockReportingServicesDatabaseServerName\$mockReportingServicesDatabaseNamedInstanceName" -PassThru | + Add-Member -MemberType NoteProperty -Name 'IsInitialized' -Value $false -PassThru | + Add-Member -MemberType NoteProperty -Name 'InstanceName' -Value $mockDefaultInstanceName -PassThru | + Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportServer' -Value '' -PassThru | + Add-Member -MemberType NoteProperty -Name 'VirtualDirectoryReportManager' -Value '' -PassThru | + Add-Member -MemberType ScriptMethod -Name SetVirtualDirectory { + $script:mockIsMethodCalled_SetVirtualDirectory = $true + + return $null + } -PassThru | + Add-Member -MemberType ScriptMethod -Name ReserveURL { + $script:mockIsMethodCalled_ReserveURL = $true + + return $null + } -PassThru | + Add-Member -MemberType ScriptMethod -Name GenerateDatabaseCreationScript { + $script:mockIsMethodCalled_GenerateDatabaseCreationScript = $true + + return @{ + Script = 'select * from something' + } + } -PassThru | + Add-Member -MemberType ScriptMethod -Name GenerateDatabaseRightsScript { + $script:mockIsMethodCalled_GenerateDatabaseRightsScript = $true + + return @{ + Script = 'select * from something' + } + } -PassThru | + Add-Member -MemberType ScriptMethod -Name SetDatabaseConnection { + $script:mockIsMethodCalled_SetDatabaseConnection = $true + + return $null + } -PassThru | + Add-Member -MemberType ScriptMethod -Name InitializeReportServer { + $script:mockIsMethodCalled_InitializeReportServer = $true + + return $null + } -PassThru -Force +} $mockGetWmiObject_ConfigurationSetting_ParameterFilter = { $Class -eq 'MSReportServer_ConfigurationSetting' @@ -116,7 +164,7 @@ try Mock -CommandName Get-ItemProperty -MockWith $mockGetItemProperty -Verifiable - $testParameters = @{ + $defaultParameters = @{ InstanceName = $mockNamedInstanceName RSSQLServer = $mockReportingServicesDatabaseServerName RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName @@ -132,7 +180,7 @@ try } It 'Should return the same values as passed as parameters' { - $resultGetTargetResource = Get-TargetResource @testParameters + $resultGetTargetResource = Get-TargetResource @defaultParameters $resultGetTargetResource.InstanceName | Should Be $mockNamedInstanceName $resultGetTargetResource.RSSQLServer | Should Be $mockReportingServicesDatabaseServerName $resultGetTargetResource.RSSQLInstanceName | Should Be $mockReportingServicesDatabaseNamedInstanceName @@ -140,7 +188,7 @@ try } It 'Should return the the state as initialized' { - $resultGetTargetResource = Get-TargetResource @testParameters + $resultGetTargetResource = Get-TargetResource @defaultParameters $resultGetTargetResource.IsInitialized | Should Be $true } } @@ -151,13 +199,16 @@ try -MockWith $mockGetWmiObject_ConfigurationSetting_DefaultInstance ` -ParameterFilter $mockGetWmiObject_ConfigurationSetting_ParameterFilter ` -Verifiable + + $testParameters = $defaultParameters.Clone() + $testParameters['InstanceName'] = $mockDefaultInstanceName } It 'Should return the same values as passed as parameters' { $resultGetTargetResource = Get-TargetResource @testParameters - $resultGetTargetResource.InstanceName | Should Be $mockNamedInstanceName + $resultGetTargetResource.InstanceName | Should Be $mockDefaultInstanceName $resultGetTargetResource.RSSQLServer | Should Be $mockReportingServicesDatabaseServerName - $resultGetTargetResource.RSSQLInstanceName | Should Be 'MSSQLSERVER' + $resultGetTargetResource.RSSQLInstanceName | Should Be $mockReportingServicesDatabaseNamedInstanceName $resultGetTargetResource | Should BeOfType [System.Collections.Hashtable] } @@ -172,7 +223,7 @@ try } It 'Should throw the correct error message' { - { Get-TargetResource @testParameters } | Should Throw 'SQL Reporting Services instance ''INSTANCE'' does not exist!' + { Get-TargetResource @defaultParameters } | Should Throw 'SQL Reporting Services instance ''INSTANCE'' does not exist!' } } } @@ -196,7 +247,7 @@ try return $true } - $testParameters = @{ + $defaultParameters = @{ InstanceName = $mockNamedInstanceName RSSQLServer = $mockReportingServicesDatabaseServerName RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName @@ -224,7 +275,7 @@ try } It 'Should configure Reporting Service without throwing an error' { - { Set-TargetResource @testParameters } | Should Not Throw + { Set-TargetResource @defaultParameters } | Should Not Throw # Test so each mock of methods was called. $script:mockIsMethodCalled_GenerateDatabaseRightsScript | Should Be $true @@ -245,7 +296,7 @@ try } It 'Should throw the correct error message' { - { Set-TargetResource @testParameters } | Should Throw 'Test-TargetResource returned false after calling set.' + { Set-TargetResource @defaultParameters } | Should Throw 'Test-TargetResource returned false after calling set.' } } } @@ -258,7 +309,7 @@ try return $true } -Verifiable - $testParameters = @{ + $defaultParameters = @{ InstanceName = $mockDefaultInstanceName RSSQLServer = $mockReportingServicesDatabaseServerName RSSQLInstanceName = $mockReportingServicesDatabaseDefaultInstanceName @@ -267,7 +318,7 @@ try BeforeEach { Mock -CommandName Get-WmiObject ` - -MockWith $mockGetWmiObject_ConfigurationSetting_NamedInstance ` + -MockWith $mockGetWmiObject_ConfigurationSetting_DefaultInstance ` -ParameterFilter $mockGetWmiObject_ConfigurationSetting_ParameterFilter ` -Verifiable @@ -278,7 +329,7 @@ try } It 'Should configure Reporting Service without throwing an error' { - { Set-TargetResource @testParameters } | Should Not Throw + { Set-TargetResource @defaultParameters } | Should Not Throw # Test so each mock of methods was called. $script:mockIsMethodCalled_GenerateDatabaseRightsScript | Should Be $true @@ -306,7 +357,7 @@ try } } -Verifiable - $testParameters = @{ + $defaultParameters = @{ InstanceName = $mockNamedInstanceName RSSQLServer = $mockReportingServicesDatabaseServerName RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName @@ -314,7 +365,7 @@ try } It 'Should return state as not in desired state' { - $resultTestTargetResource = Test-TargetResource @testParameters + $resultTestTargetResource = Test-TargetResource @defaultParameters $resultTestTargetResource | Should Be $false } } @@ -327,7 +378,7 @@ try } } -Verifiable - $testParameters = @{ + $defaultParameters = @{ InstanceName = $mockNamedInstanceName RSSQLServer = $mockReportingServicesDatabaseServerName RSSQLInstanceName = $mockReportingServicesDatabaseNamedInstanceName @@ -335,7 +386,7 @@ try } It 'Should return state as in desired state' { - $resultTestTargetResource = Test-TargetResource @testParameters + $resultTestTargetResource = Test-TargetResource @defaultParameters $resultTestTargetResource | Should Be $true } }