mirror of https://github.com/hashicorp/terraform
Merge pull request #7446 from hashicorp/b-jit-resource-validate
core: rerun resource validation before plan and applypull/7461/head
commit
3b732131d2
@ -0,0 +1,28 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func testDataSource() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Read: testDataSourceRead,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"list": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testDataSourceRead(d *schema.ResourceData, meta interface{}) error {
|
||||
d.SetId(time.Now().UTC().String())
|
||||
d.Set("list", []interface{}{"one", "two", "three"})
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -0,0 +1,184 @@
|
||||
package terraform
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
)
|
||||
|
||||
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)
|
||||
rc := &ResourceConfig{
|
||||
Raw: map[string]interface{}{"foo": "bar"},
|
||||
}
|
||||
node := &EvalValidateResource{
|
||||
Provider: &p,
|
||||
Config: &rc,
|
||||
ResourceName: "foo",
|
||||
ResourceType: "aws_instance",
|
||||
ResourceMode: config.ManagedResourceMode,
|
||||
}
|
||||
|
||||
_, 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)
|
||||
rc := &ResourceConfig{
|
||||
Raw: map[string]interface{}{"foo": "bar"},
|
||||
}
|
||||
node := &EvalValidateResource{
|
||||
Provider: &p,
|
||||
Config: &rc,
|
||||
ResourceName: "foo",
|
||||
ResourceType: "aws_ami",
|
||||
ResourceMode: config.DataResourceMode,
|
||||
}
|
||||
|
||||
_, 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)
|
||||
rc := &ResourceConfig{}
|
||||
node := &EvalValidateResource{
|
||||
Provider: &p,
|
||||
Config: &rc,
|
||||
ResourceName: "foo",
|
||||
ResourceType: "aws_instance",
|
||||
ResourceMode: config.ManagedResourceMode,
|
||||
}
|
||||
|
||||
_, 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)
|
||||
rc := &ResourceConfig{}
|
||||
node := &EvalValidateResource{
|
||||
Provider: &p,
|
||||
Config: &rc,
|
||||
ResourceName: "foo",
|
||||
ResourceType: "aws_instance",
|
||||
ResourceMode: config.ManagedResourceMode,
|
||||
}
|
||||
|
||||
_, err := node.Eval(&MockEvalContext{})
|
||||
if err == nil {
|
||||
t.Fatal("Expected an error, got none!")
|
||||
}
|
||||
|
||||
verr := err.(*EvalValidateError)
|
||||
if len(verr.Warnings) != 1 || verr.Warnings[0] != "warn" {
|
||||
t.Fatalf("Expected 1 warning 'warn', got: %#v", verr.Warnings)
|
||||
}
|
||||
if len(verr.Errors) != 1 || verr.Errors[0].Error() != "err" {
|
||||
t.Fatalf("Expected 1 error 'err', got: %#v", verr.Errors)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvalValidateResource_checksResourceName(t *testing.T) {
|
||||
mp := testProvider("aws")
|
||||
p := ResourceProvider(mp)
|
||||
rc := &ResourceConfig{}
|
||||
node := &EvalValidateResource{
|
||||
Provider: &p,
|
||||
Config: &rc,
|
||||
ResourceName: "bad*name",
|
||||
ResourceType: "aws_instance",
|
||||
ResourceMode: config.ManagedResourceMode,
|
||||
}
|
||||
|
||||
_, err := node.Eval(&MockEvalContext{})
|
||||
if err == nil {
|
||||
t.Fatal("Expected an error, got none!")
|
||||
}
|
||||
expectErr := "resource name can only contain"
|
||||
if !strings.Contains(err.Error(), expectErr) {
|
||||
t.Fatalf("Expected err: %s to contain %s", err, expectErr)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
rc := &ResourceConfig{}
|
||||
node := &EvalValidateResource{
|
||||
Provider: &p,
|
||||
Config: &rc,
|
||||
ResourceName: "foo",
|
||||
ResourceType: "aws_instance",
|
||||
ResourceMode: config.ManagedResourceMode,
|
||||
|
||||
IgnoreWarnings: true,
|
||||
}
|
||||
|
||||
_, err := node.Eval(&MockEvalContext{})
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got: %s", err)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
resource "aws_ami_list" "foo" {
|
||||
# assume this has a computed attr called "ids"
|
||||
}
|
||||
|
||||
resource "aws_instance" "foo" {
|
||||
# this is erroneously referencing the list of all ids, but
|
||||
# since it is a computed attr, the Validate walk won't catch
|
||||
# it.
|
||||
ami = "${aws_ami_list.foo.ids}"
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
data "aws_availability_zones" "azs" {}
|
||||
resource "aws_instance" "foo" {
|
||||
ami = "${data.aws_availability_zones.azs.names}"
|
||||
}
|
||||
Loading…
Reference in new issue