Skip to content

terraform_naming_convention: Add support for checks and scoped data sources #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/rules/terraform_naming_convention.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Enforces naming conventions for the following blocks:
* Local values
* Modules
* Data sources
* Checks

## Configuration

Expand All @@ -23,6 +24,7 @@ module | | Block settings to override naming convention for modules
output | | Block settings to override naming convention for output values
resource | | Block settings to override naming convention for resources
variable | | Block settings to override naming convention for input variables
check | | Block settings to override naming convention for checks


#### `format`
Expand Down
33 changes: 33 additions & 0 deletions rules/terraform_naming_convention.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type terraformNamingConventionRuleConfig struct {
Output *BlockFormatConfig `hclext:"output,block"`
Resource *BlockFormatConfig `hclext:"resource,block"`
Variable *BlockFormatConfig `hclext:"variable,block"`
Check *BlockFormatConfig `hclext:"check,block"`
}

// CustomFormatConfig defines a custom format that can be used instead of the predefined formats
Expand Down Expand Up @@ -128,6 +129,19 @@ func (r *TerraformNamingConventionRule) Check(rr tflint.Runner) error {
LabelNames: []string{"name"},
Body: &hclext.BodySchema{},
},
{
Type: "check",
LabelNames: []string{"name"},
Body: &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "data",
LabelNames: []string{"type", "name"},
Body: &hclext.BodySchema{},
},
},
},
},
},
}, &tflint.GetModuleContentOption{ExpandMode: tflint.ExpandModeNone})
if err != nil {
Expand All @@ -146,6 +160,14 @@ func (r *TerraformNamingConventionRule) Check(rr tflint.Runner) error {
return err
}
}
checkBlockName := "check"
for _, checkBlock := range blocks[checkBlockName] {
for _, block := range checkBlock.Body.Blocks {
if err := nameValidator.checkBlock(runner, r, dataBlockName, block.Labels[1], &block.DefRange); err != nil {
return err
}
}
}

// modules
moduleBlockName := "module"
Expand Down Expand Up @@ -195,6 +217,17 @@ func (r *TerraformNamingConventionRule) Check(rr tflint.Runner) error {
}
}

// checks
nameValidator, err = config.Check.getNameValidator(defaultNameValidator, &config, checkBlockName)
if err != nil {
return err
}
for _, block := range blocks[checkBlockName] {
if err := nameValidator.checkBlock(runner, r, checkBlockName, block.Labels[0], &block.DefRange); err != nil {
return err
}
}

// locals
localBlockName := "local value"
nameValidator, err = config.Locals.getNameValidator(defaultNameValidator, &config, localBlockName)
Expand Down
86 changes: 86 additions & 0 deletions rules/terraform_naming_convention_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,36 @@ data "aws_eip" "foo_bar" {
Name: fmt.Sprintf("data: %s - Valid single word", testType),
Content: `
data "aws_eip" "foo" {
}`,
Config: config,
Expected: helper.Issues{},
},
{
Name: fmt.Sprintf("data: %s - Invalid snake_case in a check block", testType),
Content: `
check "ignored" {
data "aws_eip" "dash-name" {
}
}`,
Config: config,
Expected: helper.Issues{
{
Rule: rule,
Message: fmt.Sprintf("data name `dash-name` must match the following %s", formatName),
Range: hcl.Range{
Filename: "tests.tf",
Start: hcl.Pos{Line: 3, Column: 3},
End: hcl.Pos{Line: 3, Column: 29},
},
},
},
},
{
Name: fmt.Sprintf("data: %s - Valid snake_case in a check block", testType),
Content: `
check "ignored" {
data "aws_eip" "foo_bar" {
}
}`,
Config: config,
Expected: helper.Issues{},
Expand Down Expand Up @@ -2926,3 +2956,59 @@ variable "camelCase" {
})
}
}

func Test_TerraformNamingConventionRule_Check(t *testing.T) {
rule := NewTerraformNamingConventionRule()

config := `
rule "terraform_naming_convention" {
enabled = true

check {
format = "snake_case"
}
}`

tests := []struct {
name string
content string
want helper.Issues
}{
{
name: "Invalid snake_case",
content: `
check "dash-name" {
}`,
want: helper.Issues{
{
Rule: rule,
Message: "check name `dash-name` must match the following format: snake_case",
Range: hcl.Range{
Filename: "tests.tf",
Start: hcl.Pos{Line: 2, Column: 1},
End: hcl.Pos{Line: 2, Column: 18},
},
},
},
},
{
name: "Valid snake_case",
content: `
check "foo_bar" {
}`,
want: helper.Issues{},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
runner := testRunner(t, map[string]string{"tests.tf": test.content, ".tflint.hcl": config})

if err := rule.Check(runner); err != nil {
t.Fatalf("Unexpected error occurred: %s", err)
}

helper.AssertIssues(t, test.want, runner.Runner.(*helper.Runner).Issues)
})
}
}