Terraform.tmLanguage icon indicating copy to clipboard operation
Terraform.tmLanguage copied to clipboard

Aliased Terraform providers highlighted as if they are typos

Open xRokco opened this issue 6 months ago • 4 comments
trafficstars

Hi,

Since the 2.0.0 update, it seems like aliased provider inputs are being highlighted red, as if it is a typo:

Image
providers = {
    aws                 = aws.test
    aws.secrets-manager = aws.secrets-manager
  }

I assume this isn't intended.

More generally it occurs with any key name containing a period:

Image
locals {
  foo = {
    bar.fizz = "buzz"
  }
}

As far as I know this is valid Terraform: https://developer.hashicorp.com/terraform/language/modules/develop/providers#passing-providers-explicitly

Thank you 😄

xRokco avatar May 20 '25 15:05 xRokco

Interesting, I have not seen this syntax before.

Trying to find the explanation of that in the syntax spec also does not reveal this to be valid.

  • Attribute names must be an Identifier (https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#structural-elements)
  • Identifier does not allow . (https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md#identifiers)

Is this perhaps a Terraform-specific expansion? Otherwise it might also be an undocumented feature.

FichteFoll avatar May 21 '25 12:05 FichteFoll

Ah, I see now. This is not an attribute assignment inside a block but inside an object. Objects allow = and : as separators and the left-hand side can be an identifier or an expression, which is … terrible?

According to the docs, I would interpret an object written in the form { bar.fizz = "buzz" } to assign the value "buzz" to a key whose name is contained in bar.fizz.

The relevant syntax rules are as follows:

CollectionValue = tuple | object;
objectelem = (Identifier | Expression) ("=" | ":") Expression;
Identifier = ID_Start (ID_Continue | '-')*;
Expression = (
    ExprTerm |
    Operation |
    Conditional
);
ExprTerm = (
    LiteralValue |
    CollectionValue |
    TemplateExpr |
    VariableExpr |
    FunctionCall |
    ForExpr |
    ExprTerm Index |
    ExprTerm GetAttr |
    ExprTerm Splat |
    "(" Expression ")"
);
VariableExpr = Identifier;
GetAttr = "." Identifier;

Is this how it behaves?

FichteFoll avatar May 21 '25 12:05 FichteFoll

I guess so. I wouldn't have called an aliased provider config an expression but maybe my layman's definition of them doesn't match the hcl spec.

terraform apply
╷
│ Error: Reference to undeclared resource
│ 
│   on main.tf line 3, in locals:
│    3:     bar.fizz = "buzz"
│ 
│ A managed resource "bar" "fizz" has not been declared in the root module.
╵

If I define a resource and name it to match the left hand side it tells me to wrap it in parentheses or quotes:

terraform apply
╷
│ Error: Ambiguous attribute key
│ 
│   on main.tf line 3, in locals:
│    3:     aws_vpc.name = "buzz"
│ 
│ If this expression is intended to be a reference, wrap it in parentheses. If it's instead
│ intended as a literal name containing periods, wrap it in quotes to create a string
│ literal.
╵

So as a local it forces me to clarify, but the providers block is handled specially I suppose. The aliased provider config is quite unlike anything else I've seen in Terraform - I don't know of anywhere else where the left hand side can have a period like this.

FWIW, it looks like Terraform does allow me to replace the = with a : like any other object:

module "subdomain" {
  source           = "../../../modules/subdomain_delegation"
  parent_zone_id   = "dummy"
  subdomain_prefix = "foobar"
  providers = {
    aws.parent : aws.test_1
    aws.child : aws.test_2
  }
}

xRokco avatar May 23 '25 14:05 xRokco

Thanks for checking. I'll see if I can play around with this a bit myself before I implement it, but I'll be a bit short on time over the next weeks.

FichteFoll avatar May 23 '25 18:05 FichteFoll