Public/WSL-Alpine-Install.ps1

function WSL-Alpine-Install
{
    Param(
        [switch]$Interactive = $false,
        [Parameter(Mandatory = $true)] [String]$DistroAlias,
        [String]$InstallPath
    )
    try {
        $wsl = Ensure-WSL
    }
    catch {
        Write-ColorOutput red "[ERROR] Elevated access needed to check WSL settings"
        throw "Elevated access required"
    }

    if (-not $wsl) {
        Write-ColorOutput red "[ERROR] WSL not installed"
        throw "WSL not installed"
    }
    
    if (-not($DistroAlias -match '^[^\s\\/]*$')) {
        Write-ColorOutput red "[ERROR] Provided DistroAlias contains whitespace or slash/backslash characters"
        throw "Incorrect DistroAlias"
    }
    
    if (-not($PSBoundParameters.ContainsKey('InstallPath'))) {
        $InstallPath = "$(Get-Location)\install"
        New-Item -ItemType directory -Path $InstallPath -ErrorAction SilentlyContinue | Out-Null
    }
    
    if ($PSBoundParameters.ContainsKey('InstallPath')) {
        if (Test-Path -Path $InstallPath) {
            if ( (Get-Item $InstallPath) -isnot [System.IO.DirectoryInfo]) {
                Write-ColorOutput red "[ERROR] Provided InstallPath is not a directory"
                throw "Incorrect InstallPath"
            }
        }
        if (-not(Test-Path -Path $InstallPath)) {
            Write-ColorOutput red "[ERROR] Provided InstallPath is does not exist"
            throw "Incorrect InstallPath"
        }
    }
    
    # Get all alpine versions
    $ihtml, $versions = Invoke-WebParseable -Uri https://dl-cdn.alpinelinux.org/alpine/
    if ($ihtml) {
        $prop = "IHTMLAnchorElement_pathname"
    }
    if (-not $ihtml) {
        $prop = "pathname"
    }
    
    # Only get links that match path: v[number].[number]/
    $versions = $versions.getElementsByTagName("a") | Where-Object {$_.$prop -match "v\d+\.\d+\/"}
    $parsed_versions = $versions | Select -ExpandProperty $prop | % { New-Object System.Version ($($_ -replace 'v' -replace '/')) } | Sort
    
    if ($Interactive) {
        $selected = Get-Select -Prompt "[OPER] Select which Alpine version you'd like to install:" -Options $parsed_versions
    }
    # Get latest
    if (-not $Interactive) {
        $selected = $parsed_versions.item($($parsed_versions.Count - 1))
    }
    
    $selected = $versions | Where-Object -Property $prop -Like -Value "*$($selected.toString())*"
    
    # Grab available modifications of alpine image (minimal/net etc.) - Sometimes results return null, so do until everything is available
    $selver = $selected | Select-Object -ExpandProperty $prop
    Do {
        $ihtml, $modifications = Invoke-WebParseable -Uri https://dl-cdn.alpinelinux.org/alpine/$($selver)releases/x86_64/
        $modifications = $modifications.getElementsByTagName("a") | Where-Object {$_.$prop -like "*.tar.gz"}  | Sort-Object -Property $prop
        $verif = $modifications |  Where-Object { $_.$prop -eq $null }
    }
    Until ($verif.Count -eq 0)
    if ($verif -eq $null -And $modifications.Count -eq 0) {
        Write-ColorOutput red "[ERROR] No supported images found for selected version (.tar.gz files)"
        return $false
    }
    
    # Only interested in .tar.gz images (maybe iso support next (?))
    
    $parsed_modifications = $modifications | Select -ExpandProperty $prop | % { $_ | Select-String -Pattern '(?:[^-]*-){3}' } | Select-String -Pattern '.*miniroot.*' | % { $_.Matches } | % { $_.Value  -replace '.$' } | Sort
    
    if ($Interactive) {
        $selected = Get-Select -Prompt "[OPER] Select which modification:" -Options $parsed_modifications
    }
    # Get latest minirootfs
    if (-not $Interactive) {
        $candidates = $parsed_modifications | Select-String -Pattern '.*miniroot.*'
        $found = $candidates | % { $_ -match '\d+\.\d+\.\d+_*\w*$' } | % {$matches[0]} | Sort -Unique
        $selected = $found.item($($found.Count - 1))
        $selected = $candidates | Select-String -Pattern "$selected"
    }
    
    $selected = $modifications | Where-Object -Property $prop -Like -Value "$selected*"
        
    #Download image
    $selmod = $selected | Select-Object -ExpandProperty $prop
    
    New-Item -ItemType directory -Path "$(Get-Location)\tmp" -ErrorAction SilentlyContinue | Out-Null
    $ProgressPreference = 'SilentlyContinue'
    Invoke-WebRequest -Uri https://dl-cdn.alpinelinux.org/alpine/$($selver)releases/x86_64/$selmod -OutFile "$(Get-Location)\tmp\$($DistroAlias).tar.gz"
    
    wsl --import $DistroAlias $InstallPath "$(Get-Location)\tmp\$($DistroAlias).tar.gz"
    Remove-Item -Path "$(Get-Location)\tmp" -Recurse | Out-Null
    
    wsl -d $DistroAlias -u root -e sh -c 'apk update && apk upgrade'
    
    return $true
}