diff --git a/DSCResources/MSFT_xClusterPreferredOwner/MSFT_xClusterPreferredOwner.psm1 b/DSCResources/MSFT_xClusterPreferredOwner/MSFT_xClusterPreferredOwner.psm1 index 47bd54d..e295e97 100644 --- a/DSCResources/MSFT_xClusterPreferredOwner/MSFT_xClusterPreferredOwner.psm1 +++ b/DSCResources/MSFT_xClusterPreferredOwner/MSFT_xClusterPreferredOwner.psm1 @@ -9,49 +9,52 @@ function Get-TargetResource { [OutputType([Hashtable])] param - ( - [parameter(Mandatory)] + ( + [Parameter(Mandatory = $true)] [string] $ClusterGroup, - [parameter(Mandatory)] + [parameter(Mandatory = $true)] [string] - $Clustername, + $ClusterName, - [parameter(Mandatory)] + [Parameter(Mandatory = $true)] [string[]] $Nodes, + [Parameter()] [string[]] $ClusterResources, + [Parameter()] [ValidateSet('Present', 'Absent')] [String] $Ensure = 'Present' ) - - Write-Verbose -Message "Retrieving Owner information for cluster $Clustername..." - $ownernodes = @( - + Write-Verbose -Message "Retrieving Owner information for cluster $ClusterName..." + + $ownerNodes = @( + Write-Verbose -Message "Retrieving Owner information for Cluster Group $ClusterGroup" - (((Get-ClusterGroup -cluster $Clustername)| Where-Object {$_.name -like "$ClusterGroup"} | Get-ClusterOwnerNode).ownernodes).name + (((Get-ClusterGroup -Cluster $ClusterName) | Where-Object -FilterScript {$_.Name -like "$ClusterGroup"} | Get-ClusterOwnerNode).OwnerNodes).Name if ($ClusterResources) { foreach ($resource in $ClusterResources) { Write-Verbose -Message "Retrieving Owner information for Cluster Resource $resource" - (((Get-ClusterResource -cluster $Clustername)| Where-Object {$_.name -like "$resource"} | Get-ClusterOwnerNode).ownernodes).name + (((Get-ClusterResource -Cluster $ClusterName) | Where-Object -FilterScript {$_.Name -like "$resource"} | Get-ClusterOwnerNode).OwnerNodes).Name } } ) - $ownernodes = $ownernodes | Select-Object -Unique - + + $ownerNodes = $ownerNodes | Select-Object -Unique + $returnValue = @{ ClusterGroup = $ClusterGroup - Clustername = $Clustername - Nodes = $ownernodes + Clustername = $ClusterName + Nodes = $ownerNodes ClusterResources = $ClusterResources Ensure = $Ensure } @@ -65,124 +68,128 @@ function Get-TargetResource function Set-TargetResource { param - ( - [parameter(Mandatory)] + ( + [Parameter(Mandatory = $true)] [string] $ClusterGroup, - [parameter(Mandatory)] + [Parameter(Mandatory = $true)] [string] - $Clustername, + $ClusterName, - [parameter(Mandatory)] + [Parameter(Mandatory = $true)] [string[]] $Nodes, + [Parameter()] [string[]] $ClusterResources, + [Parameter()] [ValidateSet('Present', 'Absent')] [String] $Ensure = 'Present' ) - Write-Verbose -Message "Retrieving all owners from cluster $Clustername" - $allnodes = (Get-ClusterNode -cluster $ClusterName).name + Write-Verbose -Message "Retrieving all owners from cluster $ClusterName" + $allNodes = (Get-ClusterNode -Cluster $ClusterName).Name if ($Ensure -eq 'Present') { - Write-Verbose -Message "Setting Cluster owners for Group $ClusterGroup to $nodes" - $null = (Get-ClusterGroup -cluster $ClusterName)| Where-Object {$_.name -like $ClusterGroup} | Set-ClusterOwnerNode $Nodes - $null = (Get-ClusterResource)| Where-Object {$_.OwnerGroup -like $ClusterGroup} | Set-ClusterOwnerNode $allnodes - - Write-Verbose -Message "Moving Cluster Group $ClusterGroup to node $($nodes[0])" - $null = (Get-ClusterGroup -cluster $ClusterName)| Where-Object {$_.name -like $ClusterGroup} | Move-ClusterGroup -Node $Nodes[0] - + Write-Verbose -Message "Setting Cluster owners for Group $ClusterGroup to $Nodes" + $null = (Get-ClusterGroup -Cluster $ClusterName) | Where-Object -FilterScript {$_.Name -like $ClusterGroup} | Set-ClusterOwnerNode -Owners $Nodes + $null = (Get-ClusterResource) | Where-Object {$_.OwnerGroup -like $ClusterGroup} | Set-ClusterOwnerNode -Owners $allNodes + + Write-Verbose -Message "Moving Cluster Group $ClusterGroup to node $($Nodes[0])" + $null = (Get-ClusterGroup -Cluster $ClusterName) | Where-Object -FilterScript {$_.name -like $ClusterGroup} | Move-ClusterGroup -Node $Nodes[0] + foreach ($resource in $ClusterResources) { - Write-Verbose -Message "Setting Cluster owners for Resource $resource to $nodes" - $null = (Get-ClusterResource -cluster $Clustername)| Where-Object {$_.name -like "$resource"} | Set-ClusterOwnerNode -owners $Nodes + Write-Verbose -Message "Setting Cluster owners for Resource $resource to $Nodes" + $null = (Get-ClusterResource -Cluster $ClusterName)| Where-Object -FilterScript {$_.Name -like "$resource"} | Set-ClusterOwnerNode -Owners $Nodes } } - if ($Ensure -eq 'Absent') - { - Write-Verbose -Message "Retrieving current clusterowners for group $ClusterGroup" - $currentowners = (((Get-ClusterGroup -cluster $Clustername)| Where-Object {$_.name -like "$ClusterGroup"} | Get-ClusterOwnerNode).ownernodes).name | Sort-Object -Unique - $newowners = @( - foreach ($currentowner in $currentowners) + if ($Ensure -eq 'Absent') + { + Write-Verbose -Message "Retrieving current cluster owners for group $ClusterGroup" + $currentOwners = (((Get-ClusterGroup -Cluster $ClusterName)| Where-Object -FilterScript {$_.Name -like "$ClusterGroup"} | Get-ClusterOwnerNode).OwnerNodes).Name | Sort-Object -Unique + $newOwners = @( + foreach ($currentOwner in $currentOwners) + { + if ($Nodes -notcontains $currentOwner) { - if ($Nodes -notcontains $currentowner) - { - $currentowner - } + $currentOwner } - ) - Write-Verbose -Message "Removing owners from group $($ClusterGroup): $Nodes" - $null = (Get-ClusterGroup -cluster $ClusterName)| Where-Object {$_.name -like $ClusterGroup} | Set-ClusterOwnerNode $newowners + } + ) + Write-Verbose -Message "Removing owners from group $($ClusterGroup): $Nodes" + $null = (Get-ClusterGroup -Cluster $ClusterName)| Where-Object -FilterScript {$_.Name -like $ClusterGroup} | Set-ClusterOwnerNode $newOwners - Write-Verbose -Message "Setting Cluster owners for Group $ClusterGroup to $newowners" - $null = (Get-ClusterResource)| Where-Object {$_.OwnerGroup -like $ClusterGroup} | Set-ClusterOwnerNode $allnodes + Write-Verbose -Message "Setting Cluster owners for Group $ClusterGroup to $newOwners" + $null = (Get-ClusterResource)| Where-Object -FilterScript {$_.OwnerGroup -like $ClusterGroup} | Set-ClusterOwnerNode $allNodes - Write-Verbose -Message "Moving Cluster Group $ClusterGroup to node $($newowners[0])" - $null = (Get-ClusterGroup -cluster $ClusterName)| Where-Object {$_.name -like $ClusterGroup} | Move-ClusterGroup -Node $newowners[0] + Write-Verbose -Message "Moving Cluster Group $ClusterGroup to node $($newOwners[0])" + $null = (Get-ClusterGroup -Cluster $ClusterName)| Where-Object -FilterScript {$_.Name -like $ClusterGroup} | Move-ClusterGroup -Node $newOwners[0] foreach ($resource in $ClusterResources) { Write-Verbose -Message "Retrieving current clusterowners for resource $resource" - $currentowners = ((Get-ClusterResource -cluster $Clustername | Where-Object {$_.name -like "$resource"} | Get-ClusterOwnerNode).ownernodes).name | Sort-Object -Unique - $newowners = @( - foreach ($currentowner in $currentowners) + $currentOwners = ((Get-ClusterResource -Cluster $ClusterName | Where-Object -FilterScript {$_.Name -like "$resource"} | Get-ClusterOwnerNode).OwnerNodes).Name | Sort-Object -Unique + $newOwners = @( + foreach ($currentOwner in $currentOwners) { - if ($Nodes -notcontains $currentowner) + if ($Nodes -notcontains $currentOwner) { - $currentowner + $currentOwner } } ) - Write-Verbose -Message "Setting Cluster owners for Resource $resource to $newowners" - $null = Get-ClusterResource -cluster $Clustername | Where-Object {$_.name -like "$resource"} | Set-ClusterOwnerNode -owners $newowners + Write-Verbose -Message "Setting Cluster owners for Resource $resource to $newOwners" + $null = Get-ClusterResource -Cluster $ClusterName | Where-Object -FilterScript {$_.Name -like "$resource"} | Set-ClusterOwnerNode -Owners $newOwners } - } + } } -# +# # Test-TargetResource # -function Test-TargetResource +function Test-TargetResource { [OutputType([Boolean])] param - ( - [parameter(Mandatory)] + ( + [Parameter(Mandatory = $true)] [string] $ClusterGroup, - [parameter(Mandatory)] + [Parameter(Mandatory = $true)] [string] - $Clustername, + $ClusterName, - [parameter(Mandatory)] + [Parameter(Mandatory = $true)] [string[]] $Nodes, + [Parameter()] [string[]] $ClusterResources, + [Parameter()] [ValidateSet('Present', 'Absent')] [String] $Ensure = 'Present' ) - Write-Verbose -Message "Testing Owner information for cluster $Clustername..." + Write-Verbose -Message "Testing Owner information for cluster $ClusterName..." - $getinfo = (Get-TargetResource @PSBoundParameters).Nodes + $getTargetResourceResult = (Get-TargetResource @PSBoundParameters).Nodes $result = $true if ($Ensure -eq 'Present') - { - foreach ($object in $getinfo) + { + foreach ($object in $getTargetResourceResult) { if ($Nodes -notcontains $object) { @@ -190,9 +197,10 @@ function Test-TargetResource $result = $false } } - foreach ($object in $nodes) + + foreach ($object in $Nodes) { - if ($getinfo -notcontains $object) + if ($getTargetResourceResult -notcontains $object) { Write-Verbose -Message "$object was NOT found as possible owner" $result = $false @@ -201,8 +209,8 @@ function Test-TargetResource } if ($Ensure -eq 'Absent') - { - foreach ($object in $getinfo) + { + foreach ($object in $getTargetResourceResult) { if ($Nodes -contains $object) { @@ -210,9 +218,10 @@ function Test-TargetResource $result = $false } } - foreach ($object in $nodes) + + foreach ($object in $Nodes) { - if ($getinfo -contains $object) + if ($getTargetResourceResult -contains $object) { Write-Verbose -Message "$object WAS found as possible owner" $result = $false diff --git a/README.md b/README.md index 075efcb..1d48e84 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # xFailOverCluster -The **xFailOverCluster** DSC modules contains **xCluster** and **xWaitForCluster** resources for creating and configuring failover clusters. +The **xFailOverCluster** DSC modules contains **xCluster** and **xWaitForCluster** resources for creating and configuring failover clusters. ## Contributing Please check out common DSC Resources [contributing guidelines](https://github.com/PowerShell/DscResource.Kit/blob/master/CONTRIBUTING.md). @@ -23,7 +23,7 @@ Please check out common DSC Resources [contributing guidelines](https://github.c * **IsSingleInstance** Always set to `Yes` to prevent multiple quorum settings per cluster. * **Type** Quorum type to use: *NodeMajority*, *NodeAndDiskMajority*, *NodeAndFileShareMajority*, *DiskOnly* -* **Resource** The name of the disk or file share resource to use as witness. Is optional with *NodeMajority* type. +* **Resource** The name of the disk or file share resource to use as witness. Is optional with *NodeMajority* type. ### xClusterDisk (Unreleased) @@ -42,6 +42,11 @@ Please check out common DSC Resources [contributing guidelines](https://github.c ### Unreleased +* Changes to xClusterPreferredOwner + * Script Analyzer warnings have been fixed (issue #50). This also failed the tests for the resource. +* Changes to xClusterDisk + * Fixed test that was failing in AppVeyor (issue #55). + ### 1.6.0.0 * xCluster: Fixed bug in which failure to create a new cluster would hang @@ -69,8 +74,8 @@ Please check out common DSC Resources [contributing guidelines](https://github.c ### Cluster example -In this example, we will create a failover cluster from two VMs. -We will assume that a Domain Controller already exists, and that both VMs are already domain joined. +In this example, we will create a failover cluster from two VMs. +We will assume that a Domain Controller already exists, and that both VMs are already domain joined. Furthermore, the example assumes that your certificates are installed such that DSC can appropriately handle secrets such as the Domain Administrator Credential. Finally, the xCluster module must also be installed on the VMs, as specified above. For an example of an end to end scenario, check out the SQL HA Group blog post on the PowerShell Team Blog. @@ -78,8 +83,8 @@ For an example of an end to end scenario, check out the SQL HA Group blog post o ```powershell Configuration ClusterDemo { - param([Parameter(Mandatory=$true)] - [ValidateNotNullorEmpty()] + param([Parameter(Mandatory=$true)] + [ValidateNotNullorEmpty()] [PsCredential] $domainAdminCred) Node $AllNodes.Where{$_.Role -eq "PrimaryClusterNode" }.NodeName @@ -93,7 +98,7 @@ Configuration ClusterDemo WindowsFeature RSATClusteringPowerShell { Ensure = "Present" - Name = "RSAT-Clustering-PowerShell" + Name = "RSAT-Clustering-PowerShell" DependsOn = "[WindowsFeature]FailoverFeature" } @@ -113,12 +118,12 @@ Configuration ClusterDemo DomainAdministratorCredential = $domainAdminCred DependsOn = “[WindowsFeature]RSATClusteringCmdInterface” - } + } } Node $AllNodes.Where{ $_.Role -eq "ReplicaServerNode" }.NodeName - { + { WindowsFeature FailoverFeature { Ensure = "Present" @@ -128,7 +133,7 @@ Configuration ClusterDemo WindowsFeature RSATClusteringPowerShell { Ensure = "Present" - Name = "RSAT-Clustering-PowerShell" + Name = "RSAT-Clustering-PowerShell" DependsOn = "[WindowsFeature]FailoverFeature" } @@ -147,7 +152,7 @@ Configuration ClusterDemo RetryIntervalSec = 10 RetryCount = 60 - DependsOn = “[WindowsFeature]RSATClusteringCmdInterface” + DependsOn = “[WindowsFeature]RSATClusteringCmdInterface” } xCluster joinCluster @@ -157,7 +162,7 @@ Configuration ClusterDemo DomainAdministratorCredential = $domainAdminCred DependsOn = "[xWaitForCluster]waitForCluster" - } + } } } diff --git a/Tests/MSFT_xClusterDisk.Tests.ps1 b/Tests/MSFT_xClusterDisk.Tests.ps1 index 4741823..5a796fd 100644 --- a/Tests/MSFT_xClusterDisk.Tests.ps1 +++ b/Tests/MSFT_xClusterDisk.Tests.ps1 @@ -12,7 +12,7 @@ if (!$PSScriptRoot) $RootPath = (Resolve-Path -Path "$PSScriptRoot\..").Path $ModuleName = 'MSFT_xClusterDisk' -Add-WindowsFeature -Name RSAT-Clustering-PowerShell -ErrorAction SilentlyContinue +Add-WindowsFeature -Name RSAT-Clustering-PowerShell -ErrorAction SilentlyContinue Import-Module (Join-Path -Path $RootPath -ChildPath "DSCResources\$ModuleName\$ModuleName.psm1") -Force @@ -22,7 +22,7 @@ Import-Module (Join-Path -Path $RootPath -ChildPath "DSCResources\$ModuleName\$M Describe 'xClusterDisk' { InModuleScope $ModuleName { - + $TestParameter = @{ Number = 1 Ensure = 'Present' @@ -46,7 +46,7 @@ Describe 'xClusterDisk' { Ensure = 'Present' Label = 'Wrong Label' } - + Mock -CommandName 'Get-CimInstance' -ParameterFilter { $ClassName -eq 'MSCluster_Disk' -and $Namespace -eq 'Root\MSCluster' } -MockWith { switch($Filter) { @@ -54,7 +54,7 @@ Describe 'xClusterDisk' { [PSCustomObject] @{ Name = '1' Id = '{0182f270-e2b8-4579-8c0a-176e0e05c30c}' - } + } } default { $null @@ -84,8 +84,6 @@ Describe 'xClusterDisk' { } Mock -CommandName 'Get-ClusterParameter' -ParameterFilter { $Name -eq 'DiskIdGuid' } -MockWith { - #write-host $args.count -ForegroundColor Cyan - #write-host $args -ForegroundColor Cyan switch ($InputObject.Name) { 'First Data' { @@ -100,102 +98,68 @@ Describe 'xClusterDisk' { } } } - + Context 'Validate Get-TargetResource method' { It 'Returns a [System.Collection.Hashtable] type' { - $Result = Get-TargetResource @TestParameter - $Result -is [System.Collections.Hashtable] | Should Be $true } It 'Returns current configuration' { - $Result = Get-TargetResource @TestParameter - $Result.Number | Should Be $TestParameter.Number $Result.Ensure | Should Be $TestParameter.Ensure $Result.Label | Should Be $TestParameter.Label - - $Result -is [System.Collections.Hashtable] | Should Be $true } It 'Returns absent for a disk that is absent but should be present' { - $Result = Get-TargetResource @TestParameter2 - $Result.Number | Should Be $TestParameter2.Number $Result.Ensure | Should Not Be $TestParameter2.Ensure - $Result.Label | Should Not Be $TestParameter2 .Label - - $Result -is [System.Collections.Hashtable] | Should Be $true + $Result.Label | Should Not Be $TestParameter2.Label } - - It 'Returns absent for a disk that is absent as it should be' { + It 'Returns absent for a disk that is absent as it should be' { $Result = Get-TargetResource @TestParameter3 - $Result.Number | Should Be $TestParameter3.Number $Result.Ensure | Should Be $TestParameter3.Ensure $Result.Label | Should Be '' - - $Result -is [System.Collections.Hashtable] | Should Be $true } - - It 'Returns present for a disk that is present but has the wrong label' { + It 'Returns present for a disk that is present but has the wrong label' { $Result = Get-TargetResource @TestParameter4 - $Result.Number | Should Be $TestParameter4.Number $Result.Ensure | Should Be $TestParameter4.Ensure $Result.Label | Should Not Be $TestParameter4.Label - - $Result -is [System.Collections.Hashtable] | Should Be $true } } - - Context 'Validate Set-TargetResource method' { + Context 'Validate Set-TargetResource method' { It 'Returns nothing' { - $Result = Set-TargetResource @TestParameter - $Result -eq $null | Should Be $true } } - - Context 'Validate Test-TargetResource method' { + Context 'Validate Test-TargetResource method' { It 'Check present disk that is present returns $true' { - $Result = Test-TargetResource -Ensure $TestParameter.Ensure -Label $TestParameter.Label -Number $TestParameter.Number - - $Result -is [System.Boolean] | Should Be $true $Result | Should Be $true } - - It 'Check absent disk that should be present returns $false' { + It 'Check absent disk that should be present returns $false' { $Result = Test-TargetResource -Ensure $TestParameter2.Ensure -Label $TestParameter2.Label -Number $TestParameter2.Number - - $Result -is [System.Boolean] | Should Be $true $Result | Should Be $false } - - It 'Check absent disk that is absent returns $true' { + It 'Check absent disk that is absent returns $true' { $Result = Test-TargetResource -Ensure $TestParameter3.Ensure -Label $TestParameter3.Label -Number $TestParameter3.Number - - $Result -is [System.Boolean] | Should Be $true $Result | Should Be $true } - - It 'Check that present disk but with a wrong label returns $false' { + It 'Check that present disk but with a wrong label returns $false' { $Result = Test-TargetResource -Ensure $TestParameter4.Ensure -Label $TestParameter4.Label -Number $TestParameter4.Number - - $Result -is [System.Boolean] | Should Be $true $Result | Should Be $false } }