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

SqlAGReplica: Run Update-AvailabilityGroupReplica Once for All AvailabilityReplica Changes #1840

Merged
merged 14 commits into from
Jan 24, 2023
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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- No longer throws an exception when parameter `AgtSvcAccount` is not specified.
- SqlAgReplica
- Converted unit test to Pester 5.
- `Update-AvailabilityGroupReplica` to trigger once within `Set-TargetResource`
for all AvailabilityReplica changes.
- Private function `Invoke-SetupAction` ([issue #1798](https://github.com/dsccommunity/SqlServerDsc/issues/1798)).
- Was changed to support the SQL Server 2022 GA feature `AzureExtension`
(that replaced the feature name `ARC`).
Expand Down Expand Up @@ -2409,7 +2411,7 @@ in a future release.
MSFT\_xSQLServerEndpointPermission.psm1, MSFT\_xSQLServerEndpointState.psm1,
MSFT\_xSQLServerNetwork.psm1, MSFT\_xSQLServerPermission.psm1,
MSFT\_xSQLServerReplication.psm1, MSFT\_xSQLServerScript.psm1,
SQLPSStub.psm1, SQLServerStub.psm1.
SQLPSStub.psm1, SqlServerStub.psm1.
- Opt-in for script files common tests ([issue #707](https://github.com/dsccommunity/SqlServerDsc/issues/707)).
- Removed Byte Order Mark (BOM) from the files; DSCClusterSqlBuild.ps1,
DSCFCISqlBuild.ps1, DSCSqlBuild.ps1, DSCSQLBuildEncrypted.ps1,
Expand Down
35 changes: 21 additions & 14 deletions source/DSCResources/DSC_SqlAGReplica/DSC_SqlAGReplica.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -319,33 +319,41 @@ function Set-TargetResource
$availabilityGroupReplica = $availabilityGroup.AvailabilityReplicas[$Name]
if ( $availabilityGroupReplica )
{
$availabilityGroupReplicaUpdatesRequired = $false

# Get the parameters that were submitted to the function
[System.Array] $submittedParameters = $PSBoundParameters.Keys

if ( ( $submittedParameters -contains 'FailoverMode' ) -and ( $FailoverMode -ne $availabilityGroupReplica.FailoverMode ) )
{
$availabilityGroupReplica.FailoverMode = $FailoverMode
$availabilityGroupReplicaUpdatesRequired = $true
}

if ( ( $submittedParameters -contains 'AvailabilityMode' ) -and ( $AvailabilityMode -ne $availabilityGroupReplica.AvailabilityMode ) )
{
$availabilityGroupReplica.AvailabilityMode = $AvailabilityMode
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

if ( ( $submittedParameters -contains 'BackupPriority' ) -and ( $BackupPriority -ne $availabilityGroupReplica.BackupPriority ) )
{
$availabilityGroupReplica.BackupPriority = $BackupPriority
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

# Make sure ConnectionModeInPrimaryRole has a value in order to avoid false positive matches when the parameter is not defined
if ( ( -not [System.String]::IsNullOrEmpty($ConnectionModeInPrimaryRole) ) -and ( $ConnectionModeInPrimaryRole -ne $availabilityGroupReplica.ConnectionModeInPrimaryRole ) )
{
$availabilityGroupReplica.ConnectionModeInPrimaryRole = $ConnectionModeInPrimaryRole
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

# Make sure ConnectionModeInSecondaryRole has a value in order to avoid false positive matches when the parameter is not defined
if ( ( -not [System.String]::IsNullOrEmpty($ConnectionModeInSecondaryRole) ) -and ( $ConnectionModeInSecondaryRole -ne $availabilityGroupReplica.ConnectionModeInSecondaryRole ) )
{
$availabilityGroupReplica.ConnectionModeInSecondaryRole = $ConnectionModeInSecondaryRole
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

# Break out the EndpointUrl properties
Expand All @@ -355,33 +363,27 @@ function Set-TargetResource
{
$newEndpointUrl = $availabilityGroupReplica.EndpointUrl.Replace($currentEndpointPort, $endpoint.Protocol.Tcp.ListenerPort)
$availabilityGroupReplica.EndpointUrl = $newEndpointUrl
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

if ( ( $submittedParameters -contains 'EndpointHostName' ) -and ( $EndpointHostName -ne $currentEndpointHostName ) )
{
$newEndpointUrl = $availabilityGroupReplica.EndpointUrl.Replace($currentEndpointHostName, $EndpointHostName)
$availabilityGroupReplica.EndpointUrl = $newEndpointUrl
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

if ( $currentEndpointProtocol -ne 'TCP' )
{
$newEndpointUrl = $availabilityGroupReplica.EndpointUrl.Replace($currentEndpointProtocol, 'TCP')
$availabilityGroupReplica.EndpointUrl = $newEndpointUrl
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
}

if ( ( $submittedParameters -contains 'FailoverMode' ) -and ( $FailoverMode -ne $availabilityGroupReplica.FailoverMode ) )
{
$availabilityGroupReplica.FailoverMode = $FailoverMode
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

if ( ( $submittedParameters -contains 'ReadOnlyRoutingConnectionUrl' ) -and ( $ReadOnlyRoutingConnectionUrl -ne $availabilityGroupReplica.ReadOnlyRoutingConnectionUrl ) )
{
$availabilityGroupReplica.ReadOnlyRoutingConnectionUrl = $ReadOnlyRoutingConnectionUrl
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
$availabilityGroupReplicaUpdatesRequired = $true
}

if ( ( $submittedParameters -contains 'ReadOnlyRoutingList' ) -and ( ( $ReadOnlyRoutingList -join ',' ) -ne ( $availabilityGroupReplica.ReadOnlyRoutingList -join ',' ) ) )
Expand All @@ -391,6 +393,11 @@ function Set-TargetResource
{
$availabilityGroupReplica.ReadOnlyRoutingList.Add($readOnlyRoutingListEntry) | Out-Null
}
$availabilityGroupReplicaUpdatesRequired = $true
}

if ( $availabilityGroupReplicaUpdatesRequired )
{
Update-AvailabilityGroupReplica -AvailabilityGroupReplica $availabilityGroupReplica
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/TestHelpers/CommonTestHelper.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function Import-SqlModuleStub
#>
$modulesAndStubs = @{
SQLPS = 'SQLPSStub'
SqlServer = 'SQLServerStub'
SqlServer = 'SqlServerStub'
}

# Determine which module to ensure is loaded based on the parameters passed
Expand Down
64 changes: 64 additions & 0 deletions tests/Unit/DSC_SqlAGReplica.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,70 @@ Describe 'SqlAGReplica\Set-TargetResource' {
}
}

Context 'When multiple properties are not in desired state' {
BeforeAll {
Mock -CommandName Update-AvailabilityGroupReplica
}

It 'Should set all properties with one update' {
InModuleScope -Parameters $_ -ScriptBlock {
$setTargetResourceParameters = @{
Name = 'Server1'
AvailabilityGroupName = 'AG_AllServers'
ServerName = 'Server1'
InstanceName = 'MSSQLSERVER'
PrimaryReplicaServerName = 'Server2'
PrimaryReplicaInstanceName = 'MSSQLSERVER'
Ensure = 'Present'
AvailabilityMode = 'SynchronousCommit'
BackupPriority = 60
ConnectionModeInPrimaryRole = 'AllowReadWriteConnections'
ConnectionModeInSecondaryRole = 'AllowReadIntentConnectionsOnly'
EndpointHostName = 'AnotherEndpointHostName'
FailoverMode = 'Automatic'
ReadOnlyRoutingConnectionUrl = 'TCP://Server1.domain.com:1433'
ReadOnlyRoutingList = @('Server2', 'Server1')
}

{ Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw
}

Should -Invoke -CommandName Update-AvailabilityGroupReplica -Exactly -Times 1 -Scope It
}
}

Context 'When AvailabilityMode and FailoverMode properties are not in desired state' {
BeforeAll {
Mock -CommandName Update-AvailabilityGroupReplica
}

It 'Should set both properties with one update' {
InModuleScope -Parameters $_ -ScriptBlock {
$setTargetResourceParameters = @{
Name = 'Server1'
AvailabilityGroupName = 'AG_AllServers'
ServerName = 'Server1'
InstanceName = 'MSSQLSERVER'
PrimaryReplicaServerName = 'Server2'
PrimaryReplicaInstanceName = 'MSSQLSERVER'
Ensure = 'Present'
AvailabilityMode = 'SynchronousCommit'
BackupPriority = 50
ConnectionModeInPrimaryRole = 'AllowAllConnections'
ConnectionModeInSecondaryRole = 'AllowNoConnections'
EndpointHostName = 'Server1'
FailoverMode = 'Automatic'
ReadOnlyRoutingConnectionUrl = 'TCP://Server1.domain.com:1433'
ReadOnlyRoutingList = @('Server1', 'Server2')
}

{ Set-TargetResource @setTargetResourceParameters } | Should -Not -Throw
}

Should -Invoke -CommandName Update-AvailabilityGroupReplica -Exactly -Times 1 -Scope It
}
}

Context 'When the endpoint port differ from the port in the replica''s endpoint URL' {
BeforeAll {
Mock -CommandName Update-AvailabilityGroupReplica
Expand Down