Is it possible to get the how far down the tree a change made by Terraform will be?

Hi. One of the issues I’ve needed to react to for our pipeline and reviewers is how the changes proposed by a Terraform plan are displayed. It is a LOT of information sometimes, and, for a while, not enough information to identify what is resource is being amended (due to the diff not always including the identifier of a resource).

To help the reviewer get a cleaner understanding of the proposed plan, I’ve produced a summary report using jq.

function plan_summary {
  underline "Plan Summary" =

  export LOG_PATH=test-reports/terraform-plan-summary
  export TF_LOG_PATH=$LOG_PATH-$TF_LOG.log
  export TF_PLAN_JSON=test-reports/tf-plan.json
  terraform show -json terraform.tfplan > $TF_PLAN_JSON
  jq -r '
    # Create an array of object from the following logic
    [
      # Delete any resource_change object that have a change action of "no-op".
      del(.resource_changes[]|select(.change.actions[0]|startswith("no-op")))
      |
      # Extract just the resource_change that remain
      .resource_changes[]
      |
      # Extract the required elements from each resource_change into a simpler object
      {
        "Resource address":.address,
        "Read":(if .change.actions | contains(["read"]) then " *" else " " end),
        "Deleted":(if .change.actions | contains(["delete"]) then "   *" else " " end),
        "Created":(if .change.actions | contains(["create"]) then "   *" else " " end),
        "Updated":(if .change.actions | contains(["update"]) then "   *" else " " end)
      }
    ]
    |
    if (.[0] | length) == 0 then
      "No changes"
    else
      # Generate the column headings for the resultant table.
      (
        # Use the first resource
        .[0]
        |
        # Get the keys in their defined order
        keys_unsorted
        |
        # For each key, create an underline and have these underlines in a new array (so, keys, then underlines).
        (
          .,
          map(length*"-")
        )
      ),
      # Join on the resources to the set of column headings.
      .[]
      |
      # Get just the values.
      map(.)
      |
      # Output everything using tab separation which is the picked up by the column command that follows to make a nice
      # tabular output.
      @tsv
    end
  ' $TF_PLAN_JSON | column -ts $'\t' | tee $LOG_PATH.log
  if [ $? -ne 0 ]; then
    echo "There was an issue producing the Terraform Plan Summary."
    echo ""
    return 1
  fi
  echo ""

  echo "Completed"
  echo ""
  return 0
}

This produces a nice, easy to read summary of the plan. For example:

Plan Summary
============

Resource address                                            Read  Deleted  Created  Updated
----------------                                            ----  -------  -------  -------
cloudflare_custom_hostname_fallback_origin.fallback                           *      
cloudflare_page_rule.custom_hostname_images                                   *      
cloudflare_page_rule.custom_hostname_payment_callback                         *      
cloudflare_page_rule.custom_hostname_user_files                               *      
cloudflare_record.cname_record["customdomain.co.uk"]                          *      
cloudflare_record.cname_record["customdomain.ie"]                             *      
module.efs_backup.aws_autoscaling_group.backup_efs_node                                *
module.efs_backup.aws_launch_configuration.backup_efs_node           *        *      

Completed

What I’ve been asked to look into is if it is possible to get the order of changes displayed in some way. Considering there are dependencies in some plans (i.e. resource “A” needs to be created before resource “B” before resource “C”, etc.).

Is there a “depth” or anything in the json output that can be used to identify the dependency in some way?

Hi @rquadling,

Unfortunately Terraform doesn’t track the order of operations explicitly in this way. Instead, Terraform Core just immediately starts all operations concurrently and each individual operation blocks until all of its dependencies become available. The exact order of operations can vary between runs because an action will be taken as soon as its dependencies are all ready, and that time can vary depending on how long the upstream network requests take.

1 Like

Thank you for the reply.