terraform: ResourceProvider.ReadDataDiff (shadow)
This commit is contained in:
parent
31f8d13678
commit
b0801bf125
|
@ -2,7 +2,6 @@ package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/mitchellh/copystructure"
|
"github.com/mitchellh/copystructure"
|
||||||
|
@ -85,7 +84,7 @@ func shadowContextVerify(real, shadow *Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare the diffs
|
// Compare the diffs
|
||||||
if !reflect.DeepEqual(real.diff, shadow.diff) {
|
if !real.diff.Equal(shadow.diff) {
|
||||||
result = multierror.Append(result, fmt.Errorf(
|
result = multierror.Append(result, fmt.Errorf(
|
||||||
"Real and shadow diffs do not match! "+
|
"Real and shadow diffs do not match! "+
|
||||||
"Real diff:\n\n%s\n\n"+
|
"Real diff:\n\n%s\n\n"+
|
||||||
|
|
|
@ -201,6 +201,62 @@ func (p *shadowResourceProviderReal) Refresh(
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *shadowResourceProviderReal) ValidateDataSource(
|
||||||
|
t string, c *ResourceConfig) ([]string, []error) {
|
||||||
|
key := t
|
||||||
|
configCopy := c.DeepCopy()
|
||||||
|
|
||||||
|
// Real operation
|
||||||
|
warns, errs := p.ResourceProvider.ValidateDataSource(t, c)
|
||||||
|
|
||||||
|
// Get the result
|
||||||
|
raw, ok := p.Shared.ValidateDataSource.ValueOk(key)
|
||||||
|
if !ok {
|
||||||
|
raw = new(shadowResourceProviderValidateDataSourceWrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper, ok := raw.(*shadowResourceProviderValidateDataSourceWrapper)
|
||||||
|
if !ok {
|
||||||
|
// If this fails then we just continue with our day... the shadow
|
||||||
|
// will fail to but there isn't much we can do.
|
||||||
|
log.Printf(
|
||||||
|
"[ERROR] unknown value in ValidateDataSource shadow value: %#v", raw)
|
||||||
|
return warns, errs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock the wrapper for writing and record our call
|
||||||
|
wrapper.Lock()
|
||||||
|
defer wrapper.Unlock()
|
||||||
|
|
||||||
|
wrapper.Calls = append(wrapper.Calls, &shadowResourceProviderValidateDataSource{
|
||||||
|
Config: configCopy,
|
||||||
|
Warns: warns,
|
||||||
|
Errors: errs,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Set it
|
||||||
|
p.Shared.ValidateDataSource.SetValue(key, wrapper)
|
||||||
|
|
||||||
|
// Return the result
|
||||||
|
return warns, errs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *shadowResourceProviderReal) ReadDataDiff(
|
||||||
|
info *InstanceInfo,
|
||||||
|
desired *ResourceConfig) (*InstanceDiff, error) {
|
||||||
|
// These have to be copied before the call since call can modify
|
||||||
|
desiredCopy := desired.DeepCopy()
|
||||||
|
|
||||||
|
result, err := p.ResourceProvider.ReadDataDiff(info, desired)
|
||||||
|
p.Shared.ReadDataDiff.SetValue(info.uniqueId(), &shadowResourceProviderReadDataDiff{
|
||||||
|
Desired: desiredCopy,
|
||||||
|
Result: result.DeepCopy(),
|
||||||
|
ResultErr: err,
|
||||||
|
})
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
// shadowResourceProviderShadow is the shadow resource provider. Function
|
// shadowResourceProviderShadow is the shadow resource provider. Function
|
||||||
// calls never affect real resources. This is paired with the "real" side
|
// calls never affect real resources. This is paired with the "real" side
|
||||||
// which must be called properly to enable recording.
|
// which must be called properly to enable recording.
|
||||||
|
@ -219,21 +275,23 @@ type shadowResourceProviderShared struct {
|
||||||
// NOTE: Anytime a value is added here, be sure to add it to
|
// NOTE: Anytime a value is added here, be sure to add it to
|
||||||
// the Close() method so that it is closed.
|
// the Close() method so that it is closed.
|
||||||
|
|
||||||
CloseErr shadow.Value
|
CloseErr shadow.Value
|
||||||
Input shadow.Value
|
Input shadow.Value
|
||||||
Validate shadow.Value
|
Validate shadow.Value
|
||||||
Configure shadow.Value
|
Configure shadow.Value
|
||||||
ValidateResource shadow.KeyedValue
|
ValidateResource shadow.KeyedValue
|
||||||
Apply shadow.KeyedValue
|
Apply shadow.KeyedValue
|
||||||
Diff shadow.KeyedValue
|
Diff shadow.KeyedValue
|
||||||
Refresh shadow.KeyedValue
|
Refresh shadow.KeyedValue
|
||||||
|
ValidateDataSource shadow.KeyedValue
|
||||||
|
ReadDataDiff shadow.KeyedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShared) Close() error {
|
func (p *shadowResourceProviderShared) Close() error {
|
||||||
closers := []io.Closer{
|
closers := []io.Closer{
|
||||||
&p.CloseErr, &p.Input, &p.Validate,
|
&p.CloseErr, &p.Input, &p.Validate,
|
||||||
&p.Configure, &p.ValidateResource, &p.Apply, &p.Diff,
|
&p.Configure, &p.ValidateResource, &p.Apply, &p.Diff,
|
||||||
&p.Refresh,
|
&p.Refresh, &p.ValidateDataSource, &p.ReadDataDiff,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range closers {
|
for _, c := range closers {
|
||||||
|
@ -536,6 +594,94 @@ func (p *shadowResourceProviderShadow) Refresh(
|
||||||
return result.Result, result.ResultErr
|
return result.Result, result.ResultErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *shadowResourceProviderShadow) ValidateDataSource(
|
||||||
|
t string, c *ResourceConfig) ([]string, []error) {
|
||||||
|
// Unique key
|
||||||
|
key := t
|
||||||
|
|
||||||
|
// Get the initial value
|
||||||
|
raw := p.Shared.ValidateDataSource.Value(key)
|
||||||
|
|
||||||
|
// Find a validation with our configuration
|
||||||
|
var result *shadowResourceProviderValidateDataSource
|
||||||
|
for {
|
||||||
|
// Get the value
|
||||||
|
if raw == nil {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
defer p.ErrorLock.Unlock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Unknown 'ValidateDataSource' call for %q:\n\n%#v",
|
||||||
|
key, c))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper, ok := raw.(*shadowResourceProviderValidateDataSourceWrapper)
|
||||||
|
if !ok {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
defer p.ErrorLock.Unlock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Unknown 'ValidateDataSource' shadow value: %#v", raw))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for the matching call with our configuration
|
||||||
|
wrapper.RLock()
|
||||||
|
for _, call := range wrapper.Calls {
|
||||||
|
if call.Config.Equal(c) {
|
||||||
|
result = call
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper.RUnlock()
|
||||||
|
|
||||||
|
// If we found a result, exit
|
||||||
|
if result != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for a change so we can get the wrapper again
|
||||||
|
raw = p.Shared.ValidateDataSource.WaitForChange(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Warns, result.Errors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *shadowResourceProviderShadow) ReadDataDiff(
|
||||||
|
info *InstanceInfo,
|
||||||
|
desired *ResourceConfig) (*InstanceDiff, error) {
|
||||||
|
// Unique key
|
||||||
|
key := info.uniqueId()
|
||||||
|
raw := p.Shared.ReadDataDiff.Value(key)
|
||||||
|
if raw == nil {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
defer p.ErrorLock.Unlock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Unknown 'ReadDataDiff' call for %q:\n\n%#v",
|
||||||
|
key, desired))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, ok := raw.(*shadowResourceProviderReadDataDiff)
|
||||||
|
if !ok {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
defer p.ErrorLock.Unlock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Unknown 'ReadDataDiff' shadow value: %#v", raw))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the parameters, which should be identical
|
||||||
|
if !desired.Equal(result.Desired) {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"ReadDataDiff %q had unequal configs (real, then shadow):\n\n%#v\n\n%#v",
|
||||||
|
key, result.Desired, desired))
|
||||||
|
p.ErrorLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Result, result.ResultErr
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// TODO
|
// TODO
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -546,16 +692,6 @@ func (p *shadowResourceProviderShadow) ImportState(info *InstanceInfo, id string
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) ValidateDataSource(t string, c *ResourceConfig) ([]string, []error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) ReadDataDiff(
|
|
||||||
info *InstanceInfo,
|
|
||||||
desired *ResourceConfig) (*InstanceDiff, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) ReadDataApply(
|
func (p *shadowResourceProviderShadow) ReadDataApply(
|
||||||
info *InstanceInfo,
|
info *InstanceInfo,
|
||||||
d *InstanceDiff) (*InstanceState, error) {
|
d *InstanceDiff) (*InstanceState, error) {
|
||||||
|
@ -613,3 +749,21 @@ type shadowResourceProviderRefresh struct {
|
||||||
Result *InstanceState
|
Result *InstanceState
|
||||||
ResultErr error
|
ResultErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type shadowResourceProviderValidateDataSourceWrapper struct {
|
||||||
|
sync.RWMutex
|
||||||
|
|
||||||
|
Calls []*shadowResourceProviderValidateDataSource
|
||||||
|
}
|
||||||
|
|
||||||
|
type shadowResourceProviderValidateDataSource struct {
|
||||||
|
Config *ResourceConfig
|
||||||
|
Warns []string
|
||||||
|
Errors []error
|
||||||
|
}
|
||||||
|
|
||||||
|
type shadowResourceProviderReadDataDiff struct {
|
||||||
|
Desired *ResourceConfig
|
||||||
|
Result *InstanceDiff
|
||||||
|
ResultErr error
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue