github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/internal/command/console_test.go (about)

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