hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.

Home Page:https://www.terraform.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Improve UX for displaying disappearing and known after apply elements in plan

bschaatsbergen opened this issue · comments

Terraform Version

Terraform v1.8.4

Use Cases

Improving the UX by indicating disappearing known elements as -, and mark the changed list that's known after apply as ~ indicating that something in the list is being modified.

Attempted Solutions

n/a

Proposal

As a user I would like to see an enhancement to the terraform plan output to improve clarity around disappearing and "known after apply" elements. The current representation can be confusing for users, as it’s unclear which elements will be removed from the collection and what the final state will look like after applying changes.

Current:

{
  # 13 unchanged attributes
  service_accounts = [
-   sa1@gserviceaccount,
-   sa2@gserviceaccount,
-   sa3@gserviceaccount,
  ] -> (known after apply)
}

Proposed:

{
  # 13 unchanged attributes
  ~ service_accounts = [
        "sa1@gserviceaccount",
      - "sa2@gserviceaccount",
      + (known after apply),
        "sa3@gserviceaccount",
    ]
}

This approach indicates that the list is being modified (~) and that a certain element is being removed (-).

References

No response

Hi @bschaatsbergen,

Thanks for filing the issue. The plan render already works in the way you have described, but the output shown in your example indicates that the entire list value is unknown rather than a single element. This could be because you are using an expression in the configuration which combines the new unknown value in such a way that the entire service_accounts value is not known during the plan, or it could be because service_accounts isn't a list at all, but rather a set.

Can you show a complete example of the configuration and resource being used here?

Thanks!

Indeed, I think there are two parts to this problem:

  1. The Terraform CLI plan renderer uses the - symbol on each element when it's describing the entire list being replaced with an unknown value, which is a little misleading since Terraform doesn't actually know those elements are being removed. The intended message here is "we don't know whether any of these elements will exist in the new value".
  2. This attribute belongs to a resource type implemented with the legacy plugin SDK and so I expect the SDK is losing the detail about which individual elements are known or unknown, because the SDK follows the Terraform v0.11 assumption that a collection is either wholly known or wholly unknown. Therefore this gets reduced to "entire list is becoming unknown" even if the value that was sent to the provider was a known list with an unknown element in it.

The first of these could be improved in Terraform CLI alone, perhaps by removing the - markers completely in this case:

  ~ service_accounts = [
         "sa1@gserviceaccount",
         "sa2@gserviceaccount",
         "sa3@gserviceaccount",
    ] -> (known after apply)

The ~ before service_accounts represents "this attribute is changing", but we only know that the entire list is becoming unknown and so probably better not to say anything at all about what might be happening to the individual elements, because we have no way to know.


The second of these can only be fixed by this resource type being rewritten to use the modern plugin framework, which would be a change in the provider that implements this resource type rather than a change in Terraform CLI/Core. If the provider were fixed to preserve the individual element known-ness in its plan then today's Terraform CLI would already produce something close to the requested output, as @jbardin noted:

  ~ service_accounts = [
         "sa1@gserviceaccount",
       ~ "sa2@gserviceaccount" -> (known after apply),
         "sa3@gserviceaccount",
    ]

The above is relying on our heuristic that if the list length hasn't changed then we prefer to show a diff for each element rather than a diff for the entire list, but if the list length were changing then it would appear almost exactly like the requested output:

  ~ service_accounts = [
         "sa1@gserviceaccount",
         "sa2@gserviceaccount",
       + (known after apply),
         "sa3@gserviceaccount",
    ]

We cannot achieve that rendering as long as the provider is discarding the information about which elements individual elements are known, though. That would be a feature request for the provider itself. We could still make a change for the first problem, like what I proposed above, as a less confusing presentation for the current ambiguous situation.

Just for the record, if the configuration is correct, the container type is a list, and the provider is functioning correctly, the plan output currently looks like:

~ service_accounts  = [
      "sa1@gserviceaccount",
    ~ "sa2@gserviceaccount" -> (known after apply),
      "sa3@gserviceaccount",
  ]

Thanks, @jbardin and @apparentlysmart, for the fast and detailed reply. It's great to know we already have this functionality in place for providers using the new plugin framework. To get the exact code snippet details, I'm looping in @RolphR since they're the one who provided it after we brainstormed on this.