From f24a1533f25a51e3cc5396df7ef26050f5373d5b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 1 May 2015 11:38:36 -0700 Subject: [PATCH] terraform: GraphNodeProxy --- terraform/transform_proxy.go | 55 +++++++++++++++++++++++++++++++ terraform/transform_proxy_test.go | 52 +++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 terraform/transform_proxy.go create mode 100644 terraform/transform_proxy_test.go diff --git a/terraform/transform_proxy.go b/terraform/transform_proxy.go new file mode 100644 index 0000000000..aed50ba818 --- /dev/null +++ b/terraform/transform_proxy.go @@ -0,0 +1,55 @@ +package terraform + +import ( + "github.com/hashicorp/terraform/dag" +) + +// GraphNodeProxy must be implemented by nodes that are proxies. +// +// A node that is a proxy says that anything that depends on this +// node (the proxy), should also copy all the things that the proxy +// itself depends on. Example: +// +// A => proxy => C +// +// Should transform into (two edges): +// +// A => proxy => C +// A => C +// +// The purpose for this is because some transforms only look at direct +// edge connections and the proxy generally isn't meaningful in those +// situations, so we should complete all the edges. +type GraphNodeProxy interface { + Proxy() bool +} + +// ProxyTransformer is a transformer that goes through the graph, finds +// vertices that are marked as proxies, and connects through their +// dependents. See above for what a proxy is. +type ProxyTransformer struct{} + +func (t *ProxyTransformer) Transform(g *Graph) error { + for _, v := range g.Vertices() { + pn, ok := v.(GraphNodeProxy) + if !ok { + continue + } + + // If we don't want to be proxies, don't do it + if !pn.Proxy() { + continue + } + + // Connect all the things that depend on this to things that + // we depend on as the proxy. See docs for GraphNodeProxy for + // a visual explanation. + for _, s := range g.UpEdges(v).List() { + for _, t := range g.DownEdges(v).List() { + g.Connect(dag.BasicEdge(s, t)) + } + } + } + + return nil +} diff --git a/terraform/transform_proxy_test.go b/terraform/transform_proxy_test.go new file mode 100644 index 0000000000..dc1b2cfbbf --- /dev/null +++ b/terraform/transform_proxy_test.go @@ -0,0 +1,52 @@ +package terraform + +import ( + "strings" + "testing" + + "github.com/hashicorp/terraform/dag" +) + +func TestProxyTransformer(t *testing.T) { + var g Graph + proxy := &testNodeProxy{NameValue: "proxy"} + g.Add("A") + g.Add("C") + g.Add(proxy) + g.Connect(dag.BasicEdge("A", proxy)) + g.Connect(dag.BasicEdge(proxy, "C")) + + { + tf := &ProxyTransformer{} + if err := tf.Transform(&g); err != nil { + t.Fatalf("err: %s", err) + } + } + + actual := strings.TrimSpace(g.String()) + expected := strings.TrimSpace(testProxyTransformStr) + if actual != expected { + t.Fatalf("bad: %s", actual) + } +} + +type testNodeProxy struct { + NameValue string +} + +func (n *testNodeProxy) Name() string { + return n.NameValue +} + +func (n *testNodeProxy) Proxy() bool { + return true +} + +const testProxyTransformStr = ` +A + C + proxy +C +proxy + C +`