terraform: GraphNodeDependent
This commit is contained in:
parent
8dc4c56b2e
commit
8bf725e746
|
@ -51,15 +51,21 @@ func (g *Graph) Add(v dag.Vertex) dag.Vertex {
|
|||
return v
|
||||
}
|
||||
|
||||
// ConnectTo is a helper to create edges between a node and a list of
|
||||
// targets by their DependableNames.
|
||||
func (g *Graph) ConnectTo(source dag.Vertex, target []string) []string {
|
||||
// ConnectDependent connects a GraphNodeDependent to all of its
|
||||
// GraphNodeDependables. It returns the list of dependents it was
|
||||
// unable to connect to.
|
||||
func (g *Graph) ConnectDependent(raw dag.Vertex) []string {
|
||||
g.once.Do(g.init)
|
||||
|
||||
v, ok := raw.(GraphNodeDependent)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var missing []string
|
||||
for _, t := range target {
|
||||
for _, t := range v.DependentOn() {
|
||||
if dest := g.dependableMap[t]; dest != nil {
|
||||
g.Connect(dag.BasicEdge(source, dest))
|
||||
g.Connect(dag.BasicEdge(v, dest))
|
||||
} else {
|
||||
missing = append(missing, t)
|
||||
}
|
||||
|
@ -68,6 +74,20 @@ func (g *Graph) ConnectTo(source dag.Vertex, target []string) []string {
|
|||
return missing
|
||||
}
|
||||
|
||||
// ConnectDependents goes through the graph, connecting all the
|
||||
// GraphNodeDependents to GraphNodeDependables. This is safe to call
|
||||
// multiple times.
|
||||
//
|
||||
// To get details on whether dependencies could be found/made, the more
|
||||
// specific ConnectDependent should be used.
|
||||
func (g *Graph) ConnectDependents() {
|
||||
for _, v := range g.Vertices() {
|
||||
if dv, ok := v.(GraphNodeDependent); ok {
|
||||
g.ConnectDependent(dv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) init() {
|
||||
if g.Graph == nil {
|
||||
g.Graph = new(dag.Graph)
|
||||
|
@ -86,3 +106,11 @@ func (g *Graph) init() {
|
|||
type GraphNodeDependable interface {
|
||||
DependableName() []string
|
||||
}
|
||||
|
||||
// GraphNodeDependent is an interface which says that a node depends
|
||||
// on another GraphNodeDependable by some name. By implementing this
|
||||
// interface, Graph.ConnectDependents() can be called multiple times
|
||||
// safely and efficiently.
|
||||
type GraphNodeDependent interface {
|
||||
DependentOn() []string
|
||||
}
|
||||
|
|
|
@ -14,10 +14,10 @@ import (
|
|||
type graphNodeConfig interface {
|
||||
dag.NamedVertex
|
||||
|
||||
// Variables returns the full list of variables that this node
|
||||
// depends on. The values within the slice should map to the VarName()
|
||||
// values that are returned by any nodes.
|
||||
Variables() []string
|
||||
// All graph nodes should be dependent on other things, and able to
|
||||
// be depended on.
|
||||
GraphNodeDependable
|
||||
GraphNodeDependent
|
||||
}
|
||||
|
||||
// GraphNodeConfigModule represents a module within the configuration graph.
|
||||
|
@ -29,20 +29,23 @@ type GraphNodeConfigModule struct {
|
|||
func (n *GraphNodeConfigModule) DependableName() []string {
|
||||
return []string{n.Name()}
|
||||
}
|
||||
func (n *GraphNodeConfigModule) Name() string {
|
||||
return fmt.Sprintf("module.%s", n.Module.Name)
|
||||
}
|
||||
|
||||
func (n *GraphNodeConfigModule) Variables() []string {
|
||||
func (n *GraphNodeConfigModule) DependentOn() []string {
|
||||
vars := n.Module.RawConfig.Variables
|
||||
result := make([]string, 0, len(vars))
|
||||
for _, v := range vars {
|
||||
result = append(result, varNameForVar(v))
|
||||
if vn := varNameForVar(v); vn != "" {
|
||||
result = append(result, vn)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (n *GraphNodeConfigModule) Name() string {
|
||||
return fmt.Sprintf("module.%s", n.Module.Name)
|
||||
}
|
||||
|
||||
// GraphNodeConfigProvider represents a configured provider within the
|
||||
// configuration graph. These are only immediately in the graph when an
|
||||
// explicit `provider` configuration block is in the configuration.
|
||||
|
@ -54,11 +57,17 @@ func (n *GraphNodeConfigProvider) Name() string {
|
|||
return fmt.Sprintf("provider.%s", n.Provider.Name)
|
||||
}
|
||||
|
||||
func (n *GraphNodeConfigProvider) Variables() []string {
|
||||
func (n *GraphNodeConfigProvider) DependableName() []string {
|
||||
return []string{n.Name()}
|
||||
}
|
||||
|
||||
func (n *GraphNodeConfigProvider) DependentOn() []string {
|
||||
vars := n.Provider.RawConfig.Variables
|
||||
result := make([]string, 0, len(vars))
|
||||
for _, v := range vars {
|
||||
result = append(result, varNameForVar(v))
|
||||
if vn := varNameForVar(v); vn != "" {
|
||||
result = append(result, vn)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
|
@ -73,22 +82,26 @@ func (n *GraphNodeConfigResource) DependableName() []string {
|
|||
return []string{n.Resource.Id()}
|
||||
}
|
||||
|
||||
func (n *GraphNodeConfigResource) Name() string {
|
||||
return n.Resource.Id()
|
||||
}
|
||||
|
||||
func (n *GraphNodeConfigResource) Variables() []string {
|
||||
func (n *GraphNodeConfigResource) DependentOn() []string {
|
||||
result := make([]string, len(n.Resource.DependsOn),
|
||||
len(n.Resource.RawCount.Variables)+
|
||||
len(n.Resource.RawConfig.Variables)+
|
||||
len(n.Resource.DependsOn))
|
||||
copy(result, n.Resource.DependsOn)
|
||||
for _, v := range n.Resource.RawCount.Variables {
|
||||
result = append(result, varNameForVar(v))
|
||||
if vn := varNameForVar(v); vn != "" {
|
||||
result = append(result, vn)
|
||||
}
|
||||
}
|
||||
for _, v := range n.Resource.RawConfig.Variables {
|
||||
result = append(result, varNameForVar(v))
|
||||
if vn := varNameForVar(v); vn != "" {
|
||||
result = append(result, vn)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (n *GraphNodeConfigResource) Name() string {
|
||||
return n.Resource.Id()
|
||||
}
|
||||
|
|
|
@ -18,12 +18,15 @@ func TestGraphAdd(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGraphConnectTo(t *testing.T) {
|
||||
func TestGraphConnectDependent(t *testing.T) {
|
||||
var g Graph
|
||||
g.Add(&testGraphDependable{VertexName: "a", Mock: []string{"a"}})
|
||||
b := g.Add(&testGraphDependable{VertexName: "b"})
|
||||
b := g.Add(&testGraphDependable{
|
||||
VertexName: "b",
|
||||
DependentOnMock: []string{"a"},
|
||||
})
|
||||
|
||||
if missing := g.ConnectTo(b, []string{"a"}); len(missing) > 0 {
|
||||
if missing := g.ConnectDependent(b); len(missing) > 0 {
|
||||
t.Fatalf("bad: %#v", missing)
|
||||
}
|
||||
|
||||
|
@ -35,8 +38,9 @@ func TestGraphConnectTo(t *testing.T) {
|
|||
}
|
||||
|
||||
type testGraphDependable struct {
|
||||
VertexName string
|
||||
Mock []string
|
||||
VertexName string
|
||||
DependentOnMock []string
|
||||
Mock []string
|
||||
}
|
||||
|
||||
func (v *testGraphDependable) Name() string {
|
||||
|
@ -47,6 +51,10 @@ func (v *testGraphDependable) DependableName() []string {
|
|||
return v.Mock
|
||||
}
|
||||
|
||||
func (v *testGraphDependable) DependentOn() []string {
|
||||
return v.DependentOnMock
|
||||
}
|
||||
|
||||
const testGraphAddStr = `
|
||||
42
|
||||
84
|
||||
|
|
|
@ -63,14 +63,7 @@ func (t *ConfigTransformer) Transform(g *Graph) error {
|
|||
// Build up the dependencies. We have to do this outside of the above
|
||||
// loop since the nodes need to be in place for us to build the deps.
|
||||
for _, n := range nodes {
|
||||
vars := n.Variables()
|
||||
targets := make([]string, 0, len(vars))
|
||||
for _, t := range vars {
|
||||
if t != "" {
|
||||
targets = append(targets, t)
|
||||
}
|
||||
}
|
||||
if missing := g.ConnectTo(n, targets); len(missing) > 0 {
|
||||
if missing := g.ConnectDependent(n); len(missing) > 0 {
|
||||
for _, m := range missing {
|
||||
err = multierror.Append(err, fmt.Errorf(
|
||||
"%s: missing dependency: %s", n.Name(), m))
|
||||
|
|
|
@ -29,17 +29,21 @@ func (t *OrphanTransformer) Transform(g *Graph) error {
|
|||
resourceOrphans := state.Orphans(t.Config)
|
||||
resourceVertexes := make([]dag.Vertex, len(resourceOrphans))
|
||||
for i, k := range resourceOrphans {
|
||||
resourceVertexes[i] = g.Add(&graphNodeOrphanResource{ResourceName: k})
|
||||
resourceVertexes[i] = g.Add(&graphNodeOrphanResource{
|
||||
ResourceName: k,
|
||||
dependentOn: state.Resources[k].Dependencies,
|
||||
})
|
||||
}
|
||||
|
||||
// Go over each module orphan and add it to the graph. We store the
|
||||
// vertexes and states outside so that we can connect dependencies later.
|
||||
moduleOrphans := t.State.ModuleOrphans(g.Path, t.Config)
|
||||
moduleVertexes := make([]dag.Vertex, len(moduleOrphans))
|
||||
moduleStates := make([]*ModuleState, len(moduleVertexes))
|
||||
for i, path := range moduleOrphans {
|
||||
moduleVertexes[i] = g.Add(&graphNodeOrphanModule{Path: path})
|
||||
moduleStates[i] = t.State.ModuleByPath(path)
|
||||
moduleVertexes[i] = g.Add(&graphNodeOrphanModule{
|
||||
Path: path,
|
||||
dependentOn: t.State.ModuleByPath(path).Dependencies,
|
||||
})
|
||||
}
|
||||
|
||||
// Now do the dependencies. We do this _after_ adding all the orphan
|
||||
|
@ -47,13 +51,13 @@ func (t *OrphanTransformer) Transform(g *Graph) error {
|
|||
// depend on other orphans.
|
||||
|
||||
// Resource dependencies
|
||||
for i, v := range resourceVertexes {
|
||||
g.ConnectTo(v, state.Resources[resourceOrphans[i]].Dependencies)
|
||||
for _, v := range resourceVertexes {
|
||||
g.ConnectDependent(v)
|
||||
}
|
||||
|
||||
// Module dependencies
|
||||
for i, v := range moduleVertexes {
|
||||
g.ConnectTo(v, moduleStates[i].Dependencies)
|
||||
for _, v := range moduleVertexes {
|
||||
g.ConnectDependent(v)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -62,12 +66,18 @@ func (t *OrphanTransformer) Transform(g *Graph) error {
|
|||
// graphNodeOrphanModule is the graph vertex representing an orphan resource..
|
||||
type graphNodeOrphanModule struct {
|
||||
Path []string
|
||||
|
||||
dependentOn []string
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanModule) DependableName() []string {
|
||||
return []string{n.dependableName()}
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanModule) DependentOn() []string {
|
||||
return n.dependentOn
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanModule) Name() string {
|
||||
return fmt.Sprintf("%s (orphan)", n.dependableName())
|
||||
}
|
||||
|
@ -79,12 +89,18 @@ func (n *graphNodeOrphanModule) dependableName() string {
|
|||
// graphNodeOrphanResource is the graph vertex representing an orphan resource..
|
||||
type graphNodeOrphanResource struct {
|
||||
ResourceName string
|
||||
|
||||
dependentOn []string
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) DependableName() []string {
|
||||
return []string{n.dependableName()}
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) DependentOn() []string {
|
||||
return n.dependentOn
|
||||
}
|
||||
|
||||
func (n *graphNodeOrphanResource) Name() string {
|
||||
return fmt.Sprintf("%s (orphan)", n.ResourceName)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue