mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-02 12:17:39 -06:00
8b2b569d6e
Use a slightly modified value renderer from terraform-provider-testing to display values in the console REPL, as well as outputs from the apply and outputs subcommands. Derived from code in this repository, MIT licensed: https://github.com/apparentlymart/terraform-provider-testing Note that this is technically a breaking change for the console subcommand, which would previously error if the user attempted to render an unknown value (such as an unset variable). This was marked as an unintentional side effect, with the goal being the new behaviour of rendering "(unknown)", which is why I changed the behaviour in this commit.
194 lines
4.6 KiB
Go
194 lines
4.6 KiB
Go
package command
|
|
|
|
import (
|
|
"bytes"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
|
"github.com/hashicorp/terraform/helper/copy"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
"github.com/mitchellh/cli"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
// ConsoleCommand is tested primarily with tests in the "repl" package.
|
|
// It is not tested here because the Console uses a readline-like library
|
|
// that takes over stdin/stdout. It is difficult to test directly. The
|
|
// core logic is tested in "repl"
|
|
//
|
|
// This file still contains some tests using the stdin-based input.
|
|
|
|
func TestConsole_basic(t *testing.T) {
|
|
tmp, cwd := testCwd(t)
|
|
defer testFixCwd(t, tmp, cwd)
|
|
|
|
p := testProvider()
|
|
ui := cli.NewMockUi()
|
|
c := &ConsoleCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
var output bytes.Buffer
|
|
defer testStdinPipe(t, strings.NewReader("1+5\n"))()
|
|
outCloser := testStdoutCapture(t, &output)
|
|
|
|
args := []string{}
|
|
code := c.Run(args)
|
|
outCloser()
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := output.String()
|
|
if actual != "6\n" {
|
|
t.Fatalf("bad: %q", actual)
|
|
}
|
|
}
|
|
|
|
func TestConsole_tfvars(t *testing.T) {
|
|
tmp, cwd := testCwd(t)
|
|
defer testFixCwd(t, tmp, cwd)
|
|
|
|
// Write a terraform.tvars
|
|
varFilePath := filepath.Join(tmp, "terraform.tfvars")
|
|
if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
|
|
t.Fatalf("err: %s", err)
|
|
}
|
|
|
|
p := testProvider()
|
|
p.GetSchemaReturn = &terraform.ProviderSchema{
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
"test_instance": {
|
|
Attributes: map[string]*configschema.Attribute{
|
|
"value": {Type: cty.String, Optional: true},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
ui := cli.NewMockUi()
|
|
c := &ConsoleCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
var output bytes.Buffer
|
|
defer testStdinPipe(t, strings.NewReader("var.foo\n"))()
|
|
outCloser := testStdoutCapture(t, &output)
|
|
|
|
args := []string{
|
|
testFixturePath("apply-vars"),
|
|
}
|
|
code := c.Run(args)
|
|
outCloser()
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := output.String()
|
|
if actual != "\"bar\"\n" {
|
|
t.Fatalf("bad: %q", actual)
|
|
}
|
|
}
|
|
|
|
func TestConsole_unsetRequiredVars(t *testing.T) {
|
|
// This test is verifying that it's possible to run "terraform console"
|
|
// without providing values for all required variables, without
|
|
// "terraform console" producing an interactive prompt for those variables
|
|
// or producing errors. Instead, it should allow evaluation in that
|
|
// partial context but see the unset variables values as being unknown.
|
|
|
|
tmp, cwd := testCwd(t)
|
|
defer testFixCwd(t, tmp, cwd)
|
|
|
|
p := testProvider()
|
|
p.GetSchemaReturn = &terraform.ProviderSchema{
|
|
ResourceTypes: map[string]*configschema.Block{
|
|
"test_instance": {
|
|
Attributes: map[string]*configschema.Attribute{
|
|
"value": {Type: cty.String, Optional: true},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
ui := cli.NewMockUi()
|
|
c := &ConsoleCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
var output bytes.Buffer
|
|
defer testStdinPipe(t, strings.NewReader("var.foo\n"))()
|
|
outCloser := testStdoutCapture(t, &output)
|
|
|
|
args := []string{
|
|
// This test fixture includes variable "foo" {}, which we are
|
|
// intentionally not setting here.
|
|
testFixturePath("apply-vars"),
|
|
}
|
|
code := c.Run(args)
|
|
outCloser()
|
|
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
if got, want := output.String(), "(known after apply)\n"; got != want {
|
|
t.Fatalf("unexpected output\n got: %q\nwant: %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestConsole_modules(t *testing.T) {
|
|
td := tempDir(t)
|
|
copy.CopyDir(testFixturePath("modules"), td)
|
|
defer os.RemoveAll(td)
|
|
defer testChdir(t, td)()
|
|
|
|
p := applyFixtureProvider()
|
|
ui := cli.NewMockUi()
|
|
|
|
c := &ConsoleCommand{
|
|
Meta: Meta{
|
|
testingOverrides: metaOverridesForProvider(p),
|
|
Ui: ui,
|
|
},
|
|
}
|
|
|
|
commands := map[string]string{
|
|
"module.child.myoutput\n": "\"bar\"\n",
|
|
"module.count_child[0].myoutput\n": "\"bar\"\n",
|
|
"local.foo\n": "3\n",
|
|
}
|
|
|
|
args := []string{
|
|
testFixturePath("modules"),
|
|
}
|
|
|
|
for cmd, val := range commands {
|
|
var output bytes.Buffer
|
|
defer testStdinPipe(t, strings.NewReader(cmd))()
|
|
outCloser := testStdoutCapture(t, &output)
|
|
code := c.Run(args)
|
|
outCloser()
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
actual := output.String()
|
|
if output.String() != val {
|
|
t.Fatalf("bad: %q, expected %q", actual, val)
|
|
}
|
|
}
|
|
}
|