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.
|
||||
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(string) error
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ type BuiltinEvalContext struct {
|
|||
Hooks []Hook
|
||||
InputValue UIInput
|
||||
ProviderCache map[string]ResourceProvider
|
||||
ProviderSchemas map[string]*ProviderSchema
|
||||
ProviderInputConfig map[string]map[string]interface{}
|
||||
ProviderLock *sync.Mutex
|
||||
ProvisionerCache map[string]ResourceProvisioner
|
||||
|
@ -97,6 +98,35 @@ func (ctx *BuiltinEvalContext) InitProvider(typeName, name string) (ResourceProv
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -109,6 +139,15 @@ func (ctx *BuiltinEvalContext) Provider(n string) ResourceProvider {
|
|||
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 {
|
||||
ctx.once.Do(ctx.init)
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ import (
|
|||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/hashicorp/terraform/config/configschema"
|
||||
)
|
||||
|
||||
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 {
|
||||
return &BuiltinEvalContext{}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ type MockEvalContext struct {
|
|||
ProviderName string
|
||||
ProviderProvider ResourceProvider
|
||||
|
||||
ProviderSchemaCalled bool
|
||||
ProviderSchemaName string
|
||||
ProviderSchemaSchema *ProviderSchema
|
||||
|
||||
CloseProviderCalled bool
|
||||
CloseProviderName string
|
||||
CloseProviderProvider ResourceProvider
|
||||
|
@ -119,6 +123,12 @@ func (c *MockEvalContext) Provider(n string) ResourceProvider {
|
|||
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 {
|
||||
c.CloseProviderCalled = true
|
||||
c.CloseProviderName = n
|
||||
|
|
Loading…
Reference in New Issue