DSCResources/DSC_DFSReplicationGroup/DSC_DFSReplicationGroup.psm1

$modulePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'Modules'

# Import the DFSDsc.Common Module
Import-Module -Name (Join-Path -Path $modulePath -ChildPath 'DscResource.Common')

# Import Localization Strings
$script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US'

<#
    .SYNOPSIS
    Returns the current state of a DFS Replication Group.
 
    .PARAMETER GroupName
    The name of the DFS Replication Group.
 
    .PARAMETER Ensure
    Specifies whether the DFS Replication Group should exist.
 
    .PARAMETER DomainName
    The AD domain the Replication Group should created in.
#>

function Get-TargetResource
{
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $GroupName,

        [Parameter()]
        [ValidateSet('Present','Absent')]
        [System.String]
        $Ensure = 'Present',

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

    Write-Verbose -Message ( @(
        "$($MyInvocation.MyCommand): "
        $($script:localizedData.GettingReplicationGroupMessage) `
            -f $GroupName
        ) -join '' )

    # Lookup the existing Replication Group
    $replicationGroupParameters = @{
        GroupName = $GroupName
    }

    $returnValue = $replicationGroupParameters.Clone()

    if ($DomainName)
    {
        $replicationGroupParameters += @{
            DomainName = $DomainName
        }
    } # if

    $replicationGroup = Get-DfsReplicationGroup @replicationGroupParameters `
        -ErrorAction Stop

    if ($replicationGroup)
    {
        Write-Verbose -Message ( @(
            "$($MyInvocation.MyCommand): "
            $($script:localizedData.ReplicationGroupExistsMessage) `
                -f $GroupName
            ) -join '' )

        <#
            Array paramters are disabled until this issue is resolved:
            https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/11088807-get-dscconfiguration-fails-with-embedded-cim-type
            When resolved these parameters can be added into return value
            Members = @((Get-DfsrMember @replicationGroupParameters -ErrorAction Stop).ComputerName)
            Folders = @((Get-DfsReplicatedFolder @replicationGroupParameters -ErrorAction Stop).FolderName)
        #>

        $returnValue += @{
            Ensure = 'Present'
            Description = $replicationGroup.Description
            DomainName = $replicationGroup.DomainName
            Members = @()
            Folders = @()
            ContentPaths = @()
        }
    } #if
    else
    {
        Write-Verbose -Message ( @(
            "$($MyInvocation.MyCommand): "
            $($script:localizedData.ReplicationGroupDoesNotExistMessage) `
                -f $GroupName
            ) -join '' )

        $returnValue += @{
            Ensure = 'Absent'
        }
    } # else

    return $returnValue
} # Get-TargetResource

<#
    .SYNOPSIS
    Sets the current state of a DFS Replication Group.
 
    .PARAMETER GroupName
    The name of the DFS Replication Group.
 
    .PARAMETER Ensure
    Specifies whether the DFS Replication Group should exist.
 
    .PARAMETER Description
    A description for the DFS Replication Group.
 
    .PARAMETER Members
    A list of computers that are members of this Replication Group.
    These can be specified using either the ComputerName or FQDN name
    for each member. These may alternatively be defined separately
    through the DFSReplicationGroupMember resource - NB do NOT use both
    methods in the same configuration to avoid config flapping. If an
    FQDN name is used and the DomainName parameter is set, the FQDN
    domain name must match.
 
    .PARAMETER Folders
    A list of folders that are replicated in this Replication Group.
 
    .PARAMETER Topology
    This allows a replication topology to assign to the Replication Group.
    It defaults to Manual, which will not automatically create a topology.
    If set to Fullmesh, a full mesh topology between all members will be
    created.
 
    .PARAMETER ContentPaths
    An array of DFS Replication Group Content Paths to use for each of the
    Folders. This can have one entry for each Folder in the Folders
    parameter and should be set in th same order. If any entry is not blank
    then the Content Paths will need to be set manually by
    using the DFSReplicationGroupMembership resource.
 
    .PARAMETER DomainName
    The AD domain the Replication Group should created in.
#>

function Set-TargetResource
{
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $GroupName,

        [Parameter()]
        [ValidateSet('Present','Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [System.String]
        $Description,

        [Parameter()]
        [System.String[]]
        $Members,

        [Parameter()]
        [System.String[]]
        $Folders,

        [Parameter()]
        [ValidateSet('Fullmesh','Manual')]
        [System.String]
        $Topology = 'Manual',

        [Parameter()]
        [System.String[]]
        $ContentPaths,

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

    Write-Verbose -Message ( @(
        "$($MyInvocation.MyCommand): "
        $($script:localizedData.SettingRegGroupMessage) `
            -f $GroupName
        ) -join '' )

    # Lookup the existing Replication Group
    $replicationGroupParameters = @{
        GroupName = $GroupName
    }

    if ($DomainName)
    {
        $replicationGroupParameters += @{
            DomainName = $DomainName
        }
    } # if

    $replicationGroup = Get-DfsReplicationGroup @replicationGroupParameters `
        -ErrorAction Stop

    if ($Ensure -eq 'Present')
    {
        # The rep group should exist
        Write-Verbose -Message ( @(
            "$($MyInvocation.MyCommand): "
            $($script:localizedData.EnsureReplicationGroupExistsMessage) `
                -f $GroupName
            ) -join '' )

        if ($Description)
        {
            $replicationGroupParameters += @{
                Description = $Description
            }
        } # if

        if ($replicationGroup)
        {
            # The RG exists already - Check the existing RG and members
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.ReplicationGroupExistsMessage) `
                    -f $GroupName
                ) -join '' )

            # Check the description
            if (($Description) -and ($replicationGroup.Description -ne $Description))
            {
                Set-DfsReplicationGroup @replicationGroupParameters -ErrorAction Stop

                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.ReplicationGroupDescriptionUpdatedMessage) `
                        -f $GroupName
                    ) -join '' )
            } # if
        } # if
        else
        {
            # Ths Rep Groups doesn't exist - Create it
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.ReplicationGroupDoesNotExistMessage) `
                    -f $GroupName
                ) -join '' )

            New-DfsReplicationGroup @replicationGroupParameters -ErrorAction Stop

            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.ReplicationGroupCreatedMessage) `
                    -f $GroupName
                ) -join '' )
        } # else

        # Clean up the splat so we can use it in the next cmdlets
        $replicationGroupParameters.Remove('Description')

        # Set the members (if any were passed in the array)
        if ($PSBoundParameters.ContainsKey('Members'))
        {
            # Create an array of FQDN Members from the Members Array
            $replicationGroupParameters += @{
                ComputerName = ''
            }

            foreach ($member in $Members)
            {
                $replicationGroupParameters.ComputerName = $member
                $fqdnMembers += @(
                    Get-FQDNMemberName @replicationGroupParameters
                )
            } # foreach

            $replicationGroupParameters.Remove('ComputerName')

            # Get the existing members of this DFS Rep Group
            $existingMembers = (Get-DfsrMember @replicationGroupParameters -ErrorAction Stop).DnsName

            # Add any missing members
            foreach ($Member in $fqdnMembers)
            {
                if ($member -notin $existingMembers)
                {
                    # Member is missing - add it
                    Add-DfsrMember @replicationGroupParameters `
                        -ComputerName $member `
                        -ErrorAction Stop

                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($script:localizedData.ReplicationGroupMemberAddedMessage) `
                            -f $GroupName,$member
                        ) -join '' )
                } # if
            } # foreach

            # Remove any members that shouldn't exist
            foreach ($existingMember in $existingMembers)
            {
                if ($existingMember -notin $fqdnMembers)
                {
                    # Member exists but shouldn't - remove it
                    Remove-DfsrMember @replicationGroupParameters `
                        -ComputerName $existingMember `
                        -Force `
                        -ErrorAction Stop

                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($script:localizedData.ReplicationGroupMemberRemovedMessage) `
                            -f $GroupName,$existingMember
                        ) -join '' )
                } # if
            } # foreach
        } # if

        # Get the existing folders of this DFS Rep Group
        $existingFolders = (Get-DfsReplicatedFolder @replicationGroupParameters -ErrorAction Stop).FolderName

        # Add any missing folders
        foreach ($folder in $Folders)
        {
            if ($folder -notin $existingFolders)
            {
                # Folder is missing - add it
                New-DfsReplicatedFolder @replicationGroupParameters `
                    -FolderName $folder `
                    -ErrorAction Stop

                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.ReplicationGroupFolderAddedMessage) `
                        -f $GroupName,$folder
                    ) -join '' )
            } # if
        } # foreach

        # Remove any folders that shouldn't exist
        foreach ($existingFolder in $existingFolders)
        {
            if ($existingFolder -notin $Folders)
            {
                # Folder exists but shouldn't - remove it
                Remove-DfsReplicatedFolder @replicationGroupParameters `
                    -Folder $existingFolder `
                    -Force `
                    -ErrorAction Stop

                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.ReplicationGroupFolderRemovedMessage) `
                        -f $GroupName,$existingFolder
                    ) -join '' )
            } # if
        } # foreach

        # Set the content paths (if any were passed in the array)
        if ($PSBoundParameters.ContainsKey('ContentPaths'))
        {
            # Get the current memberships for this rep group
            $memberships = Get-DfsrMembership @replicationGroupParameters `
                -ErrorAction Stop

            # Scan through the content paths array
            for ($i=0; $i -lt $Folders.Count; $i++)
            {
                $contentPath = $ContentPaths[$i]
                if ($contentPath)
                {
                    foreach ($membership in $memberships)
                    {
                        [System.String] $fqdnMemberName = Get-FQDNMemberName `
                            @replicationGroupParameters `
                            -ComputerName $membership.ComputerName

                        [System.Boolean] $primaryMember = ($fqdnMemberName -eq $fqdnMembers[0])

                        if (($membership.FolderName -ne $Folders[$i]) `
                            -or (($membership.ContentPath -eq $ContentPath) `
                            -and ($membership.PrimaryMember -eq $primaryMember)))
                        {
                            # Don't update this membership
                            continue
                        } #if

                        # The Content Path for this member needs to be set
                        Set-DfsrMembership @replicationGroupParameters `
                            -FolderName $membership.FolderName `
                            -ComputerName $membership.ComputerName `
                            -PrimaryMember $primaryMember `
                            -ContentPath $ContentPath

                        Write-Verbose -Message ( @(
                            "$($MyInvocation.MyCommand): "
                            $($script:localizedData.ReplicationGroupContentPathUpdatedMessage) `
                                -f $GroupName,$membership.ComputerName
                            ) -join '' )
                    } # foreach
                } # if
            } # foreach
        } # if

        # If any members were passed in the array
        if ($PSBoundParameters.ContainsKey('Members'))
        {
            # If the topology is not manual, automatically configure the connections
            switch ($Topology)
            {
                'Fullmesh'
                {
                    $replicationGroupParameters += @{
                        SourceComputerName = ''
                        DestinationComputerName = ''
                    }

                    # Scan through the combination of connections
                    foreach ($source in $fqdnMembers)
                    {
                        foreach ($destination in $fqdnMembers)
                        {
                            if ($source -eq $destination)
                            {
                                continue
                            } # if

                            $replicationGroupParameters.SourceComputerName = $source
                            $replicationGroupParameters.DestinationComputerName = $destination

                            $replicationGroupConnection = Get-DfsrConnection @replicationGroupParameters `
                                -ErrorAction Stop

                            if ($replicationGroupConnection)
                            {
                                if (-not $replicationGroupConnection.Enabled)
                                {
                                    Set-DfsrConnection @replicationGroupParameters `
                                        -DisableConnection $false `
                                        -ErrorAction Stop

                                    Write-Verbose -Message ( @(
                                        "$($MyInvocation.MyCommand): "
                                            $($script:localizedData.ReplicationGroupFullMeshConnectionUpdatedMessage) `
                                            -f  $GroupName,$source,$destination
                                        ) -join '' )
                                } # if
                            } # if
                            else
                            {
                                Add-DfsrConnection @replicationGroupParameters `
                                    -ErrorAction Stop

                                Write-Verbose -Message ( @(
                                    "$($MyInvocation.MyCommand): "
                                        $($script:localizedData.ReplicationGroupFullMeshConnectionAddedMessage) `
                                        -f  $GroupName,$source,$destination
                                    ) -join '' )
                            } # if
                        } # foreach
                    } # foreach
                } # 'Fullmesh'
            } # switch
        } #if
    } #if
    else
    {
        # The Rep Group should not exist
        Write-Verbose -Message ( @(
            "$($MyInvocation.MyCommand): "
            $($script:localizedData.EnsureReplicationGroupDoesNotExistMessage) `
                -f $GroupName
            ) -join '' )

        if ($replicationGroup)
        {
            # Remove the replication group
            Remove-DfsReplicationGroup @replicationGroupParameters `
                -RemoveReplicatedFolders `
                -Force `
                -ErrorAction Stop

            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.ReplicationGroupExistsRemovedMessage) `
                    -f $GroupName
                ) -join '' )
        } # if
    } # if
} # Set-TargetResource

<#
    .SYNOPSIS
    Tests the current state of a DFS Replication Group.
 
    .PARAMETER GroupName
    The name of the DFS Replication Group.
 
    .PARAMETER Ensure
    Specifies whether the DFS Replication Group should exist.
 
    .PARAMETER Description
    A description for the DFS Replication Group.
 
    .PARAMETER Members
    A list of computers that are members of this Replication Group.
    These can be specified using either the ComputerName or FQDN name
    for each member. These may alternatively be defined separately
    through the DFSReplicationGroupMember resource - NB do NOT use both
    methods in the same configuration to avoid config flapping. If an
    FQDN name is used and the DomainName parameter is set, the FQDN
    domain name must match.
 
    .PARAMETER Folders
    A list of folders that are replicated in this Replication Group.
 
    .PARAMETER Topology
    This allows a replication topology to assign to the Replication Group.
    It defaults to Manual, which will not automatically create a topology.
    If set to Fullmesh, a full mesh topology between all members will be
    created.
 
    .PARAMETER ContentPaths
    An array of DFS Replication Group Content Paths to use for each of the
    Folders. This can have one entry for each Folder in the Folders
    parameter and should be set in th same order. If any entry is not blank
    then the Content Paths will need to be set manually by
    using the DFSReplicationGroupMembership resource.
 
    .PARAMETER DomainName
    The AD domain the Replication Group should created in.
#>

function Test-TargetResource
{
    [OutputType([System.Boolean])]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $GroupName,

        [Parameter()]
        [ValidateSet('Present','Absent')]
        [System.String]
        $Ensure = 'Present',

        [Parameter()]
        [System.String]
        $Description,

        [Parameter()]
        [System.String[]]
        $Members,

        [Parameter()]
        [System.String[]]
        $Folders,

        [Parameter()]
        [ValidateSet('Fullmesh','Manual')]
        [System.String]
        $Topology = 'Manual',

        [Parameter()]
        [System.String[]]
        $ContentPaths,

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

    # Flag to signal whether settings are correct
    [System.Boolean] $desiredConfigurationMatch = $true

    Write-Verbose -Message ( @(
        "$($MyInvocation.MyCommand): "
        $($script:localizedData.TestingRegGroupMessage) `
            -f $GroupName
        ) -join '' )

    # Lookup the existing Replication Group
    $replicationGroupParameters = @{
        GroupName = $GroupName
    }

    if ($DomainName)
    {
        $replicationGroupParameters += @{
            DomainName = $DomainName
        }
    } # if

    $replicationGroup = Get-DFSReplicationGroup @replicationGroupParameters `
        -ErrorAction Stop

    if ($Ensure -eq 'Present')
    {
        # The RG should exist
        if ($replicationGroup)
        {
            # The RG exists already
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.ReplicationGroupExistsMessage) `
                    -f $GroupName
                ) -join '' )

            # Check the description
            if (($Description) -and ($replicationGroup.Description -ne $Description))
            {
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.ReplicationGroupDescriptionNeedsUpdateMessage) `
                        -f $GroupName
                    ) -join '' )

                $desiredConfigurationMatch = $false
            } # if

            # Get the members (if any were passed in the array)
            if ($PSBoundParameters.ContainsKey('Members'))
            {
                # Create an array of FQDN Members from the Members Array
                $replicationGroupParameters += @{
                    ComputerName = ''
                }

                foreach ($member in $Members)
                {
                    $replicationGroupParameters.ComputerName = $member
                    $fqdnMembers += @( Get-FQDNMemberName @replicationGroupParameters )
                } # foreach

                $replicationGroupParameters.Remove('ComputerName')

                # Compare the Members
                $existingMembers = @((Get-DfsrMember @replicationGroupParameters -ErrorAction Stop).DnsName)
                <#
                    check for null values before using compare-object
                    if one is null but not both then report difference
                    if neither are null then compare values
                #>

                if ([String]::IsNullOrEmpty($existingMembers) -and [String]::IsNullOrEmpty($fqdnMembers))
                {
                    # both are null so no difference found
                }
                elseif ([String]::IsNullOrEmpty($existingMembers) -xor [String]::IsNullOrEmpty($fqdnMembers))
                {
                    # There is a member difference of some kind.
                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($script:localizedData.ReplicationGroupMembersNeedUpdateMessage) `
                            -f $GroupName
                        ) -join '' )

                    $desiredConfigurationMatch = $false
                }
                else
                {
                    # neither variables are null so it's safe to use compare-object
                    if ((Compare-Object `
                        -ReferenceObject $fqdnMembers `
                        -DifferenceObject $existingMembers).Count -ne 0)
                    {
                        # There is a member difference of some kind.
                        Write-Verbose -Message ( @(
                            "$($MyInvocation.MyCommand): "
                            $($script:localizedData.ReplicationGroupMembersNeedUpdateMessage) `
                                -f $GroupName
                            ) -join '' )

                        $desiredConfigurationMatch = $false
                    } # if
                }
            } # if

            # Compare the Folders
            $existingFolders = @((Get-DfsReplicatedFolder @replicationGroupParameters -ErrorAction Stop).FolderName)
            <#
                check for null values before using compare-object
                if one is null but not both then report difference
                if neither are null then compare values
            #>

            if ([String]::IsNullOrEmpty($existingFolders) -and [String]::IsNullOrEmpty($Folders))
            {
                # both are null so no difference found
            }
            elseif ([String]::IsNullOrEmpty($existingFolders) -xor [String]::IsNullOrEmpty($Folders))
            {
                # There is a folder difference of some kind.
                Write-Verbose -Message ( @(
                    "$($MyInvocation.MyCommand): "
                    $($script:localizedData.ReplicationGroupFoldersNeedUpdateMessage) `
                        -f $GroupName
                    ) -join '' )

                $desiredConfigurationMatch = $false
            }
            else
            {
                # neither variables are null so it's safe to use compare-object
                if ((Compare-Object `
                    -ReferenceObject $Folders `
                    -DifferenceObject $existingFolders).Count -ne 0)
                {
                    # There is a folder difference of some kind.
                    Write-Verbose -Message ( @(
                        "$($MyInvocation.MyCommand): "
                        $($script:localizedData.ReplicationGroupFoldersNeedUpdateMessage) `
                            -f $GroupName
                        ) -join '' )

                    $desiredConfigurationMatch = $false
                } # if
            }
            # Get the content paths (if any were passed in the array)
            if ($PSBoundParameters.ContainsKey('ContentPaths'))
            {
                # Get the current memberships for this rep group
                $memberships = Get-DfsrMembership @replicationGroupParameters `
                    -ErrorAction Stop

                # Scan through the content paths array
                for ($i=0; $i -lt $Folders.Count; $i++)
                {
                    $contentPath = $ContentPaths[$i]

                    if ($contentPath)
                    {
                        foreach ($membership in $memberships)
                        {
                            [System.Boolean] $primaryMember = ($membership.ComputerName -eq $Members[0])

                            if (($membership.FolderName -ne $Folders[$i]) `
                                -or (($membership.ContentPath -eq $contentPath) `
                                -and ($membership.PrimaryMember -eq $primaryMember)))
                            {
                                # This membership is in the correct state.
                                continue
                            } # if

                            Write-Verbose -Message ( @(
                                "$($MyInvocation.MyCommand): "
                                $($script:localizedData.ReplicationGroupContentPathNeedUpdateMessage) `
                                    -f $GroupName,$membership.ComputerName
                                ) -join '' )

                            $desiredConfigurationMatch = $false
                        } # if
                    } # if
                } # foreach
            } # if

            # If any members were passed in the array
            if ($PSBoundParameters.ContainsKey('Members'))
            {
                # If the topology is not manual, check the connections are configured
                switch ($Topology)
                {
                    'Fullmesh'
                    {
                        $replicationGroupParameters += @{
                            SourceComputerName = ''
                            DestinationComputerName = ''
                        }

                        # Scan through the combination of connections
                        foreach ($source in $fqdnMembers)
                        {
                            foreach ($destination in $fqdnMembers)
                            {
                                if ($source -eq $destination)
                                {
                                    continue
                                } # if

                                $replicationGroupParameters.SourceComputerName = $source
                                $replicationGroupParameters.DestinationComputerName = $destination

                                $replicationGroupConnection = Get-DfsrConnection @replicationGroupParameters `
                                    -ErrorAction Stop

                                if ($replicationGroupConnection)
                                {
                                    if (-not $replicationGroupConnection.Enabled)
                                    {
                                        Write-Verbose -Message ( @(
                                            "$($MyInvocation.MyCommand): "
                                            $($script:localizedData.ReplicationGroupFullMeshDisabledConnectionMessage) `
                                                -f  $GroupName,$source,$destination
                                            ) -join '' )

                                        $desiredConfigurationMatch = $false
                                    } # if
                                }
                                else
                                {
                                    Write-Verbose -Message ( @(
                                        "$($MyInvocation.MyCommand): "
                                        $($script:localizedData.ReplicationGroupFullMeshMissingConnectionMessage) `
                                            -f  $GroupName,$source,$destination
                                        ) -join '' )

                                    $desiredConfigurationMatch = $false
                                } # else
                            } # foreach
                        } # foreach
                    } # 'fullmesh'
                } # switch
            } # if
        } # if
        else
        {
            # Ths RG doesn't exist but should
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                 $($script:localizedData.ReplicationGroupDoesNotExistButShouldMessage) `
                    -f  $GroupName
                ) -join '' )

            $desiredConfigurationMatch = $false
        } # else
    }
    else
    {
        # The RG should not exist
        if ($replicationGroup)
        {
            # The RG exists but should not
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                 $($script:localizedData.ReplicationGroupExistsButShouldNotMessage) `
                    -f $GroupName
                ) -join '' )

            $desiredConfigurationMatch = $false
        } # if
        else
        {
            # The RG does not exist and should not
            Write-Verbose -Message ( @(
                "$($MyInvocation.MyCommand): "
                $($script:localizedData.ReplicationGroupDoesNotExistAndShouldNotMessage) `
                    -f $GroupName
                ) -join '' )
        } # else
    } # else

    return $desiredConfigurationMatch
} # Test-TargetResource

<#
.SYNOPSIS
    Returns the FQDN Member name based on the ComputerName and DomainName that are provided.
 
    If the ComputerName is already an FQDN but the domain in the FQDN does not match the
    value passed in DomainName then throw an exception.
 
    If the ComputerName is already an FQDN and the domain in the FQDN does match the value
    passed in DomainName then the existing ComputerName is returned.
 
    If the ComputerName is not already an FQDN and the DomainName passed is not empty then
    the ComputerName and DomainName are combined and returned.
 
    If the ComputerName is not already an FQDN and the DomainName passed is empty then
    the ComputerName is returned.
 
    .PARAMETER GroupName
    The name of the DFS Replication Group.
 
    .PARAMETER ComputerName
    The computer name of the DFS Replication Group member.
 
    .PARAMETER DomainName
    The AD domain the Replication Group should created in.
#>

function Get-FQDNMemberName
{
    [OutputType([System.String])]
    param
    (
        [Parameter(Mandatory = $true)]
        [System.String]
        $GroupName,

        [Parameter(Mandatory = $true)]
        [System.String]
        $ComputerName,

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

    if ($ComputerName.Contains('.'))
    {
        if (($null -ne $DomainName) -and ($DomainName -ne ''))
        {
            if ($ComputerName -like "*.$DomainName")
            {
                return $ComputerName.ToLower()
            }
            else
            {
                New-InvalidOperationException `
                    -Message ($($script:localizedData.ReplicationGroupDomainMismatchError `
                        -f $GroupName,$ComputerName,$DomainName))
            } # if
        }
        else
        {
            return $ComputerName.ToLower()
        }
    }
    else
    {
        if (($null -ne $DomainName) -and ($DomainName -ne ''))
        {
            return "$ComputerName.$DomainName".ToLower()
        }
        else
        {
            return $ComputerName.ToLower()
        } # if
    } # if
} # Get-FQDNMemberName

Export-ModuleMember -Function *-TargetResource