diff --git a/terraform/eval_context.go b/terraform/eval_context.go index 6c8a5d9d1..7421d69cb 100644 --- a/terraform/eval_context.go +++ b/terraform/eval_context.go @@ -77,22 +77,17 @@ type EvalContext interface { ProviderInput(addrs.AbsProviderConfig) map[string]cty.Value SetProviderInput(addrs.AbsProviderConfig, map[string]cty.Value) - // InitProvisioner initializes the provisioner with the given name. - // It is an error to initialize the same provisioner more than once. - InitProvisioner(string) error - // Provisioner gets the provisioner instance with the given name (already // initialized) or returns nil if the provisioner isn't initialized. - Provisioner(string) provisioners.Interface + Provisioner(string) (provisioners.Interface, error) // ProvisionerSchema retrieves the main configuration schema for a // particular provisioner, which must have already been initialized with // InitProvisioner. ProvisionerSchema(string) *configschema.Block - // CloseProvisioner closes provisioner connections that aren't needed - // anymore. - CloseProvisioner(string) error + // CloseProvisioner closes all provisioner plugins. + CloseProvisioners() error // EvaluateBlock takes the given raw configuration block and associated // schema and evaluates it to produce a value of an object type that diff --git a/terraform/eval_context_builtin.go b/terraform/eval_context_builtin.go index 97d2ff6ef..d477c00c1 100644 --- a/terraform/eval_context_builtin.go +++ b/terraform/eval_context_builtin.go @@ -228,48 +228,41 @@ func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.AbsProviderConfig, c ma ctx.ProviderLock.Unlock() } -func (ctx *BuiltinEvalContext) InitProvisioner(n string) error { - // If we already initialized, it is an error - if p := ctx.Provisioner(n); p != nil { - return fmt.Errorf("Provisioner '%s' already initialized", n) - } - - // Warning: make sure to acquire these locks AFTER the call to Provisioner - // above, since it also acquires locks. +func (ctx *BuiltinEvalContext) Provisioner(n string) (provisioners.Interface, error) { ctx.ProvisionerLock.Lock() defer ctx.ProvisionerLock.Unlock() - p, err := ctx.Components.ResourceProvisioner(n) - if err != nil { - return err + p, ok := ctx.ProvisionerCache[n] + if !ok { + var err error + p, err = ctx.Components.ResourceProvisioner(n) + if err != nil { + return nil, err + } + + ctx.ProvisionerCache[n] = p } - ctx.ProvisionerCache[n] = p - - return nil -} - -func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface { - ctx.ProvisionerLock.Lock() - defer ctx.ProvisionerLock.Unlock() - - return ctx.ProvisionerCache[n] + return p, nil } func (ctx *BuiltinEvalContext) ProvisionerSchema(n string) *configschema.Block { return ctx.Schemas.ProvisionerConfig(n) } -func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error { +func (ctx *BuiltinEvalContext) CloseProvisioners() error { + var diags tfdiags.Diagnostics ctx.ProvisionerLock.Lock() defer ctx.ProvisionerLock.Unlock() - prov := ctx.ProvisionerCache[n] - if prov != nil { - return prov.Close() + for name, prov := range ctx.ProvisionerCache { + err := prov.Close() + if err != nil { + diags = diags.Append(fmt.Errorf("provisioner.Close %s: %s", name, err)) + } } - return nil + return diags.Err() } func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) { diff --git a/terraform/eval_context_mock.go b/terraform/eval_context_mock.go index ca8b84a6a..aa25f75f9 100644 --- a/terraform/eval_context_mock.go +++ b/terraform/eval_context_mock.go @@ -63,11 +63,6 @@ type MockEvalContext struct { ConfigureProviderConfig cty.Value ConfigureProviderDiags tfdiags.Diagnostics - InitProvisionerCalled bool - InitProvisionerName string - InitProvisionerProvisioner provisioners.Interface - InitProvisionerError error - ProvisionerCalled bool ProvisionerName string ProvisionerProvisioner provisioners.Interface @@ -76,9 +71,7 @@ type MockEvalContext struct { ProvisionerSchemaName string ProvisionerSchemaSchema *configschema.Block - CloseProvisionerCalled bool - CloseProvisionerName string - CloseProvisionerProvisioner provisioners.Interface + CloseProvisionersCalled bool EvaluateBlockCalled bool EvaluateBlockBody hcl.Body @@ -208,16 +201,10 @@ func (c *MockEvalContext) SetProviderInput(addr addrs.AbsProviderConfig, vals ma c.SetProviderInputValues = vals } -func (c *MockEvalContext) InitProvisioner(n string) error { - c.InitProvisionerCalled = true - c.InitProvisionerName = n - return c.InitProvisionerError -} - -func (c *MockEvalContext) Provisioner(n string) provisioners.Interface { +func (c *MockEvalContext) Provisioner(n string) (provisioners.Interface, error) { c.ProvisionerCalled = true c.ProvisionerName = n - return c.ProvisionerProvisioner + return c.ProvisionerProvisioner, nil } func (c *MockEvalContext) ProvisionerSchema(n string) *configschema.Block { @@ -226,9 +213,8 @@ func (c *MockEvalContext) ProvisionerSchema(n string) *configschema.Block { return c.ProvisionerSchemaSchema } -func (c *MockEvalContext) CloseProvisioner(n string) error { - c.CloseProvisionerCalled = true - c.CloseProvisionerName = n +func (c *MockEvalContext) CloseProvisioners() error { + c.CloseProvisionersCalled = true return nil }