Skip to content

Improve handling of root-only traversal expressions #2435

@wata727

Description

@wata727

Introduction

In Terraform language semantics, reference expressions are var.<NAME>, local.<NAME>, <RESOURCE TYPE>.<NAME>, etc., all consisting of multiple traversals including the attribute access operator.

However, some non-reference expressions may consist of root-only traversals. e.g.

resource "azurerm_linux_web_app_slot" "test" {
  lifecycle {
    ignore_changes = [
      tags # root-only traversal
    ]
  }
}
[for s in var.list : upper(s)] # "s" is root-only traversal
resource "aws_lambda_function" "example" {
  lifecycle {
    action_trigger {
      events = [after_create, after_update] # root-only traversal
      actions = [action.aws_lambda_invoke.example]
    }
  }
}

In particular, meta-arguments such as lifecycle are parsed as special attributes in Terraform, so they cannot be parsed as normal attributes. Specifically, an error may occur when retrieving them with the GetResourceContent API. See #2431

Proposal

Here are some options:

1. Allow root-only traversal expressions as reference expressions

Expressions like tags are inherently invalid in Terraform language semantics, but TFLint treats them as valid expressions. Their value always resolves to an unknown value.

This will likely reduce the chance of plugin developers encountering "surprising" behavior in many cases, but I'm not sure that always resolving to an unknown value is useful. For example, ignore_changes can be retrieved using the GetResourceContent API, but the "value" of these expressions is undefined. However, plugin developers can extract values ​​that look reasonable.

Considering a valid situation, there are times when you just want to extract an hcl.Expression. In TFLint, blocks are expanded in advance and the expression is evaluated at that time, so there is an issue with evaluation errors even if you are not interested in the value of the meta-argument. Here is an example attempt by #2434.

This approach may solve terraform-linters/tflint-plugin-sdk#339 as a side effect.

2. Add APIs for handling meta-arguments

Add APIs like GetResourceLifecycle and prohibit getting meta-arguments in GetResourceContent.

This approach is most aligned with Terraform language semantics and may give you more flexibility in handling meta-arguments. However, the meta-argument schema varies between Terraform versions, so some effort is required to make it robust.

3. Ignore root-only traversal expressions during expression expansion

This is based on the approach in #2434, only ignoring it when expanding blocks, since most issues are likely to occur when expanding blocks.
However, this approach is a workaround compared to options 1 and 2, so I believe it would be better to consider options 1 and 2.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementneeds-designDetailed design is required for implementation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions