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  }