terraform: add variables to Interpolator value
Fixes #10412 The context wasn't properly adding variable values to the Interpolator instance which made it so that the `console` command couldn't access variables set via tfvars and the CLI. This also adds better test coverage in command itself for this.
This commit is contained in:
parent
3288b0bf9f
commit
2f8bf5b7ec
|
@ -2,6 +2,7 @@ package command
|
|||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -336,3 +337,67 @@ func testFixCwd(t *testing.T, tmp, cwd string) {
|
|||
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
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// 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 := 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,
|
||||
State: c.state.DeepCopy(),
|
||||
StateLock: &stateLock,
|
||||
VariableValues: map[string]interface{}{},
|
||||
VariableValues: c.variables,
|
||||
VariableValuesLock: &varLock,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue