Skip to content

Commit c5bd475

Browse files
enhancement: add terraform installer (#92)
# 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.
1 parent 299566c commit c5bd475

File tree

7 files changed

+140
-63
lines changed

7 files changed

+140
-63
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The goal of this project it is to make easy to get started with Azure Landing Zo
2020

2121
### Prerequisites
2222

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

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

8383
* Supported minimum PowerShell version (7.1)
84-
* Git
8584
* Azure CLI
86-
* Terraform CLI
85+
86+
> NOTE: Terraform CLI is downloaded as part of the module if you don't already have the latest version.
8787
8888
#### Azure Landing Zone Environment with Bicep and GitHub Actions Workflows
8989

src/ALZ/Private/Get-HCLParserTool.ps1

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,11 @@ function Get-HCLParserTool {
99
)
1010

1111
if ($PSCmdlet.ShouldProcess("Download Terraform Tools", "modify")) {
12-
$os = ""
13-
if ($IsWindows) {
14-
$os = "windows"
15-
}
16-
if($IsLinux) {
17-
$os = "linux"
18-
}
19-
if($IsMacOS) {
20-
$os = "darwin"
21-
}
22-
23-
# Enum values can be seen here: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=net-7.0#fields
24-
$architecture = ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture).ToString().ToLower()
25-
26-
if($architecture -eq "x64") {
27-
$architecture = "amd64"
28-
}
29-
if($architecture -eq "x86") {
30-
$architecture = "386"
31-
}
32-
33-
$osAndArchitecture = "$($os)_$($architecture)"
34-
35-
$supportedOsAndArchitectures = @(
36-
"darwin_amd64",
37-
"darwin_arm64",
38-
"linux_386",
39-
"linux_amd64",
40-
"linux_arm64",
41-
"windows_386",
42-
"windows_amd64"
43-
)
44-
45-
if($supportedOsAndArchitectures -notcontains $osAndArchitecture) {
46-
Write-Error "Unsupported OS and architecture combination: $osAndArchitecture"
47-
exit 1
48-
}
12+
$osArchitecture = Get-OSArchitecture
4913

50-
$toolFileName = "hcl2json_$osAndArchitecture"
14+
$toolFileName = "hcl2json_$($osArchitecture.osAndArchitecture)"
5115

52-
if($os -eq "windows") {
16+
if($osArchitecture.os -eq "windows") {
5317
$toolFileName = "$($toolFileName).exe"
5418
}
5519

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

62-
if($os -ne "windows") {
26+
if($osArchitecture.os -ne "windows") {
6327
$isExecutable = $(test -x $toolFilePath; 0 -eq $LASTEXITCODE)
6428
if(!($isExecutable)) {
6529
chmod +x $toolFilePath
@@ -68,4 +32,4 @@ function Get-HCLParserTool {
6832
}
6933

7034
return $toolFilePath
71-
}
35+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
function Get-OSArchitecture {
2+
$os = ""
3+
if ($IsWindows) {
4+
$os = "windows"
5+
}
6+
if($IsLinux) {
7+
$os = "linux"
8+
}
9+
if($IsMacOS) {
10+
$os = "darwin"
11+
}
12+
13+
# Enum values can be seen here: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.architecture?view=net-7.0#fields
14+
$architecture = ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture).ToString().ToLower()
15+
16+
if($architecture -eq "x64") {
17+
$architecture = "amd64"
18+
}
19+
if($architecture -eq "x86") {
20+
$architecture = "386"
21+
}
22+
23+
$osAndArchitecture = "$($os)_$($architecture)"
24+
25+
$supportedOsAndArchitectures = @(
26+
"darwin_amd64",
27+
"darwin_arm64",
28+
"linux_386",
29+
"linux_amd64",
30+
"linux_arm64",
31+
"windows_386",
32+
"windows_amd64"
33+
)
34+
35+
if($supportedOsAndArchitectures -notcontains $osAndArchitecture) {
36+
Write-Error "Unsupported OS and architecture combination: $osAndArchitecture"
37+
exit 1
38+
}
39+
40+
return @{
41+
os = $os
42+
architecture = $architecture
43+
osAndArchitecture = $osAndArchitecture
44+
}
45+
}

src/ALZ/Private/Get-TerraformTool.ps1

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
function Get-TerraformTool {
2+
[CmdletBinding(SupportsShouldProcess = $true)]
3+
param(
4+
[Parameter(Mandatory = $false)]
5+
[string]$version = "latest",
6+
[Parameter(Mandatory = $false)]
7+
[string]$toolsPath = ".\terraform"
8+
)
9+
10+
if($version -eq "latest") {
11+
$version = (Invoke-WebRequest -Uri "https://checkpoint-api.hashicorp.com/v1/check/terraform").Content | ConvertFrom-Json | Select-Object -ExpandProperty current_version
12+
}
13+
14+
$commandDetails = Get-Command -Name terraform -ErrorAction SilentlyContinue
15+
if($commandDetails) {
16+
Write-InformationColored "Terraform already installed in $($commandDetails.Path), checking version" -ForegroundColor Green -InformationAction Continue
17+
$installedVersion = terraform version -json | ConvertFrom-Json
18+
Write-InformationColored "Installed version of Terraform: $($installedVersion.terraform_version) on $($installedVersion.platform)" -ForegroundColor Green -InformationAction Continue
19+
if($installedVersion.terraform_version -eq $version) {
20+
Write-InformationColored "Installed version of Terraform matches required version $version, skipping install" -ForegroundColor Green -InformationAction Continue
21+
return
22+
}
23+
}
24+
25+
$unzipdir = Join-Path -Path $toolsPath -ChildPath "terraform_$version"
26+
if (Test-Path $unzipdir) {
27+
Write-InformationColored "Terraform $version already installed, adding to Path." -ForegroundColor Green -InformationAction Continue
28+
if($os -eq "windows") {
29+
$env:PATH = "$($unzipdir);$env:PATH"
30+
} else {
31+
$env:PATH = "$($unzipdir):$env:PATH"
32+
}
33+
return
34+
}
35+
36+
$osArchitecture = Get-OSArchitecture
37+
38+
$zipfilePath = "$unzipdir.zip"
39+
40+
$url = "https://releases.hashicorp.com/terraform/$($version)/terraform_$($version)_$($osArchitecture.osAndArchitecture).zip"
41+
42+
if(!(Test-Path $toolsPath)) {
43+
New-Item -ItemType Directory -Path $toolsPath| Out-String | Write-Verbose
44+
}
45+
46+
Invoke-WebRequest -Uri $url -OutFile "$zipfilePath" | Out-String | Write-Verbose
47+
48+
Expand-Archive -Path $zipfilePath -DestinationPath $unzipdir
49+
50+
$toolFileName = "terraform"
51+
52+
if($osArchitecture.os -eq "windows") {
53+
$toolFileName = "$($toolFileName).exe"
54+
}
55+
56+
$toolFilePath = Join-Path -Path $unzipdir -ChildPath $toolFileName
57+
58+
if($osArchitecture.os -ne "windows") {
59+
$isExecutable = $(test -x $toolFilePath; 0 -eq $LASTEXITCODE)
60+
if(!($isExecutable)) {
61+
chmod +x $toolFilePath
62+
}
63+
}
64+
65+
if($osArchitecture.os -eq "windows") {
66+
$env:PATH = "$($unzipdir);$env:PATH"
67+
} else {
68+
$env:PATH = "$($unzipdir):$env:PATH"
69+
}
70+
71+
Remove-Item $zipfilePath
72+
Write-InformationColored "Installed Terraform version $version" -ForegroundColor Green -InformationAction Continue
73+
}

src/ALZ/Private/New-ALZEnvironmentTerraform.ps1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ function New-ALZEnvironmentTerraform {
2424
)
2525

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

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

src/ALZ/Public/Test-ALZRequirement.ps1

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,7 @@ function Test-ALZRequirement {
3939
Write-Verbose "PowerShell version $psMajorVersion.$psMinorVersion is supported."
4040
}
4141

42-
# Check if Git is installed
43-
$gitPath = Get-Command git -ErrorAction SilentlyContinue
44-
if ($gitPath) {
45-
Write-Verbose "Git is installed."
46-
} else {
47-
Write-Error "Git is not installed. Please install Git."
48-
$result = $false
49-
}
50-
51-
52-
5342
if ($alzIacProvider -eq "terraform") {
54-
# Check if Terraform is installed
55-
$terraformPath = Get-Command terraform -ErrorAction SilentlyContinue
56-
if ($terraformPath) {
57-
Write-Verbose "Terraform is installed."
58-
} else {
59-
Write-Error "Terraform is not installed. Please install Terraform."
60-
$result = $false
61-
}
6243
# Check if Azure CLI is installed
6344
$azCliPath = Get-Command az -ErrorAction SilentlyContinue
6445
if ($azCliPath) {
@@ -70,6 +51,15 @@ function Test-ALZRequirement {
7051
}
7152

7253
if ($alzIacProvider -eq "bicep") {
54+
# Check if Git is installed
55+
$gitPath = Get-Command git -ErrorAction SilentlyContinue
56+
if ($gitPath) {
57+
Write-Verbose "Git is installed."
58+
} else {
59+
Write-Error "Git is not installed. Please install Git."
60+
$result = $false
61+
}
62+
7363
# Check if VS Code is installed
7464
$vsCodePath = Get-Command code -ErrorAction SilentlyContinue
7565
if ($vsCodePath) {

src/Tests/Unit/Public/New-ALZEnvironment.Tests.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ InModuleScope 'ALZ' {
8787

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

90+
Mock -CommandName Get-TerraformTool -MockWith { }
91+
9092
Mock -CommandName Convert-HCLVariablesToUserInputConfig -MockWith {
9193
@(
9294
@{

0 commit comments

Comments
 (0)