AzureRemoteArchive/AzureRemoteArchive.psm1

Import-Module "Az.Storage"

function Get-CheckModFile {
    param(
        [Parameter(Mandatory)]
        [string]$DestinationPath
    )

    if ($DestinationPath.EndsWith("\")) {
        $DestinationPath + ".AzureRemoteArchive"
    }
    else {
        $DestinationPath + "\" + ".AzureRemoteArchive"
    }
}

function Get-AzureRemoteArchive {
    param(
        [Parameter(Mandatory)]
        [string]$DestinationPath,
        [Parameter(Mandatory)]
        [hashtable]$StorageContextProps,
        [Parameter(Mandatory)]
        [string]$Container,
        [Parameter(Mandatory)]
        [string]$Blob,
        [Parameter(Mandatory)]
        [ensure]$Ensure,
        [bool]$Force
    )

    $ErrorActionPreference = "Stop"

    

    if (Test-Path (Get-CheckModFile $DestinationPath)) {
        [ensure]$actualEnsure = "Present"
    }
    else {
        [ensure]$actualEnsure = "Absent"
    }

    return @{
        DestinationPath = $DestinationPath
        Container       = $Container
        Blob            = $Blob
        Ensure          = $actualEnsure
        Force           = $Force
    }

}



function Set-AzureRemoteArchive {
    param(
        [Parameter(Mandatory)]
        [string]$DestinationPath,
        [Parameter(Mandatory)]
        [hashtable]$StorageContextProps,
        [Parameter(Mandatory)]
        [string]$Container,
        [Parameter(Mandatory)]
        [string]$Blob,
        [Parameter(Mandatory)]
        [ensure]$Ensure,
        [bool]$Force
    )

    $ErrorActionPreference = "Stop"

    $tempFileName = (Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())) + ".zip"
    $ctx = New-AzStorageContext @StorageContextProps
    
    if (-not (Test-AzureRemoteArchive @PSBoundParameters)) {
        if ($Ensure -eq "Present") {
            Get-AzStorageBlobContent -Context $ctx -Blob $Blob -Container $Container -Destination $tempFileName | Out-Null
            Expand-Archive -Path $tempFileName -DestinationPath $DestinationPath -Force:$Force -ErrorVariable 'expandErrors'
            if ($expandErrors.Count -eq 0) {
                $blobObj.LastModified | Out-File -Encoding UTF8 (Get-CheckModFile $DestinationPath)
            } else {
                Write-Error "Extracting archive failed"
            }
            Remove-Item $tempFileName
        }
        else {
            Remove-Item -Path $DestinationPath -Force:$Force
        }
        
    }
}

function Test-AzureRemoteArchive {
    param(
        [Parameter(Mandatory)]
        [string]$DestinationPath,
        [Parameter(Mandatory)]
        [hashtable]$StorageContextProps,
        [Parameter(Mandatory)]
        [string]$Container,
        [Parameter(Mandatory)]
        [string]$Blob,
        [Parameter(Mandatory)]
        [ensure]$Ensure,
        [bool]$Force
    )

    $ErrorActionPreference = "Stop"

    $resource = Get-AzureRemoteArchive @PSBoundParameters

    if ($Ensure -ne $resource.Ensure) {
        $false
        return
    }

    # check if the blob was updated in the mean time
    if ($Ensure -eq "Present") {
        $ctx = New-AzStorageContext @StorageContextProps
    
        $blobObj = Get-AzStorageBlob -Context $ctx -Container $Container -Blob $blob
    
        $checkModFileObj = Get-ChildItem (Get-CheckModFile $DestinationPath)
        $blobObj.LastModified -le $checkModFileObj.LastWriteTime
        return
    }

    $true
}


enum Ensure {
    Absent
    Present
}


[DscResource()]
class AzureRemoteArchive {
    [DscProperty(Key)]
    [string]$DestinationPath

    [DscProperty(Mandatory)]
    [hashtable]$StorageContextProps

    [DscProperty(Mandatory)]
    [string]$Container

    [DscProperty(Mandatory)]
    [string]$Blob

    [DscProperty()]
    [ensure]$Ensure

    [DscProperty()]
    [bool]$Force


    [AzureRemoteArchive]Get() {
        $resource = Get-AzureRemoteArchive -DestinationPath $this.DestinationPath `
            -StorageContextProps $this.StorageContextProps `
            -Container $this.Container `
            -Blob $this.Blob `
            -Ensure $this.Ensure `
            -Force $this.Force
        return $resource
    }

    [void]Set() {
        Set-AzureRemoteArchive -DestinationPath $this.DestinationPath `
            -StorageContextProps $this.StorageContextProps `
            -Container $this.Container `
            -Blob $this.Blob `
            -Ensure $this.Ensure `
            -Force $this.Force
        
    }

    [bool]Test() {
        $ok = Test-AzureRemoteArchive -DestinationPath $this.DestinationPath `
            -StorageContextProps $this.StorageContextProps `
            -Container $this.Container `
            -Blob $this.Blob `
            -Ensure $this.Ensure `
            -Force $this.Force
        return $ok
    }
}