github.com/Cloud-Foundations/Dominator@v0.3.4/imagebuilder/httpd/showDirectedGraph.go (about) 1 package httpd 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "io" 8 "net/http" 9 "os/exec" 10 "time" 11 12 "github.com/Cloud-Foundations/Dominator/lib/format" 13 "github.com/Cloud-Foundations/Dominator/lib/html" 14 proto "github.com/Cloud-Foundations/Dominator/proto/imaginator" 15 ) 16 17 var processStartTime = time.Now() 18 19 func (s state) showDirectedGraphHandler(w http.ResponseWriter, 20 req *http.Request) { 21 if req.Method == "POST" { 22 s.builder.GetDirectedGraph(proto.GetDirectedGraphRequest{ 23 MaxAge: 2 * time.Second, 24 }) 25 http.Redirect(w, req, "/showDirectedGraph", http.StatusFound) 26 } 27 writer := bufio.NewWriter(w) 28 defer writer.Flush() 29 fmt.Fprintln(writer, "<title>imaginator image stream relationshops</title>") 30 fmt.Fprintln(writer, `<style> 31 table, th, td { 32 border-collapse: collapse; 33 } 34 </style>`) 35 fmt.Fprintln(writer, "<body>") 36 fmt.Fprintln(writer, "<center>") 37 fmt.Fprintln(writer, "<h1>imaginator image stream relationships</h1>") 38 fmt.Fprintln(writer, "</center>") 39 queries := req.URL.Query() 40 s.writeDirectedGraph(writer, queries["exclude"], queries["include"]) 41 fmt.Fprintln(writer, "<hr>") 42 html.WriteFooter(writer) 43 fmt.Fprintln(writer, "</body>") 44 } 45 46 func (s state) writeDirectedGraph(writer io.Writer, 47 excludes, includes []string) { 48 result, err := s.builder.GetDirectedGraph( 49 proto.GetDirectedGraphRequest{Excludes: excludes, Includes: includes}) 50 if err != nil { 51 fmt.Fprintf(writer, "error getting graph data: %s<br>\n", err) 52 return 53 } 54 if result.GeneratedAt.IsZero() { // No data yet. 55 fmt.Fprintln(writer, "No data generated yet<br>") 56 } else { 57 cmd := exec.Command("dot", "-Tsvg") 58 cmd.Stdin = bytes.NewReader(result.GraphvizDot) 59 cmd.Stdout = writer 60 cmd.Stderr = writer 61 err = cmd.Run() 62 if err == nil { 63 fmt.Fprintln(writer, "<p>") 64 } else { 65 fmt.Fprintf(writer, "error rendering graph: %s<br>\n", err) 66 fmt.Fprintln(writer, "Showing graph data:<br>") 67 fmt.Fprintln(writer, "<pre>") 68 writer.Write(result.GraphvizDot) 69 fmt.Fprintln(writer, "</pre>") 70 } 71 weblinks, _ := s.builder.GetRelationshipsQuickLinks() 72 for _, weblink := range weblinks { 73 fmt.Fprintf(writer, 74 "<a href=\"/showDirectedGraph%s\">%s</a> \n", 75 weblink.URL, weblink.Name) 76 } 77 if len(weblinks) > 0 { 78 fmt.Fprintln(writer, "<br>") 79 } 80 } 81 if len(result.FetchLog) > 0 { 82 if result.LastAttemptError == "" { 83 fmt.Fprintln(writer, 84 "<hr style=\"height:2px\"><font color=\"#bbb\">") 85 fmt.Fprintln(writer, "<b>Fetch log:</b>") 86 } else { 87 fmt.Fprintln(writer, 88 "<hr style=\"height:2px\"><font color=\"#fbb\">") 89 fmt.Fprintln(writer, "<b>Failed fetch log:</b>") 90 } 91 fmt.Fprintln(writer, "<pre>") 92 writer.Write(result.FetchLog) 93 fmt.Fprintln(writer, "</pre>") 94 fmt.Fprintln(writer, "</font>") 95 } 96 if !result.GeneratedAt.IsZero() { 97 fmt.Fprintf(writer, "Data generated at: %s<br>\n", 98 result.GeneratedAt.Format(format.TimeFormatSeconds)) 99 } 100 if result.LastAttemptError != "" { 101 fmt.Fprintf(writer, 102 "Last generation attempt at: %s failed: %s<br>\n", 103 result.LastAttemptAt.Format(format.TimeFormatSeconds), 104 result.LastAttemptError) 105 } 106 if time.Since(result.GeneratedAt) > 2*time.Second { 107 fmt.Fprintln(writer, 108 `<form enctype="application/x-www-form-urlencoded" action="/showDirectedGraph" method="post">`) 109 fmt.Fprintln(writer, 110 `<input type="submit" value="Regenerate">`) 111 } 112 }