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