github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/imageserver/httpd/showImage.go (about) 1 package httpd 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "net/http" 8 "time" 9 10 "github.com/Cloud-Foundations/Dominator/lib/format" 11 "github.com/Cloud-Foundations/Dominator/lib/image" 12 ) 13 14 var timeFormat string = "02 Jan 2006 15:04:05.99 MST" 15 16 func (s state) showImageHandler(w http.ResponseWriter, req *http.Request) { 17 writer := bufio.NewWriter(w) 18 defer writer.Flush() 19 imageName := req.URL.RawQuery 20 fmt.Fprintf(writer, "<title>image %s</title>\n", imageName) 21 fmt.Fprintln(writer, "<body>") 22 fmt.Fprintln(writer, "<h3>") 23 image := s.imageDataBase.GetImage(imageName) 24 if image == nil { 25 fmt.Fprintf(writer, "Image: %s UNKNOWN!\n", imageName) 26 return 27 } 28 fmt.Fprintf(writer, "Information for image: %s<br>\n", imageName) 29 fmt.Fprintln(writer, "</h3>") 30 fmt.Fprintf(writer, "Data size: <a href=\"listImage?%s\">%s</a><br>\n", 31 imageName, format.FormatBytes(image.FileSystem.TotalDataBytes)) 32 fmt.Fprintf(writer, "Number of data inodes: %d<br>\n", 33 image.FileSystem.NumRegularInodes) 34 if numInodes := image.FileSystem.NumComputedRegularInodes(); numInodes > 0 { 35 fmt.Fprintf(writer, 36 "Number of computed inodes: <a href=\"listComputedInodes?%s\">%d</a><br>\n", 37 imageName, numInodes) 38 } 39 if image.Filter == nil { 40 fmt.Fprintln(writer, "Image has no filter: sparse image<br>") 41 } else if len(image.Filter.FilterLines) < 1 { 42 fmt.Fprintln(writer, 43 "Filter has 0 lines (empty filter: full coverage)<br>") 44 } else { 45 fmt.Fprintf(writer, 46 "Filter has <a href=\"listFilter?%s\">%d</a> lines<br>\n", 47 imageName, len(image.Filter.FilterLines)) 48 } 49 if image.Triggers == nil || len(image.Triggers.Triggers) < 1 { 50 fmt.Fprintln(writer, "Image has no triggers<br>") 51 } else { 52 fmt.Fprintf(writer, 53 "Number of triggers: <a href=\"listTriggers?%s\">%d</a><br>\n", 54 imageName, len(image.Triggers.Triggers)) 55 } 56 if !image.ExpiresAt.IsZero() { 57 fmt.Fprintf(writer, "Expires at: %s (in %s)<br>\n", 58 image.ExpiresAt.In(time.Local).Format(timeFormat), 59 format.Duration(time.Until(image.ExpiresAt))) 60 } 61 showAnnotation(writer, image.ReleaseNotes, imageName, "Release notes", 62 "listReleaseNotes") 63 showAnnotation(writer, image.BuildLog, imageName, "Build log", 64 "listBuildLog") 65 if image.CreatedBy != "" { 66 fmt.Fprintf(writer, "Created by: %s\n<br>", image.CreatedBy) 67 } 68 if !image.CreatedOn.IsZero() { 69 fmt.Fprintf(writer, "Created on: %s (%s old)\n<br>", 70 image.CreatedOn.In(time.Local).Format(timeFormat), 71 format.Duration(time.Since(image.CreatedOn))) 72 } 73 if len(image.Packages) > 0 { 74 fmt.Fprintf(writer, 75 "Packages: <a href=\"listPackages?%s\">%d</a><br>\n", 76 imageName, len(image.Packages)) 77 } 78 fmt.Fprintln(writer, "</body>") 79 } 80 81 func showAnnotation(writer io.Writer, annotation *image.Annotation, 82 imageName string, linkName string, baseURL string) { 83 if annotation == nil { 84 return 85 } 86 var url string 87 if annotation.URL != "" { 88 url = annotation.URL 89 } else { 90 url = baseURL + "?" + imageName 91 } 92 fmt.Fprintf(writer, "<a href=\"%s\">%s</a><br>\n", url, linkName) 93 }