Skip to content

Commit 5874361

Browse files
committed
Add range to terraform_required_version errors
1 parent 5382486 commit 5874361

File tree

2 files changed

+110
-7
lines changed

2 files changed

+110
-7
lines changed

rules/terraform_required_version.go

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package rules
22

33
import (
4+
"path/filepath"
5+
"strings"
6+
47
"github.com/hashicorp/hcl/v2"
58
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
69
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
@@ -78,13 +81,57 @@ func (r *TerraformRequiredVersionRule) Check(runner tflint.Runner) error {
7881
exists = exists || ok
7982
}
8083

81-
if !exists {
82-
return runner.EmitIssue(
83-
r,
84-
`terraform "required_version" attribute is required`,
85-
hcl.Range{},
86-
)
84+
if exists {
85+
return nil
86+
}
87+
88+
var missingRange hcl.Range
89+
90+
if len(body.Blocks) > 0 {
91+
missingRange = body.Blocks[0].DefRange
92+
} else {
93+
// If there are no "terraform" blocks, create a hcl.Range for the files
94+
95+
// Find the directory common to all files
96+
var commonPath []string
97+
first := true
98+
for filename := range files {
99+
parts := strings.Split(filename, string(filepath.Separator))
100+
101+
if first {
102+
commonPath = parts
103+
first = false
104+
continue
105+
}
106+
107+
// If parts is shorter, truncate commonPath proactively
108+
if len(parts) < len(commonPath) {
109+
commonPath = commonPath[:len(parts)]
110+
}
111+
112+
for i := 0; i < len(commonPath); i++ {
113+
if commonPath[i] != parts[i] {
114+
// Truncate the common path at the point where it diverges
115+
commonPath = commonPath[:i]
116+
break
117+
}
118+
}
119+
}
120+
121+
// If the result is a directory, append an empty string to get a trailing slash in the output
122+
if len(files) > 1 {
123+
commonPath = append(commonPath, "")
124+
}
125+
126+
missingRange = hcl.Range{
127+
// If there are multiple files, this will be a directory name
128+
Filename: strings.Join(commonPath, string(filepath.Separator)),
129+
}
87130
}
88131

89-
return nil
132+
return runner.EmitIssue(
133+
r,
134+
`terraform "required_version" attribute is required`,
135+
missingRange,
136+
)
90137
}

rules/terraform_required_version_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package rules
33
import (
44
"testing"
55

6+
"github.com/hashicorp/hcl/v2"
67
"github.com/terraform-linters/tflint-plugin-sdk/helper"
78
)
89

@@ -25,6 +26,17 @@ terraform {}
2526
{
2627
Rule: NewTerraformRequiredVersionRule(),
2728
Message: "terraform \"required_version\" attribute is required",
29+
Range: hcl.Range{
30+
Filename: "module.tf",
31+
Start: hcl.Pos{
32+
Line: 2,
33+
Column: 1,
34+
},
35+
End: hcl.Pos{
36+
Line: 2,
37+
Column: 10,
38+
},
39+
},
2840
},
2941
},
3042
},
@@ -53,6 +65,23 @@ terraform {
5365
`,
5466
Expected: helper.Issues{},
5567
},
68+
{
69+
Name: "no terraform block",
70+
Content: `
71+
locals {
72+
foo = "bar"
73+
}
74+
`,
75+
Expected: helper.Issues{
76+
{
77+
Rule: NewTerraformRequiredVersionRule(),
78+
Message: "terraform \"required_version\" attribute is required",
79+
Range: hcl.Range{
80+
Filename: "module.tf",
81+
},
82+
},
83+
},
84+
},
5685
}
5786

5887
rule := NewTerraformRequiredVersionRule()
@@ -73,3 +102,30 @@ terraform {
73102
})
74103
}
75104
}
105+
106+
func Test_TerraformRequiredVersionRuleMultipleFiles(t *testing.T) {
107+
rule := NewTerraformRequiredVersionRule()
108+
109+
t.Run("multiple files no terraform blocks", func(t *testing.T) {
110+
files := map[string]string{
111+
"modules/foo/bar/other.tf": "",
112+
"modules/foo/outputs.tf": "",
113+
"modules/foo/main.tf": "",
114+
"modules/foo/variables.tf": "",
115+
}
116+
runner := helper.TestRunner(t, files)
117+
if err := rule.Check(runner); err != nil {
118+
t.Fatal(err)
119+
}
120+
121+
helper.AssertIssues(t, helper.Issues{
122+
{
123+
Rule: NewTerraformRequiredVersionRule(),
124+
Message: "terraform \"required_version\" attribute is required",
125+
Range: hcl.Range{
126+
Filename: "modules/foo/",
127+
},
128+
},
129+
}, runner.Issues)
130+
})
131+
}

0 commit comments

Comments
 (0)