rules/terraform_required_version_declaration.go (90 lines of code) (raw):

package rules import ( "github.com/hashicorp/go-multierror" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/terraform-linters/tflint-plugin-sdk/logger" "github.com/terraform-linters/tflint-plugin-sdk/tflint" "strings" ) var _ tflint.Rule = &TerraformRequiredVersionDeclarationRule{} // TerraformRequiredVersionDeclarationRule checks whether required_version field is declared at the beginning of terraform block type TerraformRequiredVersionDeclarationRule struct { tflint.DefaultRule } // NewTerraformRequiredVersionDeclarationRule returns a new rule func NewTerraformRequiredVersionDeclarationRule() *TerraformRequiredVersionDeclarationRule { return &TerraformRequiredVersionDeclarationRule{} } func (r *TerraformRequiredVersionDeclarationRule) Enabled() bool { return false } func (r *TerraformRequiredVersionDeclarationRule) Severity() tflint.Severity { return tflint.NOTICE } func (r *TerraformRequiredVersionDeclarationRule) Check(runner tflint.Runner) error { return ForFiles(runner, r.CheckFile) } // Name returns the rule name func (r *TerraformRequiredVersionDeclarationRule) Name() string { return "terraform_required_version_declaration" } func (r *TerraformRequiredVersionDeclarationRule) CheckFile(runner tflint.Runner, file *hcl.File) error { var err error body, ok := file.Body.(*hclsyntax.Body) if !ok { logger.Debug("skip terraform_required_version_declaration check since it's not hcl file") return nil } filename := body.Range().Filename if isOverrideTfFile(filename) { logger.Debug("skip terraform_required_version_declaration check since it's override file") return nil } blocks := body.Blocks for _, block := range blocks { if block.Type != "terraform" { continue } if subErr := r.checkBlock(runner, block); subErr != nil { err = multierror.Append(err, subErr) } } return err } func isOverrideTfFile(filename string) bool { return strings.HasSuffix(filename, "_override.tf") || filename == "override.tf" } func (r *TerraformRequiredVersionDeclarationRule) checkBlock(runner tflint.Runner, block *hclsyntax.Block) error { msg := "The `required_version` field should be declared at the beginning of `terraform` block" versionAttr, defined := block.Body.Attributes["required_version"] if !defined { return runner.EmitIssue( r, msg, block.DefRange(), ) } comparePos := func(pos1 hcl.Pos, pos2 hcl.Pos) bool { if pos1.Line != pos2.Line { return pos1.Line < pos2.Line } return pos1.Column < pos2.Column } for _, attr := range block.Body.Attributes { if attr.Name != "required_version" && comparePos(attr.Range().Start, versionAttr.Range().Start) { return runner.EmitIssue( r, msg, versionAttr.NameRange, ) } } for _, nestedBlock := range block.Body.Blocks { if comparePos(nestedBlock.Range().Start, versionAttr.Range().Start) { return runner.EmitIssue( r, msg, versionAttr.NameRange, ) } } return nil }