From 358fb54f75709c4c630a843dfc055c0b41102338 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Fri, 14 May 2021 09:58:28 -0700 Subject: [PATCH] core: "Did you mean" hint for missing data. prefix in references It's a relatively common mistake to try to refer to a data resource without including the data. prefix, making Terraform understand it as a reference to a managed resource. To help with that case, we'll include an additonal suggestion if we can see that there's a data resource declared with the same type and name as in the given address. --- terraform/evaluate_valid.go | 13 ++++++++++++- terraform/evaluate_valid_test.go | 6 ++++++ .../static-validate-refs/static-validate-refs.tf | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/terraform/evaluate_valid.go b/terraform/evaluate_valid.go index 0746ce507..3a8323ae5 100644 --- a/terraform/evaluate_valid.go +++ b/terraform/evaluate_valid.go @@ -203,10 +203,21 @@ func (d *evaluationStateData) staticValidateResourceReference(modCfg *configs.Co cfg := modCfg.Module.ResourceByAddr(addr) if cfg == nil { + var suggestion string + // A common mistake is omitting the data. prefix when trying to refer + // to a data resource, so we'll add a special hint for that. + if addr.Mode == addrs.ManagedResourceMode { + candidateAddr := addr // not a pointer, so this is a copy + candidateAddr.Mode = addrs.DataResourceMode + if candidateCfg := modCfg.Module.ResourceByAddr(candidateAddr); candidateCfg != nil { + suggestion = fmt.Sprintf("\n\nDid you mean the data resource %s?", candidateAddr) + } + } + diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, Summary: `Reference to undeclared resource`, - Detail: fmt.Sprintf(`A %s resource %q %q has not been declared in %s.`, modeAdjective, addr.Type, addr.Name, moduleConfigDisplayAddr(modCfg.Path)), + Detail: fmt.Sprintf(`A %s resource %q %q has not been declared in %s.%s`, modeAdjective, addr.Type, addr.Name, moduleConfigDisplayAddr(modCfg.Path), suggestion), Subject: rng.ToHCL().Ptr(), }) return diags diff --git a/terraform/evaluate_valid_test.go b/terraform/evaluate_valid_test.go index 086ca3037..9267aee65 100644 --- a/terraform/evaluate_valid_test.go +++ b/terraform/evaluate_valid_test.go @@ -32,6 +32,12 @@ func TestStaticValidateReferences(t *testing.T) { "aws_instance.nonexist", `Reference to undeclared resource: A managed resource "aws_instance" "nonexist" has not been declared in the root module.`, }, + { + "beep.boop", + `Reference to undeclared resource: A managed resource "beep" "boop" has not been declared in the root module. + +Did you mean the data resource data.beep.boop?`, + }, { "aws_instance.no_count[0]", `Unexpected resource instance key: Because aws_instance.no_count does not have "count" or "for_each" set, references to it must not include an index key. Remove the bracketed index to refer to the single instance of this resource.`, diff --git a/terraform/testdata/static-validate-refs/static-validate-refs.tf b/terraform/testdata/static-validate-refs/static-validate-refs.tf index e9f9344a8..3667a4e11 100644 --- a/terraform/testdata/static-validate-refs/static-validate-refs.tf +++ b/terraform/testdata/static-validate-refs/static-validate-refs.tf @@ -18,3 +18,6 @@ resource "boop_instance" "yep" { resource "boop_whatever" "nope" { } + +data "beep" "boop" { +}