mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-20 11:48:24 -06:00
core: load a provider's schema at initialization
This is currently not very ergonomic due to the API exposed by providers. We'll smooth this out in a later change to improve the provider API, since we know we always want the entire schema.
This commit is contained in:
parent
3822650e15
commit
a09498a8a3
@ -32,6 +32,10 @@ type EvalContext interface {
|
|||||||
// initialized) or returns nil if the provider isn't initialized.
|
// initialized) or returns nil if the provider isn't initialized.
|
||||||
Provider(string) ResourceProvider
|
Provider(string) ResourceProvider
|
||||||
|
|
||||||
|
// ProviderSchema retrieves the schema for a particular provider, which
|
||||||
|
// must have already be initialized with InitProvider.
|
||||||
|
ProviderSchema(string) *ProviderSchema
|
||||||
|
|
||||||
// CloseProvider closes provider connections that aren't needed anymore.
|
// CloseProvider closes provider connections that aren't needed anymore.
|
||||||
CloseProvider(string) error
|
CloseProvider(string) error
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ type BuiltinEvalContext struct {
|
|||||||
Hooks []Hook
|
Hooks []Hook
|
||||||
InputValue UIInput
|
InputValue UIInput
|
||||||
ProviderCache map[string]ResourceProvider
|
ProviderCache map[string]ResourceProvider
|
||||||
|
ProviderSchemas map[string]*ProviderSchema
|
||||||
ProviderInputConfig map[string]map[string]interface{}
|
ProviderInputConfig map[string]map[string]interface{}
|
||||||
ProviderLock *sync.Mutex
|
ProviderLock *sync.Mutex
|
||||||
ProvisionerCache map[string]ResourceProvisioner
|
ProvisionerCache map[string]ResourceProvisioner
|
||||||
@ -97,6 +98,35 @@ func (ctx *BuiltinEvalContext) InitProvider(typeName, name string) (ResourceProv
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.ProviderCache[name] = p
|
ctx.ProviderCache[name] = p
|
||||||
|
|
||||||
|
// Also fetch and cache the provider's schema.
|
||||||
|
// FIXME: This is using a non-ideal provider API that requires us to
|
||||||
|
// request specific resource types, but we actually just want _all_ the
|
||||||
|
// resource types, so we'll list these first. Once the provider API is
|
||||||
|
// updated we'll get enough data to populate this whole structure in
|
||||||
|
// a single call.
|
||||||
|
resourceTypes := p.Resources()
|
||||||
|
dataSources := p.DataSources()
|
||||||
|
resourceTypeNames := make([]string, len(resourceTypes))
|
||||||
|
for i, t := range resourceTypes {
|
||||||
|
resourceTypeNames[i] = t.Name
|
||||||
|
}
|
||||||
|
dataSourceNames := make([]string, len(dataSources))
|
||||||
|
for i, t := range dataSources {
|
||||||
|
dataSourceNames[i] = t.Name
|
||||||
|
}
|
||||||
|
schema, err := p.GetSchema(&ProviderSchemaRequest{
|
||||||
|
DataSources: dataSourceNames,
|
||||||
|
ResourceTypes: resourceTypeNames,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error fetching schema for %s: %s", name, err)
|
||||||
|
}
|
||||||
|
if ctx.ProviderSchemas == nil {
|
||||||
|
ctx.ProviderSchemas = make(map[string]*ProviderSchema)
|
||||||
|
}
|
||||||
|
ctx.ProviderSchemas[name] = schema
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +139,15 @@ func (ctx *BuiltinEvalContext) Provider(n string) ResourceProvider {
|
|||||||
return ctx.ProviderCache[n]
|
return ctx.ProviderCache[n]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *BuiltinEvalContext) ProviderSchema(n string) *ProviderSchema {
|
||||||
|
ctx.once.Do(ctx.init)
|
||||||
|
|
||||||
|
ctx.ProviderLock.Lock()
|
||||||
|
defer ctx.ProviderLock.Unlock()
|
||||||
|
|
||||||
|
return ctx.ProviderSchemas[n]
|
||||||
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) CloseProvider(n string) error {
|
func (ctx *BuiltinEvalContext) CloseProvider(n string) error {
|
||||||
ctx.once.Do(ctx.init)
|
ctx.once.Do(ctx.init)
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/hashicorp/terraform/config/configschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBuiltinEvalContextProviderInput(t *testing.T) {
|
func TestBuiltinEvalContextProviderInput(t *testing.T) {
|
||||||
@ -37,6 +40,78 @@ func TestBuiltinEvalContextProviderInput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuildingEvalContextInitProvider(t *testing.T) {
|
||||||
|
var lock sync.Mutex
|
||||||
|
|
||||||
|
testP := &MockResourceProvider{
|
||||||
|
ResourcesReturn: []ResourceType{
|
||||||
|
{
|
||||||
|
Name: "test_thing",
|
||||||
|
SchemaAvailable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DataSourcesReturn: []DataSource{
|
||||||
|
{
|
||||||
|
Name: "test_thing",
|
||||||
|
SchemaAvailable: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
GetSchemaReturn: &ProviderSchema{
|
||||||
|
Provider: &configschema.Block{},
|
||||||
|
ResourceTypes: map[string]*configschema.Block{
|
||||||
|
"test_thing": &configschema.Block{},
|
||||||
|
},
|
||||||
|
DataSources: map[string]*configschema.Block{
|
||||||
|
"test_thing": &configschema.Block{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := testBuiltinEvalContext(t)
|
||||||
|
ctx.ProviderLock = &lock
|
||||||
|
ctx.ProviderCache = make(map[string]ResourceProvider)
|
||||||
|
ctx.Components = &basicComponentFactory{
|
||||||
|
providers: map[string]ResourceProviderFactory{
|
||||||
|
"test": ResourceProviderFactoryFixed(testP),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := ctx.InitProvider("test", "test")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error initializing provider test: %s", err)
|
||||||
|
}
|
||||||
|
_, err = ctx.InitProvider("test", "test.foo")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error initializing provider test.foo: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
got := testP.GetSchemaRequest
|
||||||
|
want := &ProviderSchemaRequest{
|
||||||
|
DataSources: []string{"test_thing"},
|
||||||
|
ResourceTypes: []string{"test_thing"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("wrong schema request\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
schema := ctx.ProviderSchema("test")
|
||||||
|
if got, want := schema, testP.GetSchemaReturn; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("wrong schema\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
schema := ctx.ProviderSchema("test.foo")
|
||||||
|
if got, want := schema, testP.GetSchemaReturn; !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("wrong schema\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testBuiltinEvalContext(t *testing.T) *BuiltinEvalContext {
|
func testBuiltinEvalContext(t *testing.T) *BuiltinEvalContext {
|
||||||
return &BuiltinEvalContext{}
|
return &BuiltinEvalContext{}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,10 @@ type MockEvalContext struct {
|
|||||||
ProviderName string
|
ProviderName string
|
||||||
ProviderProvider ResourceProvider
|
ProviderProvider ResourceProvider
|
||||||
|
|
||||||
|
ProviderSchemaCalled bool
|
||||||
|
ProviderSchemaName string
|
||||||
|
ProviderSchemaSchema *ProviderSchema
|
||||||
|
|
||||||
CloseProviderCalled bool
|
CloseProviderCalled bool
|
||||||
CloseProviderName string
|
CloseProviderName string
|
||||||
CloseProviderProvider ResourceProvider
|
CloseProviderProvider ResourceProvider
|
||||||
@ -119,6 +123,12 @@ func (c *MockEvalContext) Provider(n string) ResourceProvider {
|
|||||||
return c.ProviderProvider
|
return c.ProviderProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *MockEvalContext) ProviderSchema(n string) *ProviderSchema {
|
||||||
|
c.ProviderSchemaCalled = true
|
||||||
|
c.ProviderSchemaName = n
|
||||||
|
return c.ProviderSchemaSchema
|
||||||
|
}
|
||||||
|
|
||||||
func (c *MockEvalContext) CloseProvider(n string) error {
|
func (c *MockEvalContext) CloseProvider(n string) error {
|
||||||
c.CloseProviderCalled = true
|
c.CloseProviderCalled = true
|
||||||
c.CloseProviderName = n
|
c.CloseProviderName = n
|
||||||
|
Loading…
Reference in New Issue
Block a user