coinbase / terraform-landscape

Improve Terraform's plan output to be easier to read and understand
Apache License 2.0
1.59k stars 116 forks source link

sort lists of key-value-pairs, for better diff quality #74

Closed david-chenevert closed 4 years ago

david-chenevert commented 6 years ago

Since 0.2.0, JSON dictionaries (aka Associative Arrays in JSON-speak) have been sorted by key, which is great. It works fine when Terraform uses JSON dictionaries to implement key-value maps (aka dictionaries aka hash'es in programmer-speak).

But, Terraform sometimes implements key-value maps as "array of key-value-pair". For example, task-definition changes for services often cause log.plan lines such as:

some_attribute_name: "[{\"environment\": [{\"name\":\"c\",\"value\":\"300\"} ,{\"name\":\"b\",\"value\":\"200\"},{\"name\":\"a\",\"value\":\"100\"}] } ]" => "[{\"environment\": [{\"name\":\"a\",\"value\":\"100\"},{\"name\":\"c\",\"value\":\"300\"},{\"name\":\"b\",\"value\":\"205\"}] } ]"

The value of "b" has changed. The other items did not change value, but did change position.

If the arrays are not sorted, the diff looks like:

~ module.a.module.b.aws_autoscaling_group.my-cluster
    container_definitions:   [
                                {
                                  "environment": [
                                    {
                             +        "name": "a",
                             +        "value": "100"
                             +      },
                             +      {
                                      "name": "c",
                                      "value": "300"
                                    },
                                    {
                                      "name": "b",
                             -        "value": "200"
                             -      },
                             -      {
                             -        "name": "a",
                             -        "value": "100"
                             +        "value": "205"
                                    }
                                  ]
                                }
                              ] (forces new resource)

In my development environment, these lists are usually dozens of elements long, and the spurious change-reports (such as "a" and "c" above) are almost impossible to reliably separate from actual differences.

Sorting these arrays by key (in this case, "name") greatly improves the output quality:

~ module.a.module.b.aws_autoscaling_group.my-cluster
    container_definitions:   "name": "a",
                                      "value": "100"
                                    },
                                    {
                                      "name": "b",
                             -        "value": "200"
                             +        "value": "205"
                                    },
                                    {
                                      "name": "c",
                                      "value": "300"
                                    } (forces new resource)

Only the value that actually changed, "b", is shown as a difference.

An implementation of this feature is here https://github.com/coinbase/terraform-landscape/pull/75

sds commented 4 years ago

Tracking in #108.