gruntwork-io / terragrunt

Terragrunt is a flexible orchestration tool that allows Infrastructure as Code written in OpenTofu/Terraform to scale.
https://terragrunt.gruntwork.io/
MIT License
8.04k stars 975 forks source link

Terragrunt run-all show plan json behaves different #1848

Closed imti283 closed 3 years ago

imti283 commented 3 years ago

I have below directory structure

\---backend
    \---us-west-2
        \---pro
            +---app1
            |   \---
            +---app2
            |   \---
            \---app3
                \---

I am running this command at backend directory -

terragrunt run-all plan -out plainplan.txt
terragrunt run-all show -json plainplan.txt > plainplanall.json

I am hoping second command should generate a combined plan.json file taking plainplan.txt from all directory(i.e app1,app2..etc) in backend directory. But seems terragrunt stops after going into one directory. I am seeing changes from only one directory in plainplanall.json.

I am expecting second command should read all plainplan.txt, merge them and generate one json file. Am I expecting something wrong or doing something wrong.

yorinasub17 commented 3 years ago

Hmm I can't repro this. I made a test project with the following dir structure:

.
├── a
│   ├── main.tf
│   └── terragrunt.hcl
├── b
│   ├── main.tf
│   └── terragrunt.hcl
├── c
│   ├── main.tf
│   └── terragrunt.hcl
└── d
    ├── main.tf
    └── terragrunt.hcl

and following main.tf in all of them:

resource "null_resource" "foo" {}

(terragrunt.hcl is empty)

And ran the exact commands you provided and ended up with the following in all.json:

{"format_version":"0.2","terraform_version":"1.0.4","planned_values":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","schema_version":0,"values":{"triggers":null},"sensitive_values":{}}]}},"resource_changes":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","change":{"actions":["create"],"before":null,"after":{"triggers":null},"after_unknown":{"id":true},"before_sensitive":false,"after_sensitive":{}}}],"configuration":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_config_key":"null","schema_version":0}]}}}
{"format_version":"0.2","terraform_version":"1.0.4","planned_values":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","schema_version":0,"values":{"triggers":null},"sensitive_values":{}}]}},"resource_changes":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","change":{"actions":["create"],"before":null,"after":{"triggers":null},"after_unknown":{"id":true},"before_sensitive":false,"after_sensitive":{}}}],"configuration":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_config_key":"null","schema_version":0}]}}}
{"format_version":"0.2","terraform_version":"1.0.4","planned_values":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","schema_version":0,"values":{"triggers":null},"sensitive_values":{}}]}},"resource_changes":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","change":{"actions":["create"],"before":null,"after":{"triggers":null},"after_unknown":{"id":true},"before_sensitive":false,"after_sensitive":{}}}],"configuration":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_config_key":"null","schema_version":0}]}}}
{"format_version":"0.2","terraform_version":"1.0.4","planned_values":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","schema_version":0,"values":{"triggers":null},"sensitive_values":{}}]}},"resource_changes":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_name":"registry.terraform.io/hashicorp/null","change":{"actions":["create"],"before":null,"after":{"triggers":null},"after_unknown":{"id":true},"before_sensitive":false,"after_sensitive":{}}}],"configuration":{"root_module":{"resources":[{"address":"null_resource.foo","mode":"managed","type":"null_resource","name":"foo","provider_config_key":"null","schema_version":0}]}}}

Note that the json output is not valid json, as it concatenates each output into a separate line. Note also that each json entry doesn't include where it came from, which makes it unparseable/unusable. This is a known issue and the use case for handling run-all show is mentioned in this issue

Since I can't reproduce the issue and the underlying bug is already reported in #1525, I will be marking this as closed. If you were intending to file a bug about a parseable run-all show output, then please follow #1525 to be notified when we start working on it + fix it. Thanks!

imti283 commented 3 years ago

Well, I was able to fix it by doing something like this in PowerShell -

$val = terragrunt run-all show -json plan.out
foreach ($v in $val.GetEnumerator()) { 
$curr = $v | ConvertFrom-Json
    foreach ($rc in $curr.resource_changes) { 
        $obj = New-Object psobject -Property @{`
            "Project"      = $curr.variables.application_op.value;
            "Action"       = $rc.change.actions
            "ResourceType" = $rc.type;
            "Adress"       = $rc.address
        }
        $returnObj += $obj
    }
}

$newtab = $returnObj | ? { $_.Action -notmatch "no-op" } | Select Project, Action, Adress, ResourceType

My assumption was all.json should contain a single json object having all value merged under single resource_changes block(instead of more than one json objects). That way it will be easier to parse and group all changes. Anyway, Thanks a lot.

karamuz commented 7 months ago

Is there a way to include where the json entry came from? I would like to match each terragrunt dir with the corresponding json plan.