Using JSON with Terraform

Summary: When using Terraform with PowerShell (or other scripting languages/applications), it’s helpful to have a single ‘source of record’ for the data or variables that drive the automation.  In this case we’re using modules to store global variables used across multiple Terraform plans. These global variables are consumed and used by Terraform as well as PowerShell. Terraform has the capability of using 2 different file formats for their modules (Hashicorp Configuration Language – HCL, and JSON). Although HCL is more human readable and editable, JSON is easier to consume by languages and applications outside of Hashicorp.

json-terraform

There is scant documentation about proper JSON formatting expected by Terraform as well as standard ways for PowerShell to consume the JSON files. Some formatting and scripting examples will be shown in this post.

\modules\variables\main.tf.json (example):

{
  "output": {
    "server_location": {
      "value": "East US"
    },
    "azurerm_resource_group": {
      "value": "RG-Terraform-East"
    },
    "subscription_id": {
      "value": "some-azure-subscription-id"
    },
    "tenant_id": {
      "value": "some-azure-tenant-id"
    },
    "domain": {
      "value": "dev.somedomain.com"
    },
    "remote_resource_group_name": {
      "value": "tf-environment"
    },
    "remote_container_share": {
      "value": "\\\\somshare.file.core.windows.net\\files"
    },
    "server_ip": {
        "value": "${lookup(var.server_ips,var.var_server_name)}"
    }
  },
  "variable": {
    "var_server_name": {},
    "server_ips": {
      "description": "Map of all server static ip addresses",
      "type": "map",
      "default": {
        "tstsqlsvr01": "10.10.10.101",
        "tstshrpntsvr02": "10.10.10.102",
        "tstisssvr03": "10.10.10.103",
        "tstiissvr04": "10.10.10.104",
        "tstiissvr05": "10.10.10.105"
      }
    }
  }
}

Note: The above example demonstrates the use of standard variables as well as an array using the ‘lookup’ method.

The following Terraform plan snippet, demonstrates referencing the module for its global variables.

Terraform Example:

module "variables" {
  source = "./modules/variables"
  var_server_name = "tstiissvr05"
}

provider "azurerm" {
  subscription_id = "${module.variables.subscription_id}"
  client_id       = "some-client-id"
  client_secret   = "some-client-secret"
  tenant_id       = "${module.variables.tenant_id}"
}

The following PowerShell snippet uses the ConvertFrom-Json cmdlet to read the JSON file as well as processing the resulting PowerShell object to extract the data into either variables or hashes.

PowerShell Example:

# Reads a Terraform JSON module and populates variables/hashes
$terraformVars = Get-Content ".\modules\variables\main.tf.json" | ConvertFrom-Json
$serverIPs = @{}
foreach ($item in $terraformVars.variable.server_ips.default.PsObject.Members | ?{ $_.MemberType -eq 'NoteProperty'}) {
  $serverIPs[$item.Name] = $item.Value
}

Write-Host "Tenant ID: $terraformVars.output.tenant_id.value"

Enjoy!

 

Advertisements