github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/command/console_test.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"path/filepath"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/terraform/internal/configs/configschema"
    11  	"github.com/hashicorp/terraform/internal/providers"
    12  	"github.com/mitchellh/cli"
    13  	"github.com/zclconf/go-cty/cty"
    14  )
    15  
    16  // ConsoleCommand is tested primarily with tests in the "repl" package.
    17  // It is not tested here because the Console uses a readline-like library
    18  // that takes over stdin/stdout. It is difficult to test directly. The
    19  // core logic is tested in "repl"
    20  //
    21  // This file still contains some tests using the stdin-based input.
    22  
    23  func TestConsole_basic(t *testing.T) {
    24  	testCwd(t)
    25  
    26  	p := testProvider()
    27  	ui := cli.NewMockUi()
    28  	view, _ := testView(t)
    29  	c := &ConsoleCommand{
    30  		Meta: Meta{
    31  			testingOverrides: metaOverridesForProvider(p),
    32  			Ui:               ui,
    33  			View:             view,
    34  		},
    35  	}
    36  
    37  	var output bytes.Buffer
    38  	defer testStdinPipe(t, strings.NewReader("1+5\n"))()
    39  	outCloser := testStdoutCapture(t, &output)
    40  
    41  	args := []string{}
    42  	code := c.Run(args)
    43  	outCloser()
    44  	if code != 0 {
    45  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    46  	}
    47  
    48  	actual := output.String()
    49  	if actual != "6\n" {
    50  		t.Fatalf("bad: %q", actual)
    51  	}
    52  }
    53  
    54  func TestConsole_tfvars(t *testing.T) {
    55  	td := t.TempDir()
    56  	testCopyDir(t, testFixturePath("apply-vars"), td)
    57  	defer testChdir(t, td)()
    58  
    59  	// Write a terraform.tvars
    60  	varFilePath := filepath.Join(td, "terraform.tfvars")
    61  	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
    62  		t.Fatalf("err: %s", err)
    63  	}
    64  
    65  	p := testProvider()
    66  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
    67  		ResourceTypes: map[string]providers.Schema{
    68  			"test_instance": {
    69  				Block: &configschema.Block{
    70  					Attributes: map[string]*configschema.Attribute{
    71  						"value": {Type: cty.String, Optional: true},
    72  					},
    73  				},
    74  			},
    75  		},
    76  	}
    77  	ui := cli.NewMockUi()
    78  	view, _ := testView(t)
    79  	c := &ConsoleCommand{
    80  		Meta: Meta{
    81  			testingOverrides: metaOverridesForProvider(p),
    82  			Ui:               ui,
    83  			View:             view,
    84  		},
    85  	}
    86  
    87  	var output bytes.Buffer
    88  	defer testStdinPipe(t, strings.NewReader("var.foo\n"))()
    89  	outCloser := testStdoutCapture(t, &output)
    90  
    91  	args := []string{}
    92  	code := c.Run(args)
    93  	outCloser()
    94  	if code != 0 {
    95  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    96  	}
    97  
    98  	actual := output.String()
    99  	if actual != "\"bar\"\n" {
   100  		t.Fatalf("bad: %q", actual)
   101  	}
   102  }
   103  
   104  func TestConsole_unsetRequiredVars(t *testing.T) {
   105  	// This test is verifying that it's possible to run "terraform console"
   106  	// without providing values for all required variables, without
   107  	// "terraform console" producing an interactive prompt for those variables
   108  	// or producing errors. Instead, it should allow evaluation in that
   109  	// partial context but see the unset variables values as being unknown.
   110  	//
   111  	// This test fixture includes variable "foo" {}, which we are
   112  	// intentionally not setting here.
   113  	td := t.TempDir()
   114  	testCopyDir(t, testFixturePath("apply-vars"), td)
   115  	defer testChdir(t, td)()
   116  
   117  	p := testProvider()
   118  	p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
   119  		ResourceTypes: map[string]providers.Schema{
   120  			"test_instance": {
   121  				Block: &configschema.Block{
   122  					Attributes: map[string]*configschema.Attribute{
   123  						"value": {Type: cty.String, Optional: true},
   124  					},
   125  				},
   126  			},
   127  		},
   128  	}
   129  	ui := cli.NewMockUi()
   130  	view, _ := testView(t)
   131  	c := &ConsoleCommand{
   132  		Meta: Meta{
   133  			testingOverrides: metaOverridesForProvider(p),
   134  			Ui:               ui,
   135  			View:             view,
   136  		},
   137  	}
   138  
   139  	var output bytes.Buffer
   140  	defer testStdinPipe(t, strings.NewReader("var.foo\n"))()
   141  	outCloser := testStdoutCapture(t, &output)
   142  
   143  	args := []string{}
   144  	code := c.Run(args)
   145  	outCloser()
   146  
   147  	if code != 0 {
   148  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   149  	}
   150  
   151  	if got, want := output.String(), "(known after apply)\n"; got != want {
   152  		t.Fatalf("unexpected output\n got: %q\nwant: %q", got, want)
   153  	}
   154  }
   155  
   156  func TestConsole_variables(t *testing.T) {
   157  	td := t.TempDir()
   158  	testCopyDir(t, testFixturePath("variables"), td)
   159  	defer testChdir(t, td)()
   160  
   161  	p := testProvider()
   162  	ui := cli.NewMockUi()
   163  	view, _ := testView(t)
   164  	c := &ConsoleCommand{
   165  		Meta: Meta{
   166  			testingOverrides: metaOverridesForProvider(p),
   167  			Ui:               ui,
   168  			View:             view,
   169  		},
   170  	}
   171  
   172  	commands := map[string]string{
   173  		"var.foo\n":          "\"bar\"\n",
   174  		"var.snack\n":        "\"popcorn\"\n",
   175  		"var.secret_snack\n": "(sensitive)\n",
   176  		"local.snack_bar\n":  "[\n  \"popcorn\",\n  (sensitive),\n]\n",
   177  	}
   178  
   179  	args := []string{}
   180  
   181  	for cmd, val := range commands {
   182  		var output bytes.Buffer
   183  		defer testStdinPipe(t, strings.NewReader(cmd))()
   184  		outCloser := testStdoutCapture(t, &output)
   185  		code := c.Run(args)
   186  		outCloser()
   187  		if code != 0 {
   188  			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   189  		}
   190  
   191  		actual := output.String()
   192  		if output.String() != val {
   193  			t.Fatalf("bad: %q, expected %q", actual, val)
   194  		}
   195  	}
   196  }
   197  
   198  func TestConsole_modules(t *testing.T) {
   199  	td := t.TempDir()
   200  	testCopyDir(t, testFixturePath("modules"), td)
   201  	defer testChdir(t, td)()
   202  
   203  	p := applyFixtureProvider()
   204  	ui := cli.NewMockUi()
   205  	view, _ := testView(t)
   206  
   207  	c := &ConsoleCommand{
   208  		Meta: Meta{
   209  			testingOverrides: metaOverridesForProvider(p),
   210  			Ui:               ui,
   211  			View:             view,
   212  		},
   213  	}
   214  
   215  	commands := map[string]string{
   216  		"module.child.myoutput\n":          "\"bar\"\n",
   217  		"module.count_child[0].myoutput\n": "\"bar\"\n",
   218  		"local.foo\n":                      "3\n",
   219  	}
   220  
   221  	args := []string{}
   222  
   223  	for cmd, val := range commands {
   224  		var output bytes.Buffer
   225  		defer testStdinPipe(t, strings.NewReader(cmd))()
   226  		outCloser := testStdoutCapture(t, &output)
   227  		code := c.Run(args)
   228  		outCloser()
   229  		if code != 0 {
   230  			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   231  		}
   232  
   233  		actual := output.String()
   234  		if output.String() != val {
   235  			t.Fatalf("bad: %q, expected %q", actual, val)
   236  		}
   237  	}
   238  }