Skip to content

Commit

Permalink
feat(tflint_bp_plugin): add min & max paramters
Browse files Browse the repository at this point in the history
  • Loading branch information
apeabody committed Aug 8, 2024
1 parent f43ba90 commit 44c2747
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 6 deletions.
40 changes: 36 additions & 4 deletions tflint-ruleset-blueprint/rules/terraform_required_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ type TerraformRequiredVersion struct {
tflint.DefaultRule
}

// TerraformRequiredVersionConfig is a config of TerraformRequiredVersion
type TerraformRequiredVersionConfig struct {
MinVersion string `hclext:"min_version,optional"`
MaxVersion string `hclext:"max_version,optional"`
}

// NewTerraformRequiredVersion returns a new rule.
func NewTerraformRequiredVersion() *TerraformRequiredVersion {
return &TerraformRequiredVersion{}
Expand Down Expand Up @@ -48,7 +54,30 @@ const (

// Checks if a module has a terraform required_version within valid range.
func (r *TerraformRequiredVersion) Check(runner tflint.Runner) error {
splitVersion := strings.Split(minimumTerraformRequiredVersion, ".")
config := &TerraformRequiredVersionConfig{}
if err := runner.DecodeRuleConfig(r.Name(), config); err != nil {
return err
}

minVersion := minimumTerraformRequiredVersion
if config.MinVersion != "" {
if _, err := version.NewSemver(config.MinVersion); err != nil {
return err
} else {
minVersion = config.MinVersion
}
}

maxVersion := maximumTerraformRequiredVersion
if config.MaxVersion != "" {
if _, err := version.NewSemver(config.MaxVersion); err != nil {
return err
} else {
maxVersion = config.MaxVersion
}
}

splitVersion := strings.Split(minVersion, ".")
majorVersion, err := strconv.Atoi(splitVersion[0])
if err != nil {
return err
Expand All @@ -66,6 +95,9 @@ func (r *TerraformRequiredVersion) Check(runner tflint.Runner) error {
minorVersion - 1,
)
} else {
if majorVersion == 0 {
return fmt.Errorf("Error: minimum version test constraint would be below zero: v%d.%d.999", majorVersion - 1, 999)
}
terraform_below_minimum_required_version = fmt.Sprintf(
"v%d.%d.999",
majorVersion - 1,
Expand All @@ -78,12 +110,12 @@ func (r *TerraformRequiredVersion) Check(runner tflint.Runner) error {
return err
}

minimum_required_version, err := version.NewVersion(minimumTerraformRequiredVersion)
minimum_required_version, err := version.NewVersion(minVersion)
if err != nil {
return err
}

maximum_required_version, err := version.NewVersion(maximumTerraformRequiredVersion)
maximum_required_version, err := version.NewVersion(maxVersion)
if err != nil {
return err
}
Expand Down Expand Up @@ -126,7 +158,7 @@ func (r *TerraformRequiredVersion) Check(runner tflint.Runner) error {
//TODO: add option for repository exemptions
if !((constraints.Check(minimum_required_version) || constraints.Check(maximum_required_version)) && !constraints.Check(below_required_version)) {
//TODO: use EmitIssueWithFix()
err := runner.EmitIssue(r, fmt.Sprintf("required_version is not inclusive of the the minimum %q and maximum %q terraform required_version: %q", minimumTerraformRequiredVersion, maximumTerraformRequiredVersion, constraints.String()), block.DefRange)
err := runner.EmitIssue(r, fmt.Sprintf("required_version is not inclusive of the the minimum %q and maximum %q terraform required_version: %q", minVersion, maxVersion, constraints.String()), block.DefRange)
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ func TestTerraformMinimumRequiredVersion(t *testing.T) {
{
dir: path.Join(terraformRequiredVersionTestDir, "multiple-invalid"),
},
{
dir: path.Join(terraformRequiredVersionTestDir, "multiple-valid-config"),
},
{
dir: path.Join(terraformRequiredVersionTestDir, "multiple-invalid-config"),
},
{
dir: path.Join(terraformRequiredVersionTestDir, "multiple-valid-config-single"),
},
}

rule := NewTerraformRequiredVersion()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
[
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \">= 1\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 1,
"Column": 1
},
"End": {
"Line": 1,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \">= 1.1\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 5,
"Column": 1
},
"End": {
"Line": 5,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \">= 1.1.0\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 9,
"Column": 1
},
"End": {
"Line": 9,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \">=1.1.0\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 13,
"Column": 1
},
"End": {
"Line": 13,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \">= 1.1.0, < 2.0\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 17,
"Column": 1
},
"End": {
"Line": 17,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \">=0.13.0\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 21,
"Column": 1
},
"End": {
"Line": 21,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \"=0.13.0\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 25,
"Column": 1
},
"End": {
"Line": 25,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \"0.13.0\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 29,
"Column": 1
},
"End": {
"Line": 29,
"Column": 10
}
}
},
{
"Message": "required_version is not inclusive of the the minimum \"1.6\" and maximum \"1.9\" terraform required_version: \"~>0.13.0\"",
"Range": {
"Filename": "main.tf",
"Start": {
"Line": 33,
"Column": 1
},
"End": {
"Line": 33,
"Column": 10
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
rule "terraform_required_version" {
enabled = true
min_version = "1.6"
max_version = "1.9"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
terraform {
required_version = ">= 1"
}

terraform {
required_version = ">= 1.1"
}

terraform {
required_version = ">= 1.1.0"
}

terraform {
required_version = ">=1.1.0"
}

terraform {
required_version = ">= 1.1.0, < 2.0"
}

terraform {
required_version = ">=0.13.0"
}

terraform {
required_version = "=0.13.0"
}

terraform {
required_version = "0.13.0"
}

terraform {
required_version = "~>0.13.0"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
rule "terraform_required_version" {
enabled = true
max_version = "1.6"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
terraform {
required_version = ">=1.3"
}

terraform {
required_version = ">= 1.3, < 2.0"
}

terraform {
required_version = "~>1.6"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
rule "terraform_required_version" {
enabled = true
min_version = "1.6"
max_version = "1.9"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
terraform {
required_version = ">=1.6"
}

terraform {
required_version = ">= 1.6, < 2.0"
}

terraform {
required_version = "~>1.6"
}

terraform {
required_version = "~>1.9"
}
6 changes: 4 additions & 2 deletions tflint-ruleset-blueprint/rules/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path"
"path/filepath"
"slices"
"strings"
"testing"

Expand All @@ -16,11 +17,12 @@ import (
const (
testdataDir = "testdata"
expectedSuffix = ".expected"
tfExt = ".tf"
updateEnvVar = "UPDATE_EXPECTED"
issueFile = "issues.json"
)

var validExtensions = []string{".tf", ".hcl"}

// ruleTC is a single rule test case.
type ruleTC struct {
// Dir with root module to be tested.
Expand Down Expand Up @@ -59,7 +61,7 @@ func configForTest(t *testing.T, subdir string) map[string]string {
if d.IsDir() && strings.HasPrefix(d.Name(), ".") {
return filepath.SkipDir
}
if !d.IsDir() && path.Ext(fp) == tfExt {
if !d.IsDir() && slices.Contains(validExtensions, path.Ext(fp)) {
relPath, err := filepath.Rel(modDir, fp)
if err != nil {
return err
Expand Down

0 comments on commit 44c2747

Please sign in to comment.