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
|
|
}
|