DSCResources/xAzureFile/xAzureFile.psm1

<#######################################################################################
 # xAzureFile : DSC Resource that will set/test/get the contents of a local file/folder
 # against
 #######################################################################################>

 


######################################################################################
# The Get-TargetResource cmdlet.
# This function will get the present list of files in the destination directory
######################################################################################
function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([Hashtable])]
    param
    (        
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Source,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Destination
    )

    $retVal = @{
        Name = $Name
        Source = $Source
        Destination = $Destination
        StorageKey = '***'
        SASToken = '***'
    }

    return $retVal
}

######################################################################################
# The Set-TargetResource cmdlet.
# This function will set a new IP Address in the current node
######################################################################################
function Set-TargetResource
{
    [CmdletBinding()]
    param
    (    
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Source,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Destination,

        [String]$StorageKey,
        
        [String]$SASToken
    )

 
    ValidateProperties @PSBoundParameters -Apply
}

######################################################################################
# The Test-TargetResource cmdlet.
# This will test if the given IP Address is among the current node's IP Address collection
######################################################################################
function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([boolean])]
    param
    (        
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Source,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Destination,

        [String]$StorageKey,
        
        [String]$SASToken
    )

    ValidateProperties @PSBoundParameters
}


#######################################################################################
# Helper function that invokes AzCopy.exe to check if files need to be downloaded.
# If the switch parameter "Apply" is set, then it will set the properties after a test
#######################################################################################
function ValidateProperties
{
    param
    (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Source,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$Destination,

        [String]$StorageKey,
        
        [String]$SASToken,

        [Switch]$Apply = $false
    )

    Write-Verbose 'Entering xAzureFile ValidateProperties'

    $Source      = StripHash($Source)
    $Destination = StripHash($Destination)
    $StorageKey  = StripHash($StorageKey)
    $SASToken    = StripHash($SASToken)

    $sourceUri = new-object -TypeName System.Uri -ArgumentList $Source
    $destUri = new-object -TypeName System.Uri -ArgumentList $Destination

    if ($sourceUri.IsFile -or $sourceUri.IsUnc -or `
        !$sourceUri.Host.EndsWith('blob.core.windows.net'))
    {
        throw "Source must be an Azure blob container"
    }

    if (!$destUri.IsFile)
    {
        throw "Destination must be a local file path"
    }

    $AzCopyPath = $PSScriptRoot + '/AzCopy.exe'
    $AzCopyArguments = $Source, $Destination, '/Z', '/S', '/Y', '/MT', '/XO'

    if ($SASToken)
    {
        $AzCopyArguments += [string]::Format('/SourceSAS:{0}', $SASToken)
    }
    elseif ($StorageKey)
    {
        $AzCopyArguments += [string]::Format('/SourceKey:{0}', $StorageKey)
    }
    else
    {
        throw "Either SASToken or StorageKey must be supplied"
    }

    if (! $Apply)
    {
        $AzCopyArguments += '/L'
    }

    $argsString = New-Object System.Text.StringBuilder
    foreach ($arg in $AzCopyArguments)
    {
        $argsString.AppendFormat("{0} ", $arg) > $null
    }
    $msg = [string]::Format('Invoking AzCopy: {0} {1}', $AzCopyPath, $argsString)
    Write-Verbose $msg

    & $AzCopyPath $AzCopyArguments | set-variable -name AzCopyOutput 

    #Write-Verbose $AzCopyOutput

    $transferedMatch = [Regex]::Match($AzCopyOutput, "Total files transferred: *(\d*)")
    $failedMatch = [Regex]::Match($AzCopyOutput, "Transfer failed: *(\d*)")

    if (!$transferedMatch -or !$transferedMatch.Groups.Count -eq 2 )
    {
        return $false
    }
    if (!$failedMatch -or !$failedMatch.Groups.Count -eq 2 )
    {
        return $false
    }

    return $transferedMatch.Groups[1].Value -gt 0 -and $failedMatch.Groups[1].Value -eq 0
}

function StripHash
{
    param
    (
        [String]$Value
    )

    if ($Value -and ([string]::IsNullOrEmpty($Value) -eq $false))
    {
        $match = [Regex]::Match($Value, "@{value=(.*)}")
        if ($match.Success)
        {
            $Value = $match.Groups[1].Value
        }
    }
    $Value
}

function ArrayToString
{
    param ($array)

    $arrayString = New-Object System.Text.StringBuilder
    foreach ($arg in $array)
    {
        $arrayString.AppendFormat("{0} ", $arg)
    }
    $arrayString
}



# FUNCTIONS TO BE EXPORTED
Export-ModuleMember -Function *-TargetResource
#Export-ModuleMember -Function *