// RunGraph contains all the necessary functionality for the OpenShift cli graph command func RunGraph(f *clientcmd.Factory, out io.Writer) error { client, kclient, err := f.Clients() if err != nil { return err } config, err := f.OpenShiftClientConfig.ClientConfig() if err != nil { return err } namespace, _, err := f.DefaultNamespace() if err != nil { return err } describer := &describe.ProjectStatusDescriber{K: kclient, C: client, Server: config.Host} g, _, err := describer.MakeGraph(namespace) if err != nil { return err } data, err := dot.Marshal(g, namespace, "", " ", false) if err != nil { return err } fmt.Fprintf(out, "%s", string(data)) return nil }
// Describe returns the output of the graph starting from the provided // image stream tag (name:tag) in namespace. Namespace is needed here // because image stream tags with the same name can be found across // different namespaces. func (d *ChainDescriber) Describe(ist *imageapi.ImageStreamTag, includeInputImages bool) (string, error) { g, err := d.MakeGraph() if err != nil { return "", err } // Retrieve the imageStreamTag node of interest istNode := g.Find(imagegraph.ImageStreamTagNodeName(ist)) if istNode == nil { return "", NotFoundErr(fmt.Sprintf("%q", ist.Name)) } buildInputEdgeKinds := []string{buildedges.BuildTriggerImageEdgeKind} if includeInputImages { buildInputEdgeKinds = append(buildInputEdgeKinds, buildedges.BuildInputImageEdgeKind) } // Partition down to the subgraph containing the ist of interest partitioned := partition(g, istNode, buildInputEdgeKinds) switch strings.ToLower(d.outputFormat) { case "dot": data, err := dot.Marshal(partitioned, fmt.Sprintf("%q", ist.Name), "", " ", false) if err != nil { return "", err } return string(data), nil case "": return d.humanReadableOutput(partitioned, istNode), nil } return "", fmt.Errorf("unknown specified format %q", d.outputFormat) }
func rend_db(w http.ResponseWriter, r *http.Request) { g, n, db, err1 := get_graph(w, r) if err1 != nil { return // Already rendered } labels, err3 := db.GetLabels() if err3 != nil { t_error.Execute(w, err3) return } data, err2 := dot.Marshal(dbViewGraph{UndirectedGraph: g.(*simple.UndirectedGraph), dbName: n, labels: labels}, "", "", "", false) if err2 != nil { t_error.Execute(w, err2) return } //fmt.Println(string(data)) buf := bytes.NewBuffer(data) dotter := exec.Command("dot", "-Tsvg") dotin, _ := dotter.StdinPipe() dotout, _ := dotter.StdoutPipe() w.Header().Set("Content-type", "image/svg+xml") dotter.Start() io.Copy(dotin, buf) dotin.Close() io.Copy(w, dotout) }
// RunStatus contains all the necessary functionality for the OpenShift cli status command. func (o StatusOptions) RunStatus() error { var ( s string err error ) switch o.outputFormat { case "": s, err = o.describer.Describe(o.namespace, "") if err != nil { return err } case "dot": g, _, err := o.describer.MakeGraph(o.namespace) if err != nil { return err } data, err := dot.Marshal(g, o.namespace, "", " ", false) if err != nil { return err } s = string(data) default: return fmt.Errorf("invalid output format provided: %s", o.outputFormat) } fmt.Fprintf(o.out, s) return nil }
func rend_path(w http.ResponseWriter, r *http.Request) { g, n, db, err1 := get_graph(w, r) if err1 != nil { return // Already rendered } labels, err3 := db.GetLabels() if err3 != nil { t_error.Execute(w, err3) return } path := strings.Split(r.URL.Path, "/") nodes := path[4:] pathnodes := make(map[int]bool) pathslice := make([]int, len(nodes)) for idx, s := range nodes { nid, err4 := strconv.Atoi(s) if err4 != nil { t_error.Execute(w, err4) return } pathnodes[nid] = true pathslice[idx] = nid } first := pathslice[0] last := pathslice[len(pathslice)-1] ng := dbPathGraph{UndirectedGraph: g.(*simple.UndirectedGraph), dbName: n, labels: labels, pathnodes: pathnodes, pathslice: pathslice, first: first, last: last} data, err2 := dot.Marshal(ng, "", "", "", false) //fmt.Println("dot:") //fmt.Println(string(data)) if err2 != nil { t_error.Execute(w, err2) return } buf := bytes.NewBuffer(data) dotter := exec.Command("dot", "-Tsvg") dotin, _ := dotter.StdinPipe() dotout, _ := dotter.StdoutPipe() w.Header().Set("Content-type", "image/svg+xml") dotter.Start() io.Copy(dotin, buf) dotin.Close() io.Copy(w, dotout) // dotter := exec.Command("dot", "-Tsvg") // dotin, _ := dotter.StdinPipe() // dotout, _ := dotter.StdoutPipe() // w.Header().Set("Content-type", "image/svg+xml") // dotter.Start() // io.WriteString(dotin, "digraph {\n") // for i := 0; i < len(nodes)-1; i++ { // io.WriteString(dotin, fmt.Sprintf("%s -> %s\n", nodes[i], nodes[i+1])) // } // io.WriteString(dotin, "}") // dotin.Close() // io.Copy(w, dotout) }
func DumpDotFile(g Graph) { b, err := dot.Marshal(g, "dump", "", " ", true) if err != nil { Error.Println(err) return } err = ioutil.WriteFile("/tmp/hover.dot", b, 0644) if err != nil { Error.Println(err) } }
// Describe returns the output of the graph starting from the provided // image stream tag (name:tag) in namespace. Namespace is needed here // because image stream tags with the same name can be found across // different namespaces. func (d *ChainDescriber) Describe(ist *imageapi.ImageStreamTag, includeInputImages, reverse bool) (string, error) { g, err := d.MakeGraph() if err != nil { return "", err } // Retrieve the imageStreamTag node of interest istNode := g.Find(imagegraph.ImageStreamTagNodeName(ist)) if istNode == nil { return "", NotFoundErr(fmt.Sprintf("%q", ist.Name)) } markers := buildanalysis.FindCircularBuilds(g, d.namer) if len(markers) > 0 { for _, marker := range markers { if strings.Contains(marker.Message, ist.Name) { return marker.Message, nil } } } buildInputEdgeKinds := []string{buildedges.BuildTriggerImageEdgeKind} if includeInputImages { buildInputEdgeKinds = append(buildInputEdgeKinds, buildedges.BuildInputImageEdgeKind) } // Partition down to the subgraph containing the imagestreamtag of interest var partitioned osgraph.Graph if reverse { partitioned = partitionReverse(g, istNode, buildInputEdgeKinds) } else { partitioned = partition(g, istNode, buildInputEdgeKinds) } switch strings.ToLower(d.outputFormat) { case "dot": data, err := dot.Marshal(partitioned, dotutil.Quote(ist.Name), "", " ", false) if err != nil { return "", err } return string(data), nil case "": return d.humanReadableOutput(partitioned, d.namer, istNode, reverse), nil } return "", fmt.Errorf("unknown specified format %q", d.outputFormat) }
func main() { g, labels, err1 := utils.ReadFileToGraph("topology.txt") if err1 != nil { fmt.Println("ReadFileToGraph:") fmt.Println(err1) return } labels = labels // fmt.Println(g); bytes, err2 := dot.Marshal(g, "", "", " ", false) if err2 != nil { fmt.Println("dot.Marshall:") fmt.Println(err1) return } fmt.Println(string(bytes)) }
func rend_node(w http.ResponseWriter, r *http.Request) { g, n, db, err1 := get_graph(w, r) if err1 != nil { return // Already rendered } parts := strings.Split(r.URL.Path, "/") srcid, err3 := strconv.Atoi(parts[4]) if err3 != nil { t_error.Execute(w, err3) return } labels, err4 := db.GetLabels() if err4 != nil { t_error.Execute(w, err4) } ng := dbNodeGraph{UndirectedGraph: simple.NewUndirectedGraph(0, math.Inf(1)), dbName: n, labels: labels} ng.AddNode(dbNodeNode{Node: simple.Node(srcid), dbName: n, label: labels[srcid]}) for _, dst := range g.From(simple.Node(srcid)) { ng.AddNode(dbNodeNode{Node: simple.Node(dst.ID()), dbName: n, label: labels[dst.ID()]}) ng.SetEdge(dbNodeEdge{simple.Edge{F: simple.Node(srcid), T: simple.Node(dst.ID()), W: g.Edge(simple.Node(srcid), dst).Weight()}}) } data, err2 := dot.Marshal(ng, "", "", "", false) if err2 != nil { t_error.Execute(w, err2) return } //fmt.Println(string(data)) buf := bytes.NewBuffer(data) dotter := exec.Command("dot", "-Tsvg") dotin, _ := dotter.StdinPipe() dotout, _ := dotter.StdoutPipe() w.Header().Set("Content-type", "image/svg+xml") dotter.Start() io.Copy(dotin, buf) dotin.Close() io.Copy(w, dotout) }