Merge pull request #10446 from hashicorp/b-console-var
terraform: add variables to Interpolator value
This commit is contained in:
commit
ee4999003c
|
@ -2,6 +2,7 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
@ -336,3 +337,67 @@ func testFixCwd(t *testing.T, tmp, cwd string) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testStdinPipe changes os.Stdin to be a pipe that sends the data from
|
||||||
|
// the reader before closing the pipe.
|
||||||
|
//
|
||||||
|
// The returned function should be deferred to properly clean up and restore
|
||||||
|
// the original stdin.
|
||||||
|
func testStdinPipe(t *testing.T, src io.Reader) func() {
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify stdin to point to our new pipe
|
||||||
|
old := os.Stdin
|
||||||
|
os.Stdin = r
|
||||||
|
|
||||||
|
// Copy the data from the reader to the pipe
|
||||||
|
go func() {
|
||||||
|
defer w.Close()
|
||||||
|
io.Copy(w, src)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
// Close our read end
|
||||||
|
r.Close()
|
||||||
|
|
||||||
|
// Reset stdin
|
||||||
|
os.Stdin = old
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify os.Stdout to write to the given buffer. Note that this is generally
|
||||||
|
// not useful since the commands are configured to write to a cli.Ui, not
|
||||||
|
// Stdout directly. Commands like `console` though use the raw stdout.
|
||||||
|
func testStdoutCapture(t *testing.T, dst io.Writer) func() {
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify stdout
|
||||||
|
old := os.Stdout
|
||||||
|
os.Stdout = w
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(doneCh)
|
||||||
|
defer r.Close()
|
||||||
|
io.Copy(dst, r)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
// Close the writer end of the pipe
|
||||||
|
w.Sync()
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
// Reset stdout
|
||||||
|
os.Stdout = old
|
||||||
|
|
||||||
|
// Wait for the data copy to complete to avoid a race reading data
|
||||||
|
<-doneCh
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,86 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
// ConsoleCommand is tested primarily with tests in the "repl" package.
|
// ConsoleCommand is tested primarily with tests in the "repl" package.
|
||||||
// It is not tested here because the Console uses a readline-like library
|
// 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
|
// that takes over stdin/stdout. It is difficult to test directly. The
|
||||||
// core logic is tested in "repl"
|
// 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 := new(cli.MockUi)
|
||||||
|
c := &ConsoleCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(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()
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &ConsoleCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ func (c *Context) Interpolater() *Interpolater {
|
||||||
Module: c.module,
|
Module: c.module,
|
||||||
State: c.state.DeepCopy(),
|
State: c.state.DeepCopy(),
|
||||||
StateLock: &stateLock,
|
StateLock: &stateLock,
|
||||||
VariableValues: map[string]interface{}{},
|
VariableValues: c.variables,
|
||||||
VariableValuesLock: &varLock,
|
VariableValuesLock: &varLock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue