¯\_(ツ)_/¯

thunder@home:~$

This is my home blog, mostly to share some useful info or code snippets
~ 1 min

Heya, Terraformers!

I wanna share with you one cool function which I wrote to get add/change/destroy values from Terraform output:

@NonCPS
def parseTerraformLog(String contents) {
  HashMap results = [
    type: "none",
    add: 0,
    change: 0,
    delete: 0,
    line: "",
    is_change: false,
  ]

  Pattern regex = Pattern.compile(/.*(Plan|Apply).*:\s(\d+).*,\s(\d+).*,\s(\d+).*/)
  Matcher matcher = regex.matcher(contents)
  if (matcher.find()) {
    results["type"] = matcher.group(1)
    results["add"] = matcher.group(2).toInteger()
    results["change"] = matcher.group(3).toInteger()
    results["destroy"] = matcher.group(4).toInteger()
    results["line"] = matcher.group(0).substring(matcher.group(0).indexOf(":")+1).trim()
    results["is_change"] = (results["add"] + results["change"] + results["destroy"]).asBoolean()
  } else {
    regex = Pattern.compile(/.*(Destroy).*:\s(\d+)\s.*/)
    matcher = regex.matcher(contents)
    if (matcher.find()) {
      results["type"] = matcher.group(1)
      results["destroy"] = matcher.group(2).toInteger()
      results["line"] = matcher.group(0).substring(matcher.group(0).indexOf("!")+1).trim()
      results["is_change"] = (results["add"] + results["change"] + results["destroy"]).asBoolean()
    }
  }
  return results
}

This function returns following keys in HashMap:

  • typeplan, apply or destroy
  • add – number of resources to add, default is 0
  • change – number of changed resources, default is 0
  • destroy – number of destoyed resources, default is 0
  • line – just a string like Destroy complete or Apply complete,
  • is_change – boolean, if there any changes – add/change/destroy, default is false

How to use it.

It’s quite simple. Wrap terraform plan with tee to save log for plan runs and then call this cool function:

tee(file: "tfPlan.log") {
  sh "time terraform plan"
}
tfResults = parseTerraformLog(readFile("tfPlan.log"))

Same for apply and destroy.

tee(file: "tfApply.log") {
  sh "time terraform apply -auto-approve"
}

HashMap tfApplyResults = parseTerraformLog(readFile("tfApply.log"))
if (tfApplyResults["is_change"]) {
  echo "${tfApplyResults["type"]}: ${tfApplyResults["line"]}"
} else {
  if (tfResults["is_change"] != tfApplyResults["is_change"]) {
    "WARN: Nothing found, but Apply should happen since Plan got some changes!"
  } else {
    echo "WARN: Nothing found, probably infrastructure is up-to-date."
  }
}

Want to note about this line:

  if (tfResults["is_change"] != tfApplyResults["is_change"]) {
    "WARN: Nothing found, but Apply should happen since Plan got some changes!"
  }

This is comparison of changes from terraform plan run and terraform apply results. Just as an example of use.

At the end, you can put some details onto summary page:

if (tfResults["line"]) {
  manager.createSummary("document.png").appendText("<h1>${tfResults["type"]} results</h1><br/>${tfResults["line"]}", false, false, false, "red")
}

That’s it.

P.S.

Don’t forget to import java.util.regex library to make it work:

import java.util.regex.Pattern
import java.util.regex.Matcher
Thank You For Reading