github.com/openshift/installer@v1.4.17/cmd/openshift-install/graph.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "reflect" 8 "regexp" 9 10 "github.com/awalterschulze/gographviz" 11 "github.com/sirupsen/logrus" 12 "github.com/spf13/cobra" 13 14 "github.com/openshift/installer/pkg/asset" 15 ) 16 17 var ( 18 graphOpts struct { 19 outputFile string 20 } 21 ) 22 23 func newGraphCmd() *cobra.Command { 24 cmd := &cobra.Command{ 25 Use: "graph", 26 Short: "Outputs the internal dependency graph for installer", 27 Long: "", 28 Args: cobra.ExactArgs(0), 29 RunE: func(cmd *cobra.Command, args []string) error { 30 return runGraphCmd(cmd, args, targets) 31 }, 32 } 33 cmd.PersistentFlags().StringVar(&graphOpts.outputFile, "output-file", "", "file where the graph is written, if empty prints the graph to Stdout.") 34 return cmd 35 } 36 37 func runGraphCmd(cmd *cobra.Command, args []string, cmdTargets []target) error { 38 g := gographviz.NewGraph() 39 g.SetName("G") 40 g.SetDir(true) 41 g.SetStrict(true) 42 43 tNodeAttr := map[string]string{ 44 string(gographviz.Shape): "box", 45 string(gographviz.Style): "filled", 46 } 47 for _, t := range cmdTargets { 48 name := fmt.Sprintf("%q", fmt.Sprintf("Target %s", t.name)) 49 g.AddNode("G", name, tNodeAttr) 50 for _, dep := range t.assets { 51 addEdge(g, name, dep) 52 } 53 } 54 55 g.AddAttr("G", "rankdir", "LR") 56 r := regexp.MustCompile(`[. ]`) 57 for _, node := range g.Nodes.Nodes { 58 cluster := r.Split(node.Name, -1)[0][1:] 59 subgraphName := "cluster_" + cluster 60 _, ok := g.SubGraphs.SubGraphs[subgraphName] 61 if !ok { 62 g.AddSubGraph("G", subgraphName, map[string]string{"label": cluster}) 63 } 64 g.AddNode(subgraphName, node.Name, nil) 65 } 66 67 out := os.Stdout 68 if graphOpts.outputFile != "" { 69 f, err := os.Create(graphOpts.outputFile) 70 if err != nil { 71 return err 72 } 73 defer f.Close() 74 out = f 75 } 76 77 if _, err := io.WriteString(out, g.String()); err != nil { 78 return err 79 } 80 return nil 81 } 82 83 func addEdge(g *gographviz.Graph, parent string, asset asset.Asset) { 84 name := fmt.Sprintf("%q", reflect.TypeOf(asset).Elem()) 85 86 if !g.IsNode(name) { 87 logrus.Debugf("adding node %s", name) 88 g.AddNode("G", name, nil) 89 } 90 if !isEdge(g, name, parent) { 91 logrus.Debugf("adding edge %s -> %s", name, parent) 92 g.AddEdge(name, parent, true, nil) 93 } 94 95 deps := asset.Dependencies() 96 for _, dep := range deps { 97 addEdge(g, name, dep) 98 } 99 } 100 101 func isEdge(g *gographviz.Graph, src, dst string) bool { 102 for _, edge := range g.Edges.Edges { 103 if edge.Src == src && edge.Dst == dst { 104 return true 105 } 106 } 107 return false 108 }