At present, we are going to implement a Terraform bootstrap script that may set up Terraform and create directories the place we will place our Terraform venture, which can then run a plan towards and deploy. This script will likely be written in PowerShell to bootstrap a brand new Terraform venture.
“Bootstrapping normally refers to a self-starting course of that’s speculated to proceed or develop with out exterior enter. Many analytical methods are sometimes known as bootstrap strategies in reference to their self-starting or self-supporting implementation” ~ Wikipedia.
📜 Script Overview
Impressed by the ALZ Accelerator bootstrap script, this script will:
- Set up-Terraform
- Downloads and installs Terraform if not current
- Handles model administration
- Helps Home windows/Mac/Linux detection
- Provides Terraform to PATH
- Creates required directories (config and output)
- Copies *.tf and *.tfvars information from config to output
- Validate file contents and paths
- Invoke-Terraform
- Initializes Terraform
- Creates execution plan
- Handles apply/destroy with non-compulsory auto-approve
- Manages working listing context
And I’ve examined it on my Home windows 11 machine and a Linux Codespace. In my examples, I’m utilizing it to run some base Terraform to deploy a brand new Useful resource Group and Storage Account within the New Zealand North Azure area.
You might additionally have a look at turning it into an executable utilizing one thing like PS2EXE, after which you possibly can run it like some other executable, as beneath:
📋 Stipulations
- PowerShell 5.1 or PowerShell Core 6.0+
- Web connectivity for downloading Terraform
- Azure CLI is put in and logged in (
az login
). It is just required if deploying to Microsoft Azure. - Write permissions to the listing the place you may run the script
🎯 Utilization Examples
Primary utilization with default parameters:
.Terraform-Bootstrap.ps1
Customized paths and auto-approved apply:
.Terraform-Bootstrap.ps1 -terraformPath "C:terraform" -configPath "C:tf-configs" -outputPath "C:tf-output" -autoApprove
Utilizing a particular Terraform model:
.Terraform-Bootstrap.ps1 -terraformPath "C:terraform" -configPath "C:tf-configs" -outputPath "C:tf-output"
💻 PowerShell Script
Terraform-Bootstrap.ps1
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[string]$terraformPath = ".terraform",
[Parameter(Mandatory = $false)]
[string]$terraformVersion = "newest",
[Parameter(Mandatory = $false)]
[string]$configPath = ".config",
[Parameter(Mandatory = $false)]
[string]$outputPath = ".output",
[Parameter(Mandatory = $false)]
[switch]$autoApprove
)
perform Set up-Terraform {
param (
[string]$model,
[string]$path
)
if ($model -eq "newest") ConvertFrom-Json
$tfCommand = Get-Command -Title terraform -ErrorAction SilentlyContinue
if ($tfCommand) {
Write-Verbose "Terraform already put in at $($tfCommand.Path)"
return
}
if (!(Take a look at-Path $path)) Out-Null
$os = if ($IsWindows) { "home windows" } else { if ($IsMacOS) { "darwin" } else { "linux" } }
$arch = if ([System.Environment]::Is64BitOperatingSystem) { "amd64" } else { "386" }
$url = "https://releases.hashicorp.com/terraform/$($model)/terraform_$($model)_${os}_${arch}.zip"
$zipFile = Be a part of-Path $path "terraform.zip"
$extractPath = Be a part of-Path $path "terraform_$model"
Write-Verbose "Downloading Terraform from $url"
Invoke-WebRequest -Uri $url -OutFile $zipFile
Write-Verbose "Extracting Terraform to $extractPath"
Increase-Archive -Path $zipFile -DestinationPath $extractPath -Drive
Take away-Merchandise $zipFile
$env:PATH = "$extractPath;$env:PATH"
}
perform Invoke-Terraform {
param (
[string]$workingDirectory,
[string]$command,
[switch]$autoApprove
)
Push-Location $workingDirectory
strive {
Write-Host "Initializing Terraform..." -ForegroundColor Inexperienced
terraform init
Write-Host "Operating terraform $command..." -ForegroundColor Inexperienced
if ($command -eq "apply" -or $command -eq "destroy") {
terraform plan -out=tfplan
if (!$autoApprove) {
$affirmation = Learn-Host "Do you need to proceed with terraform $command? (y/n)"
if ($affirmation -ne 'y') {
Write-Host "Operation cancelled" -ForegroundColor Yellow
return
}
}
if ($command -eq "apply") {
terraform apply -auto-approve tfplan
}
else {
terraform destroy -auto-approve
}
}
else {
terraform $command
}
}
lastly {
Pop-Location
}
}
strive {
if (!(Take a look at-Path $configPath)) Out-Null
Write-Host "Config listing created at $configPath. Please place Terraform information into this listing and press any key to proceed..." -ForegroundColor Yellow
Learn-Host
if (!(Take a look at-Path $outputPath)) Out-Null
Write-Host "Making certain Terraform is put in..." -ForegroundColor Inexperienced
Set up-Terraform -model $terraformVersion -path $terraformPath
Write-Host "Establishing Terraform workspace..." -ForegroundColor Inexperienced
$configPathFull = Resolve-Path $configPath -ErrorAction Cease
$outputPathFull = Resolve-Path $outputPath -ErrorAction Cease
Write-Verbose "Config Path: $configPathFull"
Write-Verbose "Output Path: $outputPathFull"
$configFiles = Get-ChildItem -Path $configPathFull -Recurse -File -Filter "*.tf" -ErrorAction Cease
$varFiles = Get-ChildItem -Path $configPathFull -Recurse -File -Filter "*.tfvars" -ErrorAction Cease
Write-Verbose "Discovered $($configFiles.Rely) .tf information"
foreach ($file in $configFiles) {
Write-Verbose "Processing file: $($file.FullName)"
if (!(Take a look at-Path $file.FullName)) {
Write-Error "Supply file not discovered: $($file.FullName)"
proceed
}
$content material = Get-Content material $file.FullName -Uncooked
if ([string]::IsNullOrWhiteSpace($content material)) {
Write-Warning "File is empty: $($file.FullName)"
proceed
}
Write-Host "Copying $($file.Title) to $outputPathFull" -ForegroundColor Inexperienced
Copy-Merchandise -Path $file.FullName -Vacation spot $outputPathFull -Drive
$destFile = Be a part of-Path $outputPathFull $file.Title
if (!(Take a look at-Path $destFile)) {
Write-Error "Failed to repeat file to: $destFile"
}
}
foreach ($file in $varFiles) {
Write-Verbose "Processing var file: $($file.FullName)"
Write-Host "Copying $($file.Title) to $outputPathFull" -ForegroundColor Inexperienced
Copy-Merchandise -Path $file.FullName -Vacation spot $outputPathFull -Drive
}
Write-Host "Operating Terraform..." -ForegroundColor Inexperienced
Invoke-Terraform -workingDirectory $outputPath -command "apply" -autoApprove:$autoApprove
}
catch {
Write-Error "Error occurred: $_"
exit 1
}
This script may also be discovered on GitHub right here, in the event you wished to fork, or open up a Pull Request with modifications.
Hopefully that is helpful for you, having a script like this implies I can shortly deploy assets which might be coded in Terraform (HCL).
📂 Instance Terraform Recordsdata
For these , right here is the bottom Terraform code I’m utilizing in my instance:
config/principal.tf
useful resource "azurerm_resource_group" "instance" {
title = "example-stgaccount-rg"
location = "New Zealand North"
}
useful resource "azurerm_storage_account" "instance" {
title = "stgacctfboot1"
resource_group_name = azurerm_resource_group.instance.title
location = azurerm_resource_group.instance.location
account_tier = "Commonplace"
account_replication_type = "LRS"
tags = {
atmosphere = "staging"
}
}
config/suppliers.tf
terraform {
required_providers {
azurerm = {
supply = "hashicorp/azurerm"
model = "4.15.0"
}
}
}
supplier "azurerm" {
subscription_id = "9dc6cc8c-5b10-403b-9a2f-5192497ca1ed"
options {}
}