terraform: shadowResourceProviderFactory
This helper helps create the factory maps for the context.
This commit is contained in:
parent
f7134d95e4
commit
02e93f5920
|
@ -68,6 +68,10 @@ type ContextOpts struct {
|
||||||
//
|
//
|
||||||
// Extra functions on Context can be found in context_*.go files.
|
// Extra functions on Context can be found in context_*.go files.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
|
// Maintainer note: Anytime this struct is changed, please verify
|
||||||
|
// that newShadowContext still does the right thing. Tests should
|
||||||
|
// fail regardless but putting this note here as well.
|
||||||
|
|
||||||
destroy bool
|
destroy bool
|
||||||
diff *Diff
|
diff *Diff
|
||||||
diffLock sync.RWMutex
|
diffLock sync.RWMutex
|
||||||
|
|
|
@ -2,6 +2,8 @@ package terraform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/mitchellh/copystructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newShadowContext creates a new context that will shadow the given context
|
// newShadowContext creates a new context that will shadow the given context
|
||||||
|
@ -16,5 +18,40 @@ import (
|
||||||
// context) will NEVER affect the real context. All structures are deep
|
// context) will NEVER affect the real context. All structures are deep
|
||||||
// copied, no real providers or resources are used, etc.
|
// copied, no real providers or resources are used, etc.
|
||||||
func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
|
func newShadowContext(c *Context) (*Context, *Context, io.Closer) {
|
||||||
return c, nil, nil
|
// Copy the targets
|
||||||
|
targetRaw, err := copystructure.Config{Lock: true}.Copy(c.targets)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the variables
|
||||||
|
varRaw, err := copystructure.Config{Lock: true}.Copy(c.variables)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The factories
|
||||||
|
providerFactory := &shadowResourceProviderFactory{Original: c.providers}
|
||||||
|
|
||||||
|
// Create the shadow
|
||||||
|
shadow := &Context{
|
||||||
|
destroy: c.destroy,
|
||||||
|
diff: c.diff.DeepCopy(),
|
||||||
|
hooks: nil, // TODO: do we need to copy? stop hook?
|
||||||
|
module: c.module,
|
||||||
|
providers: providerFactory.ShadowMap(),
|
||||||
|
provisioners: nil, //TODO
|
||||||
|
state: c.state.DeepCopy(),
|
||||||
|
targets: targetRaw.([]string),
|
||||||
|
uiInput: nil, // TODO
|
||||||
|
variables: varRaw.(map[string]interface{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the real context. This is effectively just a copy of
|
||||||
|
// the context given except we need to modify some of the values
|
||||||
|
// to point to the real side of a shadow so the shadow can compare values.
|
||||||
|
real := *c
|
||||||
|
real.providers = providerFactory.RealMap()
|
||||||
|
|
||||||
|
return &real, shadow, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/shadow"
|
||||||
|
)
|
||||||
|
|
||||||
|
// shadowResourceProviderFactory is a helper that takes an actual, original
|
||||||
|
// map of ResourceProvider factories and provides methods to create mappings
|
||||||
|
// for shadowed resource providers.
|
||||||
|
type shadowResourceProviderFactory struct {
|
||||||
|
// Original is the original factory map
|
||||||
|
Original map[string]ResourceProviderFactory
|
||||||
|
|
||||||
|
shadows shadow.KeyedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
type shadowResourceProviderFactoryEntry struct {
|
||||||
|
Real ResourceProvider
|
||||||
|
Shadow shadowResourceProvider
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RealMap returns the factory map for the "real" side of the shadow. This
|
||||||
|
// is the side that does actual work.
|
||||||
|
// TODO: test
|
||||||
|
func (f *shadowResourceProviderFactory) RealMap() map[string]ResourceProviderFactory {
|
||||||
|
m := make(map[string]ResourceProviderFactory)
|
||||||
|
for k, _ := range f.Original {
|
||||||
|
m[k] = f.realFactory(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShadowMap returns the factory map for the "shadow" side of the shadow. This
|
||||||
|
// is the side that doesn't do any actual work but does compare results
|
||||||
|
// with the real side.
|
||||||
|
// TODO: test
|
||||||
|
func (f *shadowResourceProviderFactory) ShadowMap() map[string]ResourceProviderFactory {
|
||||||
|
m := make(map[string]ResourceProviderFactory)
|
||||||
|
for k, _ := range f.Original {
|
||||||
|
m[k] = f.shadowFactory(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *shadowResourceProviderFactory) realFactory(n string) ResourceProviderFactory {
|
||||||
|
return func() (ResourceProvider, error) {
|
||||||
|
// Get the original factory function
|
||||||
|
originalF, ok := f.Original[n]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("unknown provider initialized: %s", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the entry
|
||||||
|
var entry shadowResourceProviderFactoryEntry
|
||||||
|
|
||||||
|
// Initialize it
|
||||||
|
p, err := originalF()
|
||||||
|
if err != nil {
|
||||||
|
entry.Err = err
|
||||||
|
p = nil // Just to be sure
|
||||||
|
}
|
||||||
|
|
||||||
|
if p != nil {
|
||||||
|
// Create the shadow
|
||||||
|
real, shadow := newShadowResourceProvider(p)
|
||||||
|
entry.Real = real
|
||||||
|
entry.Shadow = shadow
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the value
|
||||||
|
f.shadows.SetValue(n, &entry)
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return entry.Real, entry.Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *shadowResourceProviderFactory) shadowFactory(n string) ResourceProviderFactory {
|
||||||
|
return func() (ResourceProvider, error) {
|
||||||
|
// Get the value
|
||||||
|
raw := f.shadows.Value(n)
|
||||||
|
if raw == nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Nil shadow value for provider %q. Please report this bug.",
|
||||||
|
n)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry, ok := raw.(*shadowResourceProviderFactoryEntry)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Unknown value for shadow provider: %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return entry.Shadow, entry.Err
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue