bgpwtf/cccampix: draw the rest of the fucking owl

Change-Id: I49fd5906e69512e8f2d414f406edc0179522f225
diff --git a/bgpwtf/cccampix/verifier/statusz.go b/bgpwtf/cccampix/verifier/statusz.go
new file mode 100644
index 0000000..46e9390
--- /dev/null
+++ b/bgpwtf/cccampix/verifier/statusz.go
@@ -0,0 +1,94 @@
+package main
+
+import (
+	"context"
+	"fmt"
+	"sort"
+
+	humanize "github.com/dustin/go-humanize"
+)
+
+const processorsFragment = `
+    <style type="text/css">
+		.table td,th {
+			background-color: #eee;
+			padding: 0.2em 0.4em 0.2em 0.4em;
+		}
+		.table th {
+			background-color: #c0c0c0;
+		}
+		.table {
+			background-color: #fff;
+			border-spacing: 0.2em;
+			margin-left: auto;
+			margin-right: auto;
+		}
+	</style>
+	<div>
+	<table class="table">
+		<tr>
+      		<th>Name</th>
+			<th>Status</th>
+      		<th>Last Run</th>
+			<th>Next Run</th>
+		</tr>
+		{{range .Processors }}
+		<tr>
+			<td>{{ .Name }}</td>
+			{{ if ne .Status "OK" }}
+			<td style="background-color: #ff3030;">{{ .Status }}</td>
+			{{ else }}
+			<td>{{ .Status }}</td>
+			{{ end }}
+			<td>{{ .LastRun }}</td>
+			<td>{{ .NextRun }}</td>
+		</tr>
+		{{end}}
+	</table>
+	</div>
+`
+
+type processorsFragmentEntry struct {
+	Name    string
+	Status  string
+	LastRun string
+	NextRun string
+}
+
+func (s *service) statuszProcessors(ctx context.Context) interface{} {
+	s.processorsMu.RLock()
+	defer s.processorsMu.RUnlock()
+
+	res := struct {
+		Processors []*processorsFragmentEntry
+	}{
+		Processors: make([]*processorsFragmentEntry, len(s.processors)),
+	}
+
+	i := 0
+	for _, processor := range s.processors {
+		lastRun := "never"
+		if processor.lastRun != nil {
+			lastRun = humanize.Time(*processor.lastRun)
+		}
+		nextRun := "any second now"
+		if nr := processor.nextRun(); nr != nil {
+			nextRun = humanize.Time(*nr)
+		}
+		status := "OK"
+		if processor.lastErr != nil {
+			status = fmt.Sprintf("%v", processor.lastErr)
+		}
+		res.Processors[i] = &processorsFragmentEntry{
+			Name:    processor.name,
+			Status:  status,
+			LastRun: lastRun,
+			NextRun: nextRun,
+		}
+		i += 1
+	}
+
+	sort.Slice(res.Processors, func(i, j int) bool { return res.Processors[i].Name < res.Processors[j].Name })
+
+	return res
+}