From 38eb4bedd47efd1b444b05164b2d9381712bf296 Mon Sep 17 00:00:00 2001 From: Claudio Spizzi Date: Thu, 8 Feb 2018 01:23:49 +0100 Subject: [PATCH 1/3] Add the possibility to use ListenAll and custom IPs --- CHANGELOG.md | 4 + .../MSFT_SqlServerNetwork.psm1 | 155 ++++++++++++++++-- .../MSFT_SqlServerNetwork.schema.mof | 2 + .../en-US/MSFT_SqlServerNetwork.strings.psd1 | 2 + .../1-EnableTcpIpWithStaticPort.ps1 | 1 + .../2-EnableTcpIpWithDynamicPort.ps1 | 1 + .../3-EnableTcpIpOnCustomIP.ps1 | 30 ++++ README.md | 5 + Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 | 28 ++++ 9 files changed, 211 insertions(+), 17 deletions(-) create mode 100644 Examples/Resources/SqlServerNetwork/3-EnableTcpIpOnCustomIP.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ad7b6ffb..1a16206d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ SqlRS as the parameter UseSsl. The UseSsl parameter is of type boolean. This change was made because from SQL Server 2008 R2 this value is made an on/off switch. Read more in the article [ConfigurationSetting Method - SetSecureConnectionLevel](https://docs.microsoft.com/en-us/sql/reporting-services/wmi-provider-library-reference/configurationsetting-method-setsecureconnectionlevel). + - BREAKING CHANGE: Added new key parameter to SqlServerNetwork resource + Added IPAddress parameter to configure IP adresses. Must be a key property + to configure multiple IP adresses including the IPAll. - Updated so that named parameters are used for New-Object cmdlet. This was done to follow the style guideline. - Updated manifest and license to reflect the new year @@ -126,6 +129,7 @@ - Style cleanup in tests. - Changes to SqlServerNetwork - Added sysadmin account parameter usage to the examples. + - Added ListenAll parameter to configure if it should listen on all IP adresses. - Changes to SqlServerReplication - Fix Script Analyzer warning ([issue #263](https://github.com/PowerShell/SqlServerDsc/issues/263)). - Changes to SqlServerRole diff --git a/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 b/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 index 0ce468776..284fd012a 100644 --- a/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 +++ b/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 @@ -15,6 +15,9 @@ $script:localizedData = Get-LocalizedData -ResourceName 'MSFT_SqlServerNetwork' .PARAMETER ProtocolName The name of network protocol to be configured. Only tcp is currently supported. + + .PARAMETER IPAddress + Specify the IP address to configure. Use IPAll for all ip adresses (listen on all). #> function Get-TargetResource { @@ -30,7 +33,11 @@ function Get-TargetResource [Parameter(Mandatory = $true)] [ValidateSet('Tcp')] [System.String] - $ProtocolName + $ProtocolName, + + [Parameter(Mandatory = $true)] + [System.String] + $IPAddress ) try @@ -42,13 +49,17 @@ function Get-TargetResource Write-Verbose -Message ($script:localizedData.GetNetworkProtocol -f $ProtocolName, $InstanceName) $tcp = $managedComputerObject.ServerInstances[$InstanceName].ServerProtocols[$ProtocolName] + $ipAddressKey = Resolve-SqlProtocolIPAddress -Protocol $tcp -IPAddress $IPAddress + Write-Verbose -Message $script:localizedData.ReadingNetworkProperties $returnValue = @{ - InstanceName = $InstanceName - ProtocolName = $ProtocolName - IsEnabled = $tcp.IsEnabled - TcpDynamicPort = ($tcp.IPAddresses['IPAll'].IPAddressProperties['TcpDynamicPorts'].Value -ge 0) - TcpPort = $tcp.IPAddresses['IPAll'].IPAddressProperties['TcpPort'].Value + InstanceName = $InstanceName + ProtocolName = $ProtocolName + IPAddress = $IPAddress + IsEnabled = $(if($ipAddressKey -eq 'IPAll') { $tcp.IsEnabled } else { $tcp.IPAddresses[$ipAddressKey].IPAddressProperties['Enabled'].Value }) + ListenAll = $(if($ipAddressKey -eq 'IPAll') { $tcp.ProtocolProperties['ListenOnAllIPs'].Value } else { $null }) + TcpDynamicPort = ($tcp.IPAddresses[$ipAddressKey].IPAddressProperties['TcpDynamicPorts'].Value -ge 0) + TcpPort = $tcp.IPAddresses[$ipAddressKey].IPAddressProperties['TcpPort'].Value } $returnValue.Keys | ForEach-Object { @@ -76,9 +87,16 @@ function Get-TargetResource .PARAMETER ProtocolName The name of network protocol to be configured. Only tcp is currently supported. + .PARAMETER IPAddress + Specify the IP address to configure. Use IPAll for all ip adresses (listen on all). + .PARAMETER IsEnabled Enables or disables the network protocol. + .PARAMETER ListenAll + Enables or disables to listen on all IP adresses. Will be ignored if IPAddress is + not set to 'IPAll'. + .PARAMETER TcpDynamicPort Specifies whether the SQL Server instance should use a dynamic port. Value cannot be set to $true if TcpPort is set to a non-empty string. @@ -116,10 +134,18 @@ function Set-TargetResource [System.String] $ProtocolName, + [Parameter(Mandatory = $true)] + [System.String] + $IPAddress, + [Parameter()] [System.Boolean] $IsEnabled, + [Parameter()] + [System.Boolean] + $ListenAll, + [Parameter()] [System.Boolean] $TcpDynamicPort, @@ -143,18 +169,20 @@ function Set-TargetResource New-InvalidOperationException -Message $errorMessage } - $getTargetResourceResult = Get-TargetResource -InstanceName $InstanceName -ProtocolName $ProtocolName + $getTargetResourceResult = Get-TargetResource -InstanceName $InstanceName -ProtocolName $ProtocolName -IPAddress $IPAddress try { $applicationDomainObject = Register-SqlWmiManagement -SQLInstanceName $InstanceName $desiredState = @{ - InstanceName = $InstanceName - ProtocolName = $ProtocolName - IsEnabled = $IsEnabled - TcpDynamicPort = $TcpDynamicPort - TcpPort = $TcpPort + InstanceName = $InstanceName + ProtocolName = $ProtocolName + IPAddress = $IPAddress + ListenAll = $ListenAll + IsEnabled = $IsEnabled + TcpDynamicPort = $TcpDynamicPort + TcpPort = $TcpPort } $isRestartNeeded = $false @@ -164,13 +192,31 @@ function Set-TargetResource Write-Verbose -Message ($script:localizedData.GetNetworkProtocol -f $ProtocolName, $InstanceName) $tcp = $managedComputerObject.ServerInstances[$InstanceName].ServerProtocols[$ProtocolName] + $ipAddressKey = Resolve-SqlProtocolIPAddress -Protocol $tcp -IPAddress $IPAddress + Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'IsEnabled') if ($desiredState.IsEnabled -ine $getTargetResourceResult.IsEnabled) { Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'IsEnabled', $getTargetResourceResult.IsEnabled, $desiredState.IsEnabled) - $tcp.IsEnabled = $desiredState.IsEnabled - $tcp.Alter() + if ($ipAddressKey -eq 'IPAll') + { + $tcp.IsEnabled = $desiredState.IsEnabled + $tcp.Alter() + } + else + { + $tcp.IPAddresses[$ipAddressKey].IPAddressProperties['Enabled'].Value = $desiredState.IsEnabled + $tcp.Alter() + } + $isRestartNeeded = $true + } + Write-Verbose -Message ($script:localizedData.CheckingProperty -f 'ListenAll') + if ($desiredState.ListenAll -ine $getTargetResourceResult.ListenAll -and $ipAddressKey -eq 'IPAll') + { + Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'ListenAll', $getTargetResourceResult.ListenAll, $desiredState.ListenAll) + $tcp.ProtocolProperties['ListenOnAllIPs'].Value = $desiredState.ListenAll + $tcp.Alter() $isRestartNeeded = $true } @@ -193,7 +239,7 @@ function Set-TargetResource $toTcpDynamicPortDisplayValue = $dynamicPortDisplayValueTable[$desiredState.TcpDynamicPort] Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'TcpDynamicPorts', $fromTcpDynamicPortDisplayValue, $toTcpDynamicPortDisplayValue) - $tcp.IPAddresses['IPAll'].IPAddressProperties['TcpDynamicPorts'].Value = $desiredDynamicPortValue[$desiredState.TcpDynamicPort] + $tcp.IPAddresses[$ipAddressKey].IPAddressProperties['TcpDynamicPorts'].Value = $desiredDynamicPortValue[$desiredState.TcpDynamicPort] $tcp.Alter() $isRestartNeeded = $true @@ -215,7 +261,7 @@ function Set-TargetResource } Write-Verbose -Message ($script:localizedData.UpdatingProperty -f 'TcpPort', $fromTcpPort, $toTcpPort) - $tcp.IPAddresses['IPAll'].IPAddressProperties['TcpPort'].Value = $desiredState.TcpPort + $tcp.IPAddresses[$ipAddressKey].IPAddressProperties['TcpPort'].Value = $desiredState.TcpPort $tcp.Alter() $isRestartNeeded = $true @@ -247,9 +293,16 @@ function Set-TargetResource .PARAMETER ProtocolName The name of network protocol to be configured. Only tcp is currently supported. + .PARAMETER IPAddress + Specify the IP address to configure. Use IPAll for all ip adresses (listen on all). + .PARAMETER IsEnabled Enables or disables the network protocol. + .PARAMETER ListenAll + Enables or disables to listen on all IP adresses. Will be ignored if IPAddress is + not set to 'IPAll'. + .PARAMETER TcpDynamicPort Specifies whether the SQL Server instance should use a dynamic port. Value cannot be set to $true if TcpPort is set to a non-empty string. @@ -291,10 +344,18 @@ function Test-TargetResource [System.String] $ProtocolName, + [Parameter(Mandatory = $true)] + [System.String] + $IPAddress, + [Parameter()] [System.Boolean] $IsEnabled, + [Parameter()] + [System.Boolean] + $ListenAll, + [Parameter()] [System.Boolean] $TcpDynamicPort, @@ -318,7 +379,7 @@ function Test-TargetResource New-InvalidOperationException -Message $errorMessage } - $getTargetResourceResult = Get-TargetResource -InstanceName $InstanceName -ProtocolName $ProtocolName + $getTargetResourceResult = Get-TargetResource -InstanceName $InstanceName -ProtocolName $ProtocolName -IPAddress $IPAddress Write-Verbose -Message $script:localizedData.CompareStates @@ -346,6 +407,21 @@ function Test-TargetResource } } + if ($PSBoundParameters.ContainsKey('ListenAll') -and $IPAddress -eq 'IPAll') + { + if ($ListenAll -ne $getTargetResourceResult.ListenAll) + { + $evaluateEnableOrDisable = @{ + $true = 'enabled' + $false = 'disabled' + } + + Write-Verbose -Message ($script:localizedData.ExpectedPropertyValue -f 'ListenAll', $evaluateEnableOrDisable[$ListenAll], $evaluateEnableOrDisable[$getTargetResourceResult.ListenAll]) + + $isInDesiredState = $false + } + } + if ($PSBoundParameters.ContainsKey('TcpDynamicPort')) { if ($TcpDynamicPort -and $getTargetResourceResult.TcpDynamicPort -eq $false) @@ -380,4 +456,49 @@ function Test-TargetResource return $isInDesiredState } +<# + .SYNOPSIS + Resolve the IP Adress to the SQL Server protocol key. + + .PARAMETER Protocol + SQL Server protocol object. + + .PARAMETER IPAddress + The IP address to resolve. +#> +function Resolve-SqlProtocolIPAddress +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter(Mandatory = $true)] + $Protocol, + + [Parameter(Mandatory = $true)] + [System.String] + $IPAddress + ) + + Write-Verbose ($script:localizedData.GetSQLProtocolIPAddressKey -f $IPAddress) + + if ($IPAddress -eq 'IPAll') + { + return $IPAddress + } + else + { + $ipAddressObject = $Protocol.IPAddresses.Where({$_.IPAddress.IPAddressToString -eq $IPAddress}) + + if ($null -eq $ipAddressObject) + { + throw ($script:localizedData.IPAddressNotFoundError -f $IPAddress) + } + else + { + return $ipAddressObject.Name + } + } +} + Export-ModuleMember -Function *-TargetResource diff --git a/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.schema.mof b/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.schema.mof index 1ce38653c..8f56ae9b9 100644 --- a/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.schema.mof +++ b/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.schema.mof @@ -4,7 +4,9 @@ class MSFT_SqlServerNetwork : OMI_BaseResource [Key, Description("The name of the SQL instance to be configured.")] String InstanceName; [Required, Description("The name of network protocol to be configured. Only tcp is currently supported."), ValueMap{"Tcp"}, Values{"Tcp"}] String ProtocolName; [Write, Description("The host name of the SQL Server to be configured. Default value is $env:COMPUTERNAME.")] String ServerName; + [Key, Description("Specify the IP address to configure. Use IPAll for all ip adresses (listen on all).")] String IPAddress; [Write, Description("Enables or disables the network protocol.")] Boolean IsEnabled; + [Write, Description("Enables or disables to listen on all IP adresses. Will be ignored if IPAddress is not set to 'IPAll'.")] Boolean ListenAll; [Write, Description("Specifies whether the SQL Server instance should use a dynamic port. Value cannot be set to 'True' if TcpPort is set to a non-empty string.")] Boolean TcpDynamicPort; [Write, Description("The TCP port(s) that SQL Server should be listening on. If the IP address should listen on more than one port, list all ports separated with a comma ('1433,1500,1501'). To use this parameter set TcpDynamicPorts to 'False'.")] String TcpPort; [Write, Description("If set to $true then SQL Server and dependent services will be restarted if a change to the configuration is made. The default value is $false.")] Boolean RestartService; diff --git a/DSCResources/MSFT_SqlServerNetwork/en-US/MSFT_SqlServerNetwork.strings.psd1 b/DSCResources/MSFT_SqlServerNetwork/en-US/MSFT_SqlServerNetwork.strings.psd1 index 2454c12de..f5f49aa46 100644 --- a/DSCResources/MSFT_SqlServerNetwork/en-US/MSFT_SqlServerNetwork.strings.psd1 +++ b/DSCResources/MSFT_SqlServerNetwork/en-US/MSFT_SqlServerNetwork.strings.psd1 @@ -9,4 +9,6 @@ ConvertFrom-StringData @' CompareStates = Comparing desired state with current state. InDesiredState = System is in the desired state. ErrorDynamicAndStaticPortSpecified = Unable to set both tcp dynamic port and tcp static port. Only one can be set. + GetSQLProtocolIPAddressKey = Get the SQL protocol key for IP address [{0}]. + IPAddressNotFoundError = Specified IP address [{0}] not found. '@ diff --git a/Examples/Resources/SqlServerNetwork/1-EnableTcpIpWithStaticPort.ps1 b/Examples/Resources/SqlServerNetwork/1-EnableTcpIpWithStaticPort.ps1 index 2722e5a1e..8a1d63976 100644 --- a/Examples/Resources/SqlServerNetwork/1-EnableTcpIpWithStaticPort.ps1 +++ b/Examples/Resources/SqlServerNetwork/1-EnableTcpIpWithStaticPort.ps1 @@ -21,6 +21,7 @@ Configuration Example { InstanceName = 'MSSQLSERVER' ProtocolName = 'Tcp' + IPAddress = 'IPAll' IsEnabled = $true TCPDynamicPort = $false TCPPort = 4509 diff --git a/Examples/Resources/SqlServerNetwork/2-EnableTcpIpWithDynamicPort.ps1 b/Examples/Resources/SqlServerNetwork/2-EnableTcpIpWithDynamicPort.ps1 index 6be3708eb..e3b5fe488 100644 --- a/Examples/Resources/SqlServerNetwork/2-EnableTcpIpWithDynamicPort.ps1 +++ b/Examples/Resources/SqlServerNetwork/2-EnableTcpIpWithDynamicPort.ps1 @@ -21,6 +21,7 @@ Configuration Example { InstanceName = 'MSSQLSERVER' ProtocolName = 'Tcp' + IPAddress = 'IPAll' IsEnabled = $true TCPDynamicPort = $true RestartService = $true diff --git a/Examples/Resources/SqlServerNetwork/3-EnableTcpIpOnCustomIP.ps1 b/Examples/Resources/SqlServerNetwork/3-EnableTcpIpOnCustomIP.ps1 new file mode 100644 index 000000000..ecc7b8018 --- /dev/null +++ b/Examples/Resources/SqlServerNetwork/3-EnableTcpIpOnCustomIP.ps1 @@ -0,0 +1,30 @@ +<# +.EXAMPLE + This example will enable TCP/IP protocol and set the custom static port to 1433 + on the IP address 192.168.1.10. +#> +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $SystemAdministratorAccount + ) + + Import-DscResource -ModuleName SqlServerDsc + + node localhost + { + SqlServerNetwork 'ChangeTcpIpOnDefaultInstance' + { + InstanceName = 'MSSQLSERVER' + ProtocolName = 'Tcp' + IPAddress = '192.168.1.10' + IsEnabled = $true + TCPDynamicPort = $false + TCPPort = 1433 + PsDscRunAsCredential = $SystemAdministratorAccount + } + } +} diff --git a/README.md b/README.md index d966afeb2..e5c58d1a6 100644 --- a/README.md +++ b/README.md @@ -1243,7 +1243,11 @@ Read more about the network settings in the article Only tcp is currently supported. { tcp }. * **`[String]` ServerName** _(Write)_: The host name of the SQL Server to be configured. Default value is $env:COMPUTERNAME. +* **`[String]` IPAddress** _(Key)_: Specify the IP address to configure. Use IPAll for + all ip adresses (listen on all). * **`[Boolean]` IsEnabled** _(Write)_: Enables or disables the network protocol. +* **`[Boolean]` ListenAll** _(Write)_: Enables or disables to listen on all IP adresses. + Will be ignored if IPAddress is not set to 'IPAll'. * **`[Boolean]` TcpDynamicPort** _(Write)_: Specifies whether the SQL Server instance should use a dynamic port. Value cannot be set to $true if TcpPort is set to a non-empty string. @@ -1261,6 +1265,7 @@ Read more about the network settings in the article * [Enable TCP/IP with static port and restart SQL Server](/Examples/Resources/SqlServerNetwork/1-EnableTcpIpWithStaticPort.ps1) * [Enable TCP/IP with dynamic port](/Examples/Resources/SqlServerNetwork/2-EnableTcpIpWithDynamicPort.ps1) +* [Enable TCP/IP on custom IP](/Examples/Resources/SqlServerNetwork/3-EnableTcpIpOnCustomIP.ps1) #### Known issues diff --git a/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 b/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 index 21efdc997..fecf50207 100644 --- a/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 +++ b/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 @@ -35,6 +35,7 @@ try InModuleScope $script:DSCResourceName { $mockInstanceName = 'TEST' $mockTcpProtocolName = 'Tcp' + $mockIPAddress = 'IPAll' $mockNamedPipesProtocolName = 'NP' $mockTcpDynamicPortNumber = '24680' @@ -49,6 +50,12 @@ try return @{ $mockDynamicValue_TcpProtocolName = New-Object -TypeName Object | Add-Member -MemberType NoteProperty -Name 'IsEnabled' -Value $mockDynamicValue_IsEnabled -PassThru | + Add-Member -MemberType ScriptProperty -Name 'ProtocolProperties' -Value { + return @{ + 'ListenOnAllIPs' = New-Object -TypeName Object | + Add-Member -MemberType NoteProperty -Name 'Value' -Value $mockDynamicValue_ListenAll -PassThru -Force + } + } -PassThru | Add-Member -MemberType ScriptProperty -Name 'IPAddresses' -Value { return @{ 'IPAll' = New-Object -TypeName Object | @@ -97,6 +104,7 @@ try $mockDefaultParameters = @{ InstanceName = $mockInstanceName ProtocolName = $mockTcpProtocolName + IPAddress = $mockIPAddress } Describe "MSFT_SqlServerNetwork\Get-TargetResource" -Tag 'Get'{ @@ -116,6 +124,7 @@ try BeforeEach { $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = '' $mockDynamicValue_TcpPort = '4509' } @@ -158,6 +167,7 @@ try BeforeEach { $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = '' $mockDynamicValue_TcpPort = '4509' } @@ -189,6 +199,7 @@ try BeforeEach { $testParameters += @{ IsEnabled = $false + ListenAll = $true TcpDynamicPort = $false TcpPort = '4509' } @@ -206,6 +217,7 @@ try $testParameters += @{ TcpDynamicPort = $true IsEnabled = $false + ListenAll = $true } } @@ -220,6 +232,7 @@ try $testParameters += @{ TcpPort = '1433' IsEnabled = $true + ListenAll = $true } } @@ -234,6 +247,7 @@ try BeforeEach { $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber $mockDynamicValue_TcpPort = '' } @@ -243,6 +257,7 @@ try $testParameters += @{ TcpPort = '1433' IsEnabled = $true + ListenAll = $true } } @@ -259,6 +274,7 @@ try TcpDynamicPort = $true TcpPort = '1433' IsEnabled = $false + ListenAll = $true } } @@ -273,6 +289,7 @@ try BeforeEach { $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber $mockDynamicValue_TcpPort = '1433' } @@ -282,6 +299,7 @@ try $testParameters += @{ TcpPort = '1433' IsEnabled = $true + ListenAll = $true } } @@ -296,6 +314,7 @@ try $testParameters += @{ TcpDynamicPort = $true IsEnabled = $true + ListenAll = $true } } @@ -331,6 +350,7 @@ try # This is the values the mock will return $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = '' $mockDynamicValue_TcpPort = '4509' @@ -347,6 +367,7 @@ try BeforeEach { $testParameters += @{ IsEnabled = $false + ListenAll = $true TcpDynamicPort = $false TcpPort = '4509' RestartService = $true @@ -368,6 +389,7 @@ try BeforeEach { $testParameters += @{ IsEnabled = $true + ListenAll = $true TcpDynamicPort = $true } } @@ -384,6 +406,7 @@ try BeforeEach { $testParameters += @{ IsEnabled = $true + ListenAll = $true TcpDynamicPort = $false TcpPort = '4508' } @@ -403,6 +426,7 @@ try # This is the values the mock will return $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber $mockDynamicValue_TcpPort = '' @@ -419,6 +443,7 @@ try BeforeEach { $testParameters += @{ IsEnabled = $true + ListenAll = $true TcpDynamicPort = $false TcpPort = '4508' } @@ -439,6 +464,7 @@ try TcpDynamicPort = $true TcpPort = '1433' IsEnabled = $false + ListenAll = $true } } @@ -454,6 +480,7 @@ try # This is the values the mock will return $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = '' $mockDynamicValue_TcpPort = '4509' @@ -465,6 +492,7 @@ try $testParameters += @{ IsEnabled = $true + ListenAll = $true TcpDynamicPort = $false TcpPort = '4509' } From d94209c6706f4ae9784792aa8ba5811aa64fc0a3 Mon Sep 17 00:00:00 2001 From: Claudio Spizzi Date: Thu, 8 Feb 2018 01:41:53 +0100 Subject: [PATCH 2/3] Shorten lines to 80 chars --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e5c58d1a6..a2d61fc74 100644 --- a/README.md +++ b/README.md @@ -1243,11 +1243,11 @@ Read more about the network settings in the article Only tcp is currently supported. { tcp }. * **`[String]` ServerName** _(Write)_: The host name of the SQL Server to be configured. Default value is $env:COMPUTERNAME. -* **`[String]` IPAddress** _(Key)_: Specify the IP address to configure. Use IPAll for - all ip adresses (listen on all). +* **`[String]` IPAddress** _(Key)_: Specify the IP address to configure. Use + IPAll for all ip adresses (listen on all). * **`[Boolean]` IsEnabled** _(Write)_: Enables or disables the network protocol. -* **`[Boolean]` ListenAll** _(Write)_: Enables or disables to listen on all IP adresses. - Will be ignored if IPAddress is not set to 'IPAll'. +* **`[Boolean]` ListenAll** _(Write)_: Enables or disables to listen on all + IP adresses. Will be ignored if IPAddress is not set to 'IPAll'. * **`[Boolean]` TcpDynamicPort** _(Write)_: Specifies whether the SQL Server instance should use a dynamic port. Value cannot be set to $true if TcpPort is set to a non-empty string. From a49b92883e339f4ef24cc4b05c455fd7df9eb70c Mon Sep 17 00:00:00 2001 From: Claudio Spizzi Date: Fri, 9 Feb 2018 11:19:11 +0100 Subject: [PATCH 3/3] Add tests for the SqlServerNetwork custom IPAdress --- .../MSFT_SqlServerNetwork.psm1 | 2 +- Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 | 858 +++++++++++++----- 2 files changed, 654 insertions(+), 206 deletions(-) diff --git a/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 b/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 index 284fd012a..d7016e587 100644 --- a/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 +++ b/DSCResources/MSFT_SqlServerNetwork/MSFT_SqlServerNetwork.psm1 @@ -488,7 +488,7 @@ function Resolve-SqlProtocolIPAddress } else { - $ipAddressObject = $Protocol.IPAddresses.Where({$_.IPAddress.IPAddressToString -eq $IPAddress}) + $ipAddressObject = $Protocol.IPAddresses.Where({$_.IPAddress.IPAddressToString -eq $IPAddress})[0] if ($null -eq $ipAddressObject) { diff --git a/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 b/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 index fecf50207..40740c149 100644 --- a/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 +++ b/Tests/Unit/MSFT_SqlServerNetwork.Tests.ps1 @@ -35,7 +35,8 @@ try InModuleScope $script:DSCResourceName { $mockInstanceName = 'TEST' $mockTcpProtocolName = 'Tcp' - $mockIPAddress = 'IPAll' + $mockIPAddressIPAll = 'IPAll' + $mockIPAddressCustom = '10.0.1.11' $mockNamedPipesProtocolName = 'NP' $mockTcpDynamicPortNumber = '24680' @@ -67,6 +68,17 @@ try Add-Member -MemberType NoteProperty -Name 'Value' -Value $mockDynamicValue_TcpPort -PassThru -Force } } -PassThru -Force + 'IP1' = New-Object -TypeName Object | + Add-Member -MemberType ScriptProperty -Name 'IPAddressProperties' -Value { + return @{ + 'Enabled' = New-Object -TypeName Object | + Add-Member -MemberType NoteProperty -Name 'Value' -Value $mockDynamicValue_IsEnabled -PassThru -Force + 'TcpDynamicPorts' = New-Object -TypeName Object | + Add-Member -MemberType NoteProperty -Name 'Value' -Value $mockDynamicValue_TcpDynamicPort -PassThru -Force + 'TcpPort' = New-Object -TypeName Object | + Add-Member -MemberType NoteProperty -Name 'Value' -Value $mockDynamicValue_TcpPort -PassThru -Force + } + } -PassThru -Force } } -PassThru | Add-Member -MemberType ScriptMethod -Name 'Alter' -Value { @@ -79,9 +91,22 @@ try To be able to do this check for TcpDynamicPorts and TcpPort, then the class must be mocked in SMO.cs. #> - if ($this.IsEnabled -ne $mockExpectedValue_IsEnabled) + switch ($mockExpectedValue_IPAddressKey) { - throw ('Mock method Alter() was called with an unexpected value for IsEnabled. Expected ''{0}'', but was ''{1}''' -f $mockExpectedValue_IsEnabled, $this.IsEnabled) + 'IPAll' + { + if ($this.IsEnabled -ne $mockExpectedValue_IsEnabled) + { + throw ('Mock method Alter() was called with an unexpected value for IsEnabled. Expected ''{0}'', but was ''{1}''' -f $mockExpectedValue_IsEnabled, $this.IsEnabled) + } + } + default + { + <# + It is not possible to verify that the correct value was set here for TcpDynamicPorts and + TcpPort with the current implementation. See comment above. + #> + } } # This can be used to verify so that alter method was actually called. @@ -101,16 +126,21 @@ try return [System.AppDomain]::CreateDomain('DummyTestApplicationDomain') } - $mockDefaultParameters = @{ + $mockIPAllParameters = @{ InstanceName = $mockInstanceName ProtocolName = $mockTcpProtocolName - IPAddress = $mockIPAddress + IPAddress = $mockIPAddressIPAll } - Describe "MSFT_SqlServerNetwork\Get-TargetResource" -Tag 'Get'{ - BeforeEach { - $testParameters = $mockDefaultParameters.Clone() + $mockCustomParameters = @{ + InstanceName = $mockInstanceName + ProtocolName = $mockTcpProtocolName + IPAddress = $mockIPAddressCustom + } + Describe "MSFT_SqlServerNetwork\Get-TargetResource" -Tag 'Get' { + + BeforeEach { Mock -CommandName Register-SqlWmiManagement ` -MockWith $mockFunction_RegisterSqlWmiManagement ` -Verifiable @@ -121,39 +151,96 @@ try } Context 'When Get-TargetResource is called' { - BeforeEach { - $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName - $mockDynamicValue_IsEnabled = $true - $mockDynamicValue_ListenAll = $true - $mockDynamicValue_TcpDynamicPort = '' - $mockDynamicValue_TcpPort = '4509' - } - It 'Should return the correct values' { - $result = Get-TargetResource @testParameters - $result.IsEnabled | Should -Be $mockDynamicValue_IsEnabled - $result.TcpDynamicPort | Should -Be $false - $result.TcpPort | Should -Be $mockDynamicValue_TcpPort + Context "IPAddress: $mockIPAddressIPAll" { + + BeforeEach { + $testIPAllParameters = $mockIPAllParameters.Clone() + + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' + } + + It 'Should return the correct values' { + + # Act + $result = Get-TargetResource @testIPAllParameters - Assert-MockCalled -CommandName Register-SqlWmiManagement -Exactly -Times 1 -Scope It - Assert-MockCalled -CommandName New-Object -Exactly -Times 1 -Scope It ` - -ParameterFilter $mockFunction_NewObject_ManagedComputer_ParameterFilter + # Assert + $result.IsEnabled | Should -Be $mockDynamicValue_IsEnabled + $result.ListenAll | Should -Be $mockDynamicValue_ListenAll + $result.TcpDynamicPort | Should -Be $false + $result.TcpPort | Should -Be $mockDynamicValue_TcpPort + + Assert-MockCalled -CommandName Register-SqlWmiManagement -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName New-Object -Exactly -Times 1 -Scope It ` + -ParameterFilter $mockFunction_NewObject_ManagedComputer_ParameterFilter + } + + It 'Should return the same values as passed as parameters' { + + # Act + $result = Get-TargetResource @testIPAllParameters + + # Assert + $result.InstanceName | Should -Be $testIPAllParameters.InstanceName + $result.ProtocolName | Should -Be $testIPAllParameters.ProtocolName + $result.IPAddress | Should -Be $testIPAllParameters.IPAddress + } } - It 'Should return the same values as passed as parameters' { - $result = Get-TargetResource @testParameters - $result.InstanceName | Should -Be $testParameters.InstanceName - $result.ProtocolName | Should -Be $testParameters.ProtocolName + Context "IPAddress: $mockIPAddressCustom" { + + BeforeEach { + $testCustomParameters = $mockCustomParameters.Clone() + + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $null + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' + } + + Mock -CommandName 'Resolve-SqlProtocolIPAddress' -MockWith { 'IP1' } + + It 'Should return the correct values' { + + # Act + $result = Get-TargetResource @testCustomParameters + + # Assert + $result.IsEnabled | Should -Be $mockDynamicValue_IsEnabled + $result.ListenAll | Should -Be $mockDynamicValue_ListenAll + $result.TcpDynamicPort | Should -Be $false + $result.TcpPort | Should -Be $mockDynamicValue_TcpPort + + Assert-MockCalled -CommandName Register-SqlWmiManagement -Exactly -Times 1 -Scope It + Assert-MockCalled -CommandName New-Object -Exactly -Times 1 -Scope It ` + -ParameterFilter $mockFunction_NewObject_ManagedComputer_ParameterFilter + } + + It 'Should return the same values as passed as parameters' { + + # Act + $result = Get-TargetResource @testCustomParameters + + # Assert + $result.InstanceName | Should -Be $testCustomParameters.InstanceName + $result.ProtocolName | Should -Be $testCustomParameters.ProtocolName + $result.IPAddress | Should -Be $testCustomParameters.IPAddress + } } } Assert-VerifiableMock } - Describe "MSFT_SqlServerNetwork\Test-TargetResource" -Tag 'Test'{ - BeforeEach { - $testParameters = $mockDefaultParameters.Clone() + Describe "MSFT_SqlServerNetwork\Test-TargetResource" -Tag 'Test' { + BeforeEach { Mock -CommandName Register-SqlWmiManagement ` -MockWith $mockFunction_RegisterSqlWmiManagement ` -Verifiable @@ -163,61 +250,51 @@ try -ParameterFilter $mockFunction_NewObject_ManagedComputer_ParameterFilter -Verifiable } - Context 'When the system is not in the desired state' { + Context "IPAddress: $mockIPAddressIPAll" { + BeforeEach { - $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName - $mockDynamicValue_IsEnabled = $true - $mockDynamicValue_ListenAll = $true - $mockDynamicValue_TcpDynamicPort = '' - $mockDynamicValue_TcpPort = '4509' + $testParameters = $mockIPAllParameters.Clone() } - <# - This test does not work until support for more than one protocol - is added. See issue #14. - #> - <# - Context 'When Protocol is not in desired state' { + Context 'When the system is not in the desired state' { BeforeEach { - $testParameters += @{ - IsEnabled = $true - TcpDynamicPort = $false - TcpPort = '4509' - } - - $testParameters.ProtocolName = $mockNamedPipesProtocolName + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' } - It 'Should return $false' { - $result = Test-TargetResource @testParameters - $result | Should Be $false - } - } - #> + <# + This test does not work until support for more than one protocol + is added. See issue #14. + #> + <# + Context 'When Protocol is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + TcpDynamicPort = $false + TcpPort = '4509' + } - Context 'When IsEnabled is not in desired state' { - BeforeEach { - $testParameters += @{ - IsEnabled = $false - ListenAll = $true - TcpDynamicPort = $false - TcpPort = '4509' + $testParameters.ProtocolName = $mockNamedPipesProtocolName } - } - It 'Should return $false' { - $result = Test-TargetResource @testParameters - $result | Should -Be $false + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should Be $false + } } - } + #> - Context 'When current state is using static tcp port' { - Context 'When TcpDynamicPort is not in desired state' { + Context 'When IsEnabled is not in desired state' { BeforeEach { $testParameters += @{ - TcpDynamicPort = $true IsEnabled = $false ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4509' } } @@ -227,32 +304,90 @@ try } } - Context 'When TcpPort is not in desired state' { + Context 'When current state is using static tcp port' { + Context 'When TcpDynamicPort is not in desired state' { + BeforeEach { + $testParameters += @{ + TcpDynamicPort = $true + IsEnabled = $false + ListenAll = $true + } + } + + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should -Be $false + } + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + TcpPort = '1433' + IsEnabled = $true + ListenAll = $true + } + } + + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should -Be $false + } + } + } + + Context 'When current state is using dynamic tcp port' { + BeforeEach { + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber + $mockDynamicValue_TcpPort = '' + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + TcpPort = '1433' + IsEnabled = $true + ListenAll = $true + } + } + + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should -Be $false + } + } + } + + Context 'When both TcpDynamicPort and TcpPort are being set' { BeforeEach { $testParameters += @{ + TcpDynamicPort = $true TcpPort = '1433' - IsEnabled = $true + IsEnabled = $false ListenAll = $true } } - It 'Should return $false' { - $result = Test-TargetResource @testParameters - $result | Should -Be $false + It 'Should throw the correct error message' { + $testErrorMessage = $script:localizedData.ErrorDynamicAndStaticPortSpecified + { Test-TargetResource @testParameters } | Should -Throw $testErrorMessage } } } - Context 'When current state is using dynamic tcp port' { + Context 'When the system is in the desired state' { BeforeEach { $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true $mockDynamicValue_ListenAll = $true $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber - $mockDynamicValue_TcpPort = '' + $mockDynamicValue_TcpPort = '1433' } - Context 'When TcpPort is not in desired state' { + Context 'When TcpPort is in desired state' { BeforeEach { $testParameters += @{ TcpPort = '1433' @@ -261,66 +396,196 @@ try } } - It 'Should return $false' { + It 'Should return $true' { $result = Test-TargetResource @testParameters - $result | Should -Be $false + $result | Should -Be $true } } - } - Context 'When both TcpDynamicPort and TcpPort are being set' { - BeforeEach { - $testParameters += @{ - TcpDynamicPort = $true - TcpPort = '1433' - IsEnabled = $false - ListenAll = $true + Context 'When TcpDynamicPort is in desired state' { + BeforeEach { + $testParameters += @{ + TcpDynamicPort = $true + IsEnabled = $true + ListenAll = $true + } } - } - It 'Should throw the correct error message' { - $testErrorMessage = $script:localizedData.ErrorDynamicAndStaticPortSpecified - { Test-TargetResource @testParameters } | Should -Throw $testErrorMessage + It 'Should return $true' { + $result = Test-TargetResource @testParameters + $result | Should -Be $true + } } } } - Context 'When the system is in the desired state' { + Context "IPAddress: $mockIPAddressCustom" { + BeforeEach { - $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName - $mockDynamicValue_IsEnabled = $true - $mockDynamicValue_ListenAll = $true - $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber - $mockDynamicValue_TcpPort = '1433' + $testParameters = $mockCustomParameters.Clone() } - Context 'When TcpPort is in desired state' { + Mock -CommandName 'Resolve-SqlProtocolIPAddress' -MockWith { 'IP1' } + + Context 'When the system is not in the desired state' { BeforeEach { - $testParameters += @{ - TcpPort = '1433' - IsEnabled = $true - ListenAll = $true + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $null + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' + } + + <# + This test does not work until support for more than one protocol + is added. See issue #14. + #> + <# + Context 'When Protocol is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + TcpDynamicPort = $false + TcpPort = '4509' + } + + $testParameters.ProtocolName = $mockNamedPipesProtocolName + } + + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should Be $false } } + #> + + Context 'When IsEnabled is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $false + ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4509' + } + } - It 'Should return $true' { - $result = Test-TargetResource @testParameters - $result | Should -Be $true + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should -Be $false + } + } + + Context 'When current state is using static tcp port' { + Context 'When TcpDynamicPort is not in desired state' { + BeforeEach { + $testParameters += @{ + TcpDynamicPort = $true + IsEnabled = $false + ListenAll = $true + } + } + + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should -Be $false + } + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + TcpPort = '1433' + IsEnabled = $true + ListenAll = $true + } + } + + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should -Be $false + } + } + } + + Context 'When current state is using dynamic tcp port' { + BeforeEach { + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber + $mockDynamicValue_TcpPort = '' + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + TcpPort = '1433' + IsEnabled = $true + ListenAll = $true + } + } + + It 'Should return $false' { + $result = Test-TargetResource @testParameters + $result | Should -Be $false + } + } + } + + Context 'When both TcpDynamicPort and TcpPort are being set' { + BeforeEach { + $testParameters += @{ + TcpDynamicPort = $true + TcpPort = '1433' + IsEnabled = $false + ListenAll = $true + } + } + + It 'Should throw the correct error message' { + $testErrorMessage = $script:localizedData.ErrorDynamicAndStaticPortSpecified + { Test-TargetResource @testParameters } | Should -Throw $testErrorMessage + } } } - Context 'When TcpDynamicPort is in desired state' { + Context 'When the system is in the desired state' { BeforeEach { - $testParameters += @{ - TcpDynamicPort = $true - IsEnabled = $true - ListenAll = $true + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber + $mockDynamicValue_TcpPort = '1433' + } + + Context 'When TcpPort is in desired state' { + BeforeEach { + $testParameters += @{ + TcpPort = '1433' + IsEnabled = $true + ListenAll = $true + } + } + + It 'Should return $true' { + $result = Test-TargetResource @testParameters + $result | Should -Be $true } } - It 'Should return $true' { - $result = Test-TargetResource @testParameters - $result | Should -Be $true + Context 'When TcpDynamicPort is in desired state' { + BeforeEach { + $testParameters += @{ + TcpDynamicPort = $true + IsEnabled = $true + ListenAll = $true + } + } + + It 'Should return $true' { + $result = Test-TargetResource @testParameters + $result | Should -Be $true + } } } } @@ -328,10 +593,9 @@ try Assert-VerifiableMock } - Describe "MSFT_SqlServerNetwork\Set-TargetResource" -Tag 'Set'{ - BeforeEach { - $testParameters = $mockDefaultParameters.Clone() + Describe "MSFT_SqlServerNetwork\Set-TargetResource" -Tag 'Set' { + BeforeEach { Mock -CommandName Restart-SqlService -Verifiable Mock -CommandName Register-SqlWmiManagement ` -MockWith $mockFunction_RegisterSqlWmiManagement ` @@ -345,90 +609,194 @@ try $script:WasMethodAlterCalled = $false } - Context 'When the system is not in the desired state' { - BeforeEach { - # This is the values the mock will return - $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName - $mockDynamicValue_IsEnabled = $true - $mockDynamicValue_ListenAll = $true - $mockDynamicValue_TcpDynamicPort = '' - $mockDynamicValue_TcpPort = '4509' + Context "IPAddress: $mockIPAddressIPAll" { - <# - This is the values we expect to be set when Alter() method is called. - These values will set here to same as the values the mock will return, - but before each test the these will be set to the correct value that is - expected to be returned for that particular test. - #> - $mockExpectedValue_IsEnabled = $mockDynamicValue_IsEnabled + BeforeEach { + $testParameters = $mockIPAllParameters.Clone() } - Context 'When IsEnabled is not in desired state' { + Context 'When the system is not in the desired state' { BeforeEach { - $testParameters += @{ - IsEnabled = $false - ListenAll = $true - TcpDynamicPort = $false - TcpPort = '4509' - RestartService = $true - } - - $mockExpectedValue_IsEnabled = $false - } - - It 'Should call Set-TargetResource without throwing and should call Alter()' { - { Set-TargetResource @testParameters } | Should -Not -Throw - $script:WasMethodAlterCalled | Should -Be $true + # This is the values the mock will return + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' - Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 1 -Scope It + <# + This is the values we expect to be set when Alter() method is called. + These values will set here to same as the values the mock will return, + but before each test the these will be set to the correct value that is + expected to be returned for that particular test. + #> + $mockExpectedValue_IPAddressKey = 'IPAll' + $mockExpectedValue_IsEnabled = $mockDynamicValue_IsEnabled } - } - Context 'When current state is using static tcp port' { - Context 'When TcpDynamicPort is not in desired state' { + Context 'When IsEnabled is not in desired state' { BeforeEach { $testParameters += @{ - IsEnabled = $true + IsEnabled = $false ListenAll = $true - TcpDynamicPort = $true + TcpDynamicPort = $false + TcpPort = '4509' + RestartService = $true } + + $mockExpectedValue_IPAddressKey = 'IPAll' + $mockExpectedValue_IsEnabled = $false } It 'Should call Set-TargetResource without throwing and should call Alter()' { { Set-TargetResource @testParameters } | Should -Not -Throw $script:WasMethodAlterCalled | Should -Be $true - Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 1 -Scope It } } - Context 'When TcpPort is not in desired state' { + Context 'When current state is using static tcp port' { + Context 'When TcpDynamicPort is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $true + } + } + + It 'Should call Set-TargetResource without throwing and should call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $true + + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4508' + } + } + + It 'Should call Set-TargetResource without throwing and should call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $true + + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } + } + } + + Context 'When current state is using dynamic tcp port ' { + BeforeEach { + # This is the values the mock will return + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber + $mockDynamicValue_TcpPort = '' + + <# + This is the values we expect to be set when Alter() method is called. + These values will set here to same as the values the mock will return, + but before each test the these will be set to the correct value that is + expected to be returned for that particular test. + #> + $mockExpectedValue_IPAddressKey = 'IPAll' + $mockExpectedValue_IsEnabled = $mockDynamicValue_IsEnabled + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4508' + } + } + + It 'Should call Set-TargetResource without throwing and should call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $true + + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } + } + } + + Context 'When both TcpDynamicPort and TcpPort are being set' { BeforeEach { $testParameters += @{ - IsEnabled = $true + TcpDynamicPort = $true + TcpPort = '1433' + IsEnabled = $false ListenAll = $true - TcpDynamicPort = $false - TcpPort = '4508' } } - It 'Should call Set-TargetResource without throwing and should call Alter()' { - { Set-TargetResource @testParameters } | Should -Not -Throw - $script:WasMethodAlterCalled | Should -Be $true + It 'Should throw the correct error message' { + $testErrorMessage = ($script:localizedData.ErrorDynamicAndStaticPortSpecified) + { Set-TargetResource @testParameters } | Should -Throw $testErrorMessage + } + } + } - Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + Context 'When the system is in the desired state' { + BeforeEach { + # This is the values the mock will return + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' + + <# + We do not expect Alter() method to be called. So we set this to $null so + if it is, then it will throw an error. + #> + $mockExpectedValue_IPAddressKey = 'IPAll' + $mockExpectedValue_IsEnabled = $null + + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4509' } } + + It 'Should call Set-TargetResource without throwing and should not call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $false + + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } } + } - Context 'When current state is using dynamic tcp port ' { + Context "IPAddress: $mockIPAddressCustom" { + + BeforeEach { + $testParameters = $mockCustomParameters.Clone() + } + + Mock -CommandName 'Resolve-SqlProtocolIPAddress' -MockWith { 'IP1' } + + Context 'When the system is not in the desired state' { BeforeEach { # This is the values the mock will return $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName $mockDynamicValue_IsEnabled = $true $mockDynamicValue_ListenAll = $true - $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber - $mockDynamicValue_TcpPort = '' + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' <# This is the values we expect to be set when Alter() method is called. @@ -436,73 +804,154 @@ try but before each test the these will be set to the correct value that is expected to be returned for that particular test. #> + $mockExpectedValue_IPAddressKey = 'IP1' $mockExpectedValue_IsEnabled = $mockDynamicValue_IsEnabled } - Context 'When TcpPort is not in desired state' { + Context 'When IsEnabled is not in desired state' { BeforeEach { $testParameters += @{ - IsEnabled = $true + IsEnabled = $false ListenAll = $true TcpDynamicPort = $false - TcpPort = '4508' + TcpPort = '4509' + RestartService = $true } + + $mockExpectedValue_IPAddressKey = 'IP1' + $mockExpectedValue_IsEnabled = $false } It 'Should call Set-TargetResource without throwing and should call Alter()' { { Set-TargetResource @testParameters } | Should -Not -Throw $script:WasMethodAlterCalled | Should -Be $true - Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 1 -Scope It } } - } - Context 'When both TcpDynamicPort and TcpPort are being set' { - BeforeEach { - $testParameters += @{ - TcpDynamicPort = $true - TcpPort = '1433' - IsEnabled = $false - ListenAll = $true + Context 'When current state is using static tcp port' { + Context 'When TcpDynamicPort is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $true + } + } + + It 'Should call Set-TargetResource without throwing and should call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $true + + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4508' + } + } + + It 'Should call Set-TargetResource without throwing and should call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $true + + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } } } - It 'Should throw the correct error message' { - $testErrorMessage = ($script:localizedData.ErrorDynamicAndStaticPortSpecified) - { Set-TargetResource @testParameters } | Should -Throw $testErrorMessage + Context 'When current state is using dynamic tcp port ' { + BeforeEach { + # This is the values the mock will return + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = $mockTcpDynamicPortNumber + $mockDynamicValue_TcpPort = '' + + <# + This is the values we expect to be set when Alter() method is called. + These values will set here to same as the values the mock will return, + but before each test the these will be set to the correct value that is + expected to be returned for that particular test. + #> + $mockExpectedValue_IPAddressKey = 'IP1' + $mockExpectedValue_IsEnabled = $mockDynamicValue_IsEnabled + } + + Context 'When TcpPort is not in desired state' { + BeforeEach { + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4508' + } + } + + It 'Should call Set-TargetResource without throwing and should call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $true + + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } + } + } + + Context 'When both TcpDynamicPort and TcpPort are being set' { + BeforeEach { + $testParameters += @{ + TcpDynamicPort = $true + TcpPort = '1433' + IsEnabled = $false + ListenAll = $true + } + } + + It 'Should throw the correct error message' { + $testErrorMessage = ($script:localizedData.ErrorDynamicAndStaticPortSpecified) + { Set-TargetResource @testParameters } | Should -Throw $testErrorMessage + } } } - } - Context 'When the system is in the desired state' { - BeforeEach { - # This is the values the mock will return - $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName - $mockDynamicValue_IsEnabled = $true - $mockDynamicValue_ListenAll = $true - $mockDynamicValue_TcpDynamicPort = '' - $mockDynamicValue_TcpPort = '4509' + Context 'When the system is in the desired state' { + BeforeEach { + # This is the values the mock will return + $mockDynamicValue_TcpProtocolName = $mockTcpProtocolName + $mockDynamicValue_IsEnabled = $true + $mockDynamicValue_ListenAll = $true + $mockDynamicValue_TcpDynamicPort = '' + $mockDynamicValue_TcpPort = '4509' - <# - We do not expect Alter() method to be called. So we set this to $null so - if it is, then it will throw an error. - #> - $mockExpectedValue_IsEnabled = $null + <# + We do not expect Alter() method to be called. So we set this to $null so + if it is, then it will throw an error. + #> + $mockExpectedValue_IPAddressKey = 'IP1' + $mockExpectedValue_IsEnabled = $null - $testParameters += @{ - IsEnabled = $true - ListenAll = $true - TcpDynamicPort = $false - TcpPort = '4509' + $testParameters += @{ + IsEnabled = $true + ListenAll = $true + TcpDynamicPort = $false + TcpPort = '4509' + } } - } - It 'Should call Set-TargetResource without throwing and should not call Alter()' { - { Set-TargetResource @testParameters } | Should -Not -Throw - $script:WasMethodAlterCalled | Should -Be $false + It 'Should call Set-TargetResource without throwing and should not call Alter()' { + { Set-TargetResource @testParameters } | Should -Not -Throw + $script:WasMethodAlterCalled | Should -Be $false - Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + Assert-MockCalled -CommandName Restart-SqlService -Exactly -Times 0 -Scope It + } } } @@ -514,4 +963,3 @@ finally { Invoke-TestCleanup } -