Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SqlServerEndpoint : Add parameter "Owner" #1271

Merged
merged 4 commits into from
Jan 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
- Updated the integration test to stop the named instance while installing
the other instances to mitigate
[issue #1260](https://github.com/PowerShell/SqlServerDsc/issues/1260).
- Changes to SqlServerEndpoint
- Add the optional parameter Owner. The default owner remains the login used
for the creation of the endpoint
([issue #1251](https://github.com/PowerShell/SqlServerDsc/issues/1251).
[Maxime Daniou (@mdaniou)](https://github.com/mdaniou)

## 12.2.0.0

Expand Down
44 changes: 40 additions & 4 deletions DSCResources/MSFT_SqlServerEndpoint/MSFT_SqlServerEndpoint.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function Get-TargetResource
EndpointName = ''
Port = ''
IpAddress = ''
Owner = ''
}

$sqlServerObject = Connect-SQL -ServerName $ServerName -InstanceName $InstanceName
Expand All @@ -61,13 +62,15 @@ function Get-TargetResource
$getTargetResourceReturnValues.EndpointName = $endpointObject.Name
$getTargetResourceReturnValues.Port = $endpointObject.Protocol.Tcp.ListenerPort
$getTargetResourceReturnValues.IpAddress = $endpointObject.Protocol.Tcp.ListenerIPAddress
$getTargetResourceReturnValues.Owner = $endpointObject.Owner
}
else
{
$getTargetResourceReturnValues.Ensure = 'Absent'
$getTargetResourceReturnValues.EndpointName = ''
$getTargetResourceReturnValues.Port = ''
$getTargetResourceReturnValues.IpAddress = ''
$getTargetResourceReturnValues.Owner = ''
}
}
else
Expand Down Expand Up @@ -101,6 +104,9 @@ function Get-TargetResource

.PARAMETER IpAddress
The network IP address the endpoint is listening on. Defaults to '0.0.0.0' which means listen on any valid IP address.

.PARAMETER Owner
The owner of the endpoint. Default is the login used for the creation.
#>
function Set-TargetResource
{
Expand Down Expand Up @@ -130,7 +136,11 @@ function Set-TargetResource

[Parameter()]
[System.String]
$IpAddress = '0.0.0.0'
$IpAddress = '0.0.0.0',

[Parameter()]
[System.String]
$Owner
)

$getTargetResourceResult = Get-TargetResource -EndpointName $EndpointName -ServerName $ServerName -InstanceName $InstanceName
Expand All @@ -147,6 +157,12 @@ function Set-TargetResource
$endpointObject.ProtocolType = [Microsoft.SqlServer.Management.Smo.ProtocolType]::Tcp
$endpointObject.Protocol.Tcp.ListenerPort = $Port
$endpointObject.Protocol.Tcp.ListenerIPAddress = $IpAddress

if ($PSBoundParameters.ContainsKey('Owner'))
{
$endpointObject.Owner = $Owner
}

$endpointObject.Payload.DatabaseMirroring.ServerMirroringRole = [Microsoft.SqlServer.Management.Smo.ServerMirroringRole]::All
$endpointObject.Payload.DatabaseMirroring.EndpointEncryption = [Microsoft.SqlServer.Management.Smo.EndpointEncryption]::Required
$endpointObject.Payload.DatabaseMirroring.EndpointEncryptionAlgorithm = [Microsoft.SqlServer.Management.Smo.EndpointEncryptionAlgorithm]::Aes
Expand All @@ -172,6 +188,13 @@ function Set-TargetResource
$endpointObject.Protocol.Tcp.ListenerPort = $Port
$endpointObject.Alter()
}

if ($endpointObject.Owner -ne $Owner)
{
Write-Verbose -Message ('Updating endpoint {0} Owner to {1}.' -f $EndpointName, $Owner)
$endpointObject.Owner = $Owner
$endpointObject.Alter()
}
}
else
{
Expand Down Expand Up @@ -222,6 +245,9 @@ function Set-TargetResource

.PARAMETER IpAddress
The network IP address the endpoint is listening on. Defaults to '0.0.0.0' which means listen on any valid IP address.

.PARAMETER Owner
The owner of the endpoint. Default is the login used for the creation.
#>
function Test-TargetResource
{
Expand Down Expand Up @@ -252,7 +278,11 @@ function Test-TargetResource

[Parameter()]
[System.String]
$IpAddress = '0.0.0.0'
$IpAddress = '0.0.0.0',

[Parameter()]
[System.String]
$Owner
)

$getTargetResourceResult = Get-TargetResource -EndpointName $EndpointName -ServerName $ServerName -InstanceName $InstanceName
Expand All @@ -262,9 +292,15 @@ function Test-TargetResource

if ($getTargetResourceResult.Ensure -eq 'Present' `
-and (
$getTargetResourceResult.Port -ne $Port `
$getTargetResourceResult.Port -ne $Port `
-or $getTargetResourceResult.IpAddress -ne $IpAddress
)
)
)
{
$result = $false
}
elseif ($getTargetResourceResult.Ensure -eq 'Present' -and $Owner `
-and $getTargetResourceResult.Owner -ne $Owner
)
{
$result = $false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ class MSFT_SqlServerEndpoint : OMI_BaseResource
[Write, Description("The host name of the SQL Server to be configured. Default value is $env:COMPUTERNAME.")] String ServerName;
[Key, Description("The name of the SQL instance to be configured.")] String InstanceName;
[Write, Description("The network IP address the endpoint is listening on. Default the endpoint will listen on any valid IP address.")] String IpAddress;
[Write, Description("The owner of the endpoint. Default is the login used for the creation.")] String Owner;
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<#
.EXAMPLE
This example will add a Database Mirror endpoint with a specific listener port and a specific listener IP address.
This example will add a Database Mirror endpoint with specific listener port, listener IP address and owner.
#>
Configuration Example
{
Expand All @@ -22,6 +22,7 @@ Configuration Example
EndpointName = 'HADR'
Port = 9001
IpAddress = '192.168.0.20'
Owner = 'sa'

ServerName = 'server1.company.local'
InstanceName = 'INST1'
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1041,11 +1041,13 @@ the resource [**SqlServerEndpointPermission**](#sqlserverendpointpermission).
* **`[String]` InstanceName** _(Key)_: The name of the SQL instance to be configured.
* **`[String]` IpAddress** _(Write)_: The network IP address the endpoint is listening
on. Defaults to '0.0.0.0' which means listen on any valid IP address.
* **`[String]` Owner** _(Write)_: The owner of the endpoint. Default is the
login used for the creation.

#### Examples

* [Create an endpoint with default values](/Examples/Resources/SqlServerEndpoint/1-CreateEndpointWithDefaultValues.ps1)
* [Create an endpoint with specific port and IP address](/Examples/Resources/SqlServerEndpoint/2-CreateEndpointWithSpecificPortAndIPAddress.ps1)
* [Create an endpoint with specific port and IP address](/Examples/Resources/SqlServerEndpoint/2-CreateEndpointWithSpecificPortIPAddressOwner.ps1)
* [Remove an endpoint](/Examples/Resources/SqlServerEndpoint/3-RemoveEndpoint.ps1)

#### Known issues
Expand Down
80 changes: 74 additions & 6 deletions Tests/Unit/MSFT_SqlServerEndpoint.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@ try
$mockEndpointType = 'DatabaseMirroring'
$mockEndpointListenerPort = 5022
$mockEndpointListenerIpAddress = '0.0.0.0' # 0.0.0.0 means listen on all IP addresses.
$mockEndpointOwner = 'sa'

$mockOtherEndpointName = 'UnknownEndpoint'
$mockOtherEndpointType = 'UnknownType'
$mockOtherEndpointListenerPort = 9001
$mockOtherEndpointListenerIpAddress = '192.168.0.20'
$mockOtherEndpointOwner = 'COMPANY\OtherAcct'

$script:mockMethodAlterRan = $false
$script:mockMethodCreateRan = $false
Expand All @@ -74,13 +76,15 @@ try
$mockDynamicEndpointType = $mockEndpointType
$mockDynamicEndpointListenerPort = $mockEndpointListenerPort
$mockDynamicEndpointListenerIpAddress = $mockEndpointListenerIpAddress
$mockDynamicEndpointOwner = $mockEndpointOwner

$mockEndpointObject = {
# TypeName: Microsoft.SqlServer.Management.Smo.Endpoint
return New-Object -TypeName Object |
Add-Member -MemberType NoteProperty -Name 'Name' -Value $mockDynamicEndpointName -PassThru |
Add-Member -MemberType NoteProperty -Name 'EndpointType' -Value $mockDynamicEndpointType -PassThru |
Add-Member -MemberType NoteProperty -Name 'ProtocolType' -Value $null -PassThru |
Add-Member -MemberType NoteProperty -Name 'Owner' -Value $mockDynamicEndpointOwner -PassThru |
Add-Member -MemberType ScriptProperty -Name 'Protocol' -Value {
return New-Object -TypeName Object |
Add-Member -MemberType ScriptProperty -Name 'Tcp' -Value {
Expand Down Expand Up @@ -184,6 +188,7 @@ try
$result.EndpointName | Should -Be ''
$result.Port | Should -Be ''
$result.IpAddress | Should -Be ''
$result.Owner | Should -Be ''
}

It 'Should call the mock function Connect-SQL' {
Expand All @@ -208,6 +213,7 @@ try
$result.EndpointName | Should -Be $testParameters.EndpointName
$result.Port | Should -Be $mockEndpointListenerPort
$result.IpAddress | Should -Be $mockEndpointListenerIpAddress
$result.Owner | Should -Be $mockEndpointOwner
}

It 'Should call the mock function Connect-SQL' {
Expand Down Expand Up @@ -265,6 +271,7 @@ try
$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Port', $mockEndpointListenerPort)
$testParameters.Add('IpAddress', $mockEndpointListenerIpAddress)
$testParameters.Add('Owner', $mockEndpointOwner)

$result = Test-TargetResource @testParameters
$result | Should -Be $false
Expand Down Expand Up @@ -322,6 +329,26 @@ try

# Make sure the mock do return the correct endpoint listener IP address
$mockDynamicEndpointListenerIpAddress = $mockEndpointListenerIpAddress

# Make sure the mock do return the correct endpoint, but does not return the correct endpoint owner
$mockDynamicEndpointName = $mockEndpointName
$mockDynamicEndpointOwner = $mockOtherEndpointOwner

Context 'When listener Owner is not in desired state' {
It 'Should return that desired state is absent' {
$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Owner', $mockEndpointOwner)


$result = Test-TargetResource @testParameters
$result | Should -Be $false

Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope It
}
}

# Make sure the mock do return the correct endpoint owner
$mockDynamicEndpointOwner = $mockEndpointOwner
}

Context 'When the system is in the desired state' {
Expand Down Expand Up @@ -372,7 +399,7 @@ try
# Set what the expected endpoint name should be when Create() method is called.
$mockExpectedNameWhenCallingMethod = $mockEndpointName

It 'Should call the the method Create when desired state is to be Present (using default values)' {
It 'Should call the method Create when desired state is to be Present (using default values)' {
Mock -CommandName Get-TargetResource -MockWith {
return @{
Ensure = 'Absent'
Expand All @@ -397,7 +424,7 @@ try
# Set what the expected endpoint name should be when Create() method is called.
$mockExpectedNameWhenCallingMethod = $mockEndpointName

It 'Should call the the method Create when desired state is to be Present (setting all parameters)' {
It 'Should call the method Create when desired state is to be Present (setting all parameters)' {
Mock -CommandName Get-TargetResource -MockWith {
return @{
Ensure = 'Absent'
Expand All @@ -407,6 +434,7 @@ try
$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Port', $mockEndpointListenerPort)
$testParameters.Add('IpAddress', $mockEndpointListenerIpAddress)
$testParameters.Add('Owner', $mockEndpointOwner)

{ Set-TargetResource @testParameters } | Should -Not -Throw
$script:mockMethodCreateRan | Should -Be $true
Expand All @@ -426,7 +454,7 @@ try
# Set what the expected endpoint name should be when Drop() method is called.
$mockExpectedNameWhenCallingMethod = $mockEndpointName

It 'Should call the the method Drop when desired state is to be Absent' {
It 'Should call the method Drop when desired state is to be Absent' {
Mock -CommandName Get-TargetResource -MockWith {
return @{
Ensure = 'Present'
Expand All @@ -453,7 +481,7 @@ try
# Set what the expected endpoint name should be when Alter() method is called.
$mockExpectedNameWhenCallingMethod = $mockEndpointName

It 'Should not call Alter method when listener port is not in desired state' {
It 'Should call Alter method when listener port is not in desired state' {
Mock -CommandName Get-TargetResource -MockWith {
return @{
Ensure = 'Present'
Expand All @@ -465,6 +493,7 @@ try
$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Port', $mockOtherEndpointListenerPort)
$testParameters.Add('IpAddress', $mockEndpointListenerIpAddress)
$testParameters.Add('Owner', $mockEndpointOwner)

{ Set-TargetResource @testParameters } | Should -Not -Throw
$script:mockMethodCreateRan | Should -Be $false
Expand All @@ -484,7 +513,7 @@ try
# Set what the expected endpoint name should be when Alter() method is called.
$mockExpectedNameWhenCallingMethod = $mockEndpointName

It 'Should not call Alter method when listener IP address is not in desired state' {
It 'Should call Alter method when listener IP address is not in desired state' {
Mock -CommandName Get-TargetResource -MockWith {
return @{
Ensure = 'Present'
Expand All @@ -496,6 +525,39 @@ try
$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Port', $mockEndpointListenerPort)
$testParameters.Add('IpAddress', $mockOtherEndpointListenerIpAddress)
$testParameters.Add('Owner', $mockEndpointOwner)

{ Set-TargetResource @testParameters } | Should -Not -Throw
$script:mockMethodCreateRan | Should -Be $false
$script:mockMethodStartRan | Should -Be $false
$script:mockMethodAlterRan | Should -Be $true
$script:mockMethodDropRan | Should -Be $false

Assert-MockCalled Connect-SQL -Exactly -Times 1 -Scope It
}

# Set all method call tests variables to $false
$script:mockMethodCreateRan = $false
$script:mockMethodStartRan = $false
$script:mockMethodAlterRan = $false
$script:mockMethodDropRan = $false

# Set what the expected endpoint name should be when Alter() method is called.
$mockExpectedNameWhenCallingMethod = $mockEndpointName

It 'Should call Alter method when Owner is not in desired state' {
Mock -CommandName Get-TargetResource -MockWith {
return @{
Ensure = 'Present'
Port = $mockEndpointListenerPort
IpAddress = $mockEndpointListenerIpAddress
}
} -Verifiable

$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Port', $mockEndpointListenerPort)
$testParameters.Add('IpAddress', $mockEndpointListenerIpAddress)
$testParameters.Add('Owner', $mockOtherEndpointOwner)

{ Set-TargetResource @testParameters } | Should -Not -Throw
$script:mockMethodCreateRan | Should -Be $false
Expand All @@ -516,6 +578,7 @@ try
Ensure = 'Present'
Port = $mockEndpointListenerPort
IpAddress = $mockEndpointListenerIpAddress
Owner = $mockEndpointOwner
}
} -Verifiable

Expand All @@ -530,6 +593,7 @@ try
Ensure = 'Present'
Port = $mockEndpointListenerPort
IpAddress = $mockEndpointListenerIpAddress
Owner = $mockEndpointOwner
}
} -Verifiable

Expand All @@ -551,11 +615,12 @@ try
}
}

Context 'When the system is in the desired state' {
Context ' ' {
# Make sure the mock do return the correct endpoint
$mockDynamicEndpointName = $mockEndpointName
$mockDynamicEndpointListenerPort = $mockEndpointListenerPort
$mockDynamicEndpointListenerIpAddress = $mockEndpointListenerIpAddress
$mockDynamicEndpointOwner = $mockEndpointOwner

# Set all method call tests variables to $false
$script:mockMethodCreateRan = $false
Expand All @@ -569,12 +634,14 @@ try
Ensure = 'Present'
Port = $mockEndpointListenerPort
IpAddress = $mockEndpointListenerIpAddress
Owner = $mockEndpointOwner
}
} -Verifiable

$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Port', $mockEndpointListenerPort)
$testParameters.Add('IpAddress', $mockEndpointListenerIpAddress)
$testParameters.Add('Owner', $mockEndpointOwner)

{ Set-TargetResource @testParameters } | Should -Not -Throw
$script:mockMethodCreateRan | Should -Be $false
Expand Down Expand Up @@ -657,6 +724,7 @@ try
$testParameters.Add('Ensure', 'Present')
$testParameters.Add('Port', $mockOtherEndpointListenerPort)
$testParameters.Add('IpAddress', $mockEndpointListenerIpAddress)
$testParameters.Add('Owner', $mockEndpointOwner)

{ Set-TargetResource @testParameters } | Should -Throw 'Exception calling "Alter" with "0" argument(s): "Called mocked Alter() method on and endpoint with wrong name. Expected ''UnknownEndpoint''. But was ''DefaultEndpointMirror''."'
}
Expand Down