terraform show -json module map is empty

Created on 7 Jul 2020  路  7Comments  路  Source: hashicorp/terraform

Terraform Version

Terraform v0.12.28
+ provider.google v3.28.0

Terraform Configuration Files

# ./main.tf
module "project" {
  source          = "../../../../blueprints/gcp/project"
  billing_account = "002A75-ABB3C9-680D62"
  folder_id       = "746484843613"
  project_id      = "di-test-mod-gcp-project-1"
  owner           = "[email protected]"

  labels = {
    ac-number       = "us106088"
    env             = "non-prod"
    financial-owner = "test_owner"
    technical-owner = "wdossantosjunior"
  }
}
# ../../../../blueprints/gcp/project/main.tf
terraform {
  required_version = ">= 0.12"

  required_providers {
    google = ">= 3.13, < 4.0"
  }
}

module "project" {
  source = "../../../modules/gcp/project"

  billing_account = var.billing_account
  folder_id       = var.folder_id
  project_id      = var.project_id
  owner           = var.owner
  labels          = var.labels
}
# ../../../modules/gcp/project/main.tf
resource "google_project" "default" {
  auto_create_network = false
  billing_account     = var.billing_account
  folder_id           = var.folder_id
  labels              = var.labels
  name                = var.project_name != "" ? var.project_name : var.project_id
  project_id          = var.project_id

  lifecycle {
    prevent_destroy = true
  }
}

provider "google" {
  alias   = "dynamic"
  project = google_project.default.project_id
}

resource "google_project_iam_member" "owner" {
  project = google_project.default.project_id

  role   = "roles/owner"
  member = "user:${var.owner}"
}

resource "google_project_iam_audit_config" "audit_config" {
  project = google_project.default.project_id

  service = "allServices"

  audit_log_config {
    log_type = "ADMIN_READ"
  }

  audit_log_config {
    log_type = "DATA_READ"
  }

  audit_log_config {
    log_type = "DATA_WRITE"
  }
}

module "log_exporter" {
  source = "../bigquery-log-exporter"

  project  = google_project.default
  location = "US"

  sink = {
    name   = "audit_logs"
    filter = <<EOF
      logName = ("projects/${google_project.default.project_id}/logs/cloudaudit.googleapis.com%2Factivity"
      OR "projects/${google_project.default.project_id}/logs/cloudaudit.googleapis.com%2Fsystem_events"
      OR "projects/${google_project.default.project_id}/logs/cloudaudit.googleapis.com%2Fdata_access")
    EOF
  }

  bigquery_dataset = {
    name                       = "audit_logs"
    delete_contents_on_destroy = false
    readers                    = []
  }

  providers = {
    google = google.dynamic
  }
}

output "project_id" {
  description = "The project ID"
  value       = google_project.default.project_id
}

output "number" {
  description = "The numeric identifier of the project"
  value       = google_project.default.number
}

Debug Output

https://gist.github.com/wilson-codeminus/41d0951d92c1bd253e5ea12c62aceb5b

Crash Output

N/A

Expected Behavior

Expected to get a JSON representation of the resources present within the terraform state file

Actual Behavior

Module map object is empty:

$ terraform show -json
{"format_version":"0.1","terraform_version":"0.12.28","values":{"root_module":{}}}

Steps to Reproduce

  1. terraform init
  2. terraform apply
  3. terraform show -json

Additional Context

N/A

References

N/A

bug cli explained good first issue v0.12

All 7 comments

Hi @wilson-codeminus,

From the steps listed here, I would not expect there to be anything in the state, since there has not been anything applied.
Are you expecting to be working with an existing state file?

Yes. You're right, I forgot to add terraform apply to the steps to reproduce. I will edit it

Thanks @wilson-codeminus, I'm not sure how to reproduce this yet.

Is it possible to create an example showing the module configuration as well?
Do you have any other configuration in the root module?
Does terraform show display any resources without the -json flag?

Ok. I will expand to show the module and submodule as well.
No. That is all that is contained in the root module.
Yes. terraform show displays all the resources without the -json flag.

I'm seeing something similar where resources defined in a module that is itself defined in a module don't appear in terraform show -json but do in a normal terraform show.

I'm trying to cut my config down to the minimum to reproduce this, will update if I work it out

Here's a very simple reproduction:

main.tf

module "a" {
  source = "./a"
}

a/main.tf:

module "b" {
  source = "./b"
}

a/b/main.tf:

resource "null_resource" "none" {}

Reproduction:

  • terraform init
  • terraform apply -auto-approve
  • terraform show (shows the resource)
  • terraform show -json (shows an empty state)

Confirmed on Terraform 0.12.28 and 0.13.3.

I believe the issue is in this loop: https://github.com/hashicorp/terraform/blob/6d7904c17b2a724a32fc8f8b1f66a0788376426e/command/jsonstate/state.go#L199-L208

For my simple repro case above, this results in a moduleMap containing one key ("module.a"), as the only module in state is module.a.module.b.

This results in an empty output, because the following line only considers modules starting from root:

https://github.com/hashicorp/terraform/blob/6d7904c17b2a724a32fc8f8b1f66a0788376426e/command/jsonstate/state.go#L210-L211

The solution to this will have to ensure that we can cope with intermediate modules which do not have any resources, but do have child modules. It's not immediately obvious to me how we fix this, but I think it will be isolated to marshalRootModule and marshalModules.

Workaround: for anyone else hitting this bug, adding a null_resource instance in any modules which exclusively call other modules will ensure that their descendants are rendered in terraform show -json

Was this page helpful?
0 / 5 - 0 ratings