terraform: ResourceProvider.Validate for shadow
This commit is contained in:
parent
bb5f116cec
commit
23204d2414
|
@ -87,6 +87,17 @@ func (p *shadowResourceProviderReal) Input(
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *shadowResourceProviderReal) Validate(c *ResourceConfig) ([]string, []error) {
|
||||||
|
warns, errs := p.ResourceProvider.Validate(c)
|
||||||
|
p.Shared.Validate.SetValue(&shadowResourceProviderValidate{
|
||||||
|
Config: c.DeepCopy(),
|
||||||
|
ResultWarn: warns,
|
||||||
|
ResultErr: errs,
|
||||||
|
})
|
||||||
|
|
||||||
|
return warns, errs
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -104,6 +115,7 @@ type shadowResourceProviderShadow struct {
|
||||||
type shadowResourceProviderShared struct {
|
type shadowResourceProviderShared struct {
|
||||||
CloseErr shadow.Value
|
CloseErr shadow.Value
|
||||||
Input shadow.Value
|
Input shadow.Value
|
||||||
|
Validate shadow.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) CloseShadow() error {
|
func (p *shadowResourceProviderShadow) CloseShadow() error {
|
||||||
|
@ -160,16 +172,41 @@ func (p *shadowResourceProviderShadow) Input(
|
||||||
return result.Result, result.ResultErr
|
return result.Result, result.ResultErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) Validate(c *ResourceConfig) ([]string, []error) {
|
func (p *shadowResourceProviderShadow) Validate(c *ResourceConfig) ([]string, []error) {
|
||||||
|
// Get the result of the validate call
|
||||||
|
raw := p.Shared.Validate.Value()
|
||||||
|
if raw == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result, ok := raw.(*shadowResourceProviderValidate)
|
||||||
|
if !ok {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
defer p.ErrorLock.Unlock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Unknown 'validate' shadow value: %#v", raw))
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the parameters, which should be identical
|
||||||
|
if !c.Equal(result.Config) {
|
||||||
|
p.ErrorLock.Lock()
|
||||||
|
p.Error = multierror.Append(p.Error, fmt.Errorf(
|
||||||
|
"Validate had unequal configurations (real, then shadow):\n\n%#v\n\n%#v",
|
||||||
|
result.Config, c))
|
||||||
|
p.ErrorLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the results
|
||||||
|
return result.ResultWarn, result.ResultErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// TODO
|
||||||
|
// TODO
|
||||||
|
// TODO
|
||||||
|
// TODO
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) ValidateResource(t string, c *ResourceConfig) ([]string, []error) {
|
func (p *shadowResourceProviderShadow) ValidateResource(t string, c *ResourceConfig) ([]string, []error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -226,3 +263,9 @@ type shadowResourceProviderInput struct {
|
||||||
Result *ResourceConfig
|
Result *ResourceConfig
|
||||||
ResultErr error
|
ResultErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type shadowResourceProviderValidate struct {
|
||||||
|
Config *ResourceConfig
|
||||||
|
ResultWarn []string
|
||||||
|
ResultErr []error
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package terraform
|
package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -113,3 +114,83 @@ func TestShadowResourceProviderInput_badInput(t *testing.T) {
|
||||||
t.Fatal("should have error")
|
t.Fatal("should have error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShadowResourceProviderValidate(t *testing.T) {
|
||||||
|
mock := new(MockResourceProvider)
|
||||||
|
real, shadow := newShadowResourceProvider(mock)
|
||||||
|
|
||||||
|
// Test values
|
||||||
|
config := testResourceConfig(t, map[string]interface{}{
|
||||||
|
"foo": "bar",
|
||||||
|
})
|
||||||
|
returnWarns := []string{"foo"}
|
||||||
|
returnErrs := []error{fmt.Errorf("bar")}
|
||||||
|
|
||||||
|
// Configure the mock
|
||||||
|
mock.ValidateReturnWarns = returnWarns
|
||||||
|
mock.ValidateReturnErrors = returnErrs
|
||||||
|
|
||||||
|
// Verify that it blocks until the real func is called
|
||||||
|
var warns []string
|
||||||
|
var errs []error
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(doneCh)
|
||||||
|
warns, errs = shadow.Validate(config)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-doneCh:
|
||||||
|
t.Fatal("should block until finished")
|
||||||
|
case <-time.After(10 * time.Millisecond):
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the real func
|
||||||
|
realWarns, realErrs := real.Validate(config)
|
||||||
|
if !reflect.DeepEqual(realWarns, returnWarns) {
|
||||||
|
t.Fatalf("bad: %#v", realWarns)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(realErrs, returnErrs) {
|
||||||
|
t.Fatalf("bad: %#v", realWarns)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The shadow should finish now
|
||||||
|
<-doneCh
|
||||||
|
|
||||||
|
// Verify the shadow returned the same values
|
||||||
|
if !reflect.DeepEqual(warns, returnWarns) {
|
||||||
|
t.Fatalf("bad: %#v", warns)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(errs, returnErrs) {
|
||||||
|
t.Fatalf("bad: %#v", errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we have no errors
|
||||||
|
if err := shadow.CloseShadow(); err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShadowResourceProviderValidate_badInput(t *testing.T) {
|
||||||
|
mock := new(MockResourceProvider)
|
||||||
|
real, shadow := newShadowResourceProvider(mock)
|
||||||
|
|
||||||
|
// Test values
|
||||||
|
config := testResourceConfig(t, map[string]interface{}{
|
||||||
|
"foo": "bar",
|
||||||
|
})
|
||||||
|
configBad := testResourceConfig(t, map[string]interface{}{
|
||||||
|
"foo": "nope",
|
||||||
|
})
|
||||||
|
|
||||||
|
// Call the real with one
|
||||||
|
real.Validate(config)
|
||||||
|
|
||||||
|
// Call the shadow with another
|
||||||
|
shadow.Validate(configBad)
|
||||||
|
|
||||||
|
// Verify we have an error
|
||||||
|
if err := shadow.CloseShadow(); err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue