mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
update providers.Schemas type
Use the global providers.SchemaCache and update all schema access to the providers.Schemas, except where the provider.GetProviderSchemaResponse type name would be expected. Some tests that reuse provider factories needed a little more careful handling. Change the fixed func to only reset the provider on the first call.
This commit is contained in:
parent
9d9746560f
commit
ec3a38e5ed
@ -146,7 +146,7 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) {
|
||||
}
|
||||
|
||||
func (c *Context) Schemas(config *configs.Config, state *states.State) (*Schemas, tfdiags.Diagnostics) {
|
||||
// TODO: This method gets called multiple times on the same context with
|
||||
// FIXME: This method gets called multiple times on the same context with
|
||||
// the same inputs by different parts of Terraform that all need the
|
||||
// schemas, and it's typically quite expensive because it has to spin up
|
||||
// plugins to gather their schemas, so it'd be good to have some caching
|
||||
|
@ -2782,13 +2782,13 @@ resource "test_resource" "a" {
|
||||
},
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
t.Run("conditions pass", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
|
||||
m := req.ProposedNewState.AsValueMap()
|
||||
m["output"] = cty.StringVal("bar")
|
||||
@ -2820,6 +2820,12 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("precondition fail", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
_, diags := ctx.Plan(m, states.NewState(), &PlanOpts{
|
||||
Mode: plans.NormalMode,
|
||||
SetVariables: InputValues{
|
||||
@ -2841,6 +2847,12 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("precondition fail refresh-only", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
state := states.BuildState(func(s *states.SyncState) {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr("test_resource.a"), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"value":"boop","output":"blorp"}`),
|
||||
@ -2869,6 +2881,12 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("postcondition fail", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
|
||||
m := req.ProposedNewState.AsValueMap()
|
||||
m["output"] = cty.StringVal("")
|
||||
@ -2898,6 +2916,12 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("postcondition fail refresh-only", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
state := states.BuildState(func(s *states.SyncState) {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr("test_resource.a"), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"value":"boop","output":"blorp"}`),
|
||||
@ -2945,6 +2969,12 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("precondition and postcondition fail refresh-only", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
state := states.BuildState(func(s *states.SyncState) {
|
||||
s.SetResourceInstanceCurrent(mustResourceInstanceAddr("test_resource.a"), &states.ResourceInstanceObjectSrc{
|
||||
AttrsJSON: []byte(`{"value":"boop","output":"blorp"}`),
|
||||
@ -3054,13 +3084,12 @@ resource "test_resource" "a" {
|
||||
},
|
||||
})
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
|
||||
t.Run("conditions pass", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
p.ReadDataSourceResponse = &providers.ReadDataSourceResponse{
|
||||
State: cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.StringVal("boop"),
|
||||
@ -3106,6 +3135,11 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("precondition fail", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
_, diags := ctx.Plan(m, states.NewState(), &PlanOpts{
|
||||
Mode: plans.NormalMode,
|
||||
SetVariables: InputValues{
|
||||
@ -3127,6 +3161,11 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("precondition fail refresh-only", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
plan, diags := ctx.Plan(m, states.NewState(), &PlanOpts{
|
||||
Mode: plans.RefreshOnlyMode,
|
||||
SetVariables: InputValues{
|
||||
@ -3160,6 +3199,11 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("postcondition fail", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
p.ReadDataSourceResponse = &providers.ReadDataSourceResponse{
|
||||
State: cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.StringVal("boop"),
|
||||
@ -3187,6 +3231,11 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("postcondition fail refresh-only", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
p.ReadDataSourceResponse = &providers.ReadDataSourceResponse{
|
||||
State: cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.StringVal("boop"),
|
||||
@ -3223,6 +3272,11 @@ resource "test_resource" "a" {
|
||||
})
|
||||
|
||||
t.Run("precondition and postcondition fail refresh-only", func(t *testing.T) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
})
|
||||
p.ReadDataSourceResponse = &providers.ReadDataSourceResponse{
|
||||
State: cty.ObjectVal(map[string]cty.Value{
|
||||
"foo": cty.StringVal("nope"),
|
||||
|
@ -6,7 +6,6 @@ package terraform
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
@ -21,15 +20,6 @@ import (
|
||||
type contextPlugins struct {
|
||||
providerFactories map[addrs.Provider]providers.Factory
|
||||
provisionerFactories map[string]provisioners.Factory
|
||||
|
||||
// We memoize the schemas we've previously loaded in here, to avoid
|
||||
// repeatedly paying the cost of activating the same plugins to access
|
||||
// their schemas in various different spots. We use schemas for many
|
||||
// purposes in Terraform, so there isn't a single choke point where
|
||||
// it makes sense to preload all of them.
|
||||
providerSchemas map[addrs.Provider]*ProviderSchema
|
||||
provisionerSchemas map[string]*configschema.Block
|
||||
schemasLock sync.Mutex
|
||||
}
|
||||
|
||||
func newContextPlugins(providerFactories map[addrs.Provider]providers.Factory, provisionerFactories map[string]provisioners.Factory) *contextPlugins {
|
||||
@ -37,15 +27,9 @@ func newContextPlugins(providerFactories map[addrs.Provider]providers.Factory, p
|
||||
providerFactories: providerFactories,
|
||||
provisionerFactories: provisionerFactories,
|
||||
}
|
||||
ret.init()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (cp *contextPlugins) init() {
|
||||
cp.providerSchemas = make(map[addrs.Provider]*ProviderSchema, len(cp.providerFactories))
|
||||
cp.provisionerSchemas = make(map[string]*configschema.Block, len(cp.provisionerFactories))
|
||||
}
|
||||
|
||||
func (cp *contextPlugins) HasProvider(addr addrs.Provider) bool {
|
||||
_, ok := cp.providerFactories[addr]
|
||||
return ok
|
||||
@ -81,70 +65,53 @@ func (cp *contextPlugins) NewProvisionerInstance(typ string) (provisioners.Inter
|
||||
// ProviderSchema memoizes results by unique provider address, so it's fine
|
||||
// to repeatedly call this method with the same address if various different
|
||||
// parts of Terraform all need the same schema information.
|
||||
func (cp *contextPlugins) ProviderSchema(addr addrs.Provider) (*ProviderSchema, error) {
|
||||
cp.schemasLock.Lock()
|
||||
defer cp.schemasLock.Unlock()
|
||||
|
||||
if schema, ok := cp.providerSchemas[addr]; ok {
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
func (cp *contextPlugins) ProviderSchema(addr addrs.Provider) (providers.Schemas, error) {
|
||||
log.Printf("[TRACE] terraform.contextPlugins: Initializing provider %q to read its schema", addr)
|
||||
|
||||
// check the global schema cache first
|
||||
schemas, ok := providers.SchemaCache.Get(addr)
|
||||
if ok {
|
||||
return schemas, nil
|
||||
}
|
||||
|
||||
provider, err := cp.NewProviderInstance(addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to instantiate provider %q to obtain schema: %s", addr, err)
|
||||
return schemas, fmt.Errorf("failed to instantiate provider %q to obtain schema: %s", addr, err)
|
||||
}
|
||||
defer provider.Close()
|
||||
|
||||
resp := provider.GetProviderSchema()
|
||||
if resp.Diagnostics.HasErrors() {
|
||||
return nil, fmt.Errorf("failed to retrieve schema from provider %q: %s", addr, resp.Diagnostics.Err())
|
||||
}
|
||||
|
||||
s := &ProviderSchema{
|
||||
Provider: resp.Provider.Block,
|
||||
ResourceTypes: make(map[string]*configschema.Block),
|
||||
DataSources: make(map[string]*configschema.Block),
|
||||
|
||||
ResourceTypeSchemaVersions: make(map[string]uint64),
|
||||
return resp, fmt.Errorf("failed to retrieve schema from provider %q: %s", addr, resp.Diagnostics.Err())
|
||||
}
|
||||
|
||||
if resp.Provider.Version < 0 {
|
||||
// We're not using the version numbers here yet, but we'll check
|
||||
// for validity anyway in case we start using them in future.
|
||||
return nil, fmt.Errorf("provider %s has invalid negative schema version for its configuration blocks,which is a bug in the provider ", addr)
|
||||
return resp, fmt.Errorf("provider %s has invalid negative schema version for its configuration blocks,which is a bug in the provider ", addr)
|
||||
}
|
||||
|
||||
for t, r := range resp.ResourceTypes {
|
||||
if err := r.Block.InternalValidate(); err != nil {
|
||||
return nil, fmt.Errorf("provider %s has invalid schema for managed resource type %q, which is a bug in the provider: %q", addr, t, err)
|
||||
return resp, fmt.Errorf("provider %s has invalid schema for managed resource type %q, which is a bug in the provider: %q", addr, t, err)
|
||||
}
|
||||
s.ResourceTypes[t] = r.Block
|
||||
s.ResourceTypeSchemaVersions[t] = uint64(r.Version)
|
||||
if r.Version < 0 {
|
||||
return nil, fmt.Errorf("provider %s has invalid negative schema version for managed resource type %q, which is a bug in the provider", addr, t)
|
||||
return resp, fmt.Errorf("provider %s has invalid negative schema version for managed resource type %q, which is a bug in the provider", addr, t)
|
||||
}
|
||||
}
|
||||
|
||||
for t, d := range resp.DataSources {
|
||||
if err := d.Block.InternalValidate(); err != nil {
|
||||
return nil, fmt.Errorf("provider %s has invalid schema for data resource type %q, which is a bug in the provider: %q", addr, t, err)
|
||||
return resp, fmt.Errorf("provider %s has invalid schema for data resource type %q, which is a bug in the provider: %q", addr, t, err)
|
||||
}
|
||||
s.DataSources[t] = d.Block
|
||||
if d.Version < 0 {
|
||||
// We're not using the version numbers here yet, but we'll check
|
||||
// for validity anyway in case we start using them in future.
|
||||
return nil, fmt.Errorf("provider %s has invalid negative schema version for data resource type %q, which is a bug in the provider", addr, t)
|
||||
return resp, fmt.Errorf("provider %s has invalid negative schema version for data resource type %q, which is a bug in the provider", addr, t)
|
||||
}
|
||||
}
|
||||
|
||||
if resp.ProviderMeta.Block != nil {
|
||||
s.ProviderMeta = resp.ProviderMeta.Block
|
||||
}
|
||||
|
||||
cp.providerSchemas[addr] = s
|
||||
return s, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ProviderConfigSchema is a helper wrapper around ProviderSchema which first
|
||||
@ -157,7 +124,7 @@ func (cp *contextPlugins) ProviderConfigSchema(providerAddr addrs.Provider) (*co
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return providerSchema.Provider, nil
|
||||
return providerSchema.Provider.Block, nil
|
||||
}
|
||||
|
||||
// ResourceTypeSchema is a helper wrapper around ProviderSchema which first
|
||||
@ -188,13 +155,6 @@ func (cp *contextPlugins) ResourceTypeSchema(providerAddr addrs.Provider, resour
|
||||
// to repeatedly call this method with the same name if various different
|
||||
// parts of Terraform all need the same schema information.
|
||||
func (cp *contextPlugins) ProvisionerSchema(typ string) (*configschema.Block, error) {
|
||||
cp.schemasLock.Lock()
|
||||
defer cp.schemasLock.Unlock()
|
||||
|
||||
if schema, ok := cp.provisionerSchemas[typ]; ok {
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] terraform.contextPlugins: Initializing provisioner %q to read its schema", typ)
|
||||
provisioner, err := cp.NewProvisionerInstance(typ)
|
||||
if err != nil {
|
||||
@ -207,6 +167,5 @@ func (cp *contextPlugins) ProvisionerSchema(typ string) (*configschema.Block, er
|
||||
return nil, fmt.Errorf("failed to retrieve schema from provisioner %q: %s", typ, resp.Diagnostics.Err())
|
||||
}
|
||||
|
||||
cp.provisionerSchemas[typ] = resp.Provisioner
|
||||
return resp.Provisioner, nil
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ func simpleMockPluginLibrary() *contextPlugins {
|
||||
},
|
||||
},
|
||||
}
|
||||
ret.init() // prepare the internal cache data structures
|
||||
return ret
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ type EvalContext interface {
|
||||
//
|
||||
// This method expects an _absolute_ provider configuration address, since
|
||||
// resources in one module are able to use providers from other modules.
|
||||
ProviderSchema(addrs.AbsProviderConfig) (*ProviderSchema, error)
|
||||
ProviderSchema(addrs.AbsProviderConfig) (providers.Schemas, error)
|
||||
|
||||
// CloseProvider closes provider connections that aren't needed anymore.
|
||||
//
|
||||
|
@ -149,7 +149,22 @@ func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.
|
||||
return ctx.ProviderCache[addr.String()]
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) (*ProviderSchema, error) {
|
||||
func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) (providers.Schemas, error) {
|
||||
// first see if we have already have an initialized provider to avoid
|
||||
// re-loading it only for the schema
|
||||
p := ctx.Provider(addr)
|
||||
if p != nil {
|
||||
resp := p.GetProviderSchema()
|
||||
// convert any diagnostics here in case this is the first call
|
||||
// FIXME: better control provider instantiation so we can be sure this
|
||||
// won't be the first call to ProviderSchema
|
||||
var err error
|
||||
if resp.Diagnostics.HasErrors() {
|
||||
err = resp.Diagnostics.ErrWithWarnings()
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
return ctx.Plugins.ProviderSchema(addr.Provider)
|
||||
}
|
||||
|
||||
@ -181,16 +196,6 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, c
|
||||
return diags
|
||||
}
|
||||
|
||||
providerSchema, err := ctx.ProviderSchema(addr)
|
||||
if err != nil {
|
||||
diags = diags.Append(fmt.Errorf("failed to read schema for %s: %s", addr, err))
|
||||
return diags
|
||||
}
|
||||
if providerSchema == nil {
|
||||
diags = diags.Append(fmt.Errorf("schema for %s is not available", addr))
|
||||
return diags
|
||||
}
|
||||
|
||||
req := providers.ConfigureProviderRequest{
|
||||
TerraformVersion: version.String(),
|
||||
Config: cfg,
|
||||
|
@ -46,7 +46,7 @@ type MockEvalContext struct {
|
||||
|
||||
ProviderSchemaCalled bool
|
||||
ProviderSchemaAddr addrs.AbsProviderConfig
|
||||
ProviderSchemaSchema *ProviderSchema
|
||||
ProviderSchemaSchema providers.Schemas
|
||||
ProviderSchemaError error
|
||||
|
||||
CloseProviderCalled bool
|
||||
@ -190,7 +190,7 @@ func (c *MockEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Inter
|
||||
return c.ProviderProvider
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) (*ProviderSchema, error) {
|
||||
func (c *MockEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) (providers.Schemas, error) {
|
||||
c.ProviderSchemaCalled = true
|
||||
c.ProviderSchemaAddr = addr
|
||||
return c.ProviderSchemaSchema, c.ProviderSchemaError
|
||||
|
@ -43,20 +43,20 @@ func buildProviderConfig(ctx EvalContext, addr addrs.AbsProviderConfig, config *
|
||||
}
|
||||
|
||||
// getProvider returns the providers.Interface and schema for a given provider.
|
||||
func getProvider(ctx EvalContext, addr addrs.AbsProviderConfig) (providers.Interface, *ProviderSchema, error) {
|
||||
func getProvider(ctx EvalContext, addr addrs.AbsProviderConfig) (providers.Interface, providers.Schemas, error) {
|
||||
if addr.Provider.Type == "" {
|
||||
// Should never happen
|
||||
panic("GetProvider used with uninitialized provider configuration address")
|
||||
}
|
||||
provider := ctx.Provider(addr)
|
||||
if provider == nil {
|
||||
return nil, &ProviderSchema{}, fmt.Errorf("provider %s not initialized", addr)
|
||||
return nil, providers.Schemas{}, fmt.Errorf("provider %s not initialized", addr)
|
||||
}
|
||||
// Not all callers require a schema, so we will leave checking for a nil
|
||||
// schema to the callers.
|
||||
schema, err := ctx.ProviderSchema(addr)
|
||||
if err != nil {
|
||||
return nil, &ProviderSchema{}, fmt.Errorf("failed to read schema for provider %s: %w", addr, err)
|
||||
return nil, providers.Schemas{}, fmt.Errorf("failed to read schema for provider %s: %w", addr, err)
|
||||
}
|
||||
return provider, schema, nil
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/lang/marks"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
"github.com/hashicorp/terraform/internal/states"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
@ -264,71 +265,72 @@ func TestEvaluatorGetResource(t *testing.T) {
|
||||
},
|
||||
},
|
||||
State: stateSync,
|
||||
Plugins: schemaOnlyProvidersForTesting(map[addrs.Provider]*ProviderSchema{
|
||||
Plugins: schemaOnlyProvidersForTesting(map[addrs.Provider]providers.Schemas{
|
||||
addrs.NewDefaultProvider("test"): {
|
||||
Provider: &configschema.Block{},
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_resource": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"value": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
},
|
||||
BlockTypes: map[string]*configschema.NestedBlock{
|
||||
"nesting_list": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"value": {Type: cty.String, Optional: true},
|
||||
"sensitive_value": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
Nesting: configschema.NestingList,
|
||||
},
|
||||
"nesting_map": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"foo": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
"value": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
Nesting: configschema.NestingMap,
|
||||
},
|
||||
"nesting_set": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"baz": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingSet,
|
||||
},
|
||||
"nesting_single": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"boop": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingSingle,
|
||||
},
|
||||
"nesting_nesting": {
|
||||
Block: configschema.Block{
|
||||
BlockTypes: map[string]*configschema.NestedBlock{
|
||||
"nesting_list": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"value": {Type: cty.String, Optional: true},
|
||||
"sensitive_value": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingList,
|
||||
BlockTypes: map[string]*configschema.NestedBlock{
|
||||
"nesting_list": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"value": {Type: cty.String, Optional: true},
|
||||
"sensitive_value": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingList,
|
||||
},
|
||||
"nesting_map": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"foo": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingMap,
|
||||
},
|
||||
"nesting_set": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"baz": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingSet,
|
||||
},
|
||||
"nesting_single": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"boop": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingSingle,
|
||||
},
|
||||
"nesting_nesting": {
|
||||
Block: configschema.Block{
|
||||
BlockTypes: map[string]*configschema.NestedBlock{
|
||||
"nesting_list": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"value": {Type: cty.String, Optional: true},
|
||||
"sensitive_value": {Type: cty.String, Optional: true, Sensitive: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingList,
|
||||
},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingSingle,
|
||||
},
|
||||
Nesting: configschema.NestingSingle,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -435,29 +437,30 @@ func TestEvaluatorGetResource_changes(t *testing.T) {
|
||||
|
||||
// Set up our schemas
|
||||
schemas := &Schemas{
|
||||
Providers: map[addrs.Provider]*ProviderSchema{
|
||||
Providers: map[addrs.Provider]providers.Schemas{
|
||||
addrs.NewDefaultProvider("test"): {
|
||||
Provider: &configschema.Block{},
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_resource": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"to_mark_val": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"sensitive_value": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"sensitive_collection": {
|
||||
Type: cty.Map(cty.String),
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"to_mark_val": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"sensitive_value": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"sensitive_collection": {
|
||||
Type: cty.Map(cty.String),
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/lang"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
)
|
||||
|
||||
func TestStaticValidateReferences(t *testing.T) {
|
||||
@ -83,23 +84,29 @@ For example, to correlate with indices of a referring resource, use:
|
||||
cfg := testModule(t, "static-validate-refs")
|
||||
evaluator := &Evaluator{
|
||||
Config: cfg,
|
||||
Plugins: schemaOnlyProvidersForTesting(map[addrs.Provider]*ProviderSchema{
|
||||
Plugins: schemaOnlyProvidersForTesting(map[addrs.Provider]providers.Schemas{
|
||||
addrs.NewDefaultProvider("aws"): {
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"aws_instance": {},
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"aws_instance": {
|
||||
Block: &configschema.Block{},
|
||||
},
|
||||
},
|
||||
},
|
||||
addrs.MustParseProviderSourceString("foobar/beep"): {
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
// intentional mismatch between resource type prefix and provider type
|
||||
"boop_instance": {},
|
||||
"boop_instance": {
|
||||
Block: &configschema.Block{},
|
||||
},
|
||||
},
|
||||
DataSources: map[string]*configschema.Block{
|
||||
DataSources: map[string]providers.Schema{
|
||||
"boop_data": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -467,12 +467,12 @@ func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) {
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("b_id"),
|
||||
"test_string": cty.StringVal("a_id"),
|
||||
}), instanceSchema.ImpliedType())
|
||||
}), instanceSchema.Block.ImpliedType())
|
||||
bAfter, _ := plans.NewDynamicValue(
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("b_id"),
|
||||
"test_string": cty.StringVal("changed"),
|
||||
}), instanceSchema.ImpliedType())
|
||||
}), instanceSchema.Block.ImpliedType())
|
||||
|
||||
changes := &plans.Changes{
|
||||
Resources: []*plans.ResourceInstanceChangeSrc{
|
||||
@ -572,12 +572,12 @@ func TestApplyGraphBuilder_updateFromCBDOrphan(t *testing.T) {
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("b_id"),
|
||||
"test_string": cty.StringVal("a_id"),
|
||||
}), instanceSchema.ImpliedType())
|
||||
}), instanceSchema.Block.ImpliedType())
|
||||
bAfter, _ := plans.NewDynamicValue(
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("b_id"),
|
||||
"test_string": cty.StringVal("changed"),
|
||||
}), instanceSchema.ImpliedType())
|
||||
}), instanceSchema.Block.ImpliedType())
|
||||
|
||||
changes := &plans.Changes{
|
||||
Resources: []*plans.ResourceInstanceChangeSrc{
|
||||
|
@ -54,7 +54,7 @@ type ContextGraphWalker struct {
|
||||
variableValues map[string]map[string]cty.Value
|
||||
variableValuesLock sync.Mutex
|
||||
providerCache map[string]providers.Interface
|
||||
providerSchemas map[string]*ProviderSchema
|
||||
providerSchemas map[string]providers.Schemas
|
||||
providerLock sync.Mutex
|
||||
provisionerCache map[string]provisioners.Interface
|
||||
provisionerSchemas map[string]*configschema.Block
|
||||
@ -122,7 +122,7 @@ func (w *ContextGraphWalker) EvalContext() EvalContext {
|
||||
func (w *ContextGraphWalker) init() {
|
||||
w.contexts = make(map[string]*BuiltinEvalContext)
|
||||
w.providerCache = make(map[string]providers.Interface)
|
||||
w.providerSchemas = make(map[string]*ProviderSchema)
|
||||
w.providerSchemas = make(map[string]providers.Schemas)
|
||||
w.provisionerCache = make(map[string]provisioners.Interface)
|
||||
w.provisionerSchemas = make(map[string]*configschema.Block)
|
||||
w.variableValues = make(map[string]map[string]cty.Value)
|
||||
|
@ -137,7 +137,7 @@ func (n *NodeAbstractResourceInstance) AttachResourceState(s *states.Resource) {
|
||||
|
||||
// readDiff returns the planned change for a particular resource instance
|
||||
// object.
|
||||
func (n *NodeAbstractResourceInstance) readDiff(ctx EvalContext, providerSchema *ProviderSchema) (*plans.ResourceInstanceChange, error) {
|
||||
func (n *NodeAbstractResourceInstance) readDiff(ctx EvalContext, providerSchema providers.Schemas) (*plans.ResourceInstanceChange, error) {
|
||||
changes := ctx.Changes()
|
||||
addr := n.ResourceInstanceAddr()
|
||||
|
||||
@ -323,18 +323,13 @@ func (n *NodeAbstractResourceInstance) writeResourceInstanceStateImpl(ctx EvalCo
|
||||
return nil
|
||||
}
|
||||
|
||||
if providerSchema == nil {
|
||||
// Should never happen, unless our state object is nil
|
||||
panic("writeResourceInstanceStateImpl used with nil ProviderSchema")
|
||||
}
|
||||
|
||||
if obj != nil {
|
||||
log.Printf("[TRACE] %s: writing state object for %s", logFuncName, absAddr)
|
||||
} else {
|
||||
log.Printf("[TRACE] %s: removing state object for %s", logFuncName, absAddr)
|
||||
}
|
||||
|
||||
schema, currentVersion := (*providerSchema).SchemaForResourceAddr(absAddr.ContainingResource().Resource)
|
||||
schema, currentVersion := providerSchema.SchemaForResourceAddr(absAddr.ContainingResource().Resource)
|
||||
if schema == nil {
|
||||
// It shouldn't be possible to get this far in any real scenario
|
||||
// without a schema, but we might end up here in contrived tests that
|
||||
@ -663,10 +658,6 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
return nil, nil, keyData, diags.Append(err)
|
||||
}
|
||||
|
||||
if providerSchema == nil {
|
||||
diags = diags.Append(fmt.Errorf("provider schema is unavailable for %s", n.Addr))
|
||||
return nil, nil, keyData, diags
|
||||
}
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(resource)
|
||||
if schema == nil {
|
||||
// Should be caught during validation, so we don't bother with a pretty error here
|
||||
@ -1416,10 +1407,6 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal
|
||||
if diags.HasErrors() {
|
||||
return newVal, diags
|
||||
}
|
||||
if providerSchema == nil {
|
||||
diags = diags.Append(fmt.Errorf("provider schema not available for %s", n.Addr))
|
||||
return newVal, diags
|
||||
}
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource().Resource)
|
||||
if schema == nil {
|
||||
// Should be caught during validation, so we don't bother with a pretty error here
|
||||
@ -1539,13 +1526,10 @@ func (n *NodeAbstractResourceInstance) providerMetas(ctx EvalContext) (cty.Value
|
||||
if err != nil {
|
||||
return metaConfigVal, diags.Append(err)
|
||||
}
|
||||
if providerSchema == nil {
|
||||
return metaConfigVal, diags.Append(fmt.Errorf("provider schema not available for %s", n.Addr))
|
||||
}
|
||||
if n.ProviderMetas != nil {
|
||||
if m, ok := n.ProviderMetas[n.ResolvedProvider.Provider]; ok && m != nil {
|
||||
// if the provider doesn't support this feature, throw an error
|
||||
if providerSchema.ProviderMeta == nil {
|
||||
if providerSchema.ProviderMeta.Block == nil {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: fmt.Sprintf("Provider %s doesn't support provider_meta", n.ResolvedProvider.Provider.String()),
|
||||
@ -1554,7 +1538,7 @@ func (n *NodeAbstractResourceInstance) providerMetas(ctx EvalContext) (cty.Value
|
||||
})
|
||||
} else {
|
||||
var configDiags tfdiags.Diagnostics
|
||||
metaConfigVal, _, configDiags = ctx.EvaluateBlock(m.Config, providerSchema.ProviderMeta, nil, EvalDataForNoInstanceKey)
|
||||
metaConfigVal, _, configDiags = ctx.EvaluateBlock(m.Config, providerSchema.ProviderMeta.Block, nil, EvalDataForNoInstanceKey)
|
||||
diags = diags.Append(configDiags)
|
||||
}
|
||||
}
|
||||
@ -1580,9 +1564,6 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule
|
||||
if err != nil {
|
||||
return nil, nil, keyData, diags.Append(err)
|
||||
}
|
||||
if providerSchema == nil {
|
||||
return nil, nil, keyData, diags.Append(fmt.Errorf("provider schema not available for %s", n.Addr))
|
||||
}
|
||||
|
||||
config := *n.Config
|
||||
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource().Resource)
|
||||
@ -1851,10 +1832,6 @@ func (n *NodeAbstractResourceInstance) applyDataSource(ctx EvalContext, planned
|
||||
if err != nil {
|
||||
return nil, keyData, diags.Append(err)
|
||||
}
|
||||
if providerSchema == nil {
|
||||
return nil, keyData, diags.Append(fmt.Errorf("provider schema not available for %s", n.Addr))
|
||||
}
|
||||
|
||||
if planned != nil && planned.Action != plans.Read && planned.Action != plans.NoOp {
|
||||
// If any other action gets in here then that's always a bug; this
|
||||
// EvalNode only deals with reading.
|
||||
|
@ -171,7 +171,7 @@ func TestNodeAbstractResourceInstance_WriteResourceInstanceState(t *testing.T) {
|
||||
},
|
||||
}
|
||||
ctx.ProviderProvider = mockProvider
|
||||
ctx.ProviderSchemaSchema = mockProvider.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mockProvider.GetProviderSchema()
|
||||
|
||||
err := node.writeResourceInstanceState(ctx, obj, workingState)
|
||||
if err != nil {
|
||||
|
@ -230,7 +230,7 @@ func TestNodeAbstractResource_ReadResourceInstanceState(t *testing.T) {
|
||||
ctx := new(MockEvalContext)
|
||||
ctx.StateState = test.State.SyncWrapper()
|
||||
ctx.PathPath = addrs.RootModuleInstance
|
||||
ctx.ProviderSchemaSchema = mockProvider.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mockProvider.GetProviderSchema()
|
||||
|
||||
ctx.ProviderProvider = providers.Interface(mockProvider)
|
||||
|
||||
@ -295,7 +295,7 @@ func TestNodeAbstractResource_ReadResourceInstanceStateDeposed(t *testing.T) {
|
||||
ctx := new(MockEvalContext)
|
||||
ctx.StateState = test.State.SyncWrapper()
|
||||
ctx.PathPath = addrs.RootModuleInstance
|
||||
ctx.ProviderSchemaSchema = mockProvider.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mockProvider.GetProviderSchema()
|
||||
ctx.ProviderProvider = providers.Interface(mockProvider)
|
||||
|
||||
key := states.DeposedKey("00000001") // shim from legacy state assigns 0th deposed index this key
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/instances"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
"github.com/hashicorp/terraform/internal/plans/objchange"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
"github.com/hashicorp/terraform/internal/states"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
@ -400,7 +401,7 @@ func (n *NodeApplyableResourceInstance) managedResourcePostconditions(ctx EvalCo
|
||||
// Errors here are most often indicative of a bug in the provider, so our error
|
||||
// messages will report with that in mind. It's also possible that there's a bug
|
||||
// in Terraform's Core's own "proposed new value" code in EvalDiff.
|
||||
func (n *NodeApplyableResourceInstance) checkPlannedChange(ctx EvalContext, plannedChange, actualChange *plans.ResourceInstanceChange, providerSchema *ProviderSchema) tfdiags.Diagnostics {
|
||||
func (n *NodeApplyableResourceInstance) checkPlannedChange(ctx EvalContext, plannedChange, actualChange *plans.ResourceInstanceChange, providerSchema providers.Schemas) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
addr := n.ResourceInstanceAddr().Resource
|
||||
|
||||
|
@ -314,10 +314,6 @@ func (n *NodeDestroyDeposedResourceInstanceObject) writeResourceInstanceState(ct
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if providerSchema == nil {
|
||||
// Should never happen, unless our state object is nil
|
||||
panic("writeResourceInstanceStateDeposed used with no ProviderSchema object")
|
||||
}
|
||||
|
||||
schema, currentVersion := providerSchema.SchemaForResourceAddr(absAddr.ContainingResource().Resource)
|
||||
if schema == nil {
|
||||
|
@ -40,13 +40,15 @@ func TestNodePlanDeposedResourceInstanceObject_Execute(t *testing.T) {
|
||||
PrevRunStateState: state.DeepCopy().SyncWrapper(),
|
||||
RefreshStateState: state.DeepCopy().SyncWrapper(),
|
||||
ProviderProvider: p,
|
||||
ProviderSchemaSchema: &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
ProviderSchemaSchema: providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -96,13 +98,15 @@ func TestNodeDestroyDeposedResourceInstanceObject_Execute(t *testing.T) {
|
||||
mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`),
|
||||
)
|
||||
|
||||
schema := &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
schema := providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -111,7 +115,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_Execute(t *testing.T) {
|
||||
|
||||
p := testProvider("test")
|
||||
p.ConfigureProvider(providers.ConfigureProviderRequest{})
|
||||
p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(schema)
|
||||
p.GetProviderSchemaResponse = &schema
|
||||
|
||||
p.UpgradeResourceStateResponse = &providers.UpgradeResourceStateResponse{
|
||||
UpgradedState: cty.ObjectVal(map[string]cty.Value{
|
||||
@ -159,7 +163,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_WriteResourceInstanceState(t *
|
||||
},
|
||||
})
|
||||
ctx.ProviderProvider = mockProvider
|
||||
ctx.ProviderSchemaSchema = mockProvider.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mockProvider.GetProviderSchema()
|
||||
|
||||
obj := &states.ResourceInstanceObject{
|
||||
Value: cty.ObjectVal(map[string]cty.Value{
|
||||
@ -194,7 +198,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_ExecuteMissingState(t *testing
|
||||
ctx := &MockEvalContext{
|
||||
StateState: states.NewState().SyncWrapper(),
|
||||
ProviderProvider: simpleMockProvider(),
|
||||
ProviderSchemaSchema: p.ProviderSchema(),
|
||||
ProviderSchemaSchema: p.GetProviderSchema(),
|
||||
ChangesChanges: plans.NewChanges().SyncWrapper(),
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ func (n *NodePlannableResourceInstance) replaceTriggered(ctx EvalContext, repDat
|
||||
return diags
|
||||
}
|
||||
|
||||
func (n *NodePlannableResourceInstance) importState(ctx EvalContext, addr addrs.AbsResourceInstance, provider providers.Interface, providerSchema *ProviderSchema) (*states.ResourceInstanceObject, tfdiags.Diagnostics) {
|
||||
func (n *NodePlannableResourceInstance) importState(ctx EvalContext, addr addrs.AbsResourceInstance, provider providers.Interface, providerSchema providers.Schemas) (*states.ResourceInstanceObject, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
absAddr := addr.Resource.Absolute(ctx.Path())
|
||||
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/instances"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
@ -43,9 +42,11 @@ func TestNodeResourcePlanOrphanExecute(t *testing.T) {
|
||||
PrevRunStateState: state.DeepCopy().SyncWrapper(),
|
||||
InstanceExpanderExpander: instances.NewExpander(),
|
||||
ProviderProvider: p,
|
||||
ProviderSchemaSchema: &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"test_object": simpleTestSchema(),
|
||||
ProviderSchemaSchema: providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_object": {
|
||||
Block: simpleTestSchema(),
|
||||
},
|
||||
},
|
||||
},
|
||||
ChangesChanges: plans.NewChanges().SyncWrapper(),
|
||||
@ -107,9 +108,11 @@ func TestNodeResourcePlanOrphanExecute_alreadyDeleted(t *testing.T) {
|
||||
PrevRunStateState: prevRunState.SyncWrapper(),
|
||||
InstanceExpanderExpander: instances.NewExpander(),
|
||||
ProviderProvider: p,
|
||||
ProviderSchemaSchema: &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"test_object": simpleTestSchema(),
|
||||
ProviderSchemaSchema: providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_object": {
|
||||
Block: simpleTestSchema(),
|
||||
},
|
||||
},
|
||||
},
|
||||
ChangesChanges: changes.SyncWrapper(),
|
||||
@ -187,9 +190,11 @@ func TestNodeResourcePlanOrphanExecute_deposed(t *testing.T) {
|
||||
PrevRunStateState: prevRunState.SyncWrapper(),
|
||||
InstanceExpanderExpander: instances.NewExpander(),
|
||||
ProviderProvider: p,
|
||||
ProviderSchemaSchema: &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"test_object": simpleTestSchema(),
|
||||
ProviderSchemaSchema: providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"test_object": {
|
||||
Block: simpleTestSchema(),
|
||||
},
|
||||
},
|
||||
},
|
||||
ChangesChanges: changes.SyncWrapper(),
|
||||
|
@ -276,10 +276,6 @@ func (n *NodeValidatableResource) validateResource(ctx EvalContext) tfdiags.Diag
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
if providerSchema == nil {
|
||||
diags = diags.Append(fmt.Errorf("validateResource has nil schema for %s", n.Addr))
|
||||
return diags
|
||||
}
|
||||
|
||||
keyData := EvalDataForNoInstanceKey
|
||||
|
||||
|
@ -193,7 +193,7 @@ func TestNodeValidatableResource_ValidateResource_managedResource(t *testing.T)
|
||||
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
err := node.validateResource(ctx)
|
||||
@ -223,7 +223,7 @@ func TestNodeValidatableResource_ValidateResource_managedResourceCount(t *testin
|
||||
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
tests := []struct {
|
||||
@ -307,7 +307,7 @@ func TestNodeValidatableResource_ValidateResource_dataSource(t *testing.T) {
|
||||
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
diags := node.validateResource(ctx)
|
||||
@ -343,7 +343,7 @@ func TestNodeValidatableResource_ValidateResource_valid(t *testing.T) {
|
||||
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
diags := node.validateResource(ctx)
|
||||
@ -380,7 +380,7 @@ func TestNodeValidatableResource_ValidateResource_warningsAndErrorsPassedThrough
|
||||
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
diags := node.validateResource(ctx)
|
||||
@ -443,7 +443,7 @@ func TestNodeValidatableResource_ValidateResource_invalidDependsOn(t *testing.T)
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
diags := node.validateResource(ctx)
|
||||
@ -527,7 +527,7 @@ func TestNodeValidatableResource_ValidateResource_invalidIgnoreChangesNonexisten
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
diags := node.validateResource(ctx)
|
||||
@ -610,7 +610,7 @@ func TestNodeValidatableResource_ValidateResource_invalidIgnoreChangesComputed(t
|
||||
ctx := &MockEvalContext{}
|
||||
ctx.installSimpleEval()
|
||||
|
||||
ctx.ProviderSchemaSchema = mp.ProviderSchema()
|
||||
ctx.ProviderSchemaSchema = mp.GetProviderSchema()
|
||||
ctx.ProviderProvider = p
|
||||
|
||||
diags := node.validateResource(ctx)
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
ctyjson "github.com/zclconf/go-cty/cty/json"
|
||||
"github.com/zclconf/go-cty/cty/msgpack"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/configs/hcl2shim"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
)
|
||||
@ -112,31 +111,6 @@ func (p *MockProvider) getProviderSchema() providers.GetProviderSchemaResponse {
|
||||
}
|
||||
}
|
||||
|
||||
// ProviderSchema is a helper to convert from the internal GetProviderSchemaResponse to
|
||||
// a ProviderSchema.
|
||||
func (p *MockProvider) ProviderSchema() *ProviderSchema {
|
||||
resp := p.getProviderSchema()
|
||||
|
||||
schema := &ProviderSchema{
|
||||
Provider: resp.Provider.Block,
|
||||
ProviderMeta: resp.ProviderMeta.Block,
|
||||
ResourceTypes: map[string]*configschema.Block{},
|
||||
DataSources: map[string]*configschema.Block{},
|
||||
ResourceTypeSchemaVersions: map[string]uint64{},
|
||||
}
|
||||
|
||||
for resType, s := range resp.ResourceTypes {
|
||||
schema.ResourceTypes[resType] = s.Block
|
||||
schema.ResourceTypeSchemaVersions[resType] = uint64(s.Version)
|
||||
}
|
||||
|
||||
for dataSource, s := range resp.DataSources {
|
||||
schema.DataSources[dataSource] = s.Block
|
||||
}
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
func (p *MockProvider) ValidateProviderConfig(r providers.ValidateProviderConfigRequest) (resp providers.ValidateProviderConfigResponse) {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
@ -49,30 +49,6 @@ func mockProviderWithResourceTypeSchema(name string, schema *configschema.Block)
|
||||
}
|
||||
}
|
||||
|
||||
// getProviderSchemaResponseFromProviderSchema is a test helper to convert a
|
||||
// ProviderSchema to a GetProviderSchemaResponse for use when building a mock provider.
|
||||
func getProviderSchemaResponseFromProviderSchema(providerSchema *ProviderSchema) *providers.GetProviderSchemaResponse {
|
||||
resp := &providers.GetProviderSchemaResponse{
|
||||
Provider: providers.Schema{Block: providerSchema.Provider},
|
||||
ProviderMeta: providers.Schema{Block: providerSchema.ProviderMeta},
|
||||
ResourceTypes: map[string]providers.Schema{},
|
||||
DataSources: map[string]providers.Schema{},
|
||||
}
|
||||
|
||||
for name, schema := range providerSchema.ResourceTypes {
|
||||
resp.ResourceTypes[name] = providers.Schema{
|
||||
Block: schema,
|
||||
Version: int64(providerSchema.ResourceTypeSchemaVersions[name]),
|
||||
}
|
||||
}
|
||||
|
||||
for name, schema := range providerSchema.DataSources {
|
||||
resp.DataSources[name] = providers.Schema{Block: schema}
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// simpleMockProvider returns a MockProvider that is pre-configured
|
||||
// with schema for its own config, for a resource type called "test_object" and
|
||||
// for a data source also called "test_object".
|
||||
@ -103,3 +79,62 @@ func simpleMockProvider() *MockProvider {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ProviderSchema is a helper to convert from the internal GetProviderSchemaResponse to
|
||||
// a ProviderSchema.
|
||||
func (p *MockProvider) ProviderSchema() *ProviderSchema {
|
||||
resp := p.getProviderSchema()
|
||||
|
||||
schema := &ProviderSchema{
|
||||
Provider: resp.Provider.Block,
|
||||
ProviderMeta: resp.ProviderMeta.Block,
|
||||
ResourceTypes: map[string]*configschema.Block{},
|
||||
DataSources: map[string]*configschema.Block{},
|
||||
ResourceTypeSchemaVersions: map[string]uint64{},
|
||||
}
|
||||
|
||||
for resType, s := range resp.ResourceTypes {
|
||||
schema.ResourceTypes[resType] = s.Block
|
||||
schema.ResourceTypeSchemaVersions[resType] = uint64(s.Version)
|
||||
}
|
||||
|
||||
for dataSource, s := range resp.DataSources {
|
||||
schema.DataSources[dataSource] = s.Block
|
||||
}
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
// the type was refactored out with all the functionality handled within the
|
||||
// provider package, but we keep this here for a shim in existing tests.
|
||||
type ProviderSchema struct {
|
||||
Provider *configschema.Block
|
||||
ProviderMeta *configschema.Block
|
||||
ResourceTypes map[string]*configschema.Block
|
||||
ResourceTypeSchemaVersions map[string]uint64
|
||||
DataSources map[string]*configschema.Block
|
||||
}
|
||||
|
||||
// getProviderSchemaResponseFromProviderSchema is a test helper to convert a
|
||||
// ProviderSchema to a GetProviderSchemaResponse for use when building a mock provider.
|
||||
func getProviderSchemaResponseFromProviderSchema(providerSchema *ProviderSchema) *providers.GetProviderSchemaResponse {
|
||||
resp := &providers.GetProviderSchemaResponse{
|
||||
Provider: providers.Schema{Block: providerSchema.Provider},
|
||||
ProviderMeta: providers.Schema{Block: providerSchema.ProviderMeta},
|
||||
ResourceTypes: map[string]providers.Schema{},
|
||||
DataSources: map[string]providers.Schema{},
|
||||
}
|
||||
|
||||
for name, schema := range providerSchema.ResourceTypes {
|
||||
resp.ResourceTypes[name] = providers.Schema{
|
||||
Block: schema,
|
||||
Version: int64(providerSchema.ResourceTypeSchemaVersions[name]),
|
||||
}
|
||||
}
|
||||
|
||||
for name, schema := range providerSchema.DataSources {
|
||||
resp.DataSources[name] = providers.Schema{Block: schema}
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
@ -15,16 +15,10 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
|
||||
// ProviderSchema is an alias for providers.Schemas, which is the new location
|
||||
// for what we originally called terraform.ProviderSchema but which has
|
||||
// moved out as part of ongoing refactoring to shrink down the main "terraform"
|
||||
// package.
|
||||
type ProviderSchema = providers.Schemas
|
||||
|
||||
// Schemas is a container for various kinds of schema that Terraform needs
|
||||
// during processing.
|
||||
type Schemas struct {
|
||||
Providers map[addrs.Provider]*providers.Schemas
|
||||
Providers map[addrs.Provider]providers.Schemas
|
||||
Provisioners map[string]*configschema.Block
|
||||
}
|
||||
|
||||
@ -33,21 +27,14 @@ type Schemas struct {
|
||||
//
|
||||
// It's usually better to go use the more precise methods offered by type
|
||||
// Schemas to handle this detail automatically.
|
||||
func (ss *Schemas) ProviderSchema(provider addrs.Provider) *providers.Schemas {
|
||||
if ss.Providers == nil {
|
||||
return nil
|
||||
}
|
||||
func (ss *Schemas) ProviderSchema(provider addrs.Provider) providers.Schemas {
|
||||
return ss.Providers[provider]
|
||||
}
|
||||
|
||||
// ProviderConfig returns the schema for the provider configuration of the
|
||||
// given provider type, or nil if no such schema is available.
|
||||
func (ss *Schemas) ProviderConfig(provider addrs.Provider) *configschema.Block {
|
||||
ps := ss.ProviderSchema(provider)
|
||||
if ps == nil {
|
||||
return nil
|
||||
}
|
||||
return ps.Provider
|
||||
return ss.ProviderSchema(provider).Provider.Block
|
||||
}
|
||||
|
||||
// ResourceTypeConfig returns the schema for the configuration of a given
|
||||
@ -61,7 +48,7 @@ func (ss *Schemas) ProviderConfig(provider addrs.Provider) *configschema.Block {
|
||||
// redundant.
|
||||
func (ss *Schemas) ResourceTypeConfig(provider addrs.Provider, resourceMode addrs.ResourceMode, resourceType string) (block *configschema.Block, schemaVersion uint64) {
|
||||
ps := ss.ProviderSchema(provider)
|
||||
if ps == nil || ps.ResourceTypes == nil {
|
||||
if ps.ResourceTypes == nil {
|
||||
return nil, 0
|
||||
}
|
||||
return ps.SchemaForResourceType(resourceMode, resourceType)
|
||||
@ -85,7 +72,7 @@ func (ss *Schemas) ProvisionerConfig(name string) *configschema.Block {
|
||||
// still valid but may be incomplete.
|
||||
func loadSchemas(config *configs.Config, state *states.State, plugins *contextPlugins) (*Schemas, error) {
|
||||
schemas := &Schemas{
|
||||
Providers: map[addrs.Provider]*providers.Schemas{},
|
||||
Providers: map[addrs.Provider]providers.Schemas{},
|
||||
Provisioners: map[string]*configschema.Block{},
|
||||
}
|
||||
var diags tfdiags.Diagnostics
|
||||
@ -98,7 +85,7 @@ func loadSchemas(config *configs.Config, state *states.State, plugins *contextPl
|
||||
return schemas, diags.Err()
|
||||
}
|
||||
|
||||
func loadProviderSchemas(schemas map[addrs.Provider]*providers.Schemas, config *configs.Config, state *states.State, plugins *contextPlugins) tfdiags.Diagnostics {
|
||||
func loadProviderSchemas(schemas map[addrs.Provider]providers.Schemas, config *configs.Config, state *states.State, plugins *contextPlugins) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
ensure := func(fqn addrs.Provider) {
|
||||
@ -114,7 +101,7 @@ func loadProviderSchemas(schemas map[addrs.Provider]*providers.Schemas, config *
|
||||
// We'll put a stub in the map so we won't re-attempt this on
|
||||
// future calls, which would then repeat the same error message
|
||||
// multiple times.
|
||||
schemas[fqn] = &providers.Schemas{}
|
||||
schemas[fqn] = providers.Schemas{}
|
||||
diags = diags.Append(
|
||||
tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
|
@ -14,8 +14,8 @@ func simpleTestSchemas() *Schemas {
|
||||
provisioner := simpleMockProvisioner()
|
||||
|
||||
return &Schemas{
|
||||
Providers: map[addrs.Provider]*ProviderSchema{
|
||||
addrs.NewDefaultProvider("test"): provider.ProviderSchema(),
|
||||
Providers: map[addrs.Provider]providers.Schemas{
|
||||
addrs.NewDefaultProvider("test"): provider.GetProviderSchema(),
|
||||
},
|
||||
Provisioners: map[string]*configschema.Block{
|
||||
"test": provisioner.GetSchemaResponse.Provisioner,
|
||||
@ -31,32 +31,14 @@ func simpleTestSchemas() *Schemas {
|
||||
// The intended use for this is in testing components that use schemas to
|
||||
// drive other behavior, such as reference analysis during graph construction,
|
||||
// but that don't actually need to interact with providers otherwise.
|
||||
func schemaOnlyProvidersForTesting(schemas map[addrs.Provider]*ProviderSchema) *contextPlugins {
|
||||
func schemaOnlyProvidersForTesting(schemas map[addrs.Provider]providers.Schemas) *contextPlugins {
|
||||
factories := make(map[addrs.Provider]providers.Factory, len(schemas))
|
||||
|
||||
for providerAddr, schema := range schemas {
|
||||
|
||||
resp := &providers.GetProviderSchemaResponse{
|
||||
Provider: providers.Schema{
|
||||
Block: schema.Provider,
|
||||
},
|
||||
ResourceTypes: make(map[string]providers.Schema),
|
||||
DataSources: make(map[string]providers.Schema),
|
||||
}
|
||||
for t, tSchema := range schema.ResourceTypes {
|
||||
resp.ResourceTypes[t] = providers.Schema{
|
||||
Block: tSchema,
|
||||
Version: int64(schema.ResourceTypeSchemaVersions[t]),
|
||||
}
|
||||
}
|
||||
for t, tSchema := range schema.DataSources {
|
||||
resp.DataSources[t] = providers.Schema{
|
||||
Block: tSchema,
|
||||
}
|
||||
}
|
||||
schema := schema
|
||||
|
||||
provider := &MockProvider{
|
||||
GetProviderSchemaResponse: resp,
|
||||
GetProviderSchemaResponse: &schema,
|
||||
}
|
||||
|
||||
factories[providerAddr] = func() (providers.Interface, error) {
|
||||
|
@ -170,24 +170,24 @@ func testSetResourceInstanceTainted(module *states.Module, resource, attrsJson,
|
||||
}
|
||||
|
||||
func testProviderFuncFixed(rp providers.Interface) providers.Factory {
|
||||
return func() (providers.Interface, error) {
|
||||
if p, ok := rp.(*MockProvider); ok {
|
||||
// make sure none of the methods were "called" on this new instance
|
||||
p.GetProviderSchemaCalled = false
|
||||
p.ValidateProviderConfigCalled = false
|
||||
p.ValidateResourceConfigCalled = false
|
||||
p.ValidateDataResourceConfigCalled = false
|
||||
p.UpgradeResourceStateCalled = false
|
||||
p.ConfigureProviderCalled = false
|
||||
p.StopCalled = false
|
||||
p.ReadResourceCalled = false
|
||||
p.PlanResourceChangeCalled = false
|
||||
p.ApplyResourceChangeCalled = false
|
||||
p.ImportResourceStateCalled = false
|
||||
p.ReadDataSourceCalled = false
|
||||
p.CloseCalled = false
|
||||
}
|
||||
if p, ok := rp.(*MockProvider); ok {
|
||||
// make sure none of the methods were "called" on this new instance
|
||||
p.GetProviderSchemaCalled = false
|
||||
p.ValidateProviderConfigCalled = false
|
||||
p.ValidateResourceConfigCalled = false
|
||||
p.ValidateDataResourceConfigCalled = false
|
||||
p.UpgradeResourceStateCalled = false
|
||||
p.ConfigureProviderCalled = false
|
||||
p.StopCalled = false
|
||||
p.ReadResourceCalled = false
|
||||
p.PlanResourceChangeCalled = false
|
||||
p.ApplyResourceChangeCalled = false
|
||||
p.ImportResourceStateCalled = false
|
||||
p.ReadDataSourceCalled = false
|
||||
p.CloseCalled = false
|
||||
}
|
||||
|
||||
return func() (providers.Interface, error) {
|
||||
return rp, nil
|
||||
}
|
||||
}
|
||||
|
@ -72,13 +72,15 @@ func TestGraphNodeImportStateSubExecute(t *testing.T) {
|
||||
ctx := &MockEvalContext{
|
||||
StateState: state.SyncWrapper(),
|
||||
ProviderProvider: provider,
|
||||
ProviderSchemaSchema: &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
ProviderSchemaSchema: providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"aws_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -132,13 +134,15 @@ func TestGraphNodeImportStateSubExecuteNull(t *testing.T) {
|
||||
ctx := &MockEvalContext{
|
||||
StateState: state.SyncWrapper(),
|
||||
ProviderProvider: provider,
|
||||
ProviderSchemaSchema: &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
ProviderSchemaSchema: providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"aws_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
@ -33,18 +34,20 @@ func TestTransitiveReductionTransformer(t *testing.T) {
|
||||
|
||||
{
|
||||
transform := &AttachSchemaTransformer{
|
||||
Plugins: schemaOnlyProvidersForTesting(map[addrs.Provider]*ProviderSchema{
|
||||
Plugins: schemaOnlyProvidersForTesting(map[addrs.Provider]providers.Schemas{
|
||||
addrs.NewDefaultProvider("aws"): {
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"aws_instance": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"A": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
"B": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"A": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
"B": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -11,12 +11,13 @@ import (
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/lang"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
|
||||
// validateSelfRef checks to ensure that expressions within a particular
|
||||
// referencable block do not reference that same block.
|
||||
func validateSelfRef(addr addrs.Referenceable, config hcl.Body, providerSchema *ProviderSchema) tfdiags.Diagnostics {
|
||||
func validateSelfRef(addr addrs.Referenceable, config hcl.Body, providerSchema providers.Schemas) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
addrStrs := make([]string, 0, 1)
|
||||
@ -27,11 +28,6 @@ func validateSelfRef(addr addrs.Referenceable, config hcl.Body, providerSchema *
|
||||
addrStrs = append(addrStrs, tAddr.ContainingResource().String())
|
||||
}
|
||||
|
||||
if providerSchema == nil {
|
||||
diags = diags.Append(fmt.Errorf("provider schema unavailable while validating %s for self-references; this is a bug in Terraform and should be reported", addr))
|
||||
return diags
|
||||
}
|
||||
|
||||
var schema *configschema.Block
|
||||
switch tAddr := addr.(type) {
|
||||
case addrs.Resource:
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/providers"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hcltest"
|
||||
@ -82,13 +83,15 @@ func TestValidateSelfRef(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
ps := &ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"aws_instance": &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"foo": {
|
||||
Type: cty.String,
|
||||
Required: true,
|
||||
ps := providers.Schemas{
|
||||
ResourceTypes: map[string]providers.Schema{
|
||||
"aws_instance": {
|
||||
Block: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"foo": {
|
||||
Type: cty.String,
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user