6

I cannot seem to retrieve the public ip address output of Terraform for next step in build pipeline in AzureDevops.

Terraform state pull works and outputs to json file, cannot grep on output.

Terraform state show [options] ADDRESS does not support azure backend so cannot use or grep or filter the output

also tried to store as file and read in the value.

resource "local_file" "foo" {
    content     = "foo!"
    filename = "${path.module}/foo.bar"
}

data "azurerm_public_ip" "buildserver-pip" {
  name                = "${azurerm_public_ip.buildserver-pip.name}"
  resource_group_name = "${azurerm_virtual_machine.buildserver.resource_group_name}"
}

output "public_ip_address" {
  value = "${data.azurerm_public_ip.buildserver-pip.ip_address}"
}

expect the public ip address to be passed out so can be used in ansible playbooks, bash or python script in next step

JleruOHeP
  • 10,106
  • 3
  • 45
  • 71
DeclanG
  • 240
  • 2
  • 6
  • 21
  • wondering if this may assist https://www.terraform.io/docs/providers/terraform/d/remote_state.html – DeclanG Aug 12 '19 at 15:13
  • Not clear what you want to do, if you want to get the info from a remote state? Or just want to output the public IP? – Charles Xu Aug 13 '19 at 06:17
  • looking to get the Public IP address from either the output or the remote state. azure devops is not exporting the value for me – DeclanG Aug 13 '19 at 10:23

5 Answers5

6

Building on @JleruOHeP answer above the following solution will automatically create a variable for every output provided by the terraform script

  1. Create a PowerShell step in your release and insert the following inline PowerShell:
$json = Get-Content $env:jsonPath | Out-String | ConvertFrom-Json

foreach($prop in $json.psobject.properties) {
    Write-Host("##vso[task.setvariable variable=$($prop.Name);]$($prop.Value.value)")
}
  1. Make sure you have provided the environment variable jsonPath like this:

supply environment variable

parsonss
  • 76
  • 1
  • 2
  • Please refer to the answer by @jleruohep below as it outlines the face that we need to include the reference name too. – Arash May 27 '21 at 23:28
5

For your purpose, I will suggest you store the terraform in Azure storage account. Then you can use the remote state in another terraform file. Here is an example:

Create public IP and store the state in Azure Storage account blob:

terraform {
    backend "azurerm" {
        storage_account_name = "yourAccountName"
        container_name       = "yourContainerName"
        key                  = "terraform.tfstate"
    }
}

resource "azurerm_public_ip" "main" {
    name            = "terraform_backend_pip"
    location        = "East US"
    resource_group_name = "yourResourceGroup"
    allocation_method = "Static"
}

# this is important, you can get the remote outputs for this
output "public_address" {
    value = "${azurerm_public_ip.main.ip_address}"
}

Quote the remote state in another Terraform file:

data "terraform_remote_state" "azure" {
        backend = "azurerm"
        config = {
                storage_account_name = "charlescloudshell"
                container_name       = "terraform"
                key                  = "terraform.tfstate"
        }
}

# the remote state outputs contain all the output that you set in the above file
output "remote_backend" {
        value = "${data.terraform_remote_state.azure.outputs.public_address}"
}

The result below:

enter image description here

You can follow the steps about How to store state in Azure Storage here.

Hope it helps. And if you have any more questions, please let me know. If it works for you, please accept it as the answer.

Charles Xu
  • 29,862
  • 2
  • 22
  • 39
  • Charles this is what I have already and is correct, the issue is the value is never passed or retrieved within the azure devops agent , the next step is terraform output and nothing is returned, believe this may be an issue with azure devops and terraform plugin – DeclanG Aug 15 '19 at 09:58
  • @DeclanG It shows that the remote state just gives in its outputs if you set the output when you create the resource. Even if the output cannot display in the DevOps. – Charles Xu Aug 16 '19 at 00:40
5

If I understand your question correctly, you wanted to provision something (public ip) with terraform and then have this available for further steps via a variable. All of it in a single Azure DevOps pipeline.

It can be done with a simple output and powershell script (can be inline!):

1) I assume you already use terraform task for the pipeline (https://github.com/microsoft/azure-pipelines-extensions/tree/master/Extensions/Terraform/Src/Tasks/TerraformTaskV1)

2) Another assumption that you have an output variable (from your example - you do)

3) You canspecify the output variable from this task:

enter image description here

4) And finally add a powershell step as the next step with the simplest script and set up its environment variable to be the $(TerraformOutput.jsonOutputVariablesPath)

$json = Get-Content $env:jsonPath | Out-String | ConvertFrom-Json

Write-Host "##vso[task.setvariable variable=MyNewIp]$($json.public_ip_address.value)"

5) ....

6) PROFIT! You have the IP address available as a pipeline variable MyNewIp now!

JleruOHeP
  • 10,106
  • 3
  • 45
  • 71
2

terraform output variable

1.As shown in above images you will get variables list only if you add "Terraform by Microsoft DevLabs" as task. Other terraform providers don't support output variables. Terraform by Microsoft DevLabs

2.There is another way to convert terraform output variable to pipeline variable(In this you need to add Terraform CLI as task Terraform CLI by Charles Zipp)

Step1:Terraform code to output storage account access key

Step2:Add terraform output as task after terraform apply

  • terraform output variable will be prefixed with TF_OUT to convert it to pipeline variable
  • access pipeline variable by referencing as $(TF_OUT_variable_name)
  • Configuration directory of terraform output must be same as terraform apply

Step3:Powershell script to access pipeline variable

Reference: Terraform Output to Pipeline Variables https://marketplace.visualstudio.com/items?itemName=charleszipp.azure-pipelines-tasks-terraform

0

Contrary to what is shown in all the answers, I was not able to retrieve the value from $(TerraformOutput.jsonOutputVariablesPath).

I believe that is because I am not using the predefined terraform task, and I am rather using terraform directly from the pipeline. I was able to dynamically seed the terraform outputs to the pipeline with the following script:

PROJECT_PATH="$1"

# Retrieve the list of Terraform output variables
OUTPUT_VARIABLES=$(terraform -chdir="$PROJECT_PATH" output -json | jq -r 'keys[]')

# Iterate over each output variable and create pipeline variables
for VARIABLE in $OUTPUT_VARIABLES; do
  # Check if the output variable is sensitive
  IS_SENSITIVE=$(terraform -chdir="$PROJECT_PATH" output -json | jq -r ".$VARIABLE.sensitive")

  if [ "$IS_SENSITIVE" == "true" ]; then
    echo "##vso[task.setvariable variable=$VARIABLE;isOutput=true;issecret=true]$(terraform -chdir="$PROJECT_PATH" output -raw $VARIABLE)"
  else
    echo "##vso[task.setvariable variable=$VARIABLE;isOutput=true]$(terraform -chdir="$PROJECT_PATH" output -raw $VARIABLE)"
  fi
done
ccoutinho
  • 3,308
  • 5
  • 39
  • 47