# How to debug in Terraform


Terraform (currently) does not provide any functionality that could be compared to a `var_dump()` function like the PHP programming language has it for example. Or a debugger of any kind. However, there are a few options to get more insights about what a Terraform module is doing.

## `terraform console`
Terraform provides a `terraform console` command ([docs](https://www.terraform.io/cli/commands/console)). It can be used to test/try out expressions, read values from a module, or scripting.

### Usage
Run `terraform console` in the directory of the module that you want to debug. Pass the `-var-file` option if you are using a non-standard variable file location. For example `terraform console -var-file=./config/dev.tfvars`.

You can print the values of resources, module outputs, locals & data.

Note that it is not possible to print the values of locals, resources & data which are declared inside a child module. To be able to view them, you need to declare an output for the desired object in the child module, which makes these values available to the parent module.

For addressing the objects, use [Resource Addresses](https://www.terraform.io/cli/state/resource-addressing).

#### Usage example
Let’s assume we have a root module, which calls the `cloud_storage` child module. That module creates two Google Storage Buckets, and defines them as an output.

Let's see how we can find out what the content of that output is. Usually, to be able to see the output of a child module, we would have to "bubble it up", meaning also declaring an output in the root module, which in turn uses the child module output as value. 

Our root module’s `main.tf`:
```hcl
// ...

module "cloud_storage" {
  source = "../modules/cloud_storage"

  environment    = var.environment
  project        = var.project
  default_labels = local.default_labels
}
```

`cloud_storage` module `main.tf`:
```hcl
locals {
  bucket_configs = {
    {
      foo : {
        name : "foo-files", retention_days : 3, location : "europe-west4", storage_class : "STANDARD"
      },
      bar : {
        name : "bar-files", retention_days : 1, location : "europe-west6", storage_class : "COLDLINE"
    }
  }
}

resource "google_storage_bucket" "buckets" {
  for_each      = local.bucket_configs
  provider      = google-beta
  name          = each.value.name
  location      = each.value.location
  force_destroy = true
  uniform_bucket_level_access = false
  public_access_prevention    = "enforced"
  storage_class               = each.value.storage_class
  labels                      = var.default_labels

  versioning {
    enabled = true
  }

  dynamic "lifecycle_rule" {
    for_each = each.value.retention_days[*]
    content {
      condition {
        age = each.value.retention_days
      }

      action {
        type = "Delete"
      }
    }
  }
}
```

`cloud_storage` module `outputs.tf`:
```hcl
// This is what we want to investigate
output "buckets" {
  value = google_storage_bucket.buckets[*]
}
```

##### Printing buckets
Run the console inside the root module’s directory:
```shell
terraform console
// We are now basically "inside" the root module, and can access all the variables/resources it has direct access to.
```

Print the value of the buckets output that is defined by the `cloud_storage` module.
```shell
> module.cloud_storage.buckets
```

This will output something like this:
```json
[
  {
    "foo" = {
      "cors" = tolist([])
      "default_event_based_hold" = false
      "encryption" = tolist([])
      "force_destroy" = true
      "id" = "foo-files"
      "labels" = tomap({
        "environment" = "dev"
        "managed-by" = "tf-module--main"
      })
      "lifecycle_rule" = tolist([
        {
          "action" = toset([
            {
              "storage_class" = ""
              "type" = "Delete"
            },
          ])
          "condition" = toset([
            {
              "age" = 3
              "created_before" = ""
              "custom_time_before" = ""
              "days_since_custom_time" = 0
              "days_since_noncurrent_time" = 0
              "matches_storage_class" = tolist([])
              "noncurrent_time_before" = ""
              "num_newer_versions" = 0
              "with_state" = "ANY"
            },
          ])
        },
      ])
      "location" = "EUROPE-WEST4"
      "logging" = tolist([])
      "name" = "foo-files"
      "project" = "my-gcp-project"
      "public_access_prevention" = "enforced"
      "requester_pays" = false
      "retention_policy" = tolist([])
      "self_link" = "https://www.googleapis.com/storage/v1/b/foo-files"
      "storage_class" = "STANDARD"
      "timeouts" = null /* object */
      "uniform_bucket_level_access" = false
      "url" = "gs://foo-files"
      "versioning" = tolist([
        {
          "enabled" = true
        },
      ])
      "website" = tolist([])
    }
    "bar" = {
      "cors" = tolist([])
      "default_event_based_hold" = false
      "encryption" = tolist([])
      "force_destroy" = true
      "id" = "bar-files"
      "labels" = tomap({
        "environment" = "dev"
        "managed-by" = "tf-module--main"
      })
      "lifecycle_rule" = tolist([
        {
          "action" = toset([
            {
              "storage_class" = ""
              "type" = "Delete"
            },
          ])
          "condition" = toset([
            {
              "age" = 1
              "created_before" = ""
              "custom_time_before" = ""
              "days_since_custom_time" = 0
              "days_since_noncurrent_time" = 0
              "matches_storage_class" = tolist([])
              "noncurrent_time_before" = ""
              "num_newer_versions" = 0
              "with_state" = "ANY"
            },
          ])
        },
      ])
      "location" = "EUROPE-WEST6"
      "logging" = tolist([])
      "name" = "bar-files"
      "project" = "my-gcp-project"
      "public_access_prevention" = "enforced"
      "requester_pays" = false
      "retention_policy" = tolist([])
      "self_link" = "https://www.googleapis.com/storage/v1/b/bar-files"
      "storage_class" = "COLDLINE"
      "timeouts" = null /* object */
      "uniform_bucket_level_access" = false
      "url" = "gs://bar-files"
      "versioning" = tolist([
        {
          "enabled" = true
        },
      ])
      "website" = tolist([])
    }
  },
]
```
