terraform: provider inheritence is functional
This commit is contained in:
parent
8dbc7e0ccb
commit
1f1563c95b
|
@ -913,6 +913,37 @@ func (c *walkContext) genericWalkFn(cb genericWalkFunc) depgraph.WalkFunc {
|
|||
raw = sharedProvider.Config.RawConfig
|
||||
}
|
||||
|
||||
// If we have a parent, then merge in the parent configurations
|
||||
// properly so we "inherit" the configurations.
|
||||
if sharedProvider.Parent != nil {
|
||||
var rawMap map[string]interface{}
|
||||
if raw != nil {
|
||||
rawMap = raw.Raw
|
||||
}
|
||||
|
||||
parent := sharedProvider.Parent
|
||||
for parent != nil {
|
||||
if parent.Config != nil {
|
||||
if rawMap == nil {
|
||||
rawMap = parent.Config.RawConfig.Raw
|
||||
}
|
||||
|
||||
for k, v := range parent.Config.RawConfig.Config() {
|
||||
rawMap[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
parent = parent.Parent
|
||||
}
|
||||
|
||||
// Update our configuration to be the merged result
|
||||
var err error
|
||||
raw, err = config.NewRawConfig(rawMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error merging configurations: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
rc := NewResourceConfig(raw)
|
||||
rc.interpolate(c)
|
||||
|
||||
|
|
|
@ -1592,10 +1592,7 @@ func TestContextPlan_moduleOrphans(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestContextPlan_moduleProviderInherit(t *testing.T) {
|
||||
t.Skip()
|
||||
|
||||
var l sync.Mutex
|
||||
var ps []*MockResourceProvider
|
||||
var calls []string
|
||||
|
||||
m := testModule(t, "plan-module-provider-inherit")
|
||||
|
@ -1622,7 +1619,6 @@ func TestContextPlan_moduleProviderInherit(t *testing.T) {
|
|||
calls = append(calls, v.(string))
|
||||
return testDiffFn(info, state, c)
|
||||
}
|
||||
ps = append(ps, p)
|
||||
return p, nil
|
||||
},
|
||||
},
|
||||
|
@ -1633,10 +1629,6 @@ func TestContextPlan_moduleProviderInherit(t *testing.T) {
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if len(ps) != 2 {
|
||||
t.Fatalf("bad: %#v", ps)
|
||||
}
|
||||
|
||||
actual := calls
|
||||
sort.Strings(actual)
|
||||
expected := []string{"child", "root"}
|
||||
|
|
|
@ -68,6 +68,9 @@ type GraphOpts struct {
|
|||
// graph. This node is just a placemarker and has no associated functionality.
|
||||
const GraphRootNode = "root"
|
||||
|
||||
// GraphMeta is the metadata attached to the graph itself.
|
||||
type GraphMeta struct{}
|
||||
|
||||
// GraphNodeModule is a node type in the graph that represents a module
|
||||
// that will be created/managed.
|
||||
type GraphNodeModule struct {
|
||||
|
@ -111,6 +114,9 @@ type graphSharedProvider struct {
|
|||
Config *config.ProviderConfig
|
||||
Providers map[string]ResourceProvider
|
||||
ProviderKeys []string
|
||||
Parent *graphSharedProvider
|
||||
|
||||
parentNoun *depgraph.Noun
|
||||
}
|
||||
|
||||
// Graph builds a dependency graph of all the resources for infrastructure
|
||||
|
@ -165,6 +171,7 @@ func Graph(opts *GraphOpts) (*depgraph.Graph, error) {
|
|||
log.Printf("[DEBUG] Creating graph for path: %v", opts.ModulePath)
|
||||
|
||||
g := new(depgraph.Graph)
|
||||
g.Meta = new(GraphMeta)
|
||||
|
||||
// First, build the initial resource graph. This only has the resources
|
||||
// and no dependencies. This only adds resources that are in the config
|
||||
|
@ -791,6 +798,42 @@ func graphAddOrphans(g *depgraph.Graph, c *config.Config, mod *ModuleState) {
|
|||
// graphAddParentProviderConfigs goes through and adds/merges provider
|
||||
// configurations from the parent.
|
||||
func graphAddParentProviderConfigs(g, parent *depgraph.Graph) {
|
||||
var nounsList []*depgraph.Noun
|
||||
for _, n := range parent.Nouns {
|
||||
pn, ok := n.Meta.(*GraphNodeResourceProvider)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have a provider configuration with the exact same
|
||||
// name, then set specify the parent pointer to their shared
|
||||
// config.
|
||||
ourProviderRaw := g.Noun(n.Name)
|
||||
|
||||
// If we don't have a matching configuration, then create one.
|
||||
if ourProviderRaw == nil {
|
||||
noun := &depgraph.Noun{
|
||||
Name: n.Name,
|
||||
Meta: &GraphNodeResourceProvider{
|
||||
ID: pn.ID,
|
||||
Provider: &graphSharedProvider{
|
||||
Parent: pn.Provider,
|
||||
parentNoun: n,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
nounsList = append(nounsList, noun)
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have a matching configuration, then set the parent pointer
|
||||
ourProvider := ourProviderRaw.Meta.(*GraphNodeResourceProvider)
|
||||
ourProvider.Provider.Parent = pn.Provider
|
||||
ourProvider.Provider.parentNoun = n
|
||||
}
|
||||
|
||||
g.Nouns = append(g.Nouns, nounsList...)
|
||||
}
|
||||
|
||||
// graphAddConfigProviderConfigs adds a GraphNodeResourceProvider for every
|
||||
|
@ -1093,6 +1136,26 @@ func graphInitResourceProviders(
|
|||
func graphAddResourceProviderDeps(g *depgraph.Graph) {
|
||||
for _, rawN := range g.Nouns {
|
||||
switch n := rawN.Meta.(type) {
|
||||
case *GraphNodeModule:
|
||||
// Check if the module depends on any of our providers
|
||||
// by seeing if there is a parent node back.
|
||||
for _, moduleRaw := range n.Graph.Nouns {
|
||||
pn, ok := moduleRaw.Meta.(*GraphNodeResourceProvider)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if pn.Provider.parentNoun == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create the dependency to the provider
|
||||
dep := &depgraph.Dependency{
|
||||
Name: pn.Provider.parentNoun.Name,
|
||||
Source: rawN,
|
||||
Target: pn.Provider.parentNoun,
|
||||
}
|
||||
rawN.Deps = append(rawN.Deps, dep)
|
||||
}
|
||||
case *GraphNodeResource:
|
||||
// Not sure how this would happen, but we might as well
|
||||
// check for it.
|
||||
|
|
|
@ -868,6 +868,7 @@ aws_security_group.firewall
|
|||
aws_security_group.firewall -> provider.aws
|
||||
module.consul
|
||||
module.consul -> aws_security_group.firewall
|
||||
module.consul -> provider.aws
|
||||
provider.aws
|
||||
root
|
||||
root -> aws_instance.web
|
||||
|
@ -878,6 +879,8 @@ root
|
|||
const testTerraformGraphModulesConsulStr = `
|
||||
root: root
|
||||
aws_instance.server
|
||||
aws_instance.server -> provider.aws
|
||||
provider.aws
|
||||
root
|
||||
root -> aws_instance.server
|
||||
`
|
||||
|
@ -890,6 +893,7 @@ aws_instance.web
|
|||
aws_security_group.firewall
|
||||
aws_security_group.firewall -> provider.aws
|
||||
module.consul
|
||||
module.consul -> provider.aws
|
||||
provider.aws
|
||||
root
|
||||
root -> aws_instance.web
|
||||
|
@ -900,6 +904,8 @@ root
|
|||
const testTerraformGraphModuleOrphanConsulStr = `
|
||||
root: root
|
||||
aws_instance.old
|
||||
aws_instance.old -> provider.aws
|
||||
provider.aws
|
||||
root
|
||||
root -> aws_instance.old
|
||||
`
|
||||
|
|
Loading…
Reference in New Issue