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.
This commit is contained in:
James Bardin 2018-08-16 11:40:08 -04:00 committed by Martin Atkins
parent c45ebbc493
commit 16df9c37cf
27 changed files with 130 additions and 140 deletions

View File

@ -15,6 +15,7 @@ import (
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/lang"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
) )
@ -63,7 +64,7 @@ type ContextOpts struct {
Hooks []Hook Hooks []Hook
Parallelism int Parallelism int
ProviderResolver ResourceProviderResolver ProviderResolver providers.Resolver
Provisioners map[string]ResourceProvisionerFactory Provisioners map[string]ResourceProvisionerFactory
// If non-nil, will apply as additional constraints on the provider // 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) variables = variables.Override(opts.Variables)
// Bind available provider plugins to the constraints in config // Bind available provider plugins to the constraints in config
var providers map[string]ResourceProviderFactory var providerFactories map[string]providers.Factory
if opts.ProviderResolver != nil { if opts.ProviderResolver != nil {
var err error var err error
deps := ConfigTreeDependencies(opts.Config, state) deps := ConfigTreeDependencies(opts.Config, state)
@ -173,17 +174,17 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) {
if opts.ProviderSHA256s != nil && !opts.SkipProviderVerify { if opts.ProviderSHA256s != nil && !opts.SkipProviderVerify {
reqd.LockExecutables(opts.ProviderSHA256s) reqd.LockExecutables(opts.ProviderSHA256s)
} }
providers, err = resourceProviderFactories(opts.ProviderResolver, reqd) providerFactories, err = resourceProviderFactories(opts.ProviderResolver, reqd)
if err != nil { if err != nil {
diags = diags.Append(err) diags = diags.Append(err)
return nil, diags return nil, diags
} }
} else { } else {
providers = make(map[string]ResourceProviderFactory) providerFactories = make(map[string]providers.Factory)
} }
components := &basicComponentFactory{ components := &basicComponentFactory{
providers: providers, providers: providerFactories,
provisioners: opts.Provisioners, 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 // Copy the providers so that a misbehaved blocking Stop doesn't
// completely hang Terraform. // completely hang Terraform.
walker.providerLock.Lock() walker.providerLock.Lock()
ps := make([]ResourceProvider, 0, len(walker.providerCache)) ps := make([]providers.Interface, 0, len(walker.providerCache))
for _, p := range walker.providerCache { for _, p := range walker.providerCache {
ps = append(ps, p) ps = append(ps, p)
} }

View File

@ -2,6 +2,8 @@ package terraform
import ( import (
"fmt" "fmt"
"github.com/hashicorp/terraform/providers"
) )
// contextComponentFactory is the interface that Context uses // contextComponentFactory is the interface that Context uses
@ -12,7 +14,7 @@ type contextComponentFactory interface {
// ResourceProvider creates a new ResourceProvider with the given // ResourceProvider creates a new ResourceProvider with the given
// type. The "uid" is a unique identifier for this provider being // type. The "uid" is a unique identifier for this provider being
// initialized that can be used for internal tracking. // initialized that can be used for internal tracking.
ResourceProvider(typ, uid string) (ResourceProvider, error) ResourceProvider(typ, uid string) (providers.Interface, error)
ResourceProviders() []string ResourceProviders() []string
// ResourceProvisioner creates a new ResourceProvisioner with the // ResourceProvisioner creates a new ResourceProvisioner with the
@ -24,7 +26,7 @@ type contextComponentFactory interface {
// basicComponentFactory just calls a factory from a map directly. // basicComponentFactory just calls a factory from a map directly.
type basicComponentFactory struct { type basicComponentFactory struct {
providers map[string]ResourceProviderFactory providers map[string]providers.Factory
provisioners map[string]ResourceProvisionerFactory provisioners map[string]ResourceProvisionerFactory
} }
@ -46,7 +48,7 @@ func (c *basicComponentFactory) ResourceProvisioners() []string {
return result 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] f, ok := c.providers[typ]
if !ok { if !ok {
return nil, fmt.Errorf("unknown provider %q", typ) return nil, fmt.Errorf("unknown provider %q", typ)

View File

@ -9,6 +9,7 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
) )
@ -18,7 +19,7 @@ type EvalApply struct {
Addr addrs.ResourceInstance Addr addrs.ResourceInstance
State **states.ResourceInstanceObject State **states.ResourceInstanceObject
Change **plans.ResourceInstanceChange Change **plans.ResourceInstanceChange
Provider *ResourceProvider Provider *providers.Interface
Output **states.ResourceInstanceObject Output **states.ResourceInstanceObject
CreateNew *bool CreateNew *bool
Error *error Error *error

View File

@ -6,6 +6,7 @@ import (
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/lang"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
@ -31,7 +32,7 @@ type EvalContext interface {
// returns the implementation of the resource provider or an error. // returns the implementation of the resource provider or an error.
// //
// It is an error to initialize the same provider more than once. // 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 // Provider gets the provider instance with the given address (already
// initialized) or returns nil if the provider isn't initialized. // 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. // resources in one module are able to use providers from other modules.
// InitProvider must've been called on the EvalContext of the module // InitProvider must've been called on the EvalContext of the module
// that owns the given provider before calling this method. // 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 // ProviderSchema retrieves the schema for a particular provider, which
// must have already been initialized with InitProvider. // must have already been initialized with InitProvider.

View File

@ -7,6 +7,8 @@ import (
"sync" "sync"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/version"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
@ -53,7 +55,7 @@ type BuiltinEvalContext struct {
Components contextComponentFactory Components contextComponentFactory
Hooks []Hook Hooks []Hook
InputValue UIInput InputValue UIInput
ProviderCache map[string]ResourceProvider ProviderCache map[string]providers.Interface
ProviderInputConfig map[string]map[string]cty.Value ProviderInputConfig map[string]map[string]cty.Value
ProviderLock *sync.Mutex ProviderLock *sync.Mutex
ProvisionerCache map[string]ResourceProvisioner ProvisionerCache map[string]ResourceProvisioner
@ -100,7 +102,7 @@ func (ctx *BuiltinEvalContext) Input() UIInput {
return ctx.InputValue 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) ctx.once.Do(ctx.init)
absAddr := addr.Absolute(ctx.Path()) absAddr := addr.Absolute(ctx.Path())
@ -127,7 +129,7 @@ func (ctx *BuiltinEvalContext) InitProvider(typeName string, addr addrs.Provider
return p, nil 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.once.Do(ctx.init)
ctx.ProviderLock.Lock() ctx.ProviderLock.Lock()
@ -149,13 +151,10 @@ func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.ProviderConfig) error {
defer ctx.ProviderLock.Unlock() defer ctx.ProviderLock.Unlock()
key := addr.Absolute(ctx.Path()).String() key := addr.Absolute(ctx.Path()).String()
var provider interface{} provider := ctx.ProviderCache[key]
provider = ctx.ProviderCache[key]
if provider != nil { if provider != nil {
if p, ok := provider.(ResourceProviderCloser); ok {
delete(ctx.ProviderCache, key) delete(ctx.ProviderCache, key)
return p.Close() return provider.Close()
}
} }
return nil return nil
@ -176,13 +175,13 @@ func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.ProviderConfig, cfg
return diags return diags
} }
// FIXME: The provider API isn't yet updated to take a cty.Value directly. req := providers.ConfigureRequest{
rc := NewResourceConfigShimmed(cfg, providerSchema.Provider) TerraformVersion: version.String(),
err := p.Configure(rc) Config: cfg,
if err != nil {
diags = diags.Append(err)
} }
return diags
resp := p.Configure(req)
return resp.Diagnostics
} }
func (ctx *BuiltinEvalContext) ProviderInput(pc addrs.ProviderConfig) map[string]cty.Value { func (ctx *BuiltinEvalContext) ProviderInput(pc addrs.ProviderConfig) map[string]cty.Value {

View File

@ -11,6 +11,7 @@ import (
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/lang"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
) )
@ -31,12 +32,12 @@ type MockEvalContext struct {
InitProviderCalled bool InitProviderCalled bool
InitProviderType string InitProviderType string
InitProviderAddr addrs.ProviderConfig InitProviderAddr addrs.ProviderConfig
InitProviderProvider ResourceProvider InitProviderProvider providers.Interface
InitProviderError error InitProviderError error
ProviderCalled bool ProviderCalled bool
ProviderAddr addrs.AbsProviderConfig ProviderAddr addrs.AbsProviderConfig
ProviderProvider ResourceProvider ProviderProvider providers.Interface
ProviderSchemaCalled bool ProviderSchemaCalled bool
ProviderSchemaAddr addrs.AbsProviderConfig ProviderSchemaAddr addrs.AbsProviderConfig
@ -44,7 +45,7 @@ type MockEvalContext struct {
CloseProviderCalled bool CloseProviderCalled bool
CloseProviderAddr addrs.ProviderConfig CloseProviderAddr addrs.ProviderConfig
CloseProviderProvider ResourceProvider CloseProviderProvider providers.Interface
ProviderInputCalled bool ProviderInputCalled bool
ProviderInputAddr addrs.ProviderConfig ProviderInputAddr addrs.ProviderConfig
@ -158,14 +159,14 @@ func (c *MockEvalContext) Input() UIInput {
return c.InputInput 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.InitProviderCalled = true
c.InitProviderType = t c.InitProviderType = t
c.InitProviderAddr = addr c.InitProviderAddr = addr
return c.InitProviderProvider, c.InitProviderError 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.ProviderCalled = true
c.ProviderAddr = addr c.ProviderAddr = addr
return c.ProviderProvider return c.ProviderProvider

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
) )
@ -81,7 +82,7 @@ func (n *EvalCompareDiff) Eval(ctx EvalContext) (interface{}, error) {
type EvalDiff struct { type EvalDiff struct {
Addr addrs.ResourceInstance Addr addrs.ResourceInstance
Config *configs.Resource Config *configs.Resource
Provider *ResourceProvider Provider *providers.Interface
ProviderSchema **ProviderSchema ProviderSchema **ProviderSchema
State **states.ResourceInstanceObject State **states.ResourceInstanceObject
PreviousDiff **plans.ResourceInstanceChange PreviousDiff **plans.ResourceInstanceChange

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
) )
@ -13,7 +14,7 @@ import (
// states but won't modify any actual state. // states but won't modify any actual state.
type EvalImportState struct { type EvalImportState struct {
Addr addrs.ResourceInstance Addr addrs.ResourceInstance
Provider *ResourceProvider Provider *providers.Interface
Id string Id string
Output *[]*states.ImportedObject Output *[]*states.ImportedObject
} }

View File

@ -8,6 +8,7 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/tfdiags" "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. // a provider that is already initialized and retrieved.
type EvalConfigProvider struct { type EvalConfigProvider struct {
Addr addrs.ProviderConfig Addr addrs.ProviderConfig
Provider *ResourceProvider Provider *providers.Interface
Config *configs.Provider Config *configs.Provider
} }
@ -64,16 +65,13 @@ func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) {
configBody := buildProviderConfig(ctx, n.Addr, config) configBody := buildProviderConfig(ctx, n.Addr, config)
schema, err := provider.GetSchema(&ProviderSchemaRequest{}) resp := provider.GetSchema()
if err != nil { diags = diags.Append(resp.Diagnostics)
diags = diags.Append(err) if diags.HasErrors() {
return nil, diags.NonFatalErr() 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) configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, EvalDataForNoInstanceKey)
diags = diags.Append(evalDiags) diags = diags.Append(evalDiags)
if evalDiags.HasErrors() { if evalDiags.HasErrors() {
@ -119,7 +117,7 @@ func (n *EvalCloseProvider) Eval(ctx EvalContext) (interface{}, error) {
// interface GraphNodeProviderConsumer. // interface GraphNodeProviderConsumer.
type EvalGetProvider struct { type EvalGetProvider struct {
Addr addrs.AbsProviderConfig Addr addrs.AbsProviderConfig
Output *ResourceProvider Output *providers.Interface
// If non-nil, Schema will be updated after eval to refer to the // If non-nil, Schema will be updated after eval to refer to the
// schema of the provider. // schema of the provider.

View File

@ -3,6 +3,7 @@ package terraform
import ( import (
"fmt" "fmt"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
@ -17,7 +18,7 @@ import (
type EvalReadDataDiff struct { type EvalReadDataDiff struct {
Addr addrs.ResourceInstance Addr addrs.ResourceInstance
Config *configs.Resource Config *configs.Resource
Provider *ResourceProvider Provider *providers.Interface
ProviderSchema **ProviderSchema ProviderSchema **ProviderSchema
Output **plans.ResourceInstanceChange 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. // resource's ReadDataApply method to read data from the data source.
type EvalReadDataApply struct { type EvalReadDataApply struct {
Addr addrs.ResourceInstance Addr addrs.ResourceInstance
Provider *ResourceProvider Provider *providers.Interface
Output **states.ResourceInstanceObject Output **states.ResourceInstanceObject
Change **plans.ResourceInstanceChange Change **plans.ResourceInstanceChange
} }

View File

@ -5,6 +5,7 @@ import (
"log" "log"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
) )
@ -12,7 +13,7 @@ import (
// a resource. // a resource.
type EvalRefresh struct { type EvalRefresh struct {
Addr addrs.ResourceInstance Addr addrs.ResourceInstance
Provider *ResourceProvider Provider *providers.Interface
State **states.ResourceInstanceObject State **states.ResourceInstanceObject
Output **states.ResourceInstanceObject Output **states.ResourceInstanceObject
} }

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
) )
@ -19,7 +20,7 @@ type EvalReadState struct {
// Provider is the provider that will subsequently perform actions on // Provider is the provider that will subsequently perform actions on
// the the state object. This is used to perform any schema upgrades // the the state object. This is used to perform any schema upgrades
// that might be required to prepare the stored data for use. // 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 will be written with a pointer to the retrieved object.
Output **states.ResourceInstanceObject Output **states.ResourceInstanceObject
@ -75,7 +76,7 @@ type EvalReadStateDeposed struct {
// Provider is the provider that will subsequently perform actions on // Provider is the provider that will subsequently perform actions on
// the the state object. This is used to perform any schema upgrades // the the state object. This is used to perform any schema upgrades
// that might be required to prepare the stored data for use. // 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 will be written with a pointer to the retrieved object.
Output **states.ResourceInstanceObject Output **states.ResourceInstanceObject

View File

@ -6,8 +6,9 @@ import (
"github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert" "github.com/zclconf/go-cty/cty/convert"
@ -66,7 +67,7 @@ RETURN:
// a provider configuration. // a provider configuration.
type EvalValidateProvider struct { type EvalValidateProvider struct {
Addr addrs.ProviderConfig Addr addrs.ProviderConfig
Provider *ResourceProvider Provider *providers.Interface
Config *configs.Provider Config *configs.Provider
} }
@ -76,16 +77,13 @@ func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) {
configBody := buildProviderConfig(ctx, n.Addr, n.Config) configBody := buildProviderConfig(ctx, n.Addr, n.Config)
schema, err := provider.GetSchema(&ProviderSchemaRequest{}) resp := provider.GetSchema()
if err != nil { diags = diags.Append(resp.Diagnostics)
diags = diags.Append(err) if diags.HasErrors() {
return nil, diags.NonFatalErr() 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 { if configSchema == nil {
// Should never happen in real code, but often comes up in tests where // Should never happen in real code, but often comes up in tests where
// mock schemas are being used that tend to be incomplete. // 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() return nil, diags.NonFatalErr()
} }
// The provider API expects our legacy ResourceConfig type, so we'll need req := providers.ValidateProviderConfigRequest{
// to shim here. Config: configVal,
rc := NewResourceConfigShimmed(configVal, configSchema)
warns, errs := provider.Validate(rc)
if len(warns) == 0 && len(errs) == 0 {
return nil, nil
} }
// FIXME: Once provider.Validate itself returns diagnostics, just validateResp := provider.ValidateProviderConfig(req)
// return diags.NonFatalErr() immediately here. diags = diags.Append(validateResp.Diagnostics)
for _, warn := range warns {
diags = diags.Append(tfdiags.SimpleWarning(warn))
}
for _, err := range errs {
diags = diags.Append(err)
}
return nil, diags.NonFatalErr() return nil, diags.NonFatalErr()
} }
@ -338,7 +325,7 @@ var connectionBlockSupersetSchema = &configschema.Block{
// the configuration of a resource. // the configuration of a resource.
type EvalValidateResource struct { type EvalValidateResource struct {
Addr addrs.Resource Addr addrs.Resource
Provider *ResourceProvider Provider *providers.Interface
ProviderSchema **ProviderSchema ProviderSchema **ProviderSchema
Config *configs.Resource 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 // Provider entry point varies depending on resource mode, because
// managed resources and data resources are two distinct concepts // managed resources and data resources are two distinct concepts
// in the provider abstraction. // in the provider abstraction.
@ -418,10 +402,13 @@ func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) {
return nil, diags.Err() return nil, diags.Err()
} }
// The provider API still expects our legacy types, so we must do some req := providers.ValidateResourceTypeConfigRequest{
// shimming here. TypeName: cfg.Type,
legacyCfg := NewResourceConfigShimmed(configVal, schema) Config: configVal,
warns, errs = provider.ValidateResource(cfg.Type, legacyCfg) }
resp := provider.ValidateResourceTypeConfig(req)
diags = diags.Append(resp.Diagnostics)
if n.ConfigVal != nil { if n.ConfigVal != nil {
*n.ConfigVal = configVal *n.ConfigVal = configVal
@ -445,24 +432,13 @@ func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) {
return nil, diags.Err() return nil, diags.Err()
} }
// The provider API still expects our legacy types, so we must do some req := providers.ValidateDataSourceConfigRequest{
// shimming here. TypeName: cfg.Type,
legacyCfg := NewResourceConfigShimmed(configVal, schema) Config: configVal,
warns, errs = provider.ValidateDataSource(cfg.Type, legacyCfg)
if n.ConfigVal != nil {
*n.ConfigVal = configVal
}
} }
// FIXME: Update the provider API to actually return diagnostics here, resp := provider.ValidateDataSourceConfig(req)
// and then we can remove all this shimming and use its diagnostics diags = diags.Append(resp.Diagnostics)
// directly.
for _, warn := range warns {
diags = diags.Append(tfdiags.SimpleWarning(warn))
}
for _, err := range errs {
diags = diags.Append(err)
} }
if n.IgnoreWarnings { if n.IgnoreWarnings {

View File

@ -3,12 +3,13 @@ package terraform
import ( import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/providers"
) )
// ProviderEvalTree returns the evaluation tree for initializing and // ProviderEvalTree returns the evaluation tree for initializing and
// configuring providers. // configuring providers.
func ProviderEvalTree(n *NodeApplyableProvider, config *configs.Provider) EvalNode { func ProviderEvalTree(n *NodeApplyableProvider, config *configs.Provider) EvalNode {
var provider ResourceProvider var provider providers.Interface
addr := n.Addr addr := n.Addr
relAddr := addr.ProviderConfig relAddr := addr.ProviderConfig

View File

@ -11,6 +11,7 @@ import (
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
) )
@ -38,7 +39,7 @@ type ContextGraphWalker struct {
contextLock sync.Mutex contextLock sync.Mutex
variableValues map[string]map[string]cty.Value variableValues map[string]map[string]cty.Value
variableValuesLock sync.Mutex variableValuesLock sync.Mutex
providerCache map[string]ResourceProvider providerCache map[string]providers.Interface
providerSchemas map[string]*ProviderSchema providerSchemas map[string]*ProviderSchema
providerLock sync.Mutex providerLock sync.Mutex
provisionerCache map[string]ResourceProvisioner provisionerCache map[string]ResourceProvisioner
@ -139,7 +140,7 @@ func (w *ContextGraphWalker) ExitEvalTree(v dag.Vertex, output interface{}, err
func (w *ContextGraphWalker) init() { func (w *ContextGraphWalker) init() {
w.contexts = make(map[string]*BuiltinEvalContext) 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.providerSchemas = make(map[string]*ProviderSchema)
w.provisionerCache = make(map[string]ResourceProvisioner) w.provisionerCache = make(map[string]ResourceProvisioner)
w.provisionerSchemas = make(map[string]*configschema.Block) w.provisionerSchemas = make(map[string]*configschema.Block)

View File

@ -3,6 +3,7 @@ package terraform
import ( import (
"github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/tfdiags"
"github.com/zclconf/go-cty/cty" "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 // These variables are the state for the eval sequence below, and are
// updated through pointers. // updated through pointers.
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var change *plans.ResourceInstanceChange var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject

View File

@ -3,6 +3,7 @@ package terraform
import ( import (
"fmt" "fmt"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/plans" "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 { func (n *NodeApplyableResourceInstance) evalTreeDataResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode {
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var change *plans.ResourceInstanceChange var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject 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 { func (n *NodeApplyableResourceInstance) evalTreeManagedResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode {
// Declare a bunch of variables that are used for state during // Declare a bunch of variables that are used for state during
// evaluation. Most of this are written to by-address below. // evaluation. Most of this are written to by-address below.
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var diff, diffApply *plans.ResourceInstanceChange var diff, diffApply *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject

View File

@ -5,6 +5,7 @@ import (
"log" "log"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
@ -167,7 +168,7 @@ func (n *NodeDestroyResourceInstance) EvalTree() EvalNode {
} }
var changeApply *plans.ResourceInstanceChange var changeApply *plans.ResourceInstanceChange
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject
var err error var err error

View File

@ -6,6 +6,7 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "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 // Declare a bunch of variables that are used for state during
// evaluation. These are written to by address in the EvalNodes we // evaluation. These are written to by address in the EvalNodes we
// declare below. // declare below.
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var change *plans.ResourceInstanceChange var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/addrs" "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 { func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode {
config := n.Config config := n.Config
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var change *plans.ResourceInstanceChange var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject 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 { func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsResourceInstance, stateId string, stateDeps []string) EvalNode {
config := n.Config config := n.Config
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var change *plans.ResourceInstanceChange var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject

View File

@ -2,6 +2,7 @@ package terraform
import ( import (
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
) )
@ -38,7 +39,7 @@ func (n *NodePlannableResourceInstanceOrphan) EvalTree() EvalNode {
// evaluation. Most of this are written to by-address below. // evaluation. Most of this are written to by-address below.
var change *plans.ResourceInstanceChange var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
return &EvalSequence{ return &EvalSequence{

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "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 // Declare a bunch of variables that are used for state during
// evaluation. Most of this are written to by-address below. // evaluation. Most of this are written to by-address below.
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject
@ -225,7 +226,7 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState(
// Declare a bunch of variables that are used for state during // Declare a bunch of variables that are used for state during
// evaluation. Most of this are written to by-address below. // evaluation. Most of this are written to by-address below.
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var change *plans.ResourceInstanceChange var change *plans.ResourceInstanceChange
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject

View File

@ -2,6 +2,7 @@ package terraform
import ( import (
"github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/providers"
"github.com/zclconf/go-cty/cty" "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 // Declare the variables will be used are used to pass values along
// the evaluation sequence below. These are written to via pointers // the evaluation sequence below. These are written to via pointers
// passed to the EvalNodes. // passed to the EvalNodes.
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var configVal cty.Value var configVal cty.Value

View File

@ -5,6 +5,7 @@ import (
multierror "github.com/hashicorp/go-multierror" multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform/plugin/discovery" "github.com/hashicorp/terraform/plugin/discovery"
"github.com/hashicorp/terraform/providers"
) )
// ResourceProvider is an interface that must be implemented by any // 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 // This should be called only with configurations that have passed calls
// to config.Validate(), which ensures that all of the given version // to config.Validate(), which ensures that all of the given version
// constraints are valid. It will panic if any invalid constraints are present. // 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) ret, errs := resolver.ResolveProviders(reqd)
if errs != nil { if errs != nil {
return nil, &ResourceProviderError{ return nil, &ResourceProviderError{

View File

@ -127,42 +127,35 @@ func loadProviderSchemas(schemas map[string]*ProviderSchema, config *configs.Con
return return
} }
defer func() { defer func() {
if closer, ok := provider.(ResourceProviderCloser); ok { provider.Close()
closer.Close()
}
}() }()
// FIXME: The provider interface is currently awkward in that it resp := provider.GetSchema()
// requires us to tell the provider which resources types and data if resp.Diagnostics.HasErrors() {
// 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 {
// We'll put a stub in the map so we won't re-attempt this on // We'll put a stub in the map so we won't re-attempt this on
// future calls. // future calls.
schemas[typeName] = &ProviderSchema{} schemas[typeName] = &ProviderSchema{}
diags = diags.Append( 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 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 { if config != nil {

View File

@ -5,6 +5,7 @@ import (
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
) )
@ -80,7 +81,7 @@ func (n *graphNodeDeposedResource) SetProvider(addr addrs.AbsProviderConfig) {
func (n *graphNodeDeposedResource) EvalTree() EvalNode { func (n *graphNodeDeposedResource) EvalTree() EvalNode {
addr := n.Addr addr := n.Addr
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
var state *states.ResourceInstanceObject var state *states.ResourceInstanceObject

View File

@ -3,6 +3,7 @@ package terraform
import ( import (
"fmt" "fmt"
"github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
@ -69,7 +70,7 @@ func (n *graphNodeImportState) Path() addrs.ModuleInstance {
// GraphNodeEvalable impl. // GraphNodeEvalable impl.
func (n *graphNodeImportState) EvalTree() EvalNode { func (n *graphNodeImportState) EvalTree() EvalNode {
var provider ResourceProvider var provider providers.Interface
// Reset our states // Reset our states
n.states = nil n.states = nil
@ -200,7 +201,7 @@ func (n *graphNodeImportStateSub) EvalTree() EvalNode {
state := n.State.AsInstanceObject() state := n.State.AsInstanceObject()
var provider ResourceProvider var provider providers.Interface
var providerSchema *ProviderSchema var providerSchema *ProviderSchema
return &EvalSequence{ return &EvalSequence{
Nodes: []EvalNode{ Nodes: []EvalNode{