RemoteArchiveDSC.psm1
enum Ensure { Absent Present } $checkModFileNameDefault = ".RemoteArchive" function Get-CheckModFile { param( [Parameter(Mandatory)] [string]$DestinationPath, [Parameter(Mandatory)] [string]$CheckModFileName ) if ($DestinationPath.EndsWith("\")) { $DestinationPath + $CheckModFileName } else { $DestinationPath + "\" + $CheckModFileName } } function Get-RemoteArchive { param( [Parameter(Mandatory)] [string]$DestinationPath, [Parameter(Mandatory)] [string]$URL, [ensure]$Ensure = "Present", [switch]$Force, [string]$CheckModFileName = $checkModFileNameDefault, [switch]$UseBasicParsing ) if (Test-Path (Get-CheckModFile $DestinationPath $CheckModFileName)) { [ensure]$actualEnsure = "Present" } else { [ensure]$actualEnsure = "Absent" } @{ DestinationPath = $DestinationPath URL = $URL Ensure = $actualEnsure Force = $Force } } function Set-RemoteArchive { param( [Parameter(Mandatory)] [string]$DestinationPath, [Parameter(Mandatory)] [string]$URL, [ensure]$Ensure = "Present", [switch]$Force, [string]$CheckModFileName = $checkModFileNameDefault, [switch]$UseBasicParsing ) if (-not (Test-RemoteArchive @PSBoundParameters)) { if ($Ensure -eq "Present") { $tempFileName = (Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid().ToString())) + ".zip" $resp = Invoke-WebRequest -Method Get -Uri $URL -OutFile $tempFileName -ErrorVariable err -PassThru -UseBasicParsing:$UseBasicParsing if ($err) { Write-Error "Failed to download file from $URL" return } Expand-Archive -Path $tempFileName -DestinationPath $DestinationPath -Force:$Force -ErrorVariable 'err' if ($err) { Write-Error "Extracting archive to $DestinationPath failed" Remove-Item $tempFileName return } $resp.Headers["Last-Modified"] | Out-File -Encoding utf8 (Get-CheckModFile $DestinationPath $CheckModFileName) } else { Remove-Item $DestinationPath -Recurse -Force:$Force } } } function Test-RemoteArchive { param( [Parameter(Mandatory)] [string]$DestinationPath, [Parameter(Mandatory)] [string]$URL, [ensure]$Ensure = "Present", [switch]$Force, [string]$CheckModFileName = $checkModFileNameDefault, [switch]$UseBasicParsing ) $resource = Get-RemoteArchive @PSBoundParameters if ($Ensure -ne $resource.Ensure) { $false return } if ($Ensure -eq "Present") { $resp = Invoke-WebRequest -Method Head -Uri $URL -ErrorVariable 'err' -UseBasicParsing:$UseBasicParsing if ($err) { Write-Error "Failed to retrieve headers from $URL" return } $lastModified = $resp.Headers["Last-Modified"] if ([System.String]::IsNullOrEmpty($lastModified)) { Write-Error "The url did not return a Last-Modified header. This is required" return } $lastModified = [System.Datetime]::ParseExact($lastModified, "R", $null) # RFC-1123 $lastModified -le (Get-ChildItem (Get-CheckModFile $DestinationPath $CheckModFileName)).LastWriteTimeUtc return } $true } [DscResource()] class RemoteArchive { [DscProperty(Key)] [string]$Name [DscProperty(Mandatory)] [string]$DestinationPath [DscProperty(Mandatory)] [string]$URL [DscProperty()] [ensure]$Ensure = "Present" [DscProperty()] [bool]$Force = $false [DscProperty()] [string]$CheckModFileName = $checkModFileNameDefault [DscProperty()] [bool]$UseBasicParsing [RemoteArchive]Get() { $resource = Get-RemoteArchive -DestinationPath $this.DestinationPath ` -URL $this.URL ` -Ensure $this.Ensure ` -Force:$this.Force ` -CheckModFileName $this.CheckModFileName ` -UseBasicParsing:$this.UseBasicParsing return $resource } [void]Set() { Set-RemoteArchive -DestinationPath $this.DestinationPath ` -URL $this.URL ` -Ensure $this.Ensure ` -Force:$this.Force ` -CheckModFileName $this.CheckModFileName ` -UseBasicParsing:$this.UseBasicParsing } [bool]Test() { $ok = Test-RemoteArchive -DestinationPath $this.DestinationPath ` -URL $this.URL ` -Ensure $this.Ensure ` -Force:$this.Force ` -CheckModFileName $this.CheckModFileName ` -UseBasicParsing:$this.UseBasicParsing return $ok } } |