terraform: provider input should be scoped by path
The provider input before wasn't scoped by path, which caused non-descendant parts of the graph to grab the configuration of another sub-tree. The result is that you'd often get copied provider configurations across the module barriers. See GH-2024
This commit is contained in:
parent
cddd54c3de
commit
d0519f226d
|
@ -168,14 +168,32 @@ func (ctx *BuiltinEvalContext) ProviderInput(n string) map[string]interface{} {
|
||||||
ctx.ProviderLock.Lock()
|
ctx.ProviderLock.Lock()
|
||||||
defer ctx.ProviderLock.Unlock()
|
defer ctx.ProviderLock.Unlock()
|
||||||
|
|
||||||
return ctx.ProviderInputConfig[n]
|
// Make a copy of the path so we can safely edit it
|
||||||
|
path := ctx.Path()
|
||||||
|
pathCopy := make([]string, len(path)+1)
|
||||||
|
copy(pathCopy, path)
|
||||||
|
|
||||||
|
// Go up the tree.
|
||||||
|
for i := len(path) - 1; i >= 0; i-- {
|
||||||
|
pathCopy[i+1] = n
|
||||||
|
k := PathCacheKey(pathCopy[:i+2])
|
||||||
|
if v, ok := ctx.ProviderInputConfig[k]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) SetProviderInput(n string, c map[string]interface{}) {
|
func (ctx *BuiltinEvalContext) SetProviderInput(n string, c map[string]interface{}) {
|
||||||
ctx.ProviderLock.Lock()
|
providerPath := make([]string, len(ctx.Path())+1)
|
||||||
defer ctx.ProviderLock.Unlock()
|
copy(providerPath, ctx.Path())
|
||||||
|
providerPath[len(providerPath)-1] = n
|
||||||
|
|
||||||
ctx.ProviderInputConfig[n] = c
|
// Save the configuration
|
||||||
|
ctx.ProviderLock.Lock()
|
||||||
|
ctx.ProviderInputConfig[PathCacheKey(providerPath)] = c
|
||||||
|
ctx.ProviderLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *BuiltinEvalContext) ParentProviderConfig(n string) *ResourceConfig {
|
func (ctx *BuiltinEvalContext) ParentProviderConfig(n string) *ResourceConfig {
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuiltinEvalContextProviderInput(t *testing.T) {
|
||||||
|
var lock sync.Mutex
|
||||||
|
cache := make(map[string]map[string]interface{})
|
||||||
|
|
||||||
|
ctx1 := testBuiltinEvalContext(t)
|
||||||
|
ctx1.PathValue = []string{"root"}
|
||||||
|
ctx1.ProviderInputConfig = cache
|
||||||
|
ctx1.ProviderLock = &lock
|
||||||
|
|
||||||
|
ctx2 := testBuiltinEvalContext(t)
|
||||||
|
ctx2.PathValue = []string{"root", "child"}
|
||||||
|
ctx2.ProviderInputConfig = cache
|
||||||
|
ctx2.ProviderLock = &lock
|
||||||
|
|
||||||
|
expected1 := map[string]interface{}{"value": "foo"}
|
||||||
|
ctx1.SetProviderInput("foo", expected1)
|
||||||
|
|
||||||
|
expected2 := map[string]interface{}{"value": "bar"}
|
||||||
|
ctx2.SetProviderInput("foo", expected2)
|
||||||
|
|
||||||
|
actual1 := ctx1.ProviderInput("foo")
|
||||||
|
actual2 := ctx2.ProviderInput("foo")
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual1, expected1) {
|
||||||
|
t.Fatalf("bad: %#v %#v", actual1, expected1)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(actual2, expected2) {
|
||||||
|
t.Fatalf("bad: %#v %#v", actual2, expected2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBuiltinEvalContext(t *testing.T) *BuiltinEvalContext {
|
||||||
|
return &BuiltinEvalContext{}
|
||||||
|
}
|
Loading…
Reference in New Issue