terraform-linters / tflint

A Pluggable Terraform Linter
Mozilla Public License 2.0
4.86k stars 354 forks source link

tflint 0.40.0 ignores --only options for built in terraform module #1513

Closed tofupup closed 2 years ago

tofupup commented 2 years ago

Introduction

Running tflint 0.40.0 seems to ignore --only=<rule> options on the CLI. My interpretation of the 0.40.0 changelog and the User Guide is that --only names will override other enable/disabled rule declarations. However, it appears the default preset = "recommended" takes precedence on what gets run. If a ~/.tflint.hcl is created with preset = "all", tests that are not included in --only are still run, so there doesn't seem to be a way to run non-recommended rules without specifying it specifically in a configuration file.

Can you clarify if this is intended behavior now?

module "private-codecommit-repo" {
  source = "git::ssh://SOMEUSER@git-codecommit.us-east-2.amazonaws.com/v1/repos/private-codecommit-repo"
}

variable "var1" {
  type = string
}

Running with tflint 0.39.3 without ~/.tflint.hcl:

❯ tflint-0.39.3 --only=terraform_deprecated_interpolation --only=terraform_deprecated_index --only=terraform_unused_declarations --only=terraform_comment_syntax --only=terraform_documented_outputs --only=terraform_documented_variables --only=terraform_typed_variables --only=terraform_module_pinned_source --only=terraform_naming_convention --only=terraform_required_version --only=terraform_required_providers --only=terraform_standard_module_structure --only=terraform_workspace_remote main.tf 2>&1| egrep -i 'issue|warning|notice'
5 issue(s) found:
Notice: module name `private-codecommit-repo` must match the following format: snake_case (terraform_naming_convention)
Warning: Module source "git::ssh://SOMEUSER@git-codecommit.us-east-2.amazonaws.com/v1/repos/private-codecommit-repo" is not pinned (terraform_module_pinned_source)
Notice: `var1` variable has no description (terraform_documented_variables)
Warning: variable "var1" should be moved from main.tf to variables.tf (terraform_standard_module_structure)
Warning: variable "var1" is declared but not used (terraform_unused_declarations)

Running with tflint 0.40.0 without ~/.tflint.hcl:

❯ tflint --only=terraform_deprecated_interpolation --only=terraform_deprecated_index --only=terraform_unused_declarations --only=terraform_comment_syntax --only=terraform_documented_outputs --only=terraform_documented_variables --only=terraform_typed_variables --only=terraform_module_pinned_source --only=terraform_naming_convention --only=terraform_required_version --only=terraform_required_providers --only=terraform_standard_module_structure --only=terraform_workspace_remote main.tf 2>&1| egrep -i 'issue|warning|notice'
2 issue(s) found:
Warning: Module source "git::ssh://SOMEUSER@git-codecommit.us-east-2.amazonaws.com/v1/repos/private-codecommit-repo" is not pinned (terraform_module_pinned_source)
Warning: variable "var1" is declared but not used (terraform_unused_declarations)

Running with tflint 0.40.0 with ~/.tflint.hcl with preset ="recommended" and--only=terraform_naming_convention` removed from CLI:

❯ cat ~/.tflint.hcl
plugin "terraform" {
    // Plugin common attributes
    enabled = true
    preset = "recommended"
}
❯ tflint --only=terraform_deprecated_interpolation --only=terraform_deprecated_index --only=terraform_unused_declarations --only=terraform_comment_syntax --only=terraform_documented_outputs --only=terraform_documented_variables --only=terraform_typed_variables --only=terraform_module_pinned_source --only=terraform_required_version --only=terraform_required_providers --only=terraform_standard_module_structure --only=terraform_workspace_remote main.tf 2>&1| egrep -i 'issue|warning|notice'
2 issue(s) found:
Warning: Module source "git::ssh://SOMEUSER@git-codecommit.us-east-2.amazonaws.com/v1/repos/private-codecommit-repo" is not pinned (terraform_module_pinned_source)
Warning: variable "var1" is declared but not used (terraform_unused_declarations)

Running with tflint 0.40.0 with ~/.tflint.hcl with preset ="all" and --only=terraform_naming_convention removed from CLI:

❯ cat ~/.tflint.hcl
plugin "terraform" {
    // Plugin common attributes
    enabled = true
    preset = "all"
}
❯ tflint --only=terraform_deprecated_interpolation --only=terraform_deprecated_index --only=terraform_unused_declarations --only=terraform_comment_syntax --only=terraform_documented_outputs --only=terraform_documented_variables --only=terraform_typed_variables --only=terraform_module_pinned_source --only=terraform_required_version --only=terraform_required_providers --only=terraform_standard_module_structure --only=terraform_workspace_remote main.tf 2>&1| egrep -i 'issue|warning|notice'
5 issue(s) found:
Notice: module name `private-codecommit-repo` must match the following format: snake_case (terraform_naming_convention)
Warning: Module source "git::ssh://SOMEUSER@git-codecommit.us-east-2.amazonaws.com/v1/repos/private-codecommit-repo" is not pinned (terraform_module_pinned_source)
Notice: `var1` variable has no description (terraform_documented_variables)
Warning: variable "var1" should be moved from main.tf to variables.tf (terraform_standard_module_structure)
Warning: variable "var1" is declared but not used (terraform_unused_declarations)

Expected Behavior

I expected that --only options would override which rules were run, or at least complement the rules set by the .tflint.hcl file.

Actual behavior

It appears the settings in the .tflint.hcl file override the --only= CLI options.

Step to Reproduce

Using the simple main.tf code provided in the Introduction, the example commands provided above should reproduce what I'm seeing.

main.tf:

module "private-codecommit-repo" {
  source = "git::ssh://SOMEUSER@git-codecommit.us-east-2.amazonaws.com/v1/repos/private-codecommit-repo"
}

variable "var1" {
  type = string
}

Commands above in Introduction as well, let me know if you need more information (or if I'm using things wrong!)

Additional Context

❯ terraform -v
Terraform v1.2.8
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v4.30.0
❯ tflint -v
TFLint version 0.40.0
+ ruleset.terraform (0.1.0-bundled)
❯ tflint-0.39.3 -v
TFLint version 0.39.3
wata727 commented 2 years ago

Agreed that this behavior is not intuitive. As you say, the --only option should take precedence over other configs. However, this seems difficult to fix quickly for internal reasons. The config should be evaluated with the following priority:

  1. --only (CLI flag)
  2. --enable-rule, --disable-rule (CLI flag)
  3. rule block (config file)
  4. preset (config file)
  5. disabled_by_default (config file)

Internally, 1 and 5 are the same representation and the plugin cannot distinguish between them. The current behavior is that the --only option is identified as 5, so the config file takes precedence. I think we probably need to be able to send the --only option as another representation to the plugin and interpret it.

As a workaround, I recommend explicitly setting disabled_by_default in your .tflint.hcl file instead of using the --only option.

t3mi commented 2 years ago

@wata727 maybe I'm missing something but proposed workaround is not working for me

$ cat <<EOS > .tflint.test.hcl
config {
  disabled_by_default = true
}

rule "terraform_naming_convention" {
  enabled = true
}
EOS
$ mkdir work
$ cat <<EOS > work/main.tf
resource "aws_instance" "main-main" {
  instance_type = "tx.micro"
}
EOS
$ tree work
work
├── main.tf

0 directory, 1 file
$ tflint -c .tflint.test.hcl ./work/
2 issue(s) found:

Warning: terraform "required_version" attribute is required (terraform_required_version)

  on  line 0:
   (source code not available)

Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.1.0/docs/rules/terraform_required_version.md

Warning: Missing version constraint for provider "aws" in "required_providers" (terraform_required_providers)

  on work/main.tf line 1:
   1: resource "aws_instance" "main" {

Reference: https://github.com/terraform-linters/tflint-ruleset-terraform/blob/v0.1.0/docs/rules/terraform_required_providers.md
wata727 commented 2 years ago

It seems to be a bug that occurs because the "recommended" preset is applied by default. Try declaring the terraform plugin block:

plugin "terraform" {
  enabled = true
}