terraform: GraphVertexTransformers
This commit is contained in:
parent
af8d33ddb8
commit
4d205ebcf6
|
@ -1,7 +1,21 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// GraphTransformer is the interface that transformers implement. This
|
||||
// interface is only for transforms that need entire graph visibility.
|
||||
type GraphTransformer interface {
|
||||
Transform(*Graph) error
|
||||
}
|
||||
|
||||
// GraphVertexTransformer is an interface that transforms a single
|
||||
// Vertex within with graph. This is a specialization of GraphTransformer
|
||||
// that makes it easy to do vertex replacement.
|
||||
//
|
||||
// The GraphTransformer that runs through the GraphVertexTransformers is
|
||||
// VertexTransformer.
|
||||
type GraphVertexTransformer interface {
|
||||
Transform(dag.Vertex) (dag.Vertex, error)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
// VertexTransformer is a GraphTransformer that transforms vertices
|
||||
// using the GraphVertexTransformers. The Transforms are run in sequential
|
||||
// order. If a transform replaces a vertex then the next transform will see
|
||||
// the new vertex.
|
||||
type VertexTransformer struct {
|
||||
Transforms []GraphVertexTransformer
|
||||
}
|
||||
|
||||
func (t *VertexTransformer) Transform(g *Graph) error {
|
||||
for _, v := range g.Vertices() {
|
||||
for _, vt := range t.Transforms {
|
||||
newV, err := vt.Transform(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the vertex didn't change, then don't do anything more
|
||||
if newV == v {
|
||||
continue
|
||||
}
|
||||
|
||||
// Vertex changed, replace it within the graph
|
||||
if ok := g.Replace(v, newV); !ok {
|
||||
// This should never happen, big problem
|
||||
return fmt.Errorf(
|
||||
"Failed to replace %s with %s!\n\nSource: %#v\n\nTarget: %#v",
|
||||
dag.VertexName(v), dag.VertexName(newV), v, newV)
|
||||
}
|
||||
|
||||
// Replace v so that future transforms use the proper vertex
|
||||
v = newV
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package terraform
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/dag"
|
||||
)
|
||||
|
||||
func TestVertexTransformer_impl(t *testing.T) {
|
||||
var _ GraphTransformer = new(VertexTransformer)
|
||||
}
|
||||
|
||||
func TestVertexTransformer(t *testing.T) {
|
||||
var g Graph
|
||||
g.Add(1)
|
||||
g.Add(2)
|
||||
g.Add(3)
|
||||
g.Connect(dag.BasicEdge(1, 2))
|
||||
g.Connect(dag.BasicEdge(2, 3))
|
||||
|
||||
{
|
||||
tf := &VertexTransformer{
|
||||
Transforms: []GraphVertexTransformer{
|
||||
&testVertexTransform{Source: 2, Target: 42},
|
||||
},
|
||||
}
|
||||
if err := tf.Transform(&g); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
actual := strings.TrimSpace(g.String())
|
||||
expected := strings.TrimSpace(testVertexTransformerStr)
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
type testVertexTransform struct {
|
||||
Source, Target dag.Vertex
|
||||
}
|
||||
|
||||
func (t *testVertexTransform) Transform(v dag.Vertex) (dag.Vertex, error) {
|
||||
if t.Source == v {
|
||||
v = t.Target
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
const testVertexTransformerStr = `
|
||||
1
|
||||
42
|
||||
3
|
||||
42
|
||||
3
|
||||
`
|
Loading…
Reference in New Issue