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.
|
||||
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
|
||||
diff *Diff
|
||||
diffLock sync.RWMutex
|
||||
|
|
|
@ -2,6 +2,8 @@ package terraform
|
|||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/mitchellh/copystructure"
|
||||
)
|
||||
|
||||
// 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
|
||||
// copied, no real providers or resources are used, etc.
|
||||
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