Skip to content

Commit

Permalink
Allow config to be merged even with initial values (#1670)
Browse files Browse the repository at this point in the history
  • Loading branch information
wata727 authored Feb 5, 2023
1 parent 16e0218 commit c8ff71c
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 102 deletions.
4 changes: 3 additions & 1 deletion cmd/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ func (cli *CLI) inspect(opts Options, args []string) int {
if opts.Recursive {
// Respect "--format" and "--force" flags in recursive mode
cli.formatter.Format = opts.Format
force = opts.Force
if opts.Force != nil {
force = *opts.Force
}
} else {
cli.formatter.Format = cli.config.Format
force = cli.config.Force
Expand Down
68 changes: 47 additions & 21 deletions cmd/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ type Options struct {
EnablePlugins []string `long:"enable-plugin" description:"Enable plugins from the command line" value-name:"PLUGIN_NAME"`
Varfiles []string `long:"var-file" description:"Terraform variable file name" value-name:"FILE"`
Variables []string `long:"var" description:"Set a Terraform variable" value-name:"'foo=bar'"`
Module bool `long:"module" description:"Inspect modules"`
Module *bool `long:"module" description:"Inspect modules"`
Chdir string `long:"chdir" description:"Switch to a different working directory before executing the command" value-name:"DIR"`
Recursive bool `long:"recursive" description:"Run command in each directory recursively"`
Filter []string `long:"filter" description:"Filter issues by file names or globs" value-name:"FILE"`
Force bool `long:"force" description:"Return zero exit status even if issues found"`
Force *bool `long:"force" description:"Return zero exit status even if issues found"`
MinimumFailureSeverity string `long:"minimum-failure-severity" description:"Sets minimum severity level for exiting with a non-zero error code" choice:"error" choice:"warning" choice:"notice"`
Color bool `long:"color" description:"Enable colorized output"`
NoColor bool `long:"no-color" description:"Disable colorized output"`
Expand All @@ -50,20 +50,38 @@ func (opts *Options) toConfig() *tflint.Config {
opts.Variables = []string{}
}

log.Printf("[DEBUG] CLI Options")
log.Printf("[DEBUG] Module: %t", opts.Module)
log.Printf("[DEBUG] Force: %t", opts.Force)
log.Printf("[DEBUG] IgnoreModules:")
for name, ignore := range ignoreModules {
log.Printf("[DEBUG] %s: %t", name, ignore)
var module, moduleSet bool
if opts.Module == nil {
module = false
moduleSet = false
} else {
module = *opts.Module
moduleSet = true
}

var force, forceSet bool
if opts.Force == nil {
force = false
forceSet = false
} else {
force = *opts.Force
forceSet = true
}

log.Printf("[DEBUG] CLI Options")
log.Printf("[DEBUG] Module: %t", module)
log.Printf("[DEBUG] Force: %t", force)
log.Printf("[DEBUG] Format: %s", opts.Format)
log.Printf("[DEBUG] Varfiles: %s", strings.Join(opts.Varfiles, ", "))
log.Printf("[DEBUG] Variables: %s", strings.Join(opts.Variables, ", "))
log.Printf("[DEBUG] EnableRules: %s", strings.Join(opts.EnableRules, ", "))
log.Printf("[DEBUG] DisableRules: %s", strings.Join(opts.DisableRules, ", "))
log.Printf("[DEBUG] Only: %s", strings.Join(opts.Only, ", "))
log.Printf("[DEBUG] EnablePlugins: %s", strings.Join(opts.EnablePlugins, ", "))
log.Printf("[DEBUG] Varfiles: %s", strings.Join(opts.Varfiles, ", "))
log.Printf("[DEBUG] Variables: %s", strings.Join(opts.Variables, ", "))
log.Printf("[DEBUG] Format: %s", opts.Format)
log.Printf("[DEBUG] IgnoreModules:")
for name, ignore := range ignoreModules {
log.Printf("[DEBUG] %s: %t", name, ignore)
}

rules := map[string]*tflint.RuleConfig{}
if len(opts.Only) > 0 {
Expand Down Expand Up @@ -107,15 +125,23 @@ func (opts *Options) toConfig() *tflint.Config {
}

return &tflint.Config{
Module: opts.Module,
Force: opts.Force,
IgnoreModules: ignoreModules,
Varfiles: varfiles,
Variables: opts.Variables,
DisabledByDefault: len(opts.Only) > 0,
Only: opts.Only,
Format: opts.Format,
Rules: rules,
Plugins: plugins,
Module: module,
ModuleSet: moduleSet,

Force: force,
ForceSet: forceSet,

Format: opts.Format,
FormatSet: opts.Format != "",

DisabledByDefault: len(opts.Only) > 0,
DisabledByDefaultSet: len(opts.Only) > 0,

Varfiles: varfiles,
Variables: opts.Variables,
Only: opts.Only,
IgnoreModules: ignoreModules,
Rules: rules,
Plugins: plugins,
}
}
18 changes: 11 additions & 7 deletions cmd/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func Test_toConfig(t *testing.T) {
Command: "./tflint --module",
Expected: &tflint.Config{
Module: true,
ModuleSet: true,
Force: false,
IgnoreModules: map[string]bool{},
Varfiles: []string{},
Expand All @@ -41,6 +42,7 @@ func Test_toConfig(t *testing.T) {
Expected: &tflint.Config{
Module: false,
Force: true,
ForceSet: true,
IgnoreModules: map[string]bool{},
Varfiles: []string{},
Variables: []string{},
Expand Down Expand Up @@ -173,13 +175,14 @@ func Test_toConfig(t *testing.T) {
Name: "--only",
Command: "./tflint --only aws_instance_invalid_type",
Expected: &tflint.Config{
Module: false,
Force: false,
IgnoreModules: map[string]bool{},
Varfiles: []string{},
Variables: []string{},
DisabledByDefault: true,
Only: []string{"aws_instance_invalid_type"},
Module: false,
Force: false,
IgnoreModules: map[string]bool{},
Varfiles: []string{},
Variables: []string{},
DisabledByDefault: true,
DisabledByDefaultSet: true,
Only: []string{"aws_instance_invalid_type"},
Rules: map[string]*tflint.RuleConfig{
"aws_instance_invalid_type": {
Name: "aws_instance_invalid_type",
Expand Down Expand Up @@ -226,6 +229,7 @@ func Test_toConfig(t *testing.T) {
Variables: []string{},
DisabledByDefault: false,
Format: "compact",
FormatSet: true,
Rules: map[string]*tflint.RuleConfig{},
Plugins: map[string]*tflint.PluginConfig{},
},
Expand Down
81 changes: 54 additions & 27 deletions tflint/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,27 @@ var validFormats = []string{

// Config describes the behavior of TFLint
type Config struct {
Module bool
Force bool
IgnoreModules map[string]bool
Varfiles []string
Variables []string
DisabledByDefault bool
Only []string
PluginDir string
Format string
Rules map[string]*RuleConfig
Plugins map[string]*PluginConfig
Module bool
ModuleSet bool

Force bool
ForceSet bool

DisabledByDefault bool
DisabledByDefaultSet bool

PluginDir string
PluginDirSet bool

Format string
FormatSet bool

Varfiles []string
Variables []string
Only []string
IgnoreModules map[string]bool
Rules map[string]*RuleConfig
Plugins map[string]*PluginConfig

sources map[string][]byte
}
Expand Down Expand Up @@ -185,10 +195,12 @@ func loadConfig(file afero.File) (*Config, error) {
for name, attr := range inner.Attributes {
switch name {
case "module":
config.ModuleSet = true
if err := gohcl.DecodeExpression(attr.Expr, nil, &config.Module); err != nil {
return config, err
}
case "force":
config.ForceSet = true
if err := gohcl.DecodeExpression(attr.Expr, nil, &config.Force); err != nil {
return config, err
}
Expand All @@ -205,14 +217,17 @@ func loadConfig(file afero.File) (*Config, error) {
return config, err
}
case "disabled_by_default":
config.DisabledByDefaultSet = true
if err := gohcl.DecodeExpression(attr.Expr, nil, &config.DisabledByDefault); err != nil {
return config, err
}
case "plugin_dir":
config.PluginDirSet = true
if err := gohcl.DecodeExpression(attr.Expr, nil, &config.PluginDir); err != nil {
return config, err
}
case "format":
config.FormatSet = true
if err := gohcl.DecodeExpression(attr.Expr, nil, &config.Format); err != nil {
return config, err
}
Expand Down Expand Up @@ -252,16 +267,22 @@ func loadConfig(file afero.File) (*Config, error) {

log.Printf("[DEBUG] Config loaded")
log.Printf("[DEBUG] Module: %t", config.Module)
log.Printf("[DEBUG] ModuleSet: %t", config.ModuleSet)
log.Printf("[DEBUG] Force: %t", config.Force)
log.Printf("[DEBUG] ForceSet: %t", config.ForceSet)
log.Printf("[DEBUG] DisabledByDefault: %t", config.DisabledByDefault)
log.Printf("[DEBUG] DisabledByDefaultSet: %t", config.DisabledByDefaultSet)
log.Printf("[DEBUG] PluginDir: %s", config.PluginDir)
log.Printf("[DEBUG] PluginDirSet: %t", config.PluginDirSet)
log.Printf("[DEBUG] Format: %s", config.Format)
log.Printf("[DEBUG] FormatSet: %t", config.FormatSet)
log.Printf("[DEBUG] Varfiles: %s", strings.Join(config.Varfiles, ", "))
log.Printf("[DEBUG] Variables: %s", strings.Join(config.Variables, ", "))
log.Printf("[DEBUG] Only: %s", strings.Join(config.Only, ", "))
log.Printf("[DEBUG] IgnoreModules:")
for name, ignore := range config.IgnoreModules {
log.Printf("[DEBUG] %s: %t", name, ignore)
}
log.Printf("[DEBUG] Varfiles: %s", strings.Join(config.Varfiles, ", "))
log.Printf("[DEBUG] Variables: %s", strings.Join(config.Variables, ", "))
log.Printf("[DEBUG] DisabledByDefault: %t", config.DisabledByDefault)
log.Printf("[DEBUG] PluginDir: %s", config.PluginDir)
log.Printf("[DEBUG] Format: %s", config.Format)
log.Printf("[DEBUG] Rules:")
for name, rule := range config.Rules {
log.Printf("[DEBUG] %s: %t", name, rule.Enabled)
Expand Down Expand Up @@ -328,29 +349,35 @@ func (c *Config) Sources() map[string][]byte {
// Merge merges the two configs and applies to itself.
// Since the argument takes precedence, it can be used as overwriting of the config.
func (c *Config) Merge(other *Config) {
if other.Module {
c.Module = true
if other.ModuleSet {
c.ModuleSet = true
c.Module = other.Module
}
if other.Force {
c.Force = true
if other.ForceSet {
c.ForceSet = true
c.Force = other.Force
}
if other.DisabledByDefault {
c.DisabledByDefault = true
if other.DisabledByDefaultSet {
c.DisabledByDefaultSet = true
c.DisabledByDefault = other.DisabledByDefault
}
if other.PluginDir != "" {
if other.PluginDirSet {
c.PluginDirSet = true
c.PluginDir = other.PluginDir
}
if other.Format != "" {
if other.FormatSet {
c.FormatSet = true
c.Format = other.Format
}

for name, ignore := range other.IgnoreModules {
c.IgnoreModules[name] = ignore
}
c.Varfiles = append(c.Varfiles, other.Varfiles...)
c.Variables = append(c.Variables, other.Variables...)
c.Only = append(c.Only, other.Only...)

for name, ignore := range other.IgnoreModules {
c.IgnoreModules[name] = ignore
}

for name, rule := range other.Rules {
// HACK: If you enable the rule through the CLI instead of the file, its hcl.Body will be nil.
// In this case, only override Enabled flag
Expand Down
Loading

0 comments on commit c8ff71c

Please sign in to comment.