Created
October 27, 2018 19:17
-
-
Save Geogboe/8969f7577f5c558014e222933d563950 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Installs a given terraform plugin/provider from github | |
.EXAMPLE | |
PS C:\> ./Install-TerraformPlugin -GitHubPath Mastercard/terraform-provider-restapi | |
Install-TerraformPlugin will search github the repo: Mastercard/terraform-provider-restapi | |
foo and check if the latest version has been added to the local terraform | |
plugins dir. If not, it will downlaod and install it. | |
.NOTES | |
- Only supports Windows at the moment. | |
- Only tested on Windows 10 1809 so far. | |
- License: MIT | |
- Copywrite 2018-Present - George Bowen | |
#> | |
[CmdletBinding( PositionalBinding )] | |
param ( | |
# name of the plugin in as a github path such as Mastercard/terraform-provider-restapi | |
# also excepts and array for plugins | |
[Parameter( Mandatory )] | |
[ValidatePattern( "^\w+\/\.?" )] | |
[string[]] | |
$GitHubPath, | |
# Directory where terraform will store plugins | |
[Parameter()] | |
[ValidateScript( { Test-Path $_ })] | |
[string] | |
$PluginDir = "$env:APPDATA/terraform.d/plugins/windows_amd64", | |
# The extenion that the plugin will have. .exe for Windows | |
[Parameter( DontShow )] | |
[string] | |
$PluginExt = ".exe" | |
) | |
begin { | |
Set-StrictMode -Version 2.0 | |
$ErrorActionPreference = "Stop" | |
DATA LogMessages { | |
ConvertFrom-StringData @' | |
#culture="en-US" | |
FailedCreatePluginDir = Failed to verify or create plugin dir at path: {0} | |
ResolvingPath = Resolving plugin path for: {0}... | |
EnsureDirExists = Ensuring plugin directory exists at path: {0}... | |
DownloadingPlugin = Downloading plugin from source: {0} to dest: {1}... | |
'@ | |
} | |
# Create the plugin dir if missing | |
function Assert-PluginDirExists ( $PluginDir ) { | |
try { | |
New-Directory $PluginDir | |
} | |
catch { | |
Write-Warning ( $LogMessages.FailedCreatePluginDir -f $PluginDir ) | |
throw $_ | |
} | |
} | |
# Create a dir if missing | |
function New-Directory ( $Path ) { | |
if ( Test-DirectoryExists $Path ) { | |
return $null | |
} | |
New-Item $Path -ItemType Directory -Force | | |
Out-Null | |
} | |
# Test if a given directory exiss | |
function Test-DirectoryExists ( $Path ) { | |
Test-Path $Path | |
} | |
# Gets the path that a web request is attempting to be redirected too | |
function Get-RedirectedUrl ( $Url ) { | |
$WebReqArgs = @{ | |
Method = "HEAD" | |
UseBasicParsing = $true | |
Uri = $Url | |
MaximumRedirection = 0 | |
Verbose = $false | |
ErrorAction = "Stop" # Will throw an error if attempted to be redirected | |
OutVariable = "Response" | |
} | |
try { | |
Invoke-WebRequest @WebReqArgs | Out-Null | |
} | |
catch { | |
if ( $Response.StatusCode -eq 302 ) { | |
# return the location that the redirect was attempted | |
return $Response.Headers.location | |
} | |
else { | |
throw $_ | |
} | |
} | |
} | |
# resolves a plugin path into the github maintainer, repo name, | |
# url to latest, binaries | |
function Resolve-PluginPath ( $PluginPath ) { | |
$Plugin = [PSCustomObject]@{ | |
Maintainer = $null | |
ProjName = $null | |
Binaries = @() | |
} | |
$Plugin.Maintainer, $Plugin.ProjName = $PluginPath -split "\/" | |
$Plugin.Binaries = Get-PluginBinaries $Plugin.Maintainer $Plugin.ProjName | |
return $Plugin | |
} | |
# Get the download URL for terraform plugin from github release page | |
function Get-PluginBinaries ( $Maintainer, $ProjectName ) { | |
$GithubUrl = "https://github.com" | |
$SearchUrl = ( | |
$GithubUrl + "/" + | |
$Maintainer + "/" + | |
$ProjectName + "/releases/latest" | |
) | |
$LatestReleasesUrl = Get-RedirectedUrl $SearchUrl | |
$Bins = Get-GithubReleaseBins $LatestReleasesUrl | Where-Object { | |
$_ -match $Maintainer -AND | |
$_ -match $ProjectName -AND | |
$_ -match "\/releases\/download\/.*.\/terraform-provider-.*.-windows-amd64" | |
} | |
# prefix gituhub domain to urls | |
$Bins | ForEach-Object { | |
$GithubUrl + $_ | |
} | |
} | |
# return a list of binaries from a github releases page | |
function Get-GithubReleaseBins ( $Url ) { | |
$WebReqArgs = @{ | |
Method = "GET" | |
Uri = $Url | |
Verbose = $false | |
TimeoutSec = 5 | |
UseBasicParsing = $true | |
} | |
$Response = Invoke-WebRequest @WebReqArgs | |
# Using the css class fine all links that contain bins | |
$Releases = $Response.Links | Where-Object { | |
( $_ | Get-Member -Name class ) -AND | |
$_.class -match "d-flex flex-items-center" | |
} | |
$Releases.href | |
} | |
function Invoke-PluginDownload ( $Url, $Dest ) { | |
if ( -not ( Test-Path $Dest )) { | |
# Invoke web request is slow, using webclient class | |
[System.Net.WebClient]::new().DownloadFile( $Url, $Dest) | |
} | |
} | |
} | |
process { | |
Write-Verbose ( $LogMessages.EnsureDirExists -f $PluginDir ) | |
Assert-PluginDirExists $PluginDir | |
foreach ( $Plugin in $GitHubPath ) { | |
Write-Host ( $LogMessages.ResolvingPath -f $Plugin ) | |
$Plugin = Resolve-PluginPath $Plugin | |
foreach ( $Bin in $Plugin.Binaries ) { | |
$BinName = Split-Path $Bin -Leaf | |
$BinName = $BinName -replace '-windows-amd64' | |
$BinName = $BinName + $PluginExt | |
$DestinationPath = Join-Path $PluginDir $BinName | |
Write-Host ( $LogMessages.DownloadingPlugin -f $Bin, $DestinationPath) | |
Invoke-PluginDownload $Bin $DestinationPath | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment