How To Debug Terraform

Multiple options and techniques for debugging Terraform and OpenTofu Infrastructure plans

Access Infrastructure Data from the State

Terraform issues while using official providers and common resources are mostly configuration-related. Using terraform state the details of the resources can be examined.

Listing Resources

Use this process to list Terraform-managed infrastructure resources:

$ terraform state list 
data.aws_iam_policy_document.access_assume_role
data.aws_iam_policy_document.project_defaults
data.aws_iam_policy_document.project_ec2
aws_iam_access_key.project_1_admin
aws_iam_group.project_1_admins
aws_iam_group.project_1_devs
aws_iam_group.super_admins
aws_iam_policy.access_assume_role
aws_iam_policy.project_defaults
aws_iam_policy.project_ec2
aws_iam_user.project_1_admin
aws_iam_user.project_1_dev
aws_iam_user_policy_attachment.user_policy_access_assume_role
aws_iam_user_policy_attachment.user_policy_project_defaults
aws_subnet.ditwl-sn-za-pro-pri-02
aws_subnet.ditwl-sn-za-pro-pub-00
aws_vpc.ditlw-vpc

Accessing resources

Access Terraform resource details with terraform state show aws_vpc.name-of-resouce:

$ terraform state show aws_vpc.ditlw-vpc
# aws_vpc.ditlw-vpc:
resource "aws_vpc" "ditlw-vpc" {
    arn                                  = "arn:aws:ec2:us-east-1:831....2212234:vpc/vpc-0cb3cad6544bd2691"
    assign_generated_ipv6_cidr_block     = false
    cidr_block                           = "172.21.0.0/19"
    default_network_acl_id               = "acl-0d88e6275c2111bc4"
    default_route_table_id               = "rtb-0d1b9b2cb61c820f0"
    default_security_group_id            = "sg-0254ed1ab3ab43fa5"
    dhcp_options_id                      = "dopt-5800d822"
    enable_dns_hostnames                 = false
    enable_dns_support                   = true
    enable_network_address_usage_metrics = false
    id                                   = "vpc-0cb3cad6544bd2691"
    instance_tenancy                     = "default"
    ipv6_netmask_length                  = 0
    main_route_table_id                  = "rtb-0d1b9b2cb61c820f0"
    owner_id                             = "831....2212234"
    tags                                 = {
        "Name" = "ditlw-vpc"
    }
    tags_all                             = {
        "Name" = "ditlw-vpc"
    }
}

Debug API / Provider Communication

Useful when

Enable Terraform debug

Terraform uses the value from the environment variable TF_LOG to define the LOG level. Available values are TRACE, DEBUG, INFO, WARN or ERROR. Additionally, you can specify a destination file for the log by setting the environment variable TF_LOG_PATH to the full path of the desired destination.

Set the debug variables and execute the Terraform plan to see the output:

$export TF_LOG=DEBUG
$# Optional export TF_LOG_PATH=~/debug.txt
$terraform plan
2020/07/31 20:19:01 [WARN] Log levels other than TRACE are currently unreliable, and are supported only for backward compatibility.
  Use TF_LOG=TRACE to see Terraform's internal logs.
  ----
2020/07/31 20:19:01 [INFO] Terraform version: 0.12.26  
2020/07/31 20:19:01 [INFO] Go runtime version: go1.12.13
2020/07/31 20:19:01 [INFO] CLI args: []string{"/usr/bin/terraform", "plan"}
2020/07/31 20:19:01 [DEBUG] Attempting to open CLI config file: /home/jruiz/.terraformrc
2020/07/31 20:19:01 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2020/07/31 20:19:01 [INFO] CLI command args: []string{"plan"}
2020/07/31 20:19:01 [WARN] Log levels other than TRACE are currently unreliable, and are supported only for backward compatibility.
  Use TF_LOG=TRACE to see Terraform's internal logs.
  ----
2020/07/31 20:19:01 [DEBUG] New state was assigned lineage "cc420085-6d12-cb64-c041-a0ed135c58ed"
2020/07/31 20:19:01 [DEBUG] checking for provider in "."
2020/07/31 20:19:01 [DEBUG] checking for provider in "/usr/bin"
2020/07/31 20:19:01 [DEBUG] checking for provider in ".terraform/plugins/linux_amd64"
2020/07/31 20:19:01 [DEBUG] found provider "terraform-provider-aws_v2.67.0_x4"
2020/07/31 20:19:01 [DEBUG] found provider "terraform-provider-external_v1.2.0_x4"
2020/07/31 20:19:01 [DEBUG] found valid plugin: "aws", "2.67.0", "/home/jruiz/git/github/terraform-aws-ec2-rds-basic-free/.terraform/plugins/linux_amd64/terraform-provider-aws_v2.67.0_x4"
2020/07/31 20:19:01 [DEBUG] found valid plugin: "external", "1.2.0", "/home/jruiz/git/github/terraform-aws-ec2-rds-basic-free/.terraform/plugins/linux_amd64/terraform-provider-external_v1.2.0_x4"
2020/07/31 20:19:01 [DEBUG] checking for provisioner in "."
2020/07/31 20:19:01 [DEBUG] checking for provisioner in "/usr/bin"
2020/07/31 20:19:01 [DEBUG] checking for provisioner in ".terraform/plugins/linux_amd64"
2020/07/31 20:19:01 [INFO] backend/local: starting Plan operation
...
2020/07/31 20:19:30 [DEBUG] ProviderTransformer: "module.aws_sg_rds_mariadb_pro_pub_01.aws_security_group.default" (*terraform.NodeValidatableResource) needs provider.aws
6.aws_subnet.default - *terraform.NodeValidatableResource
    provider.aws - *terraform.NodeApplyableProvider
  module.aws_sn_zb_pro_pub_36.output.id - *terraform.NodeApplyableOutput
  module.aws_sn_zb_pro_pub_36.var.az - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.cidr - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.description - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.name - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.public - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.vpc_id - *terraform.NodeApplyableModuleVariable
  module.aws_sr_ec2_default_internet_to_ssh.aws_security_group_rule.default - *terraform.NodeValidatableResource

....
2020/07/31 20:19:30 [DEBUG] ProviderTransformer: "module.aws_sg_rds_mariadb_pro_pub_01.aws_security_group.default" (*terraform.NodeValidatableResource) needs provider.aws
6.aws_subnet.default - *terraform.NodeValidatableResource
    provider.aws - *terraform.NodeApplyableProvider
  module.aws_sn_zb_pro_pub_36.output.id - *terraform.NodeApplyableOutput
  module.aws_sn_zb_pro_pub_36.var.az - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.cidr - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.description - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.name - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.public - *terraform.NodeApplyableModuleVariable
  module.aws_sn_zb_pro_pub_36.var.vpc_id - *terraform.NodeApplyableModuleVariable
  module.aws_sr_ec2_default_internet_to_ssh.aws_security_group_rule.default - *terraform.NodeValidatableResource
...

Inspect the Terraform State file

Use the terraform state command to inspect the current state of your infrastructure. This can help you identify any issues with resource creation or modification.

terraform state list

Use Terraform Console

The Terraform console command allows you to interactively evaluate expressions and query data from your Terraform configuration and state. Access the console and evaluate expressions or inspect resources.

terraform console
module.aws_sn_zb_pro_pub_36.var.vpc_id

Generate Terraform Infrastructure Graphs

The command is used to generate a visual representation of a configuration or an execution plan.

terraform graph | dot -Tsvg > graph.svg

Leave a Reply

Your email address will not be published. Required fields are marked *


Related Cloud Tutorials

Securing your Infrastructure: Encrypting Terraform State Files with OpenTofu
Using the Terraform aws_route53_delegation_set, aws_route53_zone, and aws_route53_record resource blocks to configure DNS in AWS.
Using the Terraform aws_db_instance resource block to configure, launch, and secure RDS instances.
How to use the Terraform aws_instance resource block to configure, launch, and secure EC2 instances.
How to configure and use the Terraform aws_ami data source block to find and use AWS AMIs as templates (root volume snapshot with operating system and applications) for EC2 instances.
Javier Ruiz Cloud and SaaS Expert

Javier Ruiz

IT Wonder Lab tutorials are based on the diverse experience of Javier Ruiz, who founded and bootstrapped a SaaS company in the energy sector. His company, later acquired by a NASDAQ traded company, managed over €2 billion per year of electricity for prominent energy producers across Europe and America. Javier has over 25 years of experience in building and managing IT companies, developing cloud infrastructure, leading cross-functional teams, and transitioning his own company from on-premises, consulting, and custom software development to a successful SaaS model that scaled globally.

Are you looking for cloud automation best practices tailored to your company?

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram