diff --git a/terraform/context.go b/terraform/context.go index 374f4d92a2..be4625551c 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -65,7 +66,7 @@ type ContextOpts struct { Hooks []Hook Parallelism int ProviderResolver providers.Resolver - Provisioners map[string]ResourceProvisionerFactory + Provisioners map[string]ProvisionerFactory // If non-nil, will apply as additional constraints on the provider // plugins that will be requested from the provider resolver. @@ -775,7 +776,7 @@ func (c *Context) watchStop(walker *ContextGraphWalker) (chan struct{}, <-chan s { // Call stop on all the provisioners walker.provisionerLock.Lock() - ps := make([]ResourceProvisioner, 0, len(walker.provisionerCache)) + ps := make([]provisioners.Interface, 0, len(walker.provisionerCache)) for _, p := range walker.provisionerCache { ps = append(ps, p) } diff --git a/terraform/context_components.go b/terraform/context_components.go index c685d677b9..252da1b1c1 100644 --- a/terraform/context_components.go +++ b/terraform/context_components.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" ) // contextComponentFactory is the interface that Context uses @@ -20,14 +21,14 @@ type contextComponentFactory interface { // ResourceProvisioner creates a new ResourceProvisioner with the // given type. The "uid" is a unique identifier for this provisioner // being initialized that can be used for internal tracking. - ResourceProvisioner(typ, uid string) (ResourceProvisioner, error) + ResourceProvisioner(typ, uid string) (provisioners.Interface, error) ResourceProvisioners() []string } // basicComponentFactory just calls a factory from a map directly. type basicComponentFactory struct { providers map[string]providers.Factory - provisioners map[string]ResourceProvisionerFactory + provisioners map[string]ProvisionerFactory } func (c *basicComponentFactory) ResourceProviders() []string { @@ -57,7 +58,7 @@ func (c *basicComponentFactory) ResourceProvider(typ, uid string) (providers.Int return f() } -func (c *basicComponentFactory) ResourceProvisioner(typ, uid string) (ResourceProvisioner, error) { +func (c *basicComponentFactory) ResourceProvisioner(typ, uid string) (provisioners.Interface, error) { f, ok := c.provisioners[typ] if !ok { return nil, fmt.Errorf("unknown provisioner %q", typ) diff --git a/terraform/eval_context.go b/terraform/eval_context.go index 02137d839b..08f3059e26 100644 --- a/terraform/eval_context.go +++ b/terraform/eval_context.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" "github.com/zclconf/go-cty/cty" @@ -68,11 +69,11 @@ type EvalContext interface { // returns the implementation of the resource provisioner or an error. // // It is an error to initialize the same provisioner more than once. - InitProvisioner(string) (ResourceProvisioner, error) + InitProvisioner(string) (provisioners.Interface, error) // Provisioner gets the provisioner instance with the given name (already // initialized) or returns nil if the provisioner isn't initialized. - Provisioner(string) ResourceProvisioner + Provisioner(string) provisioners.Interface // ProvisionerSchema retrieves the main configuration schema for a // particular provisioner, which must have already been initialized with diff --git a/terraform/eval_context_builtin.go b/terraform/eval_context_builtin.go index 4e82319158..f01292abb9 100644 --- a/terraform/eval_context_builtin.go +++ b/terraform/eval_context_builtin.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/version" "github.com/hashicorp/terraform/states" @@ -58,7 +59,7 @@ type BuiltinEvalContext struct { ProviderCache map[string]providers.Interface ProviderInputConfig map[string]map[string]cty.Value ProviderLock *sync.Mutex - ProvisionerCache map[string]ResourceProvisioner + ProvisionerCache map[string]provisioners.Interface ProvisionerLock *sync.Mutex ChangesValue *plans.ChangesSync StateValue *states.SyncState @@ -211,7 +212,7 @@ func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.ProviderConfig, c map[s ctx.ProviderLock.Unlock() } -func (ctx *BuiltinEvalContext) InitProvisioner(n string) (ResourceProvisioner, error) { +func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface, error) { ctx.once.Do(ctx.init) // If we already initialized, it is an error @@ -236,7 +237,7 @@ func (ctx *BuiltinEvalContext) InitProvisioner(n string) (ResourceProvisioner, e return p, nil } -func (ctx *BuiltinEvalContext) Provisioner(n string) ResourceProvisioner { +func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface { ctx.once.Do(ctx.init) ctx.ProvisionerLock.Lock() @@ -260,13 +261,9 @@ func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error { key := PathObjectCacheKey(ctx.Path(), n) - var prov interface{} - prov = ctx.ProvisionerCache[key] + prov := ctx.ProvisionerCache[key] if prov != nil { - if p, ok := prov.(ResourceProvisionerCloser); ok { - delete(ctx.ProvisionerCache, key) - return p.Close() - } + return prov.Close() } return nil diff --git a/terraform/eval_context_mock.go b/terraform/eval_context_mock.go index ff23d5b43c..195ecc5c2f 100644 --- a/terraform/eval_context_mock.go +++ b/terraform/eval_context_mock.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform/lang" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -62,12 +63,12 @@ type MockEvalContext struct { InitProvisionerCalled bool InitProvisionerName string - InitProvisionerProvisioner ResourceProvisioner + InitProvisionerProvisioner provisioners.Interface InitProvisionerError error ProvisionerCalled bool ProvisionerName string - ProvisionerProvisioner ResourceProvisioner + ProvisionerProvisioner provisioners.Interface ProvisionerSchemaCalled bool ProvisionerSchemaName string @@ -75,7 +76,7 @@ type MockEvalContext struct { CloseProvisionerCalled bool CloseProvisionerName string - CloseProvisionerProvisioner ResourceProvisioner + CloseProvisionerProvisioner provisioners.Interface EvaluateBlockCalled bool EvaluateBlockBody hcl.Body @@ -203,13 +204,13 @@ func (c *MockEvalContext) SetProviderInput(addr addrs.ProviderConfig, vals map[s c.SetProviderInputValues = vals } -func (c *MockEvalContext) InitProvisioner(n string) (ResourceProvisioner, error) { +func (c *MockEvalContext) InitProvisioner(n string) (provisioners.Interface, error) { c.InitProvisionerCalled = true c.InitProvisionerName = n return c.InitProvisionerProvisioner, c.InitProvisionerError } -func (c *MockEvalContext) Provisioner(n string) ResourceProvisioner { +func (c *MockEvalContext) Provisioner(n string) provisioners.Interface { c.ProvisionerCalled = true c.ProvisionerName = n return c.ProvisionerProvisioner diff --git a/terraform/eval_provisioner.go b/terraform/eval_provisioner.go index b0945e3b7e..bc6b5cc76d 100644 --- a/terraform/eval_provisioner.go +++ b/terraform/eval_provisioner.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/hashicorp/terraform/configs/configschema" + "github.com/hashicorp/terraform/provisioners" ) // EvalInitProvisioner is an EvalNode implementation that initializes a provisioner @@ -32,7 +33,7 @@ func (n *EvalCloseProvisioner) Eval(ctx EvalContext) (interface{}, error) { // initialized provisioner instance for the given name. type EvalGetProvisioner struct { Name string - Output *ResourceProvisioner + Output *provisioners.Interface Schema **configschema.Block } diff --git a/terraform/eval_validate.go b/terraform/eval_validate.go index 8d24267a64..146f03fa3d 100644 --- a/terraform/eval_validate.go +++ b/terraform/eval_validate.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/tfdiags" "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/convert" @@ -111,7 +112,7 @@ func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) { // the configuration of a provisioner belonging to a resource. type EvalValidateProvisioner struct { ResourceAddr addrs.Resource - Provisioner *ResourceProvisioner + Provisioner *provisioners.Interface Schema **configschema.Block Config *configs.Provisioner ConnConfig *configs.Connection @@ -123,9 +124,6 @@ func (n *EvalValidateProvisioner) Eval(ctx EvalContext) (interface{}, error) { config := *n.Config schema := *n.Schema - var warns []string - var errs []error - var diags tfdiags.Diagnostics { @@ -142,22 +140,12 @@ func (n *EvalValidateProvisioner) Eval(ctx EvalContext) (interface{}, error) { return nil, fmt.Errorf("EvaluateBlock returned nil value") } - // The provisioner API still uses our legacy ResourceConfig type, so - // we need to shim it. - legacyRC := NewResourceConfigShimmed(configVal, schema) - - w, e := provisioner.Validate(legacyRC) - warns = append(warns, w...) - errs = append(errs, e...) - - // FIXME: Once the provisioner API itself returns diagnostics, just - // return diags.NonFatalErr() here. - for _, warn := range warns { - diags = diags.Append(tfdiags.SimpleWarning(warn)) - } - for _, err := range errs { - diags = diags.Append(err) + req := provisioners.ValidateProvisionerConfigRequest{ + Config: configVal, } + + resp := provisioner.ValidateProvisionerConfig(req) + diags = diags.Append(resp.Diagnostics) } { diff --git a/terraform/graph_walk_context.go b/terraform/graph_walk_context.go index 4b5cd69e7c..5e037ed8c3 100644 --- a/terraform/graph_walk_context.go +++ b/terraform/graph_walk_context.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -42,7 +43,7 @@ type ContextGraphWalker struct { providerCache map[string]providers.Interface providerSchemas map[string]*ProviderSchema providerLock sync.Mutex - provisionerCache map[string]ResourceProvisioner + provisionerCache map[string]provisioners.Interface provisionerSchemas map[string]*configschema.Block provisionerLock sync.Mutex } @@ -142,7 +143,7 @@ func (w *ContextGraphWalker) init() { w.contexts = make(map[string]*BuiltinEvalContext) w.providerCache = make(map[string]providers.Interface) w.providerSchemas = make(map[string]*ProviderSchema) - w.provisionerCache = make(map[string]ResourceProvisioner) + w.provisionerCache = make(map[string]provisioners.Interface) w.provisionerSchemas = make(map[string]*configschema.Block) w.variableValues = make(map[string]map[string]cty.Value) diff --git a/terraform/node_resource_validate.go b/terraform/node_resource_validate.go index ab6e590346..57bc6f1ddd 100644 --- a/terraform/node_resource_validate.go +++ b/terraform/node_resource_validate.go @@ -3,6 +3,7 @@ package terraform import ( "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/zclconf/go-cty/cty" ) @@ -55,7 +56,7 @@ func (n *NodeValidatableResource) EvalTree() EvalNode { // Validate all the provisioners for _, p := range managed.Provisioners { - var provisioner ResourceProvisioner + var provisioner provisioners.Interface var provisionerSchema *configschema.Block seq.Nodes = append( seq.Nodes, diff --git a/terraform/resource_provisioner.go b/terraform/resource_provisioner.go index e557181004..d40262aeb1 100644 --- a/terraform/resource_provisioner.go +++ b/terraform/resource_provisioner.go @@ -2,6 +2,7 @@ package terraform import ( "github.com/hashicorp/terraform/configs/configschema" + "github.com/hashicorp/terraform/provisioners" ) // ResourceProvisioner is an interface that must be implemented by any @@ -63,3 +64,7 @@ type ResourceProvisionerCloser interface { // ResourceProvisionerFactory is a function type that creates a new instance // of a resource provisioner. type ResourceProvisionerFactory func() (ResourceProvisioner, error) + +// ProvisionerFactory is a function type that creates a new instance +// of a provisioners.Interface. +type ProvisionerFactory func() (provisioners.Interface, error) diff --git a/terraform/schemas.go b/terraform/schemas.go index d61d9e865b..676fd09808 100644 --- a/terraform/schemas.go +++ b/terraform/schemas.go @@ -199,18 +199,18 @@ func loadProvisionerSchemas(schemas map[string]*configschema.Block, config *conf } }() - schema, err := provisioner.GetConfigSchema() - if err != nil { + resp := provisioner.GetSchema() + if resp.Diagnostics.HasErrors() { // We'll put a stub in the map so we won't re-attempt this on // future calls. schemas[name] = &configschema.Block{} diags = diags.Append( - fmt.Errorf("Failed to retrieve schema from provisioner %q: %s", name, err), + fmt.Errorf("Failed to retrieve schema from provisioner %q: %s", name, resp.Diagnostics.Err()), ) return } - schemas[name] = schema + schemas[name] = resp.Provisioner } if config != nil {