Skip to content

Commit

Permalink
Ignore invalid references in referencesInExpr (#1478)
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 authored Aug 12, 2022
1 parent 99d2afd commit 9bcc0e6
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 41 deletions.
8 changes: 1 addition & 7 deletions rules/terraformrules/terraform_unused_declaration.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,7 @@ func (r *TerraformUnusedDeclarationsRule) declarations(runner *tflint.Runner) (*
}

func (r *TerraformUnusedDeclarationsRule) checkForRefsInExpr(expr hcl.Expression, decl *declarations) error {
refs, diags := referencesInExpr(expr)
if diags.HasErrors() {
log.Printf("[DEBUG] Cannot find references in expression, ignoring: %v", diags)
return nil
}

for _, ref := range refs {
for _, ref := range referencesInExpr(expr) {
switch sub := ref.subject.(type) {
case inputVariableReference:
delete(decl.Variables, sub.name)
Expand Down
7 changes: 1 addition & 6 deletions rules/terraformrules/terraform_workspace_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,7 @@ func (r *TerraformWorkspaceRemoteRule) checkForTerraformWorkspaceInExpr(runner *
return nil
}

refs, diags := referencesInExpr(expr)
if diags.HasErrors() {
return diags
}

for _, ref := range refs {
for _, ref := range referencesInExpr(expr) {
switch sub := ref.subject.(type) {
case terraformReference:
if sub.name == "workspace" {
Expand Down
18 changes: 18 additions & 0 deletions rules/terraformrules/terraform_workspace_remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,24 @@ resource "aws_instance" "foo" {
},
},
},
{
Name: "with ignore_changes",
Content: `
terraform {
backend "remote" {}
}
resource "kubernetes_secret" "my_secret" {
data = {}
lifecycle {
ignore_changes = [
data
]
}
}`,
Expected: tflint.Issues{},
},
}

rule := NewTerraformWorkspaceRemoteRule()
Expand Down
51 changes: 23 additions & 28 deletions rules/terraformrules/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,35 +260,41 @@ func (d *dataResourceReference) String() string {
return fmt.Sprintf("data.%s.%s", d.typeName, d.name)
}

// referencesInExpr extracts and returns references from hcl.Expression.
// This is roughly equivalent to ReferencesInExpr in Terraform interlan API,
// but simply ignores invalid references without returing diagnostics.
// This is because it is not the responsibility of this method to detect invalid references.
// Invalid references should be caught by terraform validate.
//
// @see https://github.com/hashicorp/terraform/blob/v1.2.5/internal/lang/references.go#L75
func referencesInExpr(expr hcl.Expression) ([]*reference, hcl.Diagnostics) {
func referencesInExpr(expr hcl.Expression) []*reference {
references := []*reference{}
diags := hcl.Diagnostics{}

for _, traversal := range expr.Variables() {
name := traversal.RootName()

switch name {
case "var":
name, parseDiags := parseSingleAttrRef(traversal)
diags = diags.Extend(parseDiags)
name, diags := parseSingleAttrRef(traversal)
if diags.HasErrors() {
continue
}
references = append(references, &reference{subject: inputVariableReference{name: name}})
case "local":
name, parseDiags := parseSingleAttrRef(traversal)
diags = diags.Extend(parseDiags)
name, diags := parseSingleAttrRef(traversal)
if diags.HasErrors() {
continue
}
references = append(references, &reference{subject: localValueReference{name: name}})
case "terraform":
name, parseDiags := parseSingleAttrRef(traversal)
diags = diags.Extend(parseDiags)
name, diags := parseSingleAttrRef(traversal)
if diags.HasErrors() {
continue
}
references = append(references, &reference{subject: terraformReference{name: name}})
case "data":
if len(traversal) < 3 {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid reference",
Detail: `The "data" object must be followed by two attribute names: the data source type and the resource name.`,
Subject: traversal.SourceRange().Ptr(),
})
// The "data" object must be followed by two attribute names: the data source type and the resource name.
continue
}

Expand All @@ -299,32 +305,21 @@ func referencesInExpr(expr hcl.Expression) ([]*reference, hcl.Diagnostics) {
case hcl.TraverseAttr:
typeName = tt.Name
default:
// If it isn't a TraverseRoot then it must be a "data" reference.
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid reference",
Detail: `The "data" object does not support this operation.`,
Subject: traversal[1].SourceRange().Ptr(),
})
// The "data" object does not support this operation.
continue
}

attrTrav, ok := traversal[2].(hcl.TraverseAttr)
if !ok {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid reference",
Detail: `A reference to a data source must be followed by at least one attribute access, specifying the resource name.`,
Subject: traversal[1].SourceRange().Ptr(),
})
// A reference to a data source must be followed by at least one attribute access, specifying the resource name.
continue
}

references = append(references, &reference{subject: dataResourceReference{typeName: typeName, name: attrTrav.Name}})
}
}

return references, diags
return references
}

// @see https://github.com/hashicorp/terraform/blob/v1.2.5/internal/addrs/parse_ref.go#L392
Expand Down

0 comments on commit 9bcc0e6

Please sign in to comment.