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{