Skip to content

Commit

Permalink
Add autofix support
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 committed May 24, 2023
1 parent 599e680 commit c8ded42
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 51 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hcl/v2 v2.16.2
github.com/hashicorp/terraform-registry-address v0.2.0
github.com/terraform-linters/tflint-plugin-sdk v0.16.1
github.com/terraform-linters/tflint-plugin-sdk v0.16.2-0.20230521152637-98b8c1069ddb
github.com/zclconf/go-cty v1.13.1
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/terraform-linters/tflint-plugin-sdk v0.16.1 h1:fBfLL8KzP3pkQrNp3iQxaGoKBoMo2sFYoqmhuo6yc+A=
github.com/terraform-linters/tflint-plugin-sdk v0.16.1/go.mod h1:ltxVy04PRwptL6P/Ugz2ZeTNclYapClrLn/kVFXJGzo=
github.com/terraform-linters/tflint-plugin-sdk v0.16.2-0.20230521152637-98b8c1069ddb h1:7oOZV08MmoTqSyEm1C340d5AkdgTZxkK9zcBIi58Tus=
github.com/terraform-linters/tflint-plugin-sdk v0.16.2-0.20230521152637-98b8c1069ddb/go.mod h1:ltxVy04PRwptL6P/Ugz2ZeTNclYapClrLn/kVFXJGzo=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
Expand Down
5 changes: 4 additions & 1 deletion rules/terraform_comment_syntax.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ func (r *TerraformCommentSyntaxRule) checkComments(runner tflint.Runner, filenam
}

if strings.HasPrefix(string(token.Bytes), "//") {
if err := runner.EmitIssue(
if err := runner.EmitIssueWithFix(
r,
"Single line comments should begin with #",
token.Range,
func(f *tflint.Fixer) error {
return f.ReplaceText(f.RangeTo("//", filename, token.Range.Start), "#")
},
); err != nil {
return err
}
Expand Down
7 changes: 7 additions & 0 deletions rules/terraform_comment_syntax_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ func Test_TerraformCommentSyntaxRule(t *testing.T) {
Content string
JSON bool
Expected helper.Issues
Fixed string
}{
{
Name: "hash comment",
Expand Down Expand Up @@ -48,6 +49,7 @@ func Test_TerraformCommentSyntaxRule(t *testing.T) {
},
},
},
Fixed: `# foo`,
},
{
Name: "end-of-line hash comment",
Expand Down Expand Up @@ -82,6 +84,11 @@ variable "foo" {
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
want := map[string]string{}
if tc.Fixed != "" {
want[filename] = tc.Fixed
}
helper.AssertChanges(t, want, runner.Changes())
})
}
}
18 changes: 13 additions & 5 deletions rules/terraform_deprecated_index.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rules

import (
"fmt"
"strings"

"github.com/hashicorp/hcl/v2"
Expand Down Expand Up @@ -66,15 +67,18 @@ func (r *TerraformDeprecatedIndexRule) Check(runner tflint.Runner) error {
r.checkLegacyTraversalIndex(runner, expr.Traversal, file.Bytes)
case *hclsyntax.SplatExpr:
if strings.HasPrefix(string(expr.MarkerRange.SliceBytes(file.Bytes)), ".") {
if err := runner.EmitIssue(
if err := runner.EmitIssueWithFix(
r,
"List items should be accessed using square brackets",
expr.MarkerRange,
func(f *tflint.Fixer) error {
return f.ReplaceText(expr.MarkerRange, "[*]")
},
); err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssue()",
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
}
Expand All @@ -92,17 +96,21 @@ func (r *TerraformDeprecatedIndexRule) Check(runner tflint.Runner) error {

func (r *TerraformDeprecatedIndexRule) checkLegacyTraversalIndex(runner tflint.Runner, traversal hcl.Traversal, file []byte) hcl.Diagnostics {
for _, t := range traversal {
if _, ok := t.(hcl.TraverseIndex); ok {
if tn, ok := t.(hcl.TraverseIndex); ok {
if strings.HasPrefix(string(t.SourceRange().SliceBytes(file)), ".") {
if err := runner.EmitIssue(
if err := runner.EmitIssueWithFix(
r,
"List items should be accessed using square brackets",
t.SourceRange(),
func(f *tflint.Fixer) error {
// TODO: handle non-numeric indices
return f.ReplaceText(t.SourceRange(), fmt.Sprintf("[%s]", tn.Key.AsBigFloat().Text('f', -1)))
},
); err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssue()",
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
}
Expand Down
59 changes: 49 additions & 10 deletions rules/terraform_deprecated_index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func Test_TerraformDeprecatedIndexRule(t *testing.T) {
Name string
Content string
Expected helper.Issues
Fixed string
}{
{
Name: "deprecated dot index style",
Expand All @@ -38,6 +39,12 @@ locals {
},
},
},
Fixed: `
locals {
list = ["a"]
value = list[0]
}
`,
},
{
Name: "deprecated dot splat index style",
Expand All @@ -64,6 +71,12 @@ locals {
},
},
},
Fixed: `
locals {
maplist = [{a = "b"}]
values = maplist[*].a
}
`,
},
{
Name: "attribute access",
Expand Down Expand Up @@ -100,14 +113,14 @@ EOF
{
Name: "directive: invalid",
Content: `
locals {
servers = <<EOF
%{ for ip in aws_instance.example.*.private_ip }
server ${ip}
%{ endfor }
EOF
}
`,
locals {
servers = <<EOF
%{ for ip in aws_instance.example.*.private_ip }
server ${ip}
%{ endfor }
EOF
}
`,
Expected: helper.Issues{
{
Rule: NewTerraformDeprecatedIndexRule(),
Expand All @@ -116,15 +129,24 @@ EOF
Filename: "config.tf",
Start: hcl.Pos{
Line: 4,
Column: 36,
Column: 34,
},
End: hcl.Pos{
Line: 4,
Column: 38,
Column: 36,
},
},
},
},
Fixed: `
locals {
servers = <<EOF
%{ for ip in aws_instance.example[*].private_ip }
server ${ip}
%{ endfor }
EOF
}
`,
},
{
Name: "legacy splat and legacy index",
Expand Down Expand Up @@ -166,6 +188,12 @@ locals {
},
},
},
Fixed: `
locals {
nested_list = [["a"]]
value = nested_list[*][0]
}
`,
},
{
Name: "complex expression",
Expand All @@ -192,6 +220,12 @@ locals {
},
},
},
Fixed: `
locals {
create_namespace = true
kubernetes_namespace = local.create_namespace ? join("", kubernetes_namespace.default[*].id) : var.kubernetes_namespace
}
`,
},
}

Expand All @@ -206,6 +240,11 @@ locals {
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
want := map[string]string{}
if tc.Fixed != "" {
want["config.tf"] = tc.Fixed
}
helper.AssertChanges(t, want, runner.Changes())
})
}
}
21 changes: 18 additions & 3 deletions rules/terraform_deprecated_interpolation.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,35 @@ func (r *TerraformDeprecatedInterpolationRule) Check(runner tflint.Runner) error
}

func (r *TerraformDeprecatedInterpolationRule) checkForDeprecatedInterpolationsInExpr(runner tflint.Runner, expr hcl.Expression) hcl.Diagnostics {
if _, ok := expr.(*hclsyntax.TemplateWrapExpr); !ok {
wrapExpr, ok := expr.(*hclsyntax.TemplateWrapExpr)
if !ok {
return nil
}

err := runner.EmitIssue(
err := runner.EmitIssueWithFix(
r,
"Interpolation-only expressions are deprecated in Terraform v0.12.14",
expr.Range(),
func(f *tflint.Fixer) error {
if err := f.Remove(hcl.Range{
Filename: expr.Range().Filename,
Start: expr.Range().Start,
End: wrapExpr.Wrapped.Range().Start,
}); err != nil {
return err
}
return f.Remove(hcl.Range{
Filename: expr.Range().Filename,
Start: wrapExpr.Wrapped.Range().End,
End: expr.Range().End,
})
},
)
if err != nil {
return hcl.Diagnostics{
{
Severity: hcl.DiagError,
Summary: "failed to call EmitIssue()",
Summary: "failed to call EmitIssueWithFix()",
Detail: err.Error(),
},
}
Expand Down
59 changes: 59 additions & 0 deletions rules/terraform_deprecated_interpolation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func Test_TerraformDeprecatedInterpolationRule(t *testing.T) {
Name string
Content string
Expected helper.Issues
Fixed string
}{
{
Name: "deprecated single interpolation",
Expand All @@ -30,6 +31,10 @@ resource "null_resource" "a" {
},
},
},
Fixed: `
resource "null_resource" "a" {
triggers = var.triggers
}`,
},
{
Name: "deprecated single interpolation in provider block",
Expand All @@ -48,6 +53,10 @@ provider "null" {
},
},
},
Fixed: `
provider "null" {
foo = var.triggers["foo"]
}`,
},
{
Name: "deprecated single interpolation in locals block",
Expand All @@ -66,6 +75,10 @@ locals {
},
},
},
Fixed: `
locals {
foo = var.triggers["foo"]
}`,
},
{
Name: "deprecated single interpolation in nested block",
Expand All @@ -86,6 +99,12 @@ resource "null_resource" "a" {
},
},
},
Fixed: `
resource "null_resource" "a" {
provisioner "local-exec" {
single = var.triggers["greeting"]
}
}`,
},
{
Name: "interpolation as template",
Expand All @@ -112,6 +131,10 @@ resource "null_resource" "a" {
},
},
},
Fixed: `
resource "null_resource" "a" {
triggers = [var.triggers]
}`,
},
{
Name: "new interpolation syntax",
Expand All @@ -121,6 +144,37 @@ resource "null_resource" "a" {
}`,
Expected: helper.Issues{},
},
{
Name: "nested wraps",
Content: `
resource "null_resource" "a" {
triggers = "${"${var.triggers}"}"
}`,
Expected: helper.Issues{
{
Rule: NewTerraformDeprecatedInterpolationRule(),
Message: "Interpolation-only expressions are deprecated in Terraform v0.12.14",
Range: hcl.Range{
Filename: "config.tf",
Start: hcl.Pos{Line: 3, Column: 13},
End: hcl.Pos{Line: 3, Column: 35},
},
},
{
Rule: NewTerraformDeprecatedInterpolationRule(),
Message: "Interpolation-only expressions are deprecated in Terraform v0.12.14",
Range: hcl.Range{
Filename: "config.tf",
Start: hcl.Pos{Line: 3, Column: 16},
End: hcl.Pos{Line: 3, Column: 33},
},
},
},
Fixed: `
resource "null_resource" "a" {
triggers = var.triggers
}`,
},
}

rule := NewTerraformDeprecatedInterpolationRule()
Expand All @@ -134,6 +188,11 @@ resource "null_resource" "a" {
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
want := map[string]string{}
if tc.Fixed != "" {
want["config.tf"] = tc.Fixed
}
helper.AssertChanges(t, want, runner.Changes())
})
}
}

0 comments on commit c8ded42

Please sign in to comment.