hashicorp / hcl-lang

Schema and decoder to be used as building blocks for an HCL2-based language server.
https://pkg.go.dev/github.com/hashicorp/hcl-lang
Mozilla Public License 2.0
84 stars 24 forks source link

Consider exposing evaluated config as data to code lenses #132

Open radeksimko opened 2 years ago

radeksimko commented 2 years ago

Background

Code lens implementors can currently access PathContext.

This contains evaluated resource & data source data types (cty.Type) under ReferenceTargets (reference.Targets).

Based on feedback from @hugorut from @infracost, they would like to access evaluated data (at least evaluated as much as possible within the context, possibly with some unknowns), such that they can return cost estimations based on that data for each resource.

Proposal

Consider storing & exposing evaluated data in a format similar we use to store/expose types via ReferenceTargets.

Side Notes

It is likely we will need this anyway for https://github.com/hashicorp/terraform-ls/issues/495 and https://github.com/hashicorp/terraform-ls/issues/956

hugorut commented 2 years ago

Thanks @radeksimko for raising this issue. I'll try adding more context for our specific use case.

With @infracost, we look up resource costs using queries/filters that we build from Terraform block attributes. Let's take a simple example using aws_instance to explain.

resource "aws_instance" "web_app" {
  ami           = "ami-674cbc1e"
  instance_type = "m5.8xlarge"
  root_block_device {
    volume_size = 50
  }

  ...
}

We use the instance_type attribute to build a price filter and look this up in our pricing DB, and then output a cost component like so:

 Name                                                           Monthly Qty  Unit                        Monthly Cost

 aws_instance.web_app
 ├─ Instance usage (Linux/UNIX, on-demand, m5.8xlarge)                  730  hours                          $1,121.28
...

With our Infracost VSCode extension, we then display the overall cost of the resource above the block as a code lens:

e33bf258-baea-4490-9bed-4d36068c4475

When evaluating integration with terraform-ls and using the code lens hook, we quickly realised that this would be pretty tricky to perform with the current state of the LS and Infracost. As mentioned, the PathContext does not provide us with any evaluated attributes, so to provide correct pricing for code lens support, Infracost would have to perform its own parsing of the PathContext module and file. Currently, Infracost has no way to cache this behaviour, so we'd have to perform a complete evaluation for each code lens call, which would be problematic and slow.

At Infracost, we are working towards building an SDK with the potential that this would evolve into an LS. These features would allow us in the future to have a much more efficient and easy code lens integration.

However, @radeksimko's suggestion to provide fully evaluated attributes to the code lens functions seems to be the most logical approach to this integration. Exposing evaluated attributes would mean that all the parsing and caching behaviour could live within terraform-ls, and there wouldn't be inconsistencies in how module parsing between Infracost and Terraform.

To be clear, our requirements for this would be as follows:

  1. Access to all the evaluated attributes for each Target - this could either be as a cty.Object or the raw hcl.Block along with the current evaluation Context.
  2. We're fine with unknown attributes. We deal with this case already.
  3. We don't require access to data block attributes fetched from the cloud - but we would be interested in this in future if this is on the roadmap.