From 16df9c37cf3eca9e4a1db4e16e55495a4239681a Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 16 Aug 2018 11:40:08 -0400 Subject: [PATCH] first step in core provider type replacement Chaange ResourceProvider to providers.Interface starting from the context, and fix all type errors. This only replaced some of method calls directly applicable to the providers themselves. The resource methods will follow. --- terraform/context.go | 13 +++-- terraform/context_components.go | 8 ++- terraform/eval_apply.go | 3 +- terraform/eval_context.go | 5 +- terraform/eval_context_builtin.go | 29 +++++----- terraform/eval_context_mock.go | 11 ++-- terraform/eval_diff.go | 3 +- terraform/eval_import_state.go | 3 +- terraform/eval_provider.go | 16 +++--- terraform/eval_read_data.go | 5 +- terraform/eval_refresh.go | 3 +- terraform/eval_state.go | 5 +- terraform/eval_validate.go | 72 ++++++++---------------- terraform/evaltree_provider.go | 3 +- terraform/graph_walk_context.go | 5 +- terraform/node_data_refresh.go | 3 +- terraform/node_resource_apply.go | 5 +- terraform/node_resource_destroy.go | 3 +- terraform/node_resource_plan_destroy.go | 3 +- terraform/node_resource_plan_instance.go | 5 +- terraform/node_resource_plan_orphan.go | 3 +- terraform/node_resource_refresh.go | 5 +- terraform/node_resource_validate.go | 3 +- terraform/resource_provider.go | 3 +- terraform/schemas.go | 45 +++++++-------- terraform/transform_deposed.go | 3 +- terraform/transform_import_state.go | 5 +- 27 files changed, 130 insertions(+), 140 deletions(-) diff --git a/terraform/context.go b/terraform/context.go index 9793f2425..374f4d92a 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -63,7 +64,7 @@ type ContextOpts struct { Hooks []Hook Parallelism int - ProviderResolver ResourceProviderResolver + ProviderResolver providers.Resolver Provisioners map[string]ResourceProvisionerFactory // If non-nil, will apply as additional constraints on the provider @@ -165,7 +166,7 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) { variables = variables.Override(opts.Variables) // Bind available provider plugins to the constraints in config - var providers map[string]ResourceProviderFactory + var providerFactories map[string]providers.Factory if opts.ProviderResolver != nil { var err error deps := ConfigTreeDependencies(opts.Config, state) @@ -173,17 +174,17 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) { if opts.ProviderSHA256s != nil && !opts.SkipProviderVerify { reqd.LockExecutables(opts.ProviderSHA256s) } - providers, err = resourceProviderFactories(opts.ProviderResolver, reqd) + providerFactories, err = resourceProviderFactories(opts.ProviderResolver, reqd) if err != nil { diags = diags.Append(err) return nil, diags } } else { - providers = make(map[string]ResourceProviderFactory) + providerFactories = make(map[string]providers.Factory) } components := &basicComponentFactory{ - providers: providers, + providers: providerFactories, provisioners: opts.Provisioners, } @@ -757,7 +758,7 @@ func (c *Context) watchStop(walker *ContextGraphWalker) (chan struct{}, <-chan s // Copy the providers so that a misbehaved blocking Stop doesn't // completely hang Terraform. walker.providerLock.Lock() - ps := make([]ResourceProvider, 0, len(walker.providerCache)) + ps := make([]providers.Interface, 0, len(walker.providerCache)) for _, p := range walker.providerCache { ps = append(ps, p) } diff --git a/terraform/context_components.go b/terraform/context_components.go index 6f507445c..c685d677b 100644 --- a/terraform/context_components.go +++ b/terraform/context_components.go @@ -2,6 +2,8 @@ package terraform import ( "fmt" + + "github.com/hashicorp/terraform/providers" ) // contextComponentFactory is the interface that Context uses @@ -12,7 +14,7 @@ type contextComponentFactory interface { // ResourceProvider creates a new ResourceProvider with the given // type. The "uid" is a unique identifier for this provider being // initialized that can be used for internal tracking. - ResourceProvider(typ, uid string) (ResourceProvider, error) + ResourceProvider(typ, uid string) (providers.Interface, error) ResourceProviders() []string // ResourceProvisioner creates a new ResourceProvisioner with the @@ -24,7 +26,7 @@ type contextComponentFactory interface { // basicComponentFactory just calls a factory from a map directly. type basicComponentFactory struct { - providers map[string]ResourceProviderFactory + providers map[string]providers.Factory provisioners map[string]ResourceProvisionerFactory } @@ -46,7 +48,7 @@ func (c *basicComponentFactory) ResourceProvisioners() []string { return result } -func (c *basicComponentFactory) ResourceProvider(typ, uid string) (ResourceProvider, error) { +func (c *basicComponentFactory) ResourceProvider(typ, uid string) (providers.Interface, error) { f, ok := c.providers[typ] if !ok { return nil, fmt.Errorf("unknown provider %q", typ) diff --git a/terraform/eval_apply.go b/terraform/eval_apply.go index ddb1457ce..600f6fd0f 100644 --- a/terraform/eval_apply.go +++ b/terraform/eval_apply.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -18,7 +19,7 @@ type EvalApply struct { Addr addrs.ResourceInstance State **states.ResourceInstanceObject Change **plans.ResourceInstanceChange - Provider *ResourceProvider + Provider *providers.Interface Output **states.ResourceInstanceObject CreateNew *bool Error *error diff --git a/terraform/eval_context.go b/terraform/eval_context.go index 40c5958ff..02137d839 100644 --- a/terraform/eval_context.go +++ b/terraform/eval_context.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" "github.com/zclconf/go-cty/cty" @@ -31,7 +32,7 @@ type EvalContext interface { // returns the implementation of the resource provider or an error. // // It is an error to initialize the same provider more than once. - InitProvider(typ string, addr addrs.ProviderConfig) (ResourceProvider, error) + InitProvider(typ string, addr addrs.ProviderConfig) (providers.Interface, error) // Provider gets the provider instance with the given address (already // initialized) or returns nil if the provider isn't initialized. @@ -40,7 +41,7 @@ type EvalContext interface { // resources in one module are able to use providers from other modules. // InitProvider must've been called on the EvalContext of the module // that owns the given provider before calling this method. - Provider(addrs.AbsProviderConfig) ResourceProvider + Provider(addrs.AbsProviderConfig) providers.Interface // ProviderSchema retrieves the schema for a particular provider, which // must have already been initialized with InitProvider. diff --git a/terraform/eval_context_builtin.go b/terraform/eval_context_builtin.go index 2a1ab5ce5..4e8231915 100644 --- a/terraform/eval_context_builtin.go +++ b/terraform/eval_context_builtin.go @@ -7,6 +7,8 @@ import ( "sync" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/version" "github.com/hashicorp/terraform/states" @@ -53,7 +55,7 @@ type BuiltinEvalContext struct { Components contextComponentFactory Hooks []Hook InputValue UIInput - ProviderCache map[string]ResourceProvider + ProviderCache map[string]providers.Interface ProviderInputConfig map[string]map[string]cty.Value ProviderLock *sync.Mutex ProvisionerCache map[string]ResourceProvisioner @@ -100,7 +102,7 @@ func (ctx *BuiltinEvalContext) Input() UIInput { return ctx.InputValue } -func (ctx *BuiltinEvalContext) InitProvider(typeName string, addr addrs.ProviderConfig) (ResourceProvider, error) { +func (ctx *BuiltinEvalContext) InitProvider(typeName string, addr addrs.ProviderConfig) (providers.Interface, error) { ctx.once.Do(ctx.init) absAddr := addr.Absolute(ctx.Path()) @@ -127,7 +129,7 @@ func (ctx *BuiltinEvalContext) InitProvider(typeName string, addr addrs.Provider return p, nil } -func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) ResourceProvider { +func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface { ctx.once.Do(ctx.init) ctx.ProviderLock.Lock() @@ -149,13 +151,10 @@ func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.ProviderConfig) error { defer ctx.ProviderLock.Unlock() key := addr.Absolute(ctx.Path()).String() - var provider interface{} - provider = ctx.ProviderCache[key] + provider := ctx.ProviderCache[key] if provider != nil { - if p, ok := provider.(ResourceProviderCloser); ok { - delete(ctx.ProviderCache, key) - return p.Close() - } + delete(ctx.ProviderCache, key) + return provider.Close() } return nil @@ -176,13 +175,13 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.ProviderConfig, cfg return diags } - // FIXME: The provider API isn't yet updated to take a cty.Value directly. - rc := NewResourceConfigShimmed(cfg, providerSchema.Provider) - err := p.Configure(rc) - if err != nil { - diags = diags.Append(err) + req := providers.ConfigureRequest{ + TerraformVersion: version.String(), + Config: cfg, } - return diags + + resp := p.Configure(req) + return resp.Diagnostics } func (ctx *BuiltinEvalContext) ProviderInput(pc addrs.ProviderConfig) map[string]cty.Value { diff --git a/terraform/eval_context_mock.go b/terraform/eval_context_mock.go index 31c93a455..ff23d5b43 100644 --- a/terraform/eval_context_mock.go +++ b/terraform/eval_context_mock.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -31,12 +32,12 @@ type MockEvalContext struct { InitProviderCalled bool InitProviderType string InitProviderAddr addrs.ProviderConfig - InitProviderProvider ResourceProvider + InitProviderProvider providers.Interface InitProviderError error ProviderCalled bool ProviderAddr addrs.AbsProviderConfig - ProviderProvider ResourceProvider + ProviderProvider providers.Interface ProviderSchemaCalled bool ProviderSchemaAddr addrs.AbsProviderConfig @@ -44,7 +45,7 @@ type MockEvalContext struct { CloseProviderCalled bool CloseProviderAddr addrs.ProviderConfig - CloseProviderProvider ResourceProvider + CloseProviderProvider providers.Interface ProviderInputCalled bool ProviderInputAddr addrs.ProviderConfig @@ -158,14 +159,14 @@ func (c *MockEvalContext) Input() UIInput { return c.InputInput } -func (c *MockEvalContext) InitProvider(t string, addr addrs.ProviderConfig) (ResourceProvider, error) { +func (c *MockEvalContext) InitProvider(t string, addr addrs.ProviderConfig) (providers.Interface, error) { c.InitProviderCalled = true c.InitProviderType = t c.InitProviderAddr = addr return c.InitProviderProvider, c.InitProviderError } -func (c *MockEvalContext) Provider(addr addrs.AbsProviderConfig) ResourceProvider { +func (c *MockEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface { c.ProviderCalled = true c.ProviderAddr = addr return c.ProviderProvider diff --git a/terraform/eval_diff.go b/terraform/eval_diff.go index 74f2c2cff..7f78f1573 100644 --- a/terraform/eval_diff.go +++ b/terraform/eval_diff.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -81,7 +82,7 @@ func (n *EvalCompareDiff) Eval(ctx EvalContext) (interface{}, error) { type EvalDiff struct { Addr addrs.ResourceInstance Config *configs.Resource - Provider *ResourceProvider + Provider *providers.Interface ProviderSchema **ProviderSchema State **states.ResourceInstanceObject PreviousDiff **plans.ResourceInstanceChange diff --git a/terraform/eval_import_state.go b/terraform/eval_import_state.go index 0e5ee8c5e..e9c85cf9f 100644 --- a/terraform/eval_import_state.go +++ b/terraform/eval_import_state.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -13,7 +14,7 @@ import ( // states but won't modify any actual state. type EvalImportState struct { Addr addrs.ResourceInstance - Provider *ResourceProvider + Provider *providers.Interface Id string Output *[]*states.ImportedObject } diff --git a/terraform/eval_provider.go b/terraform/eval_provider.go index d985c1bdd..7df6584a1 100644 --- a/terraform/eval_provider.go +++ b/terraform/eval_provider.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/tfdiags" ) @@ -49,7 +50,7 @@ func buildProviderConfig(ctx EvalContext, addr addrs.ProviderConfig, config *con // a provider that is already initialized and retrieved. type EvalConfigProvider struct { Addr addrs.ProviderConfig - Provider *ResourceProvider + Provider *providers.Interface Config *configs.Provider } @@ -64,16 +65,13 @@ func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) { configBody := buildProviderConfig(ctx, n.Addr, config) - schema, err := provider.GetSchema(&ProviderSchemaRequest{}) - if err != nil { - diags = diags.Append(err) + resp := provider.GetSchema() + diags = diags.Append(resp.Diagnostics) + if diags.HasErrors() { return nil, diags.NonFatalErr() } - if schema == nil { - return nil, fmt.Errorf("schema not available for %s", n.Addr) - } - configSchema := schema.Provider + configSchema := resp.Provider.Block configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, EvalDataForNoInstanceKey) diags = diags.Append(evalDiags) if evalDiags.HasErrors() { @@ -119,7 +117,7 @@ func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) { // interface GraphNodeProviderConsumer. type EvalGetProvider struct { Addr addrs.AbsProviderConfig - Output *ResourceProvider + Output *providers.Interface // If non-nil, Schema will be updated after eval to refer to the // schema of the provider. diff --git a/terraform/eval_read_data.go b/terraform/eval_read_data.go index c8bf3476b..be2aad5bc 100644 --- a/terraform/eval_read_data.go +++ b/terraform/eval_read_data.go @@ -3,6 +3,7 @@ package terraform import ( "fmt" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/zclconf/go-cty/cty" @@ -17,7 +18,7 @@ import ( type EvalReadDataDiff struct { Addr addrs.ResourceInstance Config *configs.Resource - Provider *ResourceProvider + Provider *providers.Interface ProviderSchema **ProviderSchema Output **plans.ResourceInstanceChange @@ -134,7 +135,7 @@ func (n *EvalReadDataDiff) Eval(ctx EvalContext) (interface{}, error) { // resource's ReadDataApply method to read data from the data source. type EvalReadDataApply struct { Addr addrs.ResourceInstance - Provider *ResourceProvider + Provider *providers.Interface Output **states.ResourceInstanceObject Change **plans.ResourceInstanceChange } diff --git a/terraform/eval_refresh.go b/terraform/eval_refresh.go index 842ebc577..eb5a9f974 100644 --- a/terraform/eval_refresh.go +++ b/terraform/eval_refresh.go @@ -5,6 +5,7 @@ import ( "log" "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -12,7 +13,7 @@ import ( // a resource. type EvalRefresh struct { Addr addrs.ResourceInstance - Provider *ResourceProvider + Provider *providers.Interface State **states.ResourceInstanceObject Output **states.ResourceInstanceObject } diff --git a/terraform/eval_state.go b/terraform/eval_state.go index 791ca2517..248ae691c 100644 --- a/terraform/eval_state.go +++ b/terraform/eval_state.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -19,7 +20,7 @@ type EvalReadState struct { // Provider is the provider that will subsequently perform actions on // the the state object. This is used to perform any schema upgrades // that might be required to prepare the stored data for use. - Provider *ResourceProvider + Provider *providers.Interface // Output will be written with a pointer to the retrieved object. Output **states.ResourceInstanceObject @@ -75,7 +76,7 @@ type EvalReadStateDeposed struct { // Provider is the provider that will subsequently perform actions on // the the state object. This is used to perform any schema upgrades // that might be required to prepare the stored data for use. - Provider *ResourceProvider + Provider *providers.Interface // Output will be written with a pointer to the retrieved object. Output **states.ResourceInstanceObject diff --git a/terraform/eval_validate.go b/terraform/eval_validate.go index 548d82f50..8d24267a6 100644 --- a/terraform/eval_validate.go +++ b/terraform/eval_validate.go @@ -6,8 +6,9 @@ import ( "github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/configs/configschema" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/tfdiags" "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/convert" @@ -66,7 +67,7 @@ RETURN: // a provider configuration. type EvalValidateProvider struct { Addr addrs.ProviderConfig - Provider *ResourceProvider + Provider *providers.Interface Config *configs.Provider } @@ -76,16 +77,13 @@ func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) { configBody := buildProviderConfig(ctx, n.Addr, n.Config) - schema, err := provider.GetSchema(&ProviderSchemaRequest{}) - if err != nil { - diags = diags.Append(err) + resp := provider.GetSchema() + diags = diags.Append(resp.Diagnostics) + if diags.HasErrors() { return nil, diags.NonFatalErr() } - if schema == nil { - return nil, fmt.Errorf("no schema is available for %s", n.Addr) - } - configSchema := schema.Provider + configSchema := resp.Provider.Block if configSchema == nil { // Should never happen in real code, but often comes up in tests where // mock schemas are being used that tend to be incomplete. @@ -99,23 +97,12 @@ func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) { return nil, diags.NonFatalErr() } - // The provider API expects our legacy ResourceConfig type, so we'll need - // to shim here. - rc := NewResourceConfigShimmed(configVal, configSchema) - - warns, errs := provider.Validate(rc) - if len(warns) == 0 && len(errs) == 0 { - return nil, nil + req := providers.ValidateProviderConfigRequest{ + Config: configVal, } - // FIXME: Once provider.Validate itself returns diagnostics, just - // return diags.NonFatalErr() immediately here. - for _, warn := range warns { - diags = diags.Append(tfdiags.SimpleWarning(warn)) - } - for _, err := range errs { - diags = diags.Append(err) - } + validateResp := provider.ValidateProviderConfig(req) + diags = diags.Append(validateResp.Diagnostics) return nil, diags.NonFatalErr() } @@ -338,7 +325,7 @@ var connectionBlockSupersetSchema = &configschema.Block{ // the configuration of a resource. type EvalValidateResource struct { Addr addrs.Resource - Provider *ResourceProvider + Provider *providers.Interface ProviderSchema **ProviderSchema Config *configs.Resource @@ -393,9 +380,6 @@ func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) { } } - var warns []string - var errs []error - // Provider entry point varies depending on resource mode, because // managed resources and data resources are two distinct concepts // in the provider abstraction. @@ -418,10 +402,13 @@ func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) { return nil, diags.Err() } - // The provider API still expects our legacy types, so we must do some - // shimming here. - legacyCfg := NewResourceConfigShimmed(configVal, schema) - warns, errs = provider.ValidateResource(cfg.Type, legacyCfg) + req := providers.ValidateResourceTypeConfigRequest{ + TypeName: cfg.Type, + Config: configVal, + } + + resp := provider.ValidateResourceTypeConfig(req) + diags = diags.Append(resp.Diagnostics) if n.ConfigVal != nil { *n.ConfigVal = configVal @@ -445,24 +432,13 @@ func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) { return nil, diags.Err() } - // The provider API still expects our legacy types, so we must do some - // shimming here. - legacyCfg := NewResourceConfigShimmed(configVal, schema) - warns, errs = provider.ValidateDataSource(cfg.Type, legacyCfg) - - if n.ConfigVal != nil { - *n.ConfigVal = configVal + req := providers.ValidateDataSourceConfigRequest{ + TypeName: cfg.Type, + Config: configVal, } - } - // FIXME: Update the provider API to actually return diagnostics here, - // and then we can remove all this shimming and use its diagnostics - // directly. - for _, warn := range warns { - diags = diags.Append(tfdiags.SimpleWarning(warn)) - } - for _, err := range errs { - diags = diags.Append(err) + resp := provider.ValidateDataSourceConfig(req) + diags = diags.Append(resp.Diagnostics) } if n.IgnoreWarnings { diff --git a/terraform/evaltree_provider.go b/terraform/evaltree_provider.go index f8ad7a944..6b4df67aa 100644 --- a/terraform/evaltree_provider.go +++ b/terraform/evaltree_provider.go @@ -3,12 +3,13 @@ package terraform import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" + "github.com/hashicorp/terraform/providers" ) // ProviderEvalTree returns the evaluation tree for initializing and // configuring providers. func ProviderEvalTree(n *NodeApplyableProvider, config *configs.Provider) EvalNode { - var provider ResourceProvider + var provider providers.Interface addr := n.Addr relAddr := addr.ProviderConfig diff --git a/terraform/graph_walk_context.go b/terraform/graph_walk_context.go index feb8d7305..4b5cd69e7 100644 --- a/terraform/graph_walk_context.go +++ b/terraform/graph_walk_context.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -38,7 +39,7 @@ type ContextGraphWalker struct { contextLock sync.Mutex variableValues map[string]map[string]cty.Value variableValuesLock sync.Mutex - providerCache map[string]ResourceProvider + providerCache map[string]providers.Interface providerSchemas map[string]*ProviderSchema providerLock sync.Mutex provisionerCache map[string]ResourceProvisioner @@ -139,7 +140,7 @@ func (w *ContextGraphWalker) ExitEvalTree(v dag.Vertex, output interface{}, err func (w *ContextGraphWalker) init() { w.contexts = make(map[string]*BuiltinEvalContext) - w.providerCache = make(map[string]ResourceProvider) + w.providerCache = make(map[string]providers.Interface) w.providerSchemas = make(map[string]*ProviderSchema) w.provisionerCache = make(map[string]ResourceProvisioner) w.provisionerSchemas = make(map[string]*configschema.Block) diff --git a/terraform/node_data_refresh.go b/terraform/node_data_refresh.go index 278a0ac39..821a1b8fb 100644 --- a/terraform/node_data_refresh.go +++ b/terraform/node_data_refresh.go @@ -3,6 +3,7 @@ package terraform import ( "github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" "github.com/zclconf/go-cty/cty" @@ -118,7 +119,7 @@ func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode { // These variables are the state for the eval sequence below, and are // updated through pointers. - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject diff --git a/terraform/node_resource_apply.go b/terraform/node_resource_apply.go index 3375c96b0..ecf8a3450 100644 --- a/terraform/node_resource_apply.go +++ b/terraform/node_resource_apply.go @@ -3,6 +3,7 @@ package terraform import ( "fmt" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/plans" @@ -120,7 +121,7 @@ func (n *NodeApplyableResourceInstance) EvalTree() EvalNode { } func (n *NodeApplyableResourceInstance) evalTreeDataResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode { - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject @@ -192,7 +193,7 @@ func (n *NodeApplyableResourceInstance) evalTreeDataResource(addr addrs.AbsResou func (n *NodeApplyableResourceInstance) evalTreeManagedResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode { // Declare a bunch of variables that are used for state during // evaluation. Most of this are written to by-address below. - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var diff, diffApply *plans.ResourceInstanceChange var state *states.ResourceInstanceObject diff --git a/terraform/node_resource_destroy.go b/terraform/node_resource_destroy.go index cee16c567..cb820a0af 100644 --- a/terraform/node_resource_destroy.go +++ b/terraform/node_resource_destroy.go @@ -5,6 +5,7 @@ import ( "log" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" @@ -167,7 +168,7 @@ func (n *NodeDestroyResourceInstance) EvalTree() EvalNode { } var changeApply *plans.ResourceInstanceChange - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var state *states.ResourceInstanceObject var err error diff --git a/terraform/node_resource_plan_destroy.go b/terraform/node_resource_plan_destroy.go index fa87861e3..22191d1e7 100644 --- a/terraform/node_resource_plan_destroy.go +++ b/terraform/node_resource_plan_destroy.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -41,7 +42,7 @@ func (n *NodePlanDestroyableResourceInstance) EvalTree() EvalNode { // Declare a bunch of variables that are used for state during // evaluation. These are written to by address in the EvalNodes we // declare below. - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject diff --git a/terraform/node_resource_plan_instance.go b/terraform/node_resource_plan_instance.go index e7c95c72c..d4c0d4859 100644 --- a/terraform/node_resource_plan_instance.go +++ b/terraform/node_resource_plan_instance.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/addrs" @@ -52,7 +53,7 @@ func (n *NodePlannableResourceInstance) EvalTree() EvalNode { func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode { config := n.Config - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject @@ -107,7 +108,7 @@ func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResou func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode { config := n.Config - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject diff --git a/terraform/node_resource_plan_orphan.go b/terraform/node_resource_plan_orphan.go index 4380a42a2..8f5328375 100644 --- a/terraform/node_resource_plan_orphan.go +++ b/terraform/node_resource_plan_orphan.go @@ -2,6 +2,7 @@ package terraform import ( "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -38,7 +39,7 @@ func (n *NodePlannableResourceInstanceOrphan) EvalTree() EvalNode { // evaluation. Most of this are written to by-address below. var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema return &EvalSequence{ diff --git a/terraform/node_resource_refresh.go b/terraform/node_resource_refresh.go index 36b0d966f..857d392db 100644 --- a/terraform/node_resource_refresh.go +++ b/terraform/node_resource_refresh.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" @@ -161,7 +162,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN // Declare a bunch of variables that are used for state during // evaluation. Most of this are written to by-address below. - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var state *states.ResourceInstanceObject @@ -225,7 +226,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState( // Declare a bunch of variables that are used for state during // evaluation. Most of this are written to by-address below. - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange var state *states.ResourceInstanceObject diff --git a/terraform/node_resource_validate.go b/terraform/node_resource_validate.go index ef07c9bd9..ab6e59034 100644 --- a/terraform/node_resource_validate.go +++ b/terraform/node_resource_validate.go @@ -2,6 +2,7 @@ package terraform import ( "github.com/hashicorp/terraform/configs/configschema" + "github.com/hashicorp/terraform/providers" "github.com/zclconf/go-cty/cty" ) @@ -28,7 +29,7 @@ func (n *NodeValidatableResource) EvalTree() EvalNode { // Declare the variables will be used are used to pass values along // the evaluation sequence below. These are written to via pointers // passed to the EvalNodes. - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var configVal cty.Value diff --git a/terraform/resource_provider.go b/terraform/resource_provider.go index 7c978d220..e666fb6d2 100644 --- a/terraform/resource_provider.go +++ b/terraform/resource_provider.go @@ -5,6 +5,7 @@ import ( multierror "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform/plugin/discovery" + "github.com/hashicorp/terraform/providers" ) // ResourceProvider is an interface that must be implemented by any @@ -295,7 +296,7 @@ func ProviderHasDataSource(p ResourceProvider, n string) bool { // This should be called only with configurations that have passed calls // to config.Validate(), which ensures that all of the given version // constraints are valid. It will panic if any invalid constraints are present. -func resourceProviderFactories(resolver ResourceProviderResolver, reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, error) { +func resourceProviderFactories(resolver providers.Resolver, reqd discovery.PluginRequirements) (map[string]providers.Factory, error) { ret, errs := resolver.ResolveProviders(reqd) if errs != nil { return nil, &ResourceProviderError{ diff --git a/terraform/schemas.go b/terraform/schemas.go index b00f48062..d61d9e865 100644 --- a/terraform/schemas.go +++ b/terraform/schemas.go @@ -127,42 +127,35 @@ func loadProviderSchemas(schemas map[string]*ProviderSchema, config *configs.Con return } defer func() { - if closer, ok := provider.(ResourceProviderCloser); ok { - closer.Close() - } + provider.Close() }() - // FIXME: The provider interface is currently awkward in that it - // requires us to tell the provider which resources types and data - // sources we need. In future this will change to just return - // everything available, but for now we'll fake that by fetching all - // of the available names and then requesting them. - resourceTypes := provider.Resources() - dataSources := provider.DataSources() - resourceTypeNames := make([]string, len(resourceTypes)) - for i, o := range resourceTypes { - resourceTypeNames[i] = o.Name - } - dataSourceNames := make([]string, len(dataSources)) - for i, o := range dataSources { - dataSourceNames[i] = o.Name - } - - schema, err := provider.GetSchema(&ProviderSchemaRequest{ - ResourceTypes: resourceTypeNames, - DataSources: dataSourceNames, - }) - if err != nil { + resp := provider.GetSchema() + if resp.Diagnostics.HasErrors() { // We'll put a stub in the map so we won't re-attempt this on // future calls. schemas[typeName] = &ProviderSchema{} diags = diags.Append( - fmt.Errorf("Failed to retrieve schema from provider %q: %s", typeName, err), + fmt.Errorf("Failed to retrieve schema from provider %q: %s", typeName, resp.Diagnostics.Err()), ) return } - schemas[typeName] = schema + s := &ProviderSchema{ + Provider: resp.Provider.Block, + ResourceTypes: make(map[string]*configschema.Block), + DataSources: make(map[string]*configschema.Block), + } + + for t, r := range resp.ResourceTypes { + s.ResourceTypes[t] = r.Block + } + + for t, d := range resp.DataSources { + s.DataSources[t] = d.Block + } + + schemas[typeName] = s } if config != nil { diff --git a/terraform/transform_deposed.go b/terraform/transform_deposed.go index 729cf5403..5df9c0bda 100644 --- a/terraform/transform_deposed.go +++ b/terraform/transform_deposed.go @@ -5,6 +5,7 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -80,7 +81,7 @@ func (n *graphNodeDeposedResource) SetProvider(addr addrs.AbsProviderConfig) { func (n *graphNodeDeposedResource) EvalTree() EvalNode { addr := n.Addr - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema var state *states.ResourceInstanceObject diff --git a/terraform/transform_import_state.go b/terraform/transform_import_state.go index 1fdef1872..731174e0e 100644 --- a/terraform/transform_import_state.go +++ b/terraform/transform_import_state.go @@ -3,6 +3,7 @@ package terraform import ( "fmt" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/addrs" @@ -69,7 +70,7 @@ func (n *graphNodeImportState) Path() addrs.ModuleInstance { // GraphNodeEvalable impl. func (n *graphNodeImportState) EvalTree() EvalNode { - var provider ResourceProvider + var provider providers.Interface // Reset our states n.states = nil @@ -200,7 +201,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode { state := n.State.AsInstanceObject() - var provider ResourceProvider + var provider providers.Interface var providerSchema *ProviderSchema return &EvalSequence{ Nodes: []EvalNode{