github.com/tetrafolium/tflint@v0.8.0/tflint/config_test.go (about)

     1  package tflint
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/google/go-cmp/cmp"
    10  	"github.com/wata727/tflint/client"
    11  )
    12  
    13  func Test_LoadConfig(t *testing.T) {
    14  	currentDir, err := os.Getwd()
    15  	if err != nil {
    16  		t.Fatal(err)
    17  	}
    18  
    19  	cases := []struct {
    20  		Name     string
    21  		File     string
    22  		Fallback string
    23  		Expected *Config
    24  	}{
    25  		{
    26  			Name: "load file",
    27  			File: filepath.Join(currentDir, "test-fixtures", "config", "config.hcl"),
    28  			Expected: &Config{
    29  				DeepCheck: true,
    30  				AwsCredentials: client.AwsCredentials{
    31  					AccessKey: "AWS_ACCESS_KEY",
    32  					SecretKey: "AWS_SECRET_KEY",
    33  					Region:    "us-east-1",
    34  				},
    35  				IgnoreRule: map[string]bool{
    36  					"aws_instance_invalid_type":  true,
    37  					"aws_instance_previous_type": true,
    38  				},
    39  				IgnoreModule: map[string]bool{
    40  					"github.com/wata727/example-module": true,
    41  				},
    42  				Varfile:          []string{"example1.tfvars", "example2.tfvars"},
    43  				TerraformVersion: "0.9.11",
    44  				Rules: map[string]*RuleConfig{
    45  					"aws_instance_invalid_type": {
    46  						Name:    "aws_instance_invalid_type",
    47  						Enabled: false,
    48  					},
    49  					"aws_instance_previous_type": {
    50  						Name:    "aws_instance_previous_type",
    51  						Enabled: false,
    52  					},
    53  				},
    54  			},
    55  		},
    56  		{
    57  			Name:     "empty file",
    58  			File:     filepath.Join(currentDir, "test-fixtures", "config", "empty.hcl"),
    59  			Expected: EmptyConfig(),
    60  		},
    61  		{
    62  			Name:     "fallback",
    63  			File:     filepath.Join(currentDir, "test-fixtures", "config", "not_found.hcl"),
    64  			Fallback: filepath.Join(currentDir, "test-fixtures", "config", "fallback.hcl"),
    65  			Expected: &Config{
    66  				DeepCheck: true,
    67  				AwsCredentials: client.AwsCredentials{
    68  					AccessKey: "AWS_ACCESS_KEY",
    69  					SecretKey: "AWS_SECRET_KEY",
    70  					Region:    "us-east-1",
    71  				},
    72  				IgnoreRule:       map[string]bool{},
    73  				IgnoreModule:     map[string]bool{},
    74  				Varfile:          []string{},
    75  				TerraformVersion: "0.9.11",
    76  				Rules:            map[string]*RuleConfig{},
    77  			},
    78  		},
    79  		{
    80  			Name:     "fallback file not found",
    81  			File:     filepath.Join(currentDir, "test-fixtures", "config", "not_found.hcl"),
    82  			Fallback: filepath.Join(currentDir, "test-fixtures", "config", "fallback_not_found.hcl"),
    83  			Expected: EmptyConfig(),
    84  		},
    85  	}
    86  
    87  	for _, tc := range cases {
    88  		originalDefault := defaultConfigFile
    89  		defaultConfigFile = filepath.Join(currentDir, "test-fixtures", "config", "not_found.hcl")
    90  		originalFallback := fallbackConfigFile
    91  		fallbackConfigFile = tc.Fallback
    92  
    93  		ret, err := LoadConfig(tc.File)
    94  		if err != nil {
    95  			t.Fatalf("Failed `%s` test: Unexpected error occurred: %s", tc.Name, err)
    96  		}
    97  
    98  		if !cmp.Equal(tc.Expected, ret) {
    99  			t.Fatalf("Failed `%s` test: diff=%s", tc.Name, cmp.Diff(tc.Expected, ret))
   100  		}
   101  
   102  		defaultConfigFile = originalDefault
   103  		fallbackConfigFile = originalFallback
   104  	}
   105  }
   106  
   107  func Test_LoadConfig_error(t *testing.T) {
   108  	currentDir, err := os.Getwd()
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  
   113  	cases := []struct {
   114  		Name     string
   115  		File     string
   116  		Expected string
   117  	}{
   118  		{
   119  			Name: "file not found",
   120  			File: filepath.Join(currentDir, "test-fixtures", "config", "not_found.hcl"),
   121  			Expected: fmt.Sprintf(
   122  				"`%s` is not found",
   123  				filepath.Join(currentDir, "test-fixtures", "config", "not_found.hcl"),
   124  			),
   125  		},
   126  		{
   127  			Name: "syntax error",
   128  			File: filepath.Join(currentDir, "test-fixtures", "config", "syntax_error.hcl"),
   129  			Expected: fmt.Sprintf(
   130  				"%s:1,1-2: Invalid character; The \"`\" character is not valid. To create a multi-line string, use the \"heredoc\" syntax, like \"<<EOT\"., and 1 other diagnostic(s)",
   131  				filepath.Join(currentDir, "test-fixtures", "config", "syntax_error.hcl"),
   132  			),
   133  		},
   134  		{
   135  			Name: "invalid config",
   136  			File: filepath.Join(currentDir, "test-fixtures", "config", "invalid.hcl"),
   137  			Expected: fmt.Sprintf(
   138  				"%s:1,34-42: Extraneous label for rule; Only 1 labels (name) are expected for rule blocks.",
   139  				filepath.Join(currentDir, "test-fixtures", "config", "invalid.hcl"),
   140  			),
   141  		},
   142  	}
   143  
   144  	for _, tc := range cases {
   145  		_, err := LoadConfig(tc.File)
   146  		if err == nil {
   147  			t.Fatalf("Failed `%s` test: Expected error does not occurred", tc.Name)
   148  		}
   149  
   150  		if err.Error() != tc.Expected {
   151  			t.Fatalf("Failed `%s` test: expected error is `%s`, but get `%s`", tc.Name, tc.Expected, err.Error())
   152  		}
   153  	}
   154  }
   155  
   156  func Test_Merge(t *testing.T) {
   157  	cfg := &Config{
   158  		DeepCheck: true,
   159  		AwsCredentials: client.AwsCredentials{
   160  			AccessKey: "access_key",
   161  			SecretKey: "secret_key",
   162  			Region:    "us-east-1",
   163  		},
   164  		IgnoreModule: map[string]bool{
   165  			"github.com/wata727/example-1": true,
   166  			"github.com/wata727/example-2": false,
   167  		},
   168  		IgnoreRule: map[string]bool{
   169  			"aws_instance_invalid_type": false,
   170  			"aws_instance_invalid_ami":  true,
   171  		},
   172  		Varfile:          []string{"example1.tfvars", "example2.tfvars"},
   173  		TerraformVersion: "0.11.1",
   174  		Rules: map[string]*RuleConfig{
   175  			"aws_instance_invalid_type": {
   176  				Name:    "aws_instance_invalid_type",
   177  				Enabled: false,
   178  			},
   179  			"aws_instance_invalid_ami": {
   180  				Name:    "aws_instance_invalid_ami",
   181  				Enabled: true,
   182  			},
   183  		},
   184  	}
   185  
   186  	cases := []struct {
   187  		Name     string
   188  		Base     *Config
   189  		Other    *Config
   190  		Expected *Config
   191  	}{
   192  		{
   193  			Name:     "empty",
   194  			Base:     EmptyConfig(),
   195  			Other:    EmptyConfig(),
   196  			Expected: EmptyConfig(),
   197  		},
   198  		{
   199  			Name:     "prefer base",
   200  			Base:     cfg,
   201  			Other:    EmptyConfig(),
   202  			Expected: cfg,
   203  		},
   204  		{
   205  			Name:     "prefer other",
   206  			Base:     EmptyConfig(),
   207  			Other:    cfg,
   208  			Expected: cfg,
   209  		},
   210  		{
   211  			Name: "override and merge",
   212  			Base: &Config{
   213  				DeepCheck: true,
   214  				AwsCredentials: client.AwsCredentials{
   215  					AccessKey: "access_key",
   216  					SecretKey: "secret_key",
   217  					Profile:   "production",
   218  					Region:    "us-east-1",
   219  				},
   220  				IgnoreModule: map[string]bool{
   221  					"github.com/wata727/example-1": true,
   222  					"github.com/wata727/example-2": false,
   223  				},
   224  				IgnoreRule: map[string]bool{
   225  					"aws_instance_invalid_type": false,
   226  					"aws_instance_invalid_ami":  true,
   227  				},
   228  				Varfile:          []string{"example1.tfvars", "example2.tfvars"},
   229  				TerraformVersion: "0.11.1",
   230  				Rules: map[string]*RuleConfig{
   231  					"aws_instance_invalid_type": {
   232  						Name:    "aws_instance_invalid_type",
   233  						Enabled: false,
   234  					},
   235  					"aws_instance_invalid_ami": {
   236  						Name:    "aws_instance_invalid_ami",
   237  						Enabled: true,
   238  					},
   239  				},
   240  			},
   241  			Other: &Config{
   242  				DeepCheck: false,
   243  				AwsCredentials: client.AwsCredentials{
   244  					AccessKey: "ACCESS_KEY",
   245  					SecretKey: "SECRET_KEY",
   246  					Region:    "ap-northeast-1",
   247  				},
   248  				IgnoreModule: map[string]bool{
   249  					"github.com/wata727/example-2": true,
   250  					"github.com/wata727/example-3": false,
   251  				},
   252  				IgnoreRule: map[string]bool{
   253  					"aws_instance_invalid_ami":   false,
   254  					"aws_instance_previous_type": true,
   255  				},
   256  				Varfile:          []string{"example3.tfvars"},
   257  				TerraformVersion: "0.12.0",
   258  				Rules: map[string]*RuleConfig{
   259  					"aws_instance_invalid_ami": {
   260  						Name:    "aws_instance_invalid_ami",
   261  						Enabled: false,
   262  					},
   263  					"aws_instance_previous_type": {
   264  						Name:    "aws_instance_previous_type",
   265  						Enabled: false,
   266  					},
   267  				},
   268  			},
   269  			Expected: &Config{
   270  				DeepCheck: true, // DeepCheck will not override
   271  				AwsCredentials: client.AwsCredentials{
   272  					AccessKey: "ACCESS_KEY",
   273  					SecretKey: "SECRET_KEY",
   274  					Profile:   "production",
   275  					Region:    "ap-northeast-1",
   276  				},
   277  				IgnoreModule: map[string]bool{
   278  					"github.com/wata727/example-1": true,
   279  					"github.com/wata727/example-2": true,
   280  					"github.com/wata727/example-3": false,
   281  				},
   282  				IgnoreRule: map[string]bool{
   283  					"aws_instance_invalid_type":  false,
   284  					"aws_instance_invalid_ami":   false,
   285  					"aws_instance_previous_type": true,
   286  				},
   287  				Varfile:          []string{"example1.tfvars", "example2.tfvars", "example3.tfvars"},
   288  				TerraformVersion: "0.12.0",
   289  				Rules: map[string]*RuleConfig{
   290  					"aws_instance_invalid_type": {
   291  						Name:    "aws_instance_invalid_type",
   292  						Enabled: false,
   293  					},
   294  					"aws_instance_invalid_ami": {
   295  						Name:    "aws_instance_invalid_ami",
   296  						Enabled: false,
   297  					},
   298  					"aws_instance_previous_type": {
   299  						Name:    "aws_instance_previous_type",
   300  						Enabled: false,
   301  					},
   302  				},
   303  			},
   304  		},
   305  	}
   306  
   307  	for _, tc := range cases {
   308  		ret := tc.Base.Merge(tc.Other)
   309  		if !cmp.Equal(tc.Expected, ret) {
   310  			t.Fatalf("Failed `%s` test: diff=%s", tc.Name, cmp.Diff(tc.Expected, ret))
   311  		}
   312  	}
   313  }
   314  
   315  func Test_copy(t *testing.T) {
   316  	cfg := &Config{
   317  		DeepCheck: true,
   318  		AwsCredentials: client.AwsCredentials{
   319  			AccessKey: "access_key",
   320  			SecretKey: "secret_key",
   321  			Region:    "us-east-1",
   322  		},
   323  		IgnoreModule: map[string]bool{
   324  			"github.com/wata727/example-1": true,
   325  			"github.com/wata727/example-2": false,
   326  		},
   327  		IgnoreRule: map[string]bool{
   328  			"aws_instance_invalid_type": false,
   329  			"aws_instance_invalid_ami":  true,
   330  		},
   331  		Varfile:          []string{"example1.tfvars", "example2.tfvars"},
   332  		TerraformVersion: "0.11.1",
   333  		Rules: map[string]*RuleConfig{
   334  			"aws_instance_invalid_type": {
   335  				Name:    "aws_instance_invalid_type",
   336  				Enabled: false,
   337  			},
   338  			"aws_instance_invalid_ami": {
   339  				Name:    "aws_instance_invalid_ami",
   340  				Enabled: true,
   341  			},
   342  		},
   343  	}
   344  
   345  	cases := []struct {
   346  		Name       string
   347  		SideEffect func(*Config)
   348  	}{
   349  		{
   350  			Name: "DeepCheck",
   351  			SideEffect: func(c *Config) {
   352  				c.DeepCheck = false
   353  			},
   354  		},
   355  		{
   356  			Name: "AwsCredentials",
   357  			SideEffect: func(c *Config) {
   358  				c.AwsCredentials = client.AwsCredentials{
   359  					Profile: "production",
   360  					Region:  "us-east-1",
   361  				}
   362  			},
   363  		},
   364  		{
   365  			Name: "IgnoreModule",
   366  			SideEffect: func(c *Config) {
   367  				c.IgnoreModule["github.com/wata727/example-1"] = false
   368  			},
   369  		},
   370  		{
   371  			Name: "IgnoreRule",
   372  			SideEffect: func(c *Config) {
   373  				c.IgnoreRule["aws_instance_invalid_type"] = true
   374  			},
   375  		},
   376  		{
   377  			Name: "Varfile",
   378  			SideEffect: func(c *Config) {
   379  				c.Varfile = append(c.Varfile, "new.tfvars")
   380  			},
   381  		},
   382  		{
   383  			Name: "TerraformVersion",
   384  			SideEffect: func(c *Config) {
   385  				c.TerraformVersion = "0.12.0"
   386  			},
   387  		},
   388  		{
   389  			Name: "Rules",
   390  			SideEffect: func(c *Config) {
   391  				c.Rules["aws_instance_invalid_type"].Enabled = true
   392  			},
   393  		},
   394  	}
   395  
   396  	for _, tc := range cases {
   397  		ret := cfg.copy()
   398  		if !cmp.Equal(cfg, ret) {
   399  			t.Fatalf("The copied config doesn't match original: Diff=%s", cmp.Diff(cfg, ret))
   400  		}
   401  
   402  		tc.SideEffect(ret)
   403  		if cmp.Equal(cfg, ret) {
   404  			t.Fatalf("The original was changed when updating `%s`", tc.Name)
   405  		}
   406  	}
   407  }