Skip to content
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

terraform_module_pinned_source: support additional default_branches #1126

Merged
merged 5 commits into from
May 28, 2021
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
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