Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show data from config and state #734

Open
radeksimko opened this issue Aug 10, 2021 · 0 comments
Open

Show data from config and state #734

radeksimko opened this issue Aug 10, 2021 · 0 comments
Labels
enhancement New feature or request meta

Comments

@radeksimko
Copy link
Member

radeksimko commented Aug 10, 2021

Problem Statement

Users are provided with completion, hover data etc. today largely based on schemas for both Terraform itself (core) and individual providers.

There are situations in which schema will never be sufficient to provide enough guidance however.

  • module outputs with interpolation targeting config value - such as output "example" { value = aws_instance.test.instance_type }
  • resources with computed attributes - such as resource "aws_instance" "test" w/ public_ip
  • most data source attributes - such as data "aws_ami" "example" w/ image_id

Expected User Experience

Completion

Completing elements of computed maps/lists

Upon typing the opening bracket [ user will be presented with:

  • all known map keys, including ones sourced from the state
  • all known list element indexes, including ones sourced from the state
output "tag_value" {
  value = data.aws_instance.foo.instance_tags[ # <-- HERE e.g. "Owner" is suggested, assuming such tag exists
}
output "first_instance_id" {
  value = data.aws_instances.test.ids[ # <-- HERE e.g. 0, 1, 2, 3 etc. is suggested if 4 instance IDs are returned
}

Showing values of attributes

In addition to suggesting a primitive attribute (such as image_id in example below) user will also be presented with value below the description of the field in completion

Primitive Types

image2
image3

Complex Types (e.g. object)

image1

Hover

Block header

Given a data source or a resource block, user can hover over the header (first line of the block)

data "aws_ami" "ubuntu" {
#^^^^^^^^^^^^^^^^^^^^^^^^
# Hovering over THIS HEADER would display e.g.
# {
#   most_recent = true
#   image_id = "ami-123456789"
#   ...
# }

  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

which will display all known data based on schema, in-config values and state.

Reference

Given a reference address, user can hover over it to display the in-config value

resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
                 #^^^^^^^^^^^^^^^^^^^^^^
                 # Hovering over THIS REFERENCE would display e.g. `ami-123456789`
  instance_type = "t3.micro"
}

Proposal

Note: It is unclear whether it's avoidable but fully interpolating an expression with all references would likely require understanding dependencies between expressions and therefore blocks of code, which effectively means re-implementing Terraform's DAG in some form or shape.

See also:

Hover

There is an issue tracking support for additional hover request in LSP which would be most likely suitable for this kind of situation - as opposed to obtaining all the schema-related data + state + config data in a single request. This would also allow us to provide more flexible "progressively enhanced" UX where we can show schema-based data quickly and enhance append more content, or replace it once we obtain more data.

See more at microsoft/language-server-protocol#772

We can consider implementing such an extension to the protocol (first internally, then proposing it upstream), and/or just extend the existing textDocument/hover workflow where hcl-lang would return a lang.Address for the given position - e.g. aws_instance.example as an extra field in lang.HoverData. This would then allow the server to use it to obtain more relevant data e.g. via terraform console or terraform state show.

Completion

TODO

Blocking Questions

  • How do we obtain values from the state?
    • We could use terraform state show [address] (if machine-readable JSON output was added)
    • We could use echo [address] | terraform console (if machine-readable JSON output was added)
  • How do we obtain values from the config?
  • How do we present differences between config and state values / how do we merge it?
  • How do we deal with excessively large amount of data? e.g. github_ip_ranges
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request meta
Projects
None yet
Development

No branches or pull requests

1 participant