terraform: ResourceProvider.Diff shadow
This commit is contained in:
parent
cbbd492bce
commit
82a1158f55
|
@ -123,6 +123,21 @@ func (p *shadowResourceProviderReal) Apply(
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *shadowResourceProviderReal) Diff(
|
||||||
|
info *InstanceInfo,
|
||||||
|
state *InstanceState,
|
||||||
|
desired *ResourceConfig) (*InstanceDiff, error) {
|
||||||
|
result, err := p.ResourceProvider.Diff(info, state, desired)
|
||||||
|
p.Shared.Diff.SetValue(info.HumanId(), &shadowResourceProviderDiff{
|
||||||
|
State: state,
|
||||||
|
Desired: desired,
|
||||||
|
Result: result,
|
||||||
|
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.
|
||||||
|
@ -143,6 +158,7 @@ type shadowResourceProviderShared struct {
|
||||||
Validate shadow.Value
|
Validate shadow.Value
|
||||||
Configure shadow.Value
|
Configure shadow.Value
|
||||||
Apply shadow.KeyedValue
|
Apply shadow.KeyedValue
|
||||||
|
Diff shadow.KeyedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) CloseShadow() error {
|
func (p *shadowResourceProviderShadow) CloseShadow() error {
|
||||||
|
@ -296,6 +312,50 @@ func (p *shadowResourceProviderShadow) Apply(
|
||||||
return result.Result, result.ResultErr
|
return result.Result, result.ResultErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *shadowResourceProviderShadow) Diff(
|
||||||
|
info *InstanceInfo,
|
||||||
|
state *InstanceState,
|
||||||
|
desired *ResourceConfig) (*InstanceDiff, error) {
|
||||||
|
// Unique key
|
||||||
|
key := info.HumanId()
|
||||||
|
raw := p.Shared.Diff.Value(key)
|
||||||
|
if raw == nil {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
defer p.ErrorLock.Unlock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Unknown 'diff' call for %q:\n\n%#v\n\n%#v",
|
||||||
|
key, state, desired))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, ok := raw.(*shadowResourceProviderDiff)
|
||||||
|
if !ok {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
defer p.ErrorLock.Unlock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Unknown 'diff' shadow value: %#v", raw))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the parameters, which should be identical
|
||||||
|
if !state.Equal(result.State) {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Diff %q had unequal states (real, then shadow):\n\n%#v\n\n%#v",
|
||||||
|
key, result.State, state))
|
||||||
|
p.ErrorLock.Unlock()
|
||||||
|
}
|
||||||
|
if !desired.Equal(result.Desired) {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Diff %q had unequal states (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
|
||||||
|
@ -306,13 +366,6 @@ func (p *shadowResourceProviderShadow) ValidateResource(t string, c *ResourceCon
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) Diff(
|
|
||||||
info *InstanceInfo,
|
|
||||||
state *InstanceState,
|
|
||||||
desired *ResourceConfig) (*InstanceDiff, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) Refresh(
|
func (p *shadowResourceProviderShadow) Refresh(
|
||||||
info *InstanceInfo,
|
info *InstanceInfo,
|
||||||
s *InstanceState) (*InstanceState, error) {
|
s *InstanceState) (*InstanceState, error) {
|
||||||
|
@ -365,3 +418,10 @@ type shadowResourceProviderApply struct {
|
||||||
Result *InstanceState
|
Result *InstanceState
|
||||||
ResultErr error
|
ResultErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type shadowResourceProviderDiff struct {
|
||||||
|
State *InstanceState
|
||||||
|
Desired *ResourceConfig
|
||||||
|
Result *InstanceDiff
|
||||||
|
ResultErr error
|
||||||
|
}
|
||||||
|
|
|
@ -319,3 +319,57 @@ func TestShadowResourceProviderApply(t *testing.T) {
|
||||||
t.Fatalf("bad: %s", err)
|
t.Fatalf("bad: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShadowResourceProviderDiff(t *testing.T) {
|
||||||
|
mock := new(MockResourceProvider)
|
||||||
|
real, shadow := newShadowResourceProvider(mock)
|
||||||
|
|
||||||
|
// Test values
|
||||||
|
info := &InstanceInfo{Id: "foo"}
|
||||||
|
state := &InstanceState{ID: "foo"}
|
||||||
|
desired := testResourceConfig(t, map[string]interface{}{"foo": "bar"})
|
||||||
|
mockResult := &InstanceDiff{Destroy: true}
|
||||||
|
|
||||||
|
// Configure the mock
|
||||||
|
mock.DiffReturn = mockResult
|
||||||
|
|
||||||
|
// Verify that it blocks until the real func is called
|
||||||
|
var result *InstanceDiff
|
||||||
|
var err error
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(doneCh)
|
||||||
|
result, err = shadow.Diff(info, state, desired)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-doneCh:
|
||||||
|
t.Fatal("should block until finished")
|
||||||
|
case <-time.After(10 * time.Millisecond):
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the real func
|
||||||
|
realResult, realErr := real.Diff(info, state, desired)
|
||||||
|
if !reflect.DeepEqual(realResult, mockResult) {
|
||||||
|
t.Fatalf("bad: %#v", realResult)
|
||||||
|
}
|
||||||
|
if realErr != nil {
|
||||||
|
t.Fatalf("bad: %#v", realErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The shadow should finish now
|
||||||
|
<-doneCh
|
||||||
|
|
||||||
|
// Verify the shadow returned the same values
|
||||||
|
if !reflect.DeepEqual(result, mockResult) {
|
||||||
|
t.Fatalf("bad: %#v", result)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we have no errors
|
||||||
|
if err := shadow.CloseShadow(); err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue