PSTerraformEnv.psm1

# I am making an attempt to support macOS and Windows but I don't have any
# systems with those operating systems to test on. Let me know how it goes.
if ($IsLinux) {
  $Platform = "linux"
} elseif ($IsMacOS) {
  $Platform = "darwin"
} elseif ($IsWindows) {
  $Platform = "windows"
} else {
  throw "OS not supported"
}

if ([string]::IsNullOrEmpty($env:TFENV_ROOT)) { $env:TFENV_ROOT = "$HOME/.config/tfenv" }
if ([string]::IsNullOrEmpty($env:TFENV_REMOTE)) { $env:TFENV_REMOTE = "https://releases.hashicorp.com" }

$VersionsPath = "$env:TFENV_ROOT/versions"

Test-Path $VersionsPath || 
  throw 'No versions of terraform installed. Install one with: Install-TerraformVersion'

Switch -exact ([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture)
{
    "X64"   { $Arch = "amd64" }
    "X86"   { $Arch = "386"   }
    "ARM"   { $Arch = "arm"   }
    "ARM64" { $Arch = "arm64" }
}

Function Get-InstalledTerraformVersion() {
  [CmdletBinding()]
  Param(
    [Parameter(Position=0)]
    $Version = "",
    $Path = "$VersionsPath"
  )
  $LocalVersions = (Get-ChildItem -Path $Path terraform-*).Name
  [regex]::Matches($LocalVersions, "\d+\.\d+\.\d+(-(rc|beta|alpha|oci)\d*)?").Value | 
    Sort-Object -Unique -Stable | where { $_ -match $Version }
}
Set-Alias gitfv Get-InstalledTerraformVersion


Function Remove-TerraformVersion() {
  [CmdletBinding()]
  Param(
    [Parameter(Position=0,mandatory=$true)]
    $Version
  )
  if ([string]::IsNullOrEmpty($Version)) {
    throw "You must specify a version number to remove. 'Remove-TerraformVersion 1.0.1'"
  }
  Get-ChildItem "$VersionsPath/terraform-${Version}" `
    | Sort-Object -Bottom 1 -Descending `
    | Remove-Item -Verbose -Confirm
}
Set-Alias rtfv Remove-TerraformVersion

Function Install-TerraformVersion() {
  [CmdletBinding()]
  Param(
    [Parameter(Position=0)]
    $Version = ([string]::IsNullOrEmpty($env:TF_VERSION)) ? $(Get-Content "$PWD/.terraform-version") : $env:TF_VERSION,
    $DownloadPath = "/tmp",
    $InstallPath = "$env:TFENV_ROOT/versions"
  )

  $ArchiveFileName = "terraform_${Version}_${Platform}_${Arch}.zip"
  $DownloadFile = "$DownloadPath/$ArchiveFileName"
  $TempFile = "$DownloadPath/terraform"

  $VersionUri = "${env:TFENV_REMOTE}/terraform/${Version}"

  $Uri = "${VersionUri}/$ArchiveFileName"
  Invoke-WebRequest -Uri "$Uri" -OutFile "$DownloadFile"
  Expand-Archive -Force -Path "$DownloadFile" -DestinationPath $DownloadPath
  Move-Item -Force -Path "$TempFile" -Destination "$InstallPath/terraform-${Version}" && Remove-Item "$DownloadFile"
  if (-not $IsWindows) {
    (Test-Path "$InstallPath/terraform-${Version}" | Out-Null) && chmod 700 "$InstallPath/terraform-${Version}"
  }
}
Set-Alias itfv Install-TerraformVersion

Function Switch-TerraformVersion() {
  [CmdletBinding()]
  Param(
    [Parameter(Position=0)]
    $Version = ([string]::IsNullOrEmpty($env:TF_VERSION)) ? $(Get-Content "$PWD/.terraform-version") : $env:TF_VERSION
  )
  if ([string]::IsNullOrEmpty($Version)) { throw "No version specified. Either ""'1.0.1' > .terraform-version && Switch-TerraformVersion"" or ""Switch-TerraformVersion 1.0.1""" }
  Write-Host "Swtiching to Terraform v${Version}"
  New-Item -Force -ItemType SymbolicLink -Path "$VersionsPath" -name terraform -value terraform-$Version -Confirm
}
Set-Alias swtfv Switch-TerraformVersion

Function Find-TerraformVersion() {
  [CmdletBinding()]
  Param(
    [Parameter(Position=0)]
    $Version = ""
  )
  $RemoteVersions = Invoke-RestMethod "${env:TFENV_REMOTE}/terraform/"
  [regex]::Matches($RemoteVersions, "\d+\.\d+\.\d+(-(rc|beta|alpha|oci)\d*)?").Value | Sort-Object -Unique -Stable  | where { $_ -match $Version }
}
Set-Alias fdtfv Find-TerraformVersion

# to interact with terraform, lets set a couple aliases so nothing needs to be added to the PATH
Set-Alias tf "$VersionsPath/terraform"
Set-Alias terraform "$VersionsPath/terraform"