364 lines
11 KiB
Go
364 lines
11 KiB
Go
package terraform
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sync"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
ctyjson "github.com/zclconf/go-cty/cty/json"
|
|
|
|
"github.com/hashicorp/terraform/internal/configs/hcl2shim"
|
|
"github.com/hashicorp/terraform/internal/providers"
|
|
)
|
|
|
|
var _ providers.Interface = (*MockProvider)(nil)
|
|
|
|
// MockProvider implements providers.Interface but mocks out all the
|
|
// calls for testing purposes.
|
|
type MockProvider struct {
|
|
sync.Mutex
|
|
|
|
// Anything you want, in case you need to store extra data with the mock.
|
|
Meta interface{}
|
|
|
|
GetSchemaCalled bool
|
|
GetSchemaReturn *ProviderSchema // This is using ProviderSchema directly rather than providers.GetProviderSchemaResponse for compatibility with old tests
|
|
|
|
ValidateProviderConfigCalled bool
|
|
ValidateProviderConfigResponse providers.ValidateProviderConfigResponse
|
|
ValidateProviderConfigRequest providers.ValidateProviderConfigRequest
|
|
ValidateProviderConfigFn func(providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse
|
|
|
|
ValidateResourceConfigCalled bool
|
|
ValidateResourceConfigTypeName string
|
|
ValidateResourceConfigResponse providers.ValidateResourceConfigResponse
|
|
ValidateResourceConfigRequest providers.ValidateResourceConfigRequest
|
|
ValidateResourceConfigFn func(providers.ValidateResourceConfigRequest) providers.ValidateResourceConfigResponse
|
|
|
|
ValidateDataResourceConfigCalled bool
|
|
ValidateDataResourceConfigTypeName string
|
|
ValidateDataResourceConfigResponse providers.ValidateDataResourceConfigResponse
|
|
ValidateDataResourceConfigRequest providers.ValidateDataResourceConfigRequest
|
|
ValidateDataResourceConfigFn func(providers.ValidateDataResourceConfigRequest) providers.ValidateDataResourceConfigResponse
|
|
|
|
UpgradeResourceStateCalled bool
|
|
UpgradeResourceStateTypeName string
|
|
UpgradeResourceStateResponse providers.UpgradeResourceStateResponse
|
|
UpgradeResourceStateRequest providers.UpgradeResourceStateRequest
|
|
UpgradeResourceStateFn func(providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse
|
|
|
|
ConfigureProviderCalled bool
|
|
ConfigureProviderResponse providers.ConfigureProviderResponse
|
|
ConfigureProviderRequest providers.ConfigureProviderRequest
|
|
ConfigureProviderFn func(providers.ConfigureProviderRequest) providers.ConfigureProviderResponse
|
|
|
|
StopCalled bool
|
|
StopFn func() error
|
|
StopResponse error
|
|
|
|
ReadResourceCalled bool
|
|
ReadResourceResponse providers.ReadResourceResponse
|
|
ReadResourceRequest providers.ReadResourceRequest
|
|
ReadResourceFn func(providers.ReadResourceRequest) providers.ReadResourceResponse
|
|
|
|
PlanResourceChangeCalled bool
|
|
PlanResourceChangeResponse providers.PlanResourceChangeResponse
|
|
PlanResourceChangeRequest providers.PlanResourceChangeRequest
|
|
PlanResourceChangeFn func(providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse
|
|
|
|
ApplyResourceChangeCalled bool
|
|
ApplyResourceChangeResponse providers.ApplyResourceChangeResponse
|
|
ApplyResourceChangeRequest providers.ApplyResourceChangeRequest
|
|
ApplyResourceChangeFn func(providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse
|
|
|
|
ImportResourceStateCalled bool
|
|
ImportResourceStateResponse providers.ImportResourceStateResponse
|
|
ImportResourceStateRequest providers.ImportResourceStateRequest
|
|
ImportResourceStateFn func(providers.ImportResourceStateRequest) providers.ImportResourceStateResponse
|
|
// Legacy return type for existing tests, which will be shimmed into an
|
|
// ImportResourceStateResponse if set
|
|
ImportStateReturn []*InstanceState
|
|
|
|
ReadDataSourceCalled bool
|
|
ReadDataSourceResponse providers.ReadDataSourceResponse
|
|
ReadDataSourceRequest providers.ReadDataSourceRequest
|
|
ReadDataSourceFn func(providers.ReadDataSourceRequest) providers.ReadDataSourceResponse
|
|
|
|
CloseCalled bool
|
|
CloseError error
|
|
}
|
|
|
|
func (p *MockProvider) GetProviderSchema() providers.GetProviderSchemaResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
p.GetSchemaCalled = true
|
|
return p.getSchema()
|
|
}
|
|
|
|
func (p *MockProvider) getSchema() providers.GetProviderSchemaResponse {
|
|
// This version of getSchema doesn't do any locking, so it's suitable to
|
|
// call from other methods of this mock as long as they are already
|
|
// holding the lock.
|
|
|
|
ret := providers.GetProviderSchemaResponse{
|
|
Provider: providers.Schema{},
|
|
DataSources: map[string]providers.Schema{},
|
|
ResourceTypes: map[string]providers.Schema{},
|
|
}
|
|
if p.GetSchemaReturn != nil {
|
|
ret.Provider.Block = p.GetSchemaReturn.Provider
|
|
ret.ProviderMeta.Block = p.GetSchemaReturn.ProviderMeta
|
|
for n, s := range p.GetSchemaReturn.DataSources {
|
|
ret.DataSources[n] = providers.Schema{
|
|
Block: s,
|
|
}
|
|
}
|
|
for n, s := range p.GetSchemaReturn.ResourceTypes {
|
|
ret.ResourceTypes[n] = providers.Schema{
|
|
Version: int64(p.GetSchemaReturn.ResourceTypeSchemaVersions[n]),
|
|
Block: s,
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func (p *MockProvider) ValidateProviderConfig(r providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ValidateProviderConfigCalled = true
|
|
p.ValidateProviderConfigRequest = r
|
|
if p.ValidateProviderConfigFn != nil {
|
|
return p.ValidateProviderConfigFn(r)
|
|
}
|
|
return p.ValidateProviderConfigResponse
|
|
}
|
|
|
|
func (p *MockProvider) ValidateResourceConfig(r providers.ValidateResourceConfigRequest) providers.ValidateResourceConfigResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ValidateResourceConfigCalled = true
|
|
p.ValidateResourceConfigRequest = r
|
|
|
|
if p.ValidateResourceConfigFn != nil {
|
|
return p.ValidateResourceConfigFn(r)
|
|
}
|
|
|
|
return p.ValidateResourceConfigResponse
|
|
}
|
|
|
|
func (p *MockProvider) ValidateDataResourceConfig(r providers.ValidateDataResourceConfigRequest) providers.ValidateDataResourceConfigResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ValidateDataResourceConfigCalled = true
|
|
p.ValidateDataResourceConfigRequest = r
|
|
|
|
if p.ValidateDataResourceConfigFn != nil {
|
|
return p.ValidateDataResourceConfigFn(r)
|
|
}
|
|
|
|
return p.ValidateDataResourceConfigResponse
|
|
}
|
|
|
|
func (p *MockProvider) UpgradeResourceState(r providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
schemas := p.getSchema()
|
|
schema := schemas.ResourceTypes[r.TypeName]
|
|
schemaType := schema.Block.ImpliedType()
|
|
|
|
p.UpgradeResourceStateCalled = true
|
|
p.UpgradeResourceStateRequest = r
|
|
|
|
if p.UpgradeResourceStateFn != nil {
|
|
return p.UpgradeResourceStateFn(r)
|
|
}
|
|
|
|
resp := p.UpgradeResourceStateResponse
|
|
|
|
if resp.UpgradedState == cty.NilVal {
|
|
switch {
|
|
case r.RawStateFlatmap != nil:
|
|
v, err := hcl2shim.HCL2ValueFromFlatmap(r.RawStateFlatmap, schemaType)
|
|
if err != nil {
|
|
resp.Diagnostics = resp.Diagnostics.Append(err)
|
|
return resp
|
|
}
|
|
resp.UpgradedState = v
|
|
case len(r.RawStateJSON) > 0:
|
|
v, err := ctyjson.Unmarshal(r.RawStateJSON, schemaType)
|
|
|
|
if err != nil {
|
|
resp.Diagnostics = resp.Diagnostics.Append(err)
|
|
return resp
|
|
}
|
|
resp.UpgradedState = v
|
|
}
|
|
}
|
|
return resp
|
|
}
|
|
|
|
func (p *MockProvider) ConfigureProvider(r providers.ConfigureProviderRequest) providers.ConfigureProviderResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ConfigureProviderCalled = true
|
|
p.ConfigureProviderRequest = r
|
|
|
|
if p.ConfigureProviderFn != nil {
|
|
return p.ConfigureProviderFn(r)
|
|
}
|
|
|
|
return p.ConfigureProviderResponse
|
|
}
|
|
|
|
func (p *MockProvider) 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 provider 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 *MockProvider) ReadResource(r providers.ReadResourceRequest) providers.ReadResourceResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ReadResourceCalled = true
|
|
p.ReadResourceRequest = r
|
|
|
|
if p.ReadResourceFn != nil {
|
|
return p.ReadResourceFn(r)
|
|
}
|
|
|
|
resp := p.ReadResourceResponse
|
|
if resp.NewState != cty.NilVal {
|
|
// make sure the NewState fits the schema
|
|
// This isn't always the case for the existing tests
|
|
newState, err := p.GetSchemaReturn.ResourceTypes[r.TypeName].CoerceValue(resp.NewState)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
resp.NewState = newState
|
|
return resp
|
|
}
|
|
|
|
// just return the same state we received
|
|
resp.NewState = r.PriorState
|
|
return resp
|
|
}
|
|
|
|
func (p *MockProvider) PlanResourceChange(r providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.PlanResourceChangeCalled = true
|
|
p.PlanResourceChangeRequest = r
|
|
|
|
if p.PlanResourceChangeFn != nil {
|
|
return p.PlanResourceChangeFn(r)
|
|
}
|
|
|
|
return p.PlanResourceChangeResponse
|
|
}
|
|
|
|
func (p *MockProvider) ApplyResourceChange(r providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
|
|
p.Lock()
|
|
p.ApplyResourceChangeCalled = true
|
|
p.ApplyResourceChangeRequest = r
|
|
p.Unlock()
|
|
|
|
if p.ApplyResourceChangeFn != nil {
|
|
return p.ApplyResourceChangeFn(r)
|
|
}
|
|
|
|
return p.ApplyResourceChangeResponse
|
|
}
|
|
|
|
func (p *MockProvider) ImportResourceState(r providers.ImportResourceStateRequest) providers.ImportResourceStateResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
if p.ImportStateReturn != nil {
|
|
for _, is := range p.ImportStateReturn {
|
|
if is.Attributes == nil {
|
|
is.Attributes = make(map[string]string)
|
|
}
|
|
is.Attributes["id"] = is.ID
|
|
|
|
typeName := is.Ephemeral.Type
|
|
// Use the requested type if the resource has no type of it's own.
|
|
// We still return the empty type, which will error, but this prevents a panic.
|
|
if typeName == "" {
|
|
typeName = r.TypeName
|
|
}
|
|
|
|
schema := p.GetSchemaReturn.ResourceTypes[typeName]
|
|
if schema == nil {
|
|
panic("no schema found for " + typeName)
|
|
}
|
|
|
|
private, err := json.Marshal(is.Meta)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
state, err := hcl2shim.HCL2ValueFromFlatmap(is.Attributes, schema.ImpliedType())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
state, err = schema.CoerceValue(state)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
p.ImportResourceStateResponse.ImportedResources = append(
|
|
p.ImportResourceStateResponse.ImportedResources,
|
|
providers.ImportedResource{
|
|
TypeName: is.Ephemeral.Type,
|
|
State: state,
|
|
Private: private,
|
|
})
|
|
}
|
|
}
|
|
|
|
p.ImportResourceStateCalled = true
|
|
p.ImportResourceStateRequest = r
|
|
if p.ImportResourceStateFn != nil {
|
|
return p.ImportResourceStateFn(r)
|
|
}
|
|
|
|
return p.ImportResourceStateResponse
|
|
}
|
|
|
|
func (p *MockProvider) ReadDataSource(r providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
p.ReadDataSourceCalled = true
|
|
p.ReadDataSourceRequest = r
|
|
|
|
if p.ReadDataSourceFn != nil {
|
|
return p.ReadDataSourceFn(r)
|
|
}
|
|
|
|
return p.ReadDataSourceResponse
|
|
}
|
|
|
|
func (p *MockProvider) Close() error {
|
|
p.CloseCalled = true
|
|
return p.CloseError
|
|
}
|