Skip to content

Commit

Permalink
Run Update-AvailabilityGroupReplica Once for All AvailabilityReplica …
Browse files Browse the repository at this point in the history
…Changes (#1840)

- SqlAgReplica
  - `Update-AvailabilityGroupReplica` to trigger once within `Set-TargetResource`
    for all AvailabilityReplica changes.
  • Loading branch information
hollanjs authored Jan 24, 2023
1 parent 979800d commit 86869cd
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 16 deletions.
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

0 comments on commit 86869cd

Please sign in to comment.