github.com/terraform-linters/tflint@v0.51.2-0.20240520175844-3750771571b6/integrationtest/inspection/inspection_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "log" 9 "os" 10 "path/filepath" 11 "runtime" 12 "strings" 13 "testing" 14 "text/template" 15 16 "github.com/google/go-cmp/cmp" 17 "github.com/terraform-linters/tflint/cmd" 18 "github.com/terraform-linters/tflint/formatter" 19 "github.com/terraform-linters/tflint/tflint" 20 ) 21 22 func TestMain(m *testing.M) { 23 log.SetOutput(io.Discard) 24 os.Exit(m.Run()) 25 } 26 27 type meta struct { 28 Version string 29 } 30 31 func TestIntegration(t *testing.T) { 32 cases := []struct { 33 Name string 34 Command string 35 Env map[string]string 36 Dir string 37 }{ 38 { 39 Name: "basic", 40 Command: "./tflint --format json", 41 Dir: "basic", 42 }, 43 { 44 Name: "override", 45 Command: "./tflint --format json", 46 Dir: "override", 47 }, 48 { 49 Name: "variables", 50 Command: "./tflint --format json --var-file variables.tfvars --var var=var", 51 Dir: "variables", 52 }, 53 { 54 Name: "module", 55 Command: "./tflint --format json --ignore-module ./ignore_module", 56 Dir: "module", 57 }, 58 { 59 Name: "without module init", 60 Command: "./tflint --format json", 61 Dir: "without_module_init", 62 }, 63 { 64 Name: "with module init", 65 Command: "./tflint --format json --call-module-type all", 66 Dir: "with_module_init", 67 }, 68 { 69 Name: "no calling module", 70 Command: "./tflint --format json --call-module-type none", 71 Dir: "no_calling_module", 72 }, 73 { 74 Name: "plugin", 75 Command: "./tflint --format json", 76 Dir: "plugin", 77 }, 78 { 79 Name: "jsonsyntax", 80 Command: "./tflint --format json", 81 Dir: "jsonsyntax", 82 }, 83 { 84 Name: "path", 85 Command: "./tflint --format json", 86 Dir: "path", 87 }, 88 { 89 Name: "init from cwd", 90 Command: "./tflint --format json", 91 Dir: "init-cwd/root", 92 }, 93 { 94 Name: "enable rule which has required configuration by CLI options", 95 Command: "./tflint --format json --enable-rule aws_s3_bucket_with_config_example", 96 Dir: "enable-required-config-rule-by-cli", 97 }, 98 { 99 Name: "enable rule which does not have required configuration by CLI options", 100 Command: "./tflint --format json --enable-rule aws_db_instance_with_default_config_example", 101 Dir: "enable-config-rule-by-cli", 102 }, 103 { 104 Name: "heredoc", 105 Command: "./tflint --format json", 106 Dir: "heredoc", 107 }, 108 { 109 Name: "config parse error with HCL metadata", 110 Command: "./tflint --format json", 111 Dir: "bad-config", 112 }, 113 { 114 Name: "conditional resources", 115 Command: "./tflint --format json", 116 Dir: "conditional", 117 }, 118 { 119 Name: "dynamic blocks", 120 Command: "./tflint --format json", 121 Dir: "dynblock", 122 }, 123 { 124 Name: "unknown dynamic blocks", 125 Command: "./tflint --format json", 126 Dir: "dynblock-unknown", 127 }, 128 { 129 Name: "provider config", 130 Command: "./tflint --format json", 131 Dir: "provider-config", 132 }, 133 { 134 Name: "rule config", 135 Command: "./tflint --format json", 136 Dir: "rule-config", 137 }, 138 { 139 Name: "disabled rules", 140 Command: "./tflint --format json", 141 Dir: "disabled-rules", 142 }, 143 { 144 Name: "cty-based eval", 145 Command: "./tflint --format json", 146 Dir: "cty-based-eval", 147 }, 148 { 149 Name: "map attribute eval", 150 Command: "./tflint --format json", 151 Dir: "map-attribute", 152 }, 153 { 154 Name: "rule config with --enable-rule", 155 Command: "tflint --enable-rule aws_s3_bucket_with_config_example --format json", 156 Dir: "rule-config", 157 }, 158 { 159 Name: "rule config with --only", 160 Command: "tflint --only aws_s3_bucket_with_config_example --format json", 161 Dir: "rule-config", 162 }, 163 { 164 Name: "rule config without required attributes", 165 Command: "tflint --format json", 166 Dir: "rule-required-config", 167 }, 168 { 169 Name: "rule config without optional attributes", 170 Command: "tflint --format json", 171 Dir: "rule-optional-config", 172 }, 173 { 174 Name: "enable plugin by CLI", 175 Command: "tflint --enable-plugin testing --format json", 176 Dir: "enable-plugin-by-cli", 177 }, 178 { 179 Name: "eval on root context", 180 Command: "tflint --format json", 181 Dir: "eval-on-root-context", 182 }, 183 { 184 Name: "sensitve variable", 185 Command: "tflint --format json", 186 Dir: "sensitive", 187 }, 188 { 189 Name: "just attributes", 190 Command: "tflint --format json", 191 Dir: "just-attributes", 192 }, 193 { 194 Name: "incompatible host version", 195 Command: "tflint --format json", 196 Dir: "incompatible-host", 197 }, 198 { 199 Name: "expand resources/modules", 200 Command: "tflint --format json", 201 Dir: "expand", 202 }, 203 { 204 Name: "chdir", 205 Command: "tflint --chdir dir --var-file from_cli.tfvars --format json", 206 Dir: "chdir", 207 }, 208 { 209 Name: "functions", 210 Command: "tflint --format json", 211 Dir: "functions", 212 }, 213 } 214 215 // Disable the bundled plugin because the `os.Executable()` is go(1) in the tests 216 tflint.DisableBundledPlugin = true 217 defer func() { 218 tflint.DisableBundledPlugin = false 219 }() 220 221 dir, _ := os.Getwd() 222 for _, tc := range cases { 223 t.Run(tc.Name, func(t *testing.T) { 224 testDir := filepath.Join(dir, tc.Dir) 225 226 defer func() { 227 if err := os.Chdir(dir); err != nil { 228 t.Fatal(err) 229 } 230 }() 231 if err := os.Chdir(testDir); err != nil { 232 t.Fatal(err) 233 } 234 235 if tc.Env != nil { 236 for k, v := range tc.Env { 237 t.Setenv(k, v) 238 } 239 } 240 241 outStream, errStream := new(bytes.Buffer), new(bytes.Buffer) 242 cli, err := cmd.NewCLI(outStream, errStream) 243 if err != nil { 244 t.Fatal(err) 245 } 246 args := strings.Split(tc.Command, " ") 247 248 cli.Run(args) 249 250 rawWant, err := readResultFile(testDir) 251 if err != nil { 252 t.Fatal(err) 253 } 254 var want *formatter.JSONOutput 255 if err := json.Unmarshal(rawWant, &want); err != nil { 256 t.Fatal(err) 257 } 258 259 var got *formatter.JSONOutput 260 if err := json.Unmarshal(outStream.Bytes(), &got); err != nil { 261 t.Fatal(err) 262 } 263 264 if diff := cmp.Diff(got, want); diff != "" { 265 t.Fatal(diff) 266 } 267 }) 268 } 269 } 270 271 func readResultFile(dir string) ([]byte, error) { 272 resultFile := "result.json" 273 if runtime.GOOS == "windows" { 274 if _, err := os.Stat(filepath.Join(dir, "result_windows.json")); !os.IsNotExist(err) { 275 resultFile = "result_windows.json" 276 } 277 } 278 if _, err := os.Stat(fmt.Sprintf("%s.tmpl", resultFile)); !os.IsNotExist(err) { 279 resultFile = fmt.Sprintf("%s.tmpl", resultFile) 280 } 281 282 if !strings.HasSuffix(resultFile, ".tmpl") { 283 return os.ReadFile(filepath.Join(dir, resultFile)) 284 } 285 286 want := new(bytes.Buffer) 287 tmpl := template.Must(template.ParseFiles(filepath.Join(dir, resultFile))) 288 if err := tmpl.Execute(want, meta{Version: tflint.Version.String()}); err != nil { 289 return nil, err 290 } 291 return want.Bytes(), nil 292 }