Skip to content

Instantly share code, notes, and snippets.

@wreulicke
Created February 13, 2023 00:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wreulicke/4c4007b3d1f03acfe7081e535b9573c2 to your computer and use it in GitHub Desktop.
Save wreulicke/4c4007b3d1f03acfe7081e535b9573c2 to your computer and use it in GitHub Desktop.
Collect unused datasources in terraform
package main
import (
"fmt"
"log"
"os"
"strings"
"github.com/awalterschulze/gographviz"
)
func render(graph *gographviz.Graph) error {
_, err := fmt.Println(graph.String())
return err
}
func read(path string) (*gographviz.Graph, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
graphAst, err := gographviz.ParseString(string(b))
if err != nil {
return nil, err
}
graph := gographviz.NewGraph()
return graph, gographviz.Analyse(graphAst, graph)
}
func collectTransitiveDeps(graph *gographviz.Graph, nodeName string, visited, transitive map[string]bool) {
if visited[nodeName] {
return
}
_, found := graph.Nodes.Lookup[nodeName]
if found {
visited[nodeName] = true
transitive[nodeName] = true
edges := graph.Edges.SrcToDsts[nodeName]
for dst := range edges {
collectTransitiveDeps(graph, dst, visited, transitive)
}
}
}
func collectDeps(graph *gographviz.Graph) {
transitiveDepsToDatasource := map[string]bool{}
visited := map[string]bool{}
edges := graph.Edges.Sorted()
for _, e := range edges {
var found bool
if strings.HasPrefix(e.Dst, "\"[root] data.") {
found = true
}
if found {
collectTransitiveDeps(graph, e.Src, visited, transitiveDepsToDatasource)
}
}
for _, n := range graph.Nodes.Sorted() {
_, found := transitiveDepsToDatasource[n.Name]
if found || !strings.HasPrefix(n.Name, "\"[root] data.") {
parents := graph.Relations.ChildToParents[n.Name]
for p := range parents {
err := graph.RemoveNode(p, n.Name)
if err != nil {
fmt.Println(err)
}
}
}
}
}
func tweak(graph *gographviz.Graph) {
collectDeps(graph)
}
func mainInternal() error {
graph, err := read("terraform.dot")
if err != nil {
return err
}
tweak(graph)
return render(graph)
}
func main() {
if err := mainInternal(); err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment