command/meta: validate config immediately

* config: test for validating multi-vars (passes)

* command/plan: test invalid run

* command/meta: validate module on load
This commit is contained in:
Mitchell Hashimoto 2016-09-03 15:26:49 -07:00 committed by James Nugent
parent d31656af91
commit 609219fc65
8 changed files with 65 additions and 4 deletions

View File

@ -2,6 +2,7 @@ package command
import ( import (
"fmt" "fmt"
"log"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
@ -27,7 +28,11 @@ const DefaultBackupExtension = ".backup"
const DefaultParallelism = 10 const DefaultParallelism = 10
func validateContext(ctx *terraform.Context, ui cli.Ui) bool { func validateContext(ctx *terraform.Context, ui cli.Ui) bool {
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 { log.Println("[INFO] Validating the context...")
ws, es := ctx.Validate()
log.Printf("[INFO] Validation result: %d warnings, %d errors", len(ws), len(es))
if len(ws) > 0 || len(es) > 0 {
ui.Output( ui.Output(
"There are warnings and/or errors related to your configuration. Please\n" + "There are warnings and/or errors related to your configuration. Please\n" +
"fix these before continuing.\n") "fix these before continuing.\n")

View File

@ -165,6 +165,11 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
return nil, false, fmt.Errorf("Error downloading modules: %s", err) return nil, false, fmt.Errorf("Error downloading modules: %s", err)
} }
// Validate the module right away
if err := mod.Validate(); err != nil {
return nil, false, err
}
opts.Module = mod opts.Module = mod
opts.Parallelism = copts.Parallelism opts.Parallelism = copts.Parallelism
opts.State = state.State() opts.State = state.State()

View File

@ -395,6 +395,40 @@ func TestPlan_statePast(t *testing.T) {
} }
} }
func TestPlan_validate(t *testing.T) {
// This is triggered by not asking for input so we have to set this to false
test = false
defer func() { test = true }()
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("err: %s", err)
}
if err := os.Chdir(testFixturePath("plan-invalid")); err != nil {
t.Fatalf("err: %s", err)
}
defer os.Chdir(cwd)
p := testProvider()
ui := new(cli.MockUi)
c := &PlanCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}
args := []string{}
if code := c.Run(args); code != 1 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}
actual := ui.ErrorWriter.String()
if !strings.Contains(actual, "can't reference") {
t.Fatalf("bad: %s", actual)
}
}
func TestPlan_vars(t *testing.T) { func TestPlan_vars(t *testing.T) {
p := testProvider() p := testProvider()
ui := new(cli.MockUi) ui := new(cli.MockUi)

View File

@ -765,8 +765,7 @@ func pushTFVars() []atlas.TFVar {
return []atlas.TFVar{ return []atlas.TFVar{
{"bar", "foo", false}, {"bar", "foo", false},
{"baz", `{ {"baz", `{
A = "a" A = "a"
interp = "${file("t.txt")}"
}`, true}, }`, true},
{"fob", `["a", "quotes \"in\" quotes"]`, true}, {"fob", `["a", "quotes \"in\" quotes"]`, true},
{"foo", "bar", false}, {"foo", "bar", false},

View File

@ -0,0 +1,7 @@
resource "test_instance" "foo" {
count = 5
}
resource "test_instance" "bar" {
count = "${length(test_instance.foo.*.id)}"
}

View File

@ -7,7 +7,6 @@ variable "baz" {
default = { default = {
"A" = "a" "A" = "a"
interp = "${file("t.txt")}"
} }
} }

View File

@ -195,6 +195,13 @@ func TestConfigValidate_countResourceVar(t *testing.T) {
} }
} }
func TestConfigValidate_countResourceVarMulti(t *testing.T) {
c := testConfig(t, "validate-count-resource-var-multi")
if err := c.Validate(); err == nil {
t.Fatal("should not be valid")
}
}
func TestConfigValidate_countUserVar(t *testing.T) { func TestConfigValidate_countUserVar(t *testing.T) {
c := testConfig(t, "validate-count-user-var") c := testConfig(t, "validate-count-user-var")
if err := c.Validate(); err != nil { if err := c.Validate(); err != nil {

View File

@ -0,0 +1,5 @@
resource "aws_instance" "foo" {}
resource "aws_instance" "web" {
count = "${length(aws_instance.foo.*.bar)}"
}