terraform: shadow resource provider tests begin
This commit is contained in:
parent
d37bb87bf2
commit
bb5f116cec
|
@ -48,6 +48,9 @@ func newShadowResourceProvider(p ResourceProvider) (ResourceProvider, shadowReso
|
||||||
// Create the shadow that watches the real value
|
// Create the shadow that watches the real value
|
||||||
shadow := &shadowResourceProviderShadow{
|
shadow := &shadowResourceProviderShadow{
|
||||||
Shared: &shared,
|
Shared: &shared,
|
||||||
|
|
||||||
|
resources: p.Resources(),
|
||||||
|
dataSources: p.DataSources(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return real, shadow
|
return real, shadow
|
||||||
|
@ -62,18 +65,6 @@ type shadowResourceProviderReal struct {
|
||||||
Shared *shadowResourceProviderShared
|
Shared *shadowResourceProviderShared
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderReal) Resources() []ResourceType {
|
|
||||||
result := p.ResourceProvider.Resources()
|
|
||||||
p.Shared.Resources.SetValue(result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *shadowResourceProviderReal) DataSources() []DataSource {
|
|
||||||
result := p.ResourceProvider.DataSources()
|
|
||||||
p.Shared.DataSources.SetValue(result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *shadowResourceProviderReal) Close() error {
|
func (p *shadowResourceProviderReal) Close() error {
|
||||||
var result error
|
var result error
|
||||||
if c, ok := p.ResourceProvider.(ResourceProviderCloser); ok {
|
if c, ok := p.ResourceProvider.(ResourceProviderCloser); ok {
|
||||||
|
@ -88,8 +79,8 @@ func (p *shadowResourceProviderReal) Input(
|
||||||
input UIInput, c *ResourceConfig) (*ResourceConfig, error) {
|
input UIInput, c *ResourceConfig) (*ResourceConfig, error) {
|
||||||
result, err := p.ResourceProvider.Input(input, c)
|
result, err := p.ResourceProvider.Input(input, c)
|
||||||
p.Shared.Input.SetValue(&shadowResourceProviderInput{
|
p.Shared.Input.SetValue(&shadowResourceProviderInput{
|
||||||
Config: c,
|
Config: c.DeepCopy(),
|
||||||
Result: result,
|
Result: result.DeepCopy(),
|
||||||
ResultErr: err,
|
ResultErr: err,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -102,35 +93,32 @@ func (p *shadowResourceProviderReal) Input(
|
||||||
type shadowResourceProviderShadow struct {
|
type shadowResourceProviderShadow struct {
|
||||||
Shared *shadowResourceProviderShared
|
Shared *shadowResourceProviderShared
|
||||||
|
|
||||||
|
// Cached values that are expected to not change
|
||||||
|
resources []ResourceType
|
||||||
|
dataSources []DataSource
|
||||||
|
|
||||||
Error error // Error is the list of errors from the shadow
|
Error error // Error is the list of errors from the shadow
|
||||||
ErrorLock sync.Mutex
|
ErrorLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
type shadowResourceProviderShared struct {
|
type shadowResourceProviderShared struct {
|
||||||
CloseErr shadow.Value
|
CloseErr shadow.Value
|
||||||
Input shadow.Value
|
Input shadow.Value
|
||||||
Resources shadow.Value
|
|
||||||
DataSources shadow.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) CloseShadow() error { return nil }
|
func (p *shadowResourceProviderShadow) CloseShadow() error {
|
||||||
|
// For now, just return the error. What we need to do in the future
|
||||||
|
// is marked the provider as "closed" so that any subsequent calls
|
||||||
|
// will fail out.
|
||||||
|
return p.Error
|
||||||
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) Resources() []ResourceType {
|
func (p *shadowResourceProviderShadow) Resources() []ResourceType {
|
||||||
v := p.Shared.Resources.Value()
|
return p.resources
|
||||||
if v == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.([]ResourceType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) DataSources() []DataSource {
|
func (p *shadowResourceProviderShadow) DataSources() []DataSource {
|
||||||
v := p.Shared.DataSources.Value()
|
return p.dataSources
|
||||||
if v == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.([]DataSource)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *shadowResourceProviderShadow) Close() error {
|
func (p *shadowResourceProviderShadow) Close() error {
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShadowResourceProvider_cachedValues(t *testing.T) {
|
||||||
|
mock := new(MockResourceProvider)
|
||||||
|
real, shadow := newShadowResourceProvider(mock)
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
{
|
||||||
|
actual := shadow.Resources()
|
||||||
|
expected := real.Resources()
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Fatalf("bad:\n\n%#v\n\n%#v", actual, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataSources
|
||||||
|
{
|
||||||
|
actual := shadow.DataSources()
|
||||||
|
expected := real.DataSources()
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Fatalf("bad:\n\n%#v\n\n%#v", actual, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShadowResourceProviderInput(t *testing.T) {
|
||||||
|
mock := new(MockResourceProvider)
|
||||||
|
real, shadow := newShadowResourceProvider(mock)
|
||||||
|
|
||||||
|
// Test values
|
||||||
|
ui := new(MockUIInput)
|
||||||
|
config := testResourceConfig(t, map[string]interface{}{
|
||||||
|
"foo": "bar",
|
||||||
|
})
|
||||||
|
returnConfig := testResourceConfig(t, map[string]interface{}{
|
||||||
|
"bar": "baz",
|
||||||
|
})
|
||||||
|
|
||||||
|
// Configure the mock
|
||||||
|
mock.InputReturnConfig = returnConfig
|
||||||
|
|
||||||
|
// Verify that it blocks until the real input is called
|
||||||
|
var actual *ResourceConfig
|
||||||
|
var err error
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(doneCh)
|
||||||
|
actual, err = shadow.Input(ui, config)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-doneCh:
|
||||||
|
t.Fatal("should block until finished")
|
||||||
|
case <-time.After(10 * time.Millisecond):
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the real input
|
||||||
|
realResult, realErr := real.Input(ui, config)
|
||||||
|
if !realResult.Equal(returnConfig) {
|
||||||
|
t.Fatalf("bad: %#v", realResult)
|
||||||
|
}
|
||||||
|
if realErr != nil {
|
||||||
|
t.Fatalf("bad: %s", realErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The shadow should finish now
|
||||||
|
<-doneCh
|
||||||
|
|
||||||
|
// Verify the shadow returned the same values
|
||||||
|
if !actual.Equal(returnConfig) {
|
||||||
|
t.Fatalf("bad: %#v", actual)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we have no errors
|
||||||
|
if err := shadow.CloseShadow(); err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShadowResourceProviderInput_badInput(t *testing.T) {
|
||||||
|
mock := new(MockResourceProvider)
|
||||||
|
real, shadow := newShadowResourceProvider(mock)
|
||||||
|
|
||||||
|
// Test values
|
||||||
|
ui := new(MockUIInput)
|
||||||
|
config := testResourceConfig(t, map[string]interface{}{
|
||||||
|
"foo": "bar",
|
||||||
|
})
|
||||||
|
configBad := testResourceConfig(t, map[string]interface{}{
|
||||||
|
"foo": "nope",
|
||||||
|
})
|
||||||
|
|
||||||
|
// Call the real with one
|
||||||
|
real.Input(ui, config)
|
||||||
|
|
||||||
|
// Call the shadow with another
|
||||||
|
_, err := shadow.Input(ui, configBad)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify we have an error
|
||||||
|
if err := shadow.CloseShadow(); err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue