Skip to content

Commit

Permalink
terraform_module_pinned_source: support additional default_branches (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
bendrucker committed May 28, 2021
1 parent ca0cec4 commit 0c6a3ed
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 30 deletions.
10 changes: 7 additions & 3 deletions docs/rules/terraform_module_pinned_source.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ Name | Default | Value
--- | --- | ---
enabled | true | Boolean
style | `flexible` | `flexible`, `semver`
default_branches | `["master", "main", "default", "develop"]` |

```hcl
rule "terraform_module_pinned_source" {
enabled = true
style = "flexible"
default_branches = ["dev"]
}
```

Configured `default_branches` will be appended to the defaults rather than overriding them.

## Example

### style = "flexible"
Expand Down Expand Up @@ -51,14 +55,14 @@ Warning: Module source "git://hashicorp.com/consul.git" is not pinned (terraform
Reference: https://github.com/terraform-linters/tflint/blob/v0.15.0/docs/rules/terraform_module_pinned_source.md
Warning: Module source "git://hashicorp.com/consul.git?ref=master" uses default ref "master" (terraform_module_pinned_source)
Warning: Module source "git://hashicorp.com/consul.git?ref=master" uses a default branch as ref (master) (terraform_module_pinned_source)
on template.tf line 6:
6: source = "git://hashicorp.com/consul.git?ref=master"
Reference: https://github.com/terraform-linters/tflint/blob/v0.15.0/docs/rules/terraform_module_pinned_source.md
Warning: Module source "hg::http://hashicorp.com/consul.hg?rev=default" uses default rev "default" (terraform_module_pinned_source)
Warning: Module source "hg::http://hashicorp.com/consul.hg?rev=default" uses a default branch as rev (default) (terraform_module_pinned_source)
on template.tf line 10:
10: source = "hg::http://hashicorp.com/consul.hg?rev=default"
Expand Down Expand Up @@ -96,7 +100,7 @@ Warning: Module source "git://hashicorp.com/consul.git" is not pinned (terraform
Reference: https://github.com/terraform-linters/tflint/blob/v0.15.0/docs/rules/terraform_module_pinned_source.md
Warning: Module source "git://hashicorp.com/consul.git?ref=feature" uses a ref which is not a version string (terraform_module_pinned_source)
Warning: Module source "git://hashicorp.com/consul.git?ref=feature" uses a ref which is not a semantic version string (terraform_module_pinned_source)
on template.tf line 6:
6: source = "git://hashicorp.com/consul.git?ref=feature"
Expand Down
34 changes: 16 additions & 18 deletions rules/terraformrules/terraform_module_pinned_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ type TerraformModulePinnedSourceRule struct {
}

type terraformModulePinnedSourceRuleConfig struct {
Style string `hcl:"style,optional"`
Style string `hcl:"style,optional"`
DefaultBranches []string `hcl:"default_branches,optional"`
}

// NewTerraformModulePinnedSourceRule returns new rule with default attributes
Expand Down Expand Up @@ -60,6 +61,7 @@ func (r *TerraformModulePinnedSourceRule) Check(runner *tflint.Runner) error {
log.Printf("[TRACE] Check `%s` rule for `%s` runner", r.Name(), runner.TFConfigPath())

config := terraformModulePinnedSourceRuleConfig{Style: "flexible"}
config.DefaultBranches = append(config.DefaultBranches, "master", "main", "default", "develop")
if err := runner.DecodeRuleConfig(r.Name(), &config); err != nil {
return err
}
Expand Down Expand Up @@ -113,30 +115,26 @@ func (r *TerraformModulePinnedSourceRule) checkModule(runner *tflint.Runner, mod

func (r *TerraformModulePinnedSourceRule) checkRevision(runner *tflint.Runner, module *configs.ModuleCall, config terraformModulePinnedSourceRuleConfig, key string, value string) error {
switch config.Style {
// The "flexible" style enforces to pin source, except for the default branch
// The "flexible" style requires a revision that is not a default branch
case "flexible":
if key == "ref" && value == "master" {
runner.EmitIssue(
r,
fmt.Sprintf("Module source \"%s\" uses default %s \"master\"", module.SourceAddr, key),
module.SourceAddrRange,
)
}

if key == "rev" && value == "default" {
runner.EmitIssue(
r,
fmt.Sprintf("Module source \"%s\" uses default %s \"default\"", module.SourceAddr, key),
module.SourceAddrRange,
)
for _, branch := range config.DefaultBranches {
if value == branch {
runner.EmitIssue(
r,
fmt.Sprintf("Module source \"%s\" uses a default branch as %s (%s)", module.SourceAddr, key, branch),
module.SourceAddrRange,
)

return nil
}
}
// The "semver" style enforces to pin source like semantic versioning
// The "semver" style requires a revision that is a semantic version
case "semver":
_, err := semver.NewVersion(value)
if err != nil {
runner.EmitIssue(
r,
fmt.Sprintf("Module source \"%s\" uses a %s which is not a version string", module.SourceAddr, key),
fmt.Sprintf("Module source \"%s\" uses a %s which is not a semantic version string", module.SourceAddr, key),
module.SourceAddrRange,
)
}
Expand Down
41 changes: 32 additions & 9 deletions rules/terraformrules/terraform_module_pinned_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module "default_git" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"git://hashicorp.com/consul.git?ref=master\" uses default ref \"master\"",
Message: "Module source \"git://hashicorp.com/consul.git?ref=master\" uses a default branch as ref (master)",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand Down Expand Up @@ -82,7 +82,7 @@ rule "terraform_module_pinned_source" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"git://hashicorp.com/consul.git?ref=pinned\" uses a ref which is not a version string",
Message: "Module source \"git://hashicorp.com/consul.git?ref=pinned\" uses a ref which is not a semantic version string",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand Down Expand Up @@ -162,7 +162,7 @@ module "default_git" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"github.com/hashicorp/consul.git?ref=master\" uses default ref \"master\"",
Message: "Module source \"github.com/hashicorp/consul.git?ref=master\" uses a default branch as ref (master)",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand Down Expand Up @@ -201,7 +201,7 @@ rule "terraform_module_pinned_source" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"github.com/hashicorp/consul.git?ref=pinned\" uses a ref which is not a version string",
Message: "Module source \"github.com/hashicorp/consul.git?ref=pinned\" uses a ref which is not a semantic version string",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand Down Expand Up @@ -250,7 +250,7 @@ module "default_git" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"bitbucket.org/hashicorp/tf-test-git.git?ref=master\" uses default ref \"master\"",
Message: "Module source \"bitbucket.org/hashicorp/tf-test-git.git?ref=master\" uses a default branch as ref (master)",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand Down Expand Up @@ -281,7 +281,7 @@ rule "terraform_module_pinned_source" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"bitbucket.org/hashicorp/tf-test-git.git?ref=pinned\" uses a ref which is not a version string",
Message: "Module source \"bitbucket.org/hashicorp/tf-test-git.git?ref=pinned\" uses a ref which is not a semantic version string",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand Down Expand Up @@ -351,7 +351,7 @@ module "default_generic_git_https" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"git::https://hashicorp.com/consul.git?ref=master\" uses default ref \"master\"",
Message: "Module source \"git::https://hashicorp.com/consul.git?ref=master\" uses a default branch as ref (master)",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand All @@ -370,7 +370,7 @@ module "default_generic_git_ssh" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"git::ssh://git@github.com/owner/repo.git?ref=master\" uses default ref \"master\"",
Message: "Module source \"git::ssh://git@github.com/owner/repo.git?ref=master\" uses a default branch as ref (master)",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand All @@ -397,6 +397,29 @@ module "pinned_generic_git_ssh" {
`,
Expected: tflint.Issues{},
},
{
Name: "github module reference is unpinned via custom branches",
Content: `
module "pinned_git" {
source = "github.com/hashicorp/consul.git?ref=foo"
}`,
Config: `
rule "terraform_module_pinned_source" {
enabled = true
default_branches = ["foo"]
}`,
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"github.com/hashicorp/consul.git?ref=foo\" uses a default branch as ref (foo)",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
End: hcl.Pos{Line: 3, Column: 53},
},
},
},
},
{
Name: "mercurial module is not pinned",
Content: `
Expand Down Expand Up @@ -424,7 +447,7 @@ module "default_mercurial" {
Expected: tflint.Issues{
{
Rule: NewTerraformModulePinnedSourceRule(),
Message: "Module source \"hg::http://hashicorp.com/consul.hg?rev=default\" uses default rev \"default\"",
Message: "Module source \"hg::http://hashicorp.com/consul.hg?rev=default\" uses a default branch as rev (default)",
Range: hcl.Range{
Filename: "module.tf",
Start: hcl.Pos{Line: 3, Column: 12},
Expand Down

0 comments on commit 0c6a3ed

Please sign in to comment.