mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
a57337327d
References from a resource-level connection blocks were not returned from NodeAbstractResource.References, causing the provisioner connection attributes to sometimes be evaluated too early.
154 lines
4.2 KiB
Go
154 lines
4.2 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/convert"
|
|
|
|
"github.com/hashicorp/terraform/provisioners"
|
|
)
|
|
|
|
var _ provisioners.Interface = (*MockProvisioner)(nil)
|
|
|
|
// MockProvisioner implements provisioners.Interface but mocks out all the
|
|
// calls for testing purposes.
|
|
type MockProvisioner struct {
|
|
sync.Mutex
|
|
// Anything you want, in case you need to store extra data with the mock.
|
|
Meta interface{}
|
|
|
|
GetSchemaCalled bool
|
|
GetSchemaResponse provisioners.GetSchemaResponse
|
|
|
|
ValidateProvisionerConfigCalled bool
|
|
ValidateProvisionerConfigRequest provisioners.ValidateProvisionerConfigRequest
|
|
ValidateProvisionerConfigResponse provisioners.ValidateProvisionerConfigResponse
|
|
ValidateProvisionerConfigFn func(provisioners.ValidateProvisionerConfigRequest) provisioners.ValidateProvisionerConfigResponse
|
|
|
|
ProvisionResourceCalled bool
|
|
ProvisionResourceRequest provisioners.ProvisionResourceRequest
|
|
ProvisionResourceResponse provisioners.ProvisionResourceResponse
|
|
ProvisionResourceFn func(provisioners.ProvisionResourceRequest) provisioners.ProvisionResourceResponse
|
|
|
|
StopCalled bool
|
|
StopResponse error
|
|
StopFn func() error
|
|
|
|
CloseCalled bool
|
|
CloseResponse error
|
|
CloseFn func() error
|
|
|
|
// Legacy callbacks: if these are set, we will shim incoming calls for
|
|
// new-style methods to these old-fashioned terraform.ResourceProvider
|
|
// mock callbacks, for the benefit of older tests that were written against
|
|
// the old mock API.
|
|
ApplyFn func(rs *InstanceState, c *ResourceConfig) error
|
|
}
|
|
|
|
func (p *MockProvisioner) GetSchema() provisioners.GetSchemaResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.GetSchemaCalled = true
|
|
return p.getSchema()
|
|
}
|
|
|
|
// getSchema is the implementation of GetSchema, which can be called from other
|
|
// methods on MockProvisioner that may already be holding the lock.
|
|
func (p *MockProvisioner) getSchema() provisioners.GetSchemaResponse {
|
|
return p.GetSchemaResponse
|
|
}
|
|
|
|
func (p *MockProvisioner) ValidateProvisionerConfig(r provisioners.ValidateProvisionerConfigRequest) provisioners.ValidateProvisionerConfigResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ValidateProvisionerConfigCalled = true
|
|
p.ValidateProvisionerConfigRequest = r
|
|
if p.ValidateProvisionerConfigFn != nil {
|
|
return p.ValidateProvisionerConfigFn(r)
|
|
}
|
|
return p.ValidateProvisionerConfigResponse
|
|
}
|
|
|
|
func (p *MockProvisioner) ProvisionResource(r provisioners.ProvisionResourceRequest) provisioners.ProvisionResourceResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ProvisionResourceCalled = true
|
|
p.ProvisionResourceRequest = r
|
|
if p.ApplyFn != nil {
|
|
if !r.Config.IsKnown() {
|
|
panic(fmt.Sprintf("cannot provision with unknown value: %#v", r.Config))
|
|
}
|
|
|
|
schema := p.getSchema()
|
|
rc := NewResourceConfigShimmed(r.Config, schema.Provisioner)
|
|
connVal := r.Connection
|
|
connMap := map[string]string{}
|
|
|
|
if !connVal.IsNull() && connVal.IsKnown() {
|
|
for it := connVal.ElementIterator(); it.Next(); {
|
|
ak, av := it.Element()
|
|
name := ak.AsString()
|
|
|
|
if !av.IsKnown() || av.IsNull() {
|
|
continue
|
|
}
|
|
|
|
av, _ = convert.Convert(av, cty.String)
|
|
connMap[name] = av.AsString()
|
|
}
|
|
}
|
|
|
|
// We no longer pass the full instance state to a provisioner, so we'll
|
|
// construct a partial one that should be good enough for what existing
|
|
// test mocks need.
|
|
is := &InstanceState{
|
|
Ephemeral: EphemeralState{
|
|
ConnInfo: connMap,
|
|
},
|
|
}
|
|
var resp provisioners.ProvisionResourceResponse
|
|
err := p.ApplyFn(is, rc)
|
|
if err != nil {
|
|
resp.Diagnostics = resp.Diagnostics.Append(err)
|
|
}
|
|
return resp
|
|
}
|
|
if p.ProvisionResourceFn != nil {
|
|
fn := p.ProvisionResourceFn
|
|
return fn(r)
|
|
}
|
|
|
|
return p.ProvisionResourceResponse
|
|
}
|
|
|
|
func (p *MockProvisioner) Stop() error {
|
|
// We intentionally don't lock in this one because the whole point of this
|
|
// method is to be called concurrently with another operation that can
|
|
// be cancelled. The provisioner itself is responsible for handling
|
|
// any concurrency concerns in this case.
|
|
|
|
p.StopCalled = true
|
|
if p.StopFn != nil {
|
|
return p.StopFn()
|
|
}
|
|
|
|
return p.StopResponse
|
|
}
|
|
|
|
func (p *MockProvisioner) Close() error {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.CloseCalled = true
|
|
if p.CloseFn != nil {
|
|
return p.CloseFn()
|
|
}
|
|
|
|
return p.CloseResponse
|
|
}
|