Skip to content

Commit

Permalink
enhancement: add terraform installer (#92)
Browse files Browse the repository at this point in the history
# Pull Request

## Issue

Not applicable.

## Description

This is an enhancement to ensure the dependency on a recent version of
Terraform is handled. This PR checks for and installs the latest version
into a local path if needed. The install script supports multiple os and
architecture.

## License

By submitting this pull request, I confirm that my contribution is made
under the terms of the projects associated license.
  • Loading branch information
jaredfholgate authored Dec 11, 2023
1 parent 299566c commit c5bd475
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 63 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The goal of this project it is to make easy to get started with Azure Landing Zo

### Prerequisites

In order to use this module you will need PowerShell 7.1 or higher.
In order to use this module you will need PowerShell 7.1 or higher.
Download and install the latest version from the official PowerShell GitHub releases page: [PowerShell Releases](https://github.com/PowerShell/PowerShell/releases)

To make PowerShell 7 your default instead of version 5, consider setting an alias.
Expand Down Expand Up @@ -81,9 +81,9 @@ Test-ALZRequirement -IaC "terraform"
This currently tests for:

* Supported minimum PowerShell version (7.1)
* Git
* Azure CLI
* Terraform CLI

> NOTE: Terraform CLI is downloaded as part of the module if you don't already have the latest version.
#### Azure Landing Zone Environment with Bicep and GitHub Actions Workflows

Expand Down
46 changes: 5 additions & 41 deletions src/ALZ/Private/Get-HCLParserTool.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,11 @@ function Get-HCLParserTool {
)

if ($PSCmdlet.ShouldProcess("Download Terraform Tools", "modify")) {
$os = ""
if ($IsWindows) {
$os = "windows"
}
if($IsLinux) {
$os = "linux"
}
if($IsMacOS) {
$os = "darwin"
}

# Enum values can be seen here: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=net-7.0#fields
$architecture = ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture).ToString().ToLower()

if($architecture -eq "x64") {
$architecture = "amd64"
}
if($architecture -eq "x86") {
$architecture = "386"
}

$osAndArchitecture = "$($os)_$($architecture)"

$supportedOsAndArchitectures = @(
"darwin_amd64",
"darwin_arm64",
"linux_386",
"linux_amd64",
"linux_arm64",
"windows_386",
"windows_amd64"
)

if($supportedOsAndArchitectures -notcontains $osAndArchitecture) {
Write-Error "Unsupported OS and architecture combination: $osAndArchitecture"
exit 1
}
$osArchitecture = Get-OSArchitecture

$toolFileName = "hcl2json_$osAndArchitecture"
$toolFileName = "hcl2json_$($osArchitecture.osAndArchitecture)"

if($os -eq "windows") {
if($osArchitecture.os -eq "windows") {
$toolFileName = "$($toolFileName).exe"
}

Expand All @@ -59,7 +23,7 @@ function Get-HCLParserTool {
Invoke-WebRequest -Uri "https://github.com/tmccombs/hcl2json/releases/download/$($toolVersion)/$($toolFileName)" -OutFile "$toolFilePath" | Out-String | Write-Verbose
}

if($os -ne "windows") {
if($osArchitecture.os -ne "windows") {
$isExecutable = $(test -x $toolFilePath; 0 -eq $LASTEXITCODE)
if(!($isExecutable)) {
chmod +x $toolFilePath
Expand All @@ -68,4 +32,4 @@ function Get-HCLParserTool {
}

return $toolFilePath
}
}
45 changes: 45 additions & 0 deletions src/ALZ/Private/Get-OsArchitecture.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function Get-OSArchitecture {
$os = ""
if ($IsWindows) {
$os = "windows"
}
if($IsLinux) {
$os = "linux"
}
if($IsMacOS) {
$os = "darwin"
}

# Enum values can be seen here: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=net-7.0#fields
$architecture = ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture).ToString().ToLower()

if($architecture -eq "x64") {
$architecture = "amd64"
}
if($architecture -eq "x86") {
$architecture = "386"
}

$osAndArchitecture = "$($os)_$($architecture)"

$supportedOsAndArchitectures = @(
"darwin_amd64",
"darwin_arm64",
"linux_386",
"linux_amd64",
"linux_arm64",
"windows_386",
"windows_amd64"
)

if($supportedOsAndArchitectures -notcontains $osAndArchitecture) {
Write-Error "Unsupported OS and architecture combination: $osAndArchitecture"
exit 1
}

return @{
os = $os
architecture = $architecture
osAndArchitecture = $osAndArchitecture
}
}
73 changes: 73 additions & 0 deletions src/ALZ/Private/Get-TerraformTool.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
function Get-TerraformTool {
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[Parameter(Mandatory = $false)]
[string]$version = "latest",
[Parameter(Mandatory = $false)]
[string]$toolsPath = ".\terraform"
)

if($version -eq "latest") {
$version = (Invoke-WebRequest -Uri "https://checkpoint-api.hashicorp.com/v1/check/terraform").Content | ConvertFrom-Json | Select-Object -ExpandProperty current_version
}

$commandDetails = Get-Command -Name terraform -ErrorAction SilentlyContinue
if($commandDetails) {
Write-InformationColored "Terraform already installed in $($commandDetails.Path), checking version" -ForegroundColor Green -InformationAction Continue
$installedVersion = terraform version -json | ConvertFrom-Json
Write-InformationColored "Installed version of Terraform: $($installedVersion.terraform_version) on $($installedVersion.platform)" -ForegroundColor Green -InformationAction Continue
if($installedVersion.terraform_version -eq $version) {
Write-InformationColored "Installed version of Terraform matches required version $version, skipping install" -ForegroundColor Green -InformationAction Continue
return
}
}

$unzipdir = Join-Path -Path $toolsPath -ChildPath "terraform_$version"
if (Test-Path $unzipdir) {
Write-InformationColored "Terraform $version already installed, adding to Path." -ForegroundColor Green -InformationAction Continue
if($os -eq "windows") {
$env:PATH = "$($unzipdir);$env:PATH"
} else {
$env:PATH = "$($unzipdir):$env:PATH"
}
return
}

$osArchitecture = Get-OSArchitecture

$zipfilePath = "$unzipdir.zip"

$url = "https://releases.hashicorp.com/terraform/$($version)/terraform_$($version)_$($osArchitecture.osAndArchitecture).zip"

if(!(Test-Path $toolsPath)) {
New-Item -ItemType Directory -Path $toolsPath| Out-String | Write-Verbose
}

Invoke-WebRequest -Uri $url -OutFile "$zipfilePath" | Out-String | Write-Verbose

Expand-Archive -Path $zipfilePath -DestinationPath $unzipdir

$toolFileName = "terraform"

if($osArchitecture.os -eq "windows") {
$toolFileName = "$($toolFileName).exe"
}

$toolFilePath = Join-Path -Path $unzipdir -ChildPath $toolFileName

if($osArchitecture.os -ne "windows") {
$isExecutable = $(test -x $toolFilePath; 0 -eq $LASTEXITCODE)
if(!($isExecutable)) {
chmod +x $toolFilePath
}
}

if($osArchitecture.os -eq "windows") {
$env:PATH = "$($unzipdir);$env:PATH"
} else {
$env:PATH = "$($unzipdir):$env:PATH"
}

Remove-Item $zipfilePath
Write-InformationColored "Installed Terraform version $version" -ForegroundColor Green -InformationAction Continue
}
3 changes: 3 additions & 0 deletions src/ALZ/Private/New-ALZEnvironmentTerraform.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ function New-ALZEnvironmentTerraform {
)

if ($PSCmdlet.ShouldProcess("ALZ-Terraform module configuration", "modify")) {
Write-InformationColored "Checking you have the latest version of Terraform installed..." -ForegroundColor Green -InformationAction Continue
$toolsPath = Join-Path -Path $alzEnvironmentDestination -ChildPath ".tools"
Get-TerraformTool -version "latest" -toolsPath $toolsPath

Write-InformationColored "Downloading alz-terraform-accelerator Terraform module to $alzEnvironmentDestination" -ForegroundColor Green -InformationAction Continue

Expand Down
28 changes: 9 additions & 19 deletions src/ALZ/Public/Test-ALZRequirement.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,7 @@ function Test-ALZRequirement {
Write-Verbose "PowerShell version $psMajorVersion.$psMinorVersion is supported."
}

# Check if Git is installed
$gitPath = Get-Command git -ErrorAction SilentlyContinue
if ($gitPath) {
Write-Verbose "Git is installed."
} else {
Write-Error "Git is not installed. Please install Git."
$result = $false
}



if ($alzIacProvider -eq "terraform") {
# Check if Terraform is installed
$terraformPath = Get-Command terraform -ErrorAction SilentlyContinue
if ($terraformPath) {
Write-Verbose "Terraform is installed."
} else {
Write-Error "Terraform is not installed. Please install Terraform."
$result = $false
}
# Check if Azure CLI is installed
$azCliPath = Get-Command az -ErrorAction SilentlyContinue
if ($azCliPath) {
Expand All @@ -70,6 +51,15 @@ function Test-ALZRequirement {
}

if ($alzIacProvider -eq "bicep") {
# Check if Git is installed
$gitPath = Get-Command git -ErrorAction SilentlyContinue
if ($gitPath) {
Write-Verbose "Git is installed."
} else {
Write-Error "Git is not installed. Please install Git."
$result = $false
}

# Check if VS Code is installed
$vsCodePath = Get-Command code -ErrorAction SilentlyContinue
if ($vsCodePath) {
Expand Down
2 changes: 2 additions & 0 deletions src/Tests/Unit/Public/New-ALZEnvironment.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ InModuleScope 'ALZ' {

Mock -CommandName Get-HCLParserTool -MockWith { "test" }

Mock -CommandName Get-TerraformTool -MockWith { }

Mock -CommandName Convert-HCLVariablesToUserInputConfig -MockWith {
@(
@{
Expand Down

0 comments on commit c5bd475

Please sign in to comment.