2016-06-30 18:22:20 -05:00
|
|
|
package terraform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
|
|
"github.com/hashicorp/terraform/config/configschema"
|
|
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/configs"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
2016-06-30 18:22:20 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestEvalValidateResource_managedResource(t *testing.T) {
|
|
|
|
mp := testProvider("aws")
|
|
|
|
mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) {
|
|
|
|
expected := "aws_instance"
|
|
|
|
if rt != expected {
|
|
|
|
t.Fatalf("expected: %s, got: %s", expected, rt)
|
|
|
|
}
|
|
|
|
expected = "bar"
|
|
|
|
val, _ := c.Get("foo")
|
|
|
|
if val != expected {
|
|
|
|
t.Fatalf("expected: %s, got: %s", expected, val)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
p := ResourceProvider(mp)
|
2018-05-04 21:24:06 -05:00
|
|
|
rc := &configs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
Config: configs.SynthBody("", map[string]cty.Value{
|
|
|
|
"foo": cty.StringVal("bar"),
|
|
|
|
}),
|
|
|
|
}
|
2016-06-30 18:22:20 -05:00
|
|
|
node := &EvalValidateResource{
|
2018-05-04 21:24:06 -05:00
|
|
|
Addr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Provider: &p,
|
|
|
|
Config: rc,
|
2016-06-30 18:22:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
_, err := node.Eval(&MockEvalContext{})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !mp.ValidateResourceCalled {
|
|
|
|
t.Fatal("Expected ValidateResource to be called, but it was not!")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEvalValidateResource_dataSource(t *testing.T) {
|
|
|
|
mp := testProvider("aws")
|
|
|
|
mp.ValidateDataSourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) {
|
|
|
|
expected := "aws_ami"
|
|
|
|
if rt != expected {
|
|
|
|
t.Fatalf("expected: %s, got: %s", expected, rt)
|
|
|
|
}
|
|
|
|
expected = "bar"
|
|
|
|
val, _ := c.Get("foo")
|
|
|
|
if val != expected {
|
|
|
|
t.Fatalf("expected: %s, got: %s", expected, val)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
p := ResourceProvider(mp)
|
2018-05-04 21:24:06 -05:00
|
|
|
rc := &configs.Resource{
|
|
|
|
Mode: addrs.DataResourceMode,
|
|
|
|
Type: "aws_ami",
|
|
|
|
Name: "foo",
|
|
|
|
Config: configs.SynthBody("", map[string]cty.Value{
|
|
|
|
"foo": cty.StringVal("bar"),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
|
2016-06-30 18:22:20 -05:00
|
|
|
node := &EvalValidateResource{
|
2018-05-04 21:24:06 -05:00
|
|
|
Addr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.DataResourceMode,
|
|
|
|
Type: "aws_ami",
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Provider: &p,
|
|
|
|
Config: rc,
|
2016-06-30 18:22:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
_, err := node.Eval(&MockEvalContext{})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !mp.ValidateDataSourceCalled {
|
|
|
|
t.Fatal("Expected ValidateDataSource to be called, but it was not!")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEvalValidateResource_validReturnsNilError(t *testing.T) {
|
|
|
|
mp := testProvider("aws")
|
|
|
|
mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
p := ResourceProvider(mp)
|
2018-05-04 21:24:06 -05:00
|
|
|
rc := &configs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
Config: configs.SynthBody("", map[string]cty.Value{}),
|
|
|
|
}
|
2016-06-30 18:22:20 -05:00
|
|
|
node := &EvalValidateResource{
|
2018-05-04 21:24:06 -05:00
|
|
|
Addr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Provider: &p,
|
|
|
|
Config: rc,
|
2016-06-30 18:22:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
_, err := node.Eval(&MockEvalContext{})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Expected nil error, got: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEvalValidateResource_warningsAndErrorsPassedThrough(t *testing.T) {
|
|
|
|
mp := testProvider("aws")
|
|
|
|
mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) {
|
|
|
|
ws = append(ws, "warn")
|
|
|
|
es = append(es, errors.New("err"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
p := ResourceProvider(mp)
|
2018-05-04 21:24:06 -05:00
|
|
|
rc := &configs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
Config: configs.SynthBody("", map[string]cty.Value{}),
|
|
|
|
}
|
2016-06-30 18:22:20 -05:00
|
|
|
node := &EvalValidateResource{
|
2018-05-04 21:24:06 -05:00
|
|
|
Addr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Provider: &p,
|
|
|
|
Config: rc,
|
2016-06-30 18:22:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
_, err := node.Eval(&MockEvalContext{})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("Expected an error, got none!")
|
|
|
|
}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
diags = diags.Append(err)
|
|
|
|
bySeverity := map[tfdiags.Severity]tfdiags.Diagnostics{}
|
|
|
|
for _, diag := range diags {
|
|
|
|
bySeverity[diag.Severity()] = append(bySeverity[diag.Severity()], diag)
|
2016-06-30 18:22:20 -05:00
|
|
|
}
|
2018-05-04 21:24:06 -05:00
|
|
|
if len(bySeverity[tfdiags.Warning]) != 1 || bySeverity[tfdiags.Warning][0].Description().Summary != "warn" {
|
|
|
|
t.Fatalf("Expected 1 warning 'warn', got: %#v", bySeverity[tfdiags.Warning])
|
2016-06-30 18:22:20 -05:00
|
|
|
}
|
2018-05-04 21:24:06 -05:00
|
|
|
if len(bySeverity[tfdiags.Error]) != 1 || bySeverity[tfdiags.Error][0].Description().Summary != "err" {
|
|
|
|
t.Fatalf("Expected 1 error 'err', got: %#v", bySeverity[tfdiags.Error])
|
2016-06-30 18:22:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEvalValidateResource_ignoreWarnings(t *testing.T) {
|
|
|
|
mp := testProvider("aws")
|
|
|
|
mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) {
|
|
|
|
ws = append(ws, "warn")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
p := ResourceProvider(mp)
|
2018-05-04 21:24:06 -05:00
|
|
|
rc := &configs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
Config: configs.SynthBody("", map[string]cty.Value{}),
|
|
|
|
}
|
2016-06-30 18:22:20 -05:00
|
|
|
node := &EvalValidateResource{
|
2018-05-04 21:24:06 -05:00
|
|
|
Addr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "aws_instance",
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Provider: &p,
|
|
|
|
Config: rc,
|
2016-06-30 18:22:20 -05:00
|
|
|
|
|
|
|
IgnoreWarnings: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := node.Eval(&MockEvalContext{})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Expected no error, got: %s", err)
|
|
|
|
}
|
|
|
|
}
|
2017-04-05 17:34:59 -05:00
|
|
|
|
|
|
|
func TestEvalValidateProvisioner_valid(t *testing.T) {
|
|
|
|
mp := &MockResourceProvisioner{}
|
|
|
|
var p ResourceProvisioner = mp
|
|
|
|
ctx := &MockEvalContext{}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
schema := &configschema.Block{}
|
2017-04-05 17:34:59 -05:00
|
|
|
|
|
|
|
node := &EvalValidateProvisioner{
|
2018-05-04 21:24:06 -05:00
|
|
|
ResourceAddr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "foo",
|
|
|
|
Name: "bar",
|
|
|
|
},
|
|
|
|
},
|
2017-04-05 17:34:59 -05:00
|
|
|
Provisioner: &p,
|
2018-05-04 21:24:06 -05:00
|
|
|
Schema: &schema,
|
|
|
|
Config: &configs.Provisioner{
|
|
|
|
Type: "baz",
|
|
|
|
Config: hcl.EmptyBody(),
|
|
|
|
},
|
|
|
|
ConnConfig: &configs.Connection{
|
|
|
|
Type: "ssh",
|
|
|
|
Config: hcl.EmptyBody(),
|
|
|
|
},
|
2017-04-05 17:34:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
result, err := node.Eval(ctx)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("node.Eval failed: %s", err)
|
|
|
|
}
|
|
|
|
if result != nil {
|
|
|
|
t.Errorf("node.Eval returned non-nil result")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !mp.ValidateCalled {
|
2018-05-04 21:24:06 -05:00
|
|
|
t.Fatalf("p.Validate not called")
|
2017-04-05 17:34:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEvalValidateProvisioner_warning(t *testing.T) {
|
|
|
|
mp := &MockResourceProvisioner{}
|
|
|
|
var p ResourceProvisioner = mp
|
|
|
|
ctx := &MockEvalContext{}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
schema := &configschema.Block{}
|
2017-04-05 17:34:59 -05:00
|
|
|
|
|
|
|
node := &EvalValidateProvisioner{
|
2018-05-04 21:24:06 -05:00
|
|
|
ResourceAddr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "foo",
|
|
|
|
Name: "bar",
|
|
|
|
},
|
|
|
|
},
|
2017-04-05 17:34:59 -05:00
|
|
|
Provisioner: &p,
|
2018-05-04 21:24:06 -05:00
|
|
|
Schema: &schema,
|
|
|
|
Config: &configs.Provisioner{
|
|
|
|
Type: "baz",
|
|
|
|
Config: hcl.EmptyBody(),
|
|
|
|
},
|
|
|
|
ConnConfig: &configs.Connection{
|
|
|
|
Type: "ssh",
|
|
|
|
Config: hcl.EmptyBody(),
|
|
|
|
},
|
2017-04-05 17:34:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
mp.ValidateReturnWarns = []string{"foo is deprecated"}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
_, err := node.Eval(ctx)
|
2017-04-05 17:34:59 -05:00
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("node.Eval succeeded; want error")
|
|
|
|
}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
diags = diags.Append(err)
|
|
|
|
if len(diags) != 1 {
|
|
|
|
t.Fatalf("wrong number of diagsnostics in %#v; want one warning", diags)
|
2017-04-05 17:34:59 -05:00
|
|
|
}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
if got, want := diags[0].Description().Summary, mp.ValidateReturnWarns[0]; got != want {
|
|
|
|
t.Fatalf("wrong warning %q; want %q", got, want)
|
2017-04-05 17:34:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEvalValidateProvisioner_connectionInvalid(t *testing.T) {
|
|
|
|
var p ResourceProvisioner = &MockResourceProvisioner{}
|
|
|
|
ctx := &MockEvalContext{}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
schema := &configschema.Block{}
|
2017-04-05 17:34:59 -05:00
|
|
|
|
|
|
|
node := &EvalValidateProvisioner{
|
2018-05-04 21:24:06 -05:00
|
|
|
ResourceAddr: addrs.ResourceInstance{
|
|
|
|
Resource: addrs.Resource{
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
Type: "foo",
|
|
|
|
Name: "bar",
|
|
|
|
},
|
|
|
|
},
|
2017-04-05 17:34:59 -05:00
|
|
|
Provisioner: &p,
|
2018-05-04 21:24:06 -05:00
|
|
|
Schema: &schema,
|
|
|
|
Config: &configs.Provisioner{
|
|
|
|
Type: "baz",
|
|
|
|
Config: hcl.EmptyBody(),
|
|
|
|
},
|
|
|
|
ConnConfig: &configs.Connection{
|
|
|
|
Type: "ssh",
|
|
|
|
Config: configs.SynthBody("", map[string]cty.Value{
|
|
|
|
"bananananananana": cty.StringVal("foo"),
|
|
|
|
"bazaz": cty.StringVal("bar"),
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := node.Eval(ctx)
|
2017-04-05 17:34:59 -05:00
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("node.Eval succeeded; want error")
|
|
|
|
}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
diags = diags.Append(err)
|
|
|
|
if len(diags) != 2 {
|
|
|
|
t.Fatalf("wrong number of diagsnostics in %#v; want two errors", diags)
|
2017-04-05 17:34:59 -05:00
|
|
|
}
|
|
|
|
|
2018-05-04 21:24:06 -05:00
|
|
|
errStr := diags.Err().Error()
|
|
|
|
if !(strings.Contains(errStr, "bananananananana") && strings.Contains(errStr, "bazaz")) {
|
|
|
|
t.Fatalf("wrong errors %q; want something about each of our invalid connInfo keys", errStr)
|
2017-04-05 17:34:59 -05:00
|
|
|
}
|
|
|
|
}
|