VladRassokhin / intellij-hcl

HCL language support for IntelliJ platform based IDEs
Apache License 2.0
244 stars 47 forks source link

Locals map interpolation problem. #281

Open ctrlok opened 4 years ago

ctrlok commented 4 years ago

Thank you for opening an issue. In this template paragraph text could be removed, however please retain headers.

Prerequisites

Installation details

GoLand 2019.3.1 Build #GO-193.5662.65, built on December 23, 2019 Licensed to Vsevolod Poliakov Subscription is active until February 7, 2020 Runtime version: 11.0.5+10-b520.17 x86_64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o macOS 10.15.3 GC: ParNew, ConcurrentMarkSweep Memory: 1979M Cores: 16 Registry: run.processes.with.pty=TRUE, ide.completion.variant.limit=500, suggest.all.run.configurations.from.context=true, folding.check.collapse.state.before.placeholder.text=TRUE, ide.balloon.shadow.size=0, ideFeaturesTrainer.welcomeScreen.tutorialsTree=TRUE Non-Bundled Plugins: BashSupport, IdeaVIM, Key Promoter X, PythonCore, SnakeYAML plugin, com.chrisrm.idea.MaterialThemeUI, com.daylerees.rainglow, com.intellij.tasks, izhangzhihao.rainbow.brackets, name.kropp.intellij.makefile, org.intellij.plugins.hcl, org.toml.lang

Terraform Configuration Files

locals {
  current = local.workspace[terraform.workspace]
  workspace = {
    production = {
      dns_name = "some_name"
    }
  }
}

Expected Behavior

When I write local.current or local.workspace[terraform.workspace] or local.workspace["production"] I expected to see dns_name in autocomplete result and no errors.

Actual Behavior

I see the production field and this is not valid. In any of these three cases, I should see dns_name. Also, now I see an error 'unresolved references' but terraform works. So, probably it's some kind map syntax interpolation problem.

Steps to Reproduce

Create an empty tf file and put here:

locals {
  workspace = {
    production = {
      dns_name = "some_name"
    }
  }
}

locals {
  current = local.workspace["production"].dns_name
}

You will see an error.

ctrlok commented 4 years ago

Hm, probably this issue is related to the [#279] as well.

eriksw commented 4 years ago

This also affects list(object({...})) variables as well. 😞

In the following examples, the .id and .prefix are spurious Unresolved reference ... errors in the ide, but are 100% fine in Terraform:

data "aws_partition" "current" {}

locals {
  bucket_resources = [for bucket in var.buckets : format("arn:%s:s3:::%s", data.aws_partition.current.partition, bucket.id)]
  object_resources = [for bucket in var.buckets : format("arn:%s:s3:::%s/%s*", data.aws_partition.current.partition, bucket.id, bucket.prefix)]
  resources        = setunion(local.bucket_resources, local.object_resources)
}

variable "buckets" {
  type = list(object({
    id     = string
    prefix = string
  }))
}
mountainerd commented 4 years ago

Implementing some Terraform code as demonstrated in the for_each documentation errors out in the editor as well. It's pretty close to what @eriksw mentions above.

locals {
  # setproduct works with sets and lists, but our variables are both maps
  # so we'll need to convert them first.
  networks = [
    for key, network in var.networks : {
      key        = key
      cidr_block = network.cidr_block
    }
  ]
  subnets = [
    for key, subnet in var.subnets : {
      key    = key
      number = subnet.number
    }
  ]

  network_subnets = [
    # in pair, element zero is a network and element one is a subnet,
    # in all unique combinations.
    for pair in setproduct(local.networks, local.subnets) : {
      network_key = pair[0].key
      subnet_key  = pair[1].key
      network_id  = aws_vpc.example[pair[0].key].id

      # The cidr_block is derived from the corresponding network. See the
      # cidrsubnet function for more information on how this calculation works.
      cidr_block = cidrsubnet(pair[0].cidr_block, 4, pair[1].number)
    }
  ]
}

resource "aws_subnet" "example" {
  # local.network_subnets is a list, so we must now project it into a map
  # where each key is unique. We'll combine the network and subnet keys to
  # produce a single unique key per instance.
  for_each = {
    for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
  }

  vpc_id            = each.value.network_id
  availability_zone = each.value.subnet_key
  cidr_block        = each.value_cidr_block
}

When you get to the for_each statement in the resource block, .network_key and .subnet_key both are highlighted as unresolved references. I only add the comment in the event seeing another example helps. I certainly don't intend to add noise and am very appreciative of the effort and thoughtfulness put into this plugin for working with HCL.