diff --git a/terraform/context_validate_test.go b/terraform/context_validate_test.go index 4b3665e9a4..af512c59e0 100644 --- a/terraform/context_validate_test.go +++ b/terraform/context_validate_test.go @@ -887,7 +887,7 @@ func TestContext2Validate_selfRefMulti(t *testing.T) { ResourceTypes: map[string]*configschema.Block{ "aws_instance": { Attributes: map[string]*configschema.Attribute{ - "foo": {Type: cty.List(cty.String), Optional: true}, + "foo": {Type: cty.String, Optional: true}, }, }, }, diff --git a/terraform/eval_validate_selfref.go b/terraform/eval_validate_selfref.go index b4f060603a..c577fc2919 100644 --- a/terraform/eval_validate_selfref.go +++ b/terraform/eval_validate_selfref.go @@ -3,22 +3,21 @@ package terraform import ( "fmt" - "github.com/hashicorp/terraform/tfdiags" - - "github.com/hashicorp/terraform/lang" - "github.com/hashicorp/hcl2/hcl" + "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/config/configschema" + "github.com/hashicorp/terraform/lang" + "github.com/hashicorp/terraform/tfdiags" ) // EvalValidateSelfRef is an EvalNode implementation that checks to ensure that // expressions within a particular referencable block do not reference that // same block. type EvalValidateSelfRef struct { - Addr addrs.Referenceable - Config hcl.Body - Schema *configschema.Block + Addr addrs.Referenceable + Config hcl.Body + ProviderSchema **ProviderSchema } func (n *EvalValidateSelfRef) Eval(ctx EvalContext) (interface{}, error) { @@ -33,7 +32,34 @@ func (n *EvalValidateSelfRef) Eval(ctx EvalContext) (interface{}, error) { addrStrs = append(addrStrs, tAddr.ContainingResource().String()) } - refs, _ := lang.ReferencesInBlock(n.Config, n.Schema) + if n.ProviderSchema == nil || *n.ProviderSchema == nil { + return nil, fmt.Errorf("provider schema unavailable while validating %s for self-references; this is a bug in Terraform and should be reported", addr) + } + + providerSchema := *n.ProviderSchema + var schema *configschema.Block + switch tAddr := addr.(type) { + case addrs.Resource: + switch tAddr.Mode { + case addrs.ManagedResourceMode: + schema = providerSchema.ResourceTypes[tAddr.Type] + case addrs.DataResourceMode: + schema = providerSchema.DataSources[tAddr.Type] + } + case addrs.ResourceInstance: + switch tAddr.Resource.Mode { + case addrs.ManagedResourceMode: + schema = providerSchema.ResourceTypes[tAddr.Resource.Type] + case addrs.DataResourceMode: + schema = providerSchema.DataSources[tAddr.Resource.Type] + } + } + + if schema == nil { + return nil, fmt.Errorf("no schema available for %s to validate for self-references; this is a bug in Terraform and should be reported", addr) + } + + refs, _ := lang.ReferencesInBlock(n.Config, schema) for _, ref := range refs { for _, addrStr := range addrStrs { if ref.Subject.String() == addrStr { diff --git a/terraform/eval_validate_selfref_test.go b/terraform/eval_validate_selfref_test.go index f828e990b9..461b06a833 100644 --- a/terraform/eval_validate_selfref_test.go +++ b/terraform/eval_validate_selfref_test.go @@ -80,18 +80,24 @@ func TestEvalValidateSelfRef(t *testing.T) { }, }) - n := &EvalValidateSelfRef{ - Addr: test.Addr, - Config: body, - Schema: &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "foo": { - Type: cty.String, - Required: true, + ps := &ProviderSchema{ + ResourceTypes: map[string]*configschema.Block{ + "aws_instance": &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "foo": { + Type: cty.String, + Required: true, + }, }, }, }, } + + n := &EvalValidateSelfRef{ + Addr: test.Addr, + Config: body, + ProviderSchema: &ps, + } result, err := n.Eval(nil) if result != nil { t.Fatal("result should always be nil") diff --git a/terraform/node_resource_validate.go b/terraform/node_resource_validate.go index d20087b38b..064e0cef90 100644 --- a/terraform/node_resource_validate.go +++ b/terraform/node_resource_validate.go @@ -124,15 +124,16 @@ func (n *NodeValidatableResourceInstance) EvalTree() EvalNode { seq := &EvalSequence{ Nodes: []EvalNode{ - &EvalValidateSelfRef{ - Addr: addr.Resource, - Config: config.Config, - }, &EvalGetProvider{ Addr: n.ResolvedProvider, Output: &provider, Schema: &providerSchema, }, + &EvalValidateSelfRef{ + Addr: addr.Resource, + Config: config.Config, + ProviderSchema: &providerSchema, + }, &EvalValidateResource{ Addr: addr.Resource, Provider: &provider,