diff --git a/.gitignore b/.gitignore
index e62eda10..fbc4daf7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ fairwinds
Tiltfile
main
+.DS_Store
diff --git a/config.yml b/config.yml
new file mode 100644
index 00000000..6f1d3f1c
--- /dev/null
+++ b/config.yml
@@ -0,0 +1,15 @@
+resources:
+ requests:
+ cpu:
+ min: 100m
+ max: 1
+ memory:
+ min: 100M
+ max: 3G
+ limits:
+ cpu:
+ min: 150m
+ max: 2
+ memory:
+ min: 150M
+ max: 4G
diff --git a/main.go b/main.go
index d42d26b6..df1d8409 100644
--- a/main.go
+++ b/main.go
@@ -21,6 +21,7 @@ import (
"os"
conf "github.com/reactiveops/fairwinds/pkg/config"
+ "github.com/reactiveops/fairwinds/pkg/dashboard"
"github.com/reactiveops/fairwinds/pkg/validator"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
@@ -49,7 +50,8 @@ func main() {
c, err := conf.ParseFile("config.yml")
if err != nil {
- return
+ glog.Println("Error parsing config.yml:", err)
+ os.Exit(1)
}
if *webhook {
@@ -62,9 +64,18 @@ func main() {
}
func startDashboardServer(c conf.Configuration) {
- http.HandleFunc("/validate", func(w http.ResponseWriter, r *http.Request) { validator.DeployHandler(w, r, c) })
- http.HandleFunc("/ping", validator.PingHandler)
- glog.Println("Starting Fairwinds dashboard webserver on port 8080.")
+ http.HandleFunc("/results.json", func(w http.ResponseWriter, r *http.Request) {
+ dashboard.RenderJSON(w, r, c)
+ })
+ http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("public/"))))
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != "/" {
+ http.NotFound(w, r)
+ return
+ }
+ dashboard.Render(w, r, c)
+ })
+ glog.Println("Starting Fairwinds dashboard server on port 8080.")
glog.Fatal(http.ListenAndServe(":8080", nil))
}
diff --git a/pkg/dashboard/dashboard.go b/pkg/dashboard/dashboard.go
new file mode 100644
index 00000000..d2caebde
--- /dev/null
+++ b/pkg/dashboard/dashboard.go
@@ -0,0 +1,80 @@
+package dashboard
+
+import (
+ "encoding/json"
+ "html/template"
+ "log"
+ "net/http"
+
+ conf "github.com/reactiveops/fairwinds/pkg/config"
+ "github.com/reactiveops/fairwinds/pkg/kube"
+ "github.com/reactiveops/fairwinds/pkg/validator"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+type DashboardData struct {
+ ClusterSummary *validator.ResultSummary
+ NamespacedResults []validator.NamespacedResult
+}
+
+var tmpl = template.Must(template.ParseFiles("pkg/dashboard/templates/charts.gohtml"))
+
+func Render(w http.ResponseWriter, r *http.Request, c conf.Configuration) {
+ dashboardData := getDashboardData()
+ tmpl.Execute(w, dashboardData)
+}
+
+func RenderJSON(w http.ResponseWriter, r *http.Request, c conf.Configuration) {
+ results := []validator.Results{}
+ pods, err := kube.CoreV1API.Pods("").List(metav1.ListOptions{})
+ if err != nil {
+ http.Error(w, "Error Fetching Pods", 500)
+ return
+ }
+ log.Println("pods count:", len(pods.Items))
+ for _, pod := range pods.Items {
+ result := validator.ValidatePods(c, &pod.Spec, validator.Results{})
+ results = append(results, result)
+ }
+ w.WriteHeader(http.StatusOK)
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(results)
+}
+
+func getDashboardData() DashboardData {
+ return DashboardData{
+ ClusterSummary: &validator.ResultSummary{
+ Successes: 46,
+ Warnings: 8,
+ Failures: 5,
+ },
+ NamespacedResults: []validator.NamespacedResult{{
+ Namespace: "kube-system",
+ Results: []validator.ResourceResult{{
+ Name: "tiller",
+ Type: "Deployment",
+ Summary: &validator.ResultSummary{
+ Successes: 7,
+ Warnings: 3,
+ Failures: 2,
+ },
+ Messages: []validator.ResultMessage{{
+ Message: "Image Tag Specified",
+ Type: "success",
+ }, {
+ Message: "Liveness Probe Specified",
+ Type: "success",
+ }, {
+ Message: "Readiness Probe Specified",
+ Type: "success",
+ }, {
+ Message: "Container Running As Root",
+ Type: "warning",
+ }, {
+ Message: "Resource requests are not set",
+ Type: "failure",
+ }},
+ }},
+ }},
+ }
+}
diff --git a/pkg/dashboard/templates/charts.gohtml b/pkg/dashboard/templates/charts.gohtml
new file mode 100644
index 00000000..ecbf61f1
--- /dev/null
+++ b/pkg/dashboard/templates/charts.gohtml
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+ Fairwinds
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Scores By Namespace:
+
+
+
+
+ {{ range .NamespacedResults }}
+
+
Namespace: {{ .Namespace }}
+
+
+ {{ range .Results }}
+
+ |
+ {{ .Type }}: {{ .Name }}
+
+ |
+
+
+ |
+
+ {{ end }}
+
+
+ {{ end }}
+
+
+
+
+
+
diff --git a/pkg/dashboard/templates/dashboard.gohtml b/pkg/dashboard/templates/dashboard.gohtml
new file mode 100644
index 00000000..6a6d73a1
--- /dev/null
+++ b/pkg/dashboard/templates/dashboard.gohtml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+ Fairwinds
+
+
+
+
+
+
+
+
+
+
+
+
+
Overall Score:
+
{{ .ClusterSummary.Score }}%
+
+
+
+ Successes:
+ {{ .ClusterSummary.Successes }}
+
+
+ Warnings:
+ {{ .ClusterSummary.Warnings }}
+
+
+ Failures:
+ {{ .ClusterSummary.Failures }}
+
+
+
+
+{{ range .NamespacedResults }}
+
+
+
+ {{ range .Results }}
+
+ |
+ {{ .Type }}: {{ .Name }}
+
+ |
+
+
+ |
+
+ {{ end }}
+
+{{ end }}
+
+
+
diff --git a/pkg/validator/types.go b/pkg/validator/types.go
new file mode 100644
index 00000000..a65cfd14
--- /dev/null
+++ b/pkg/validator/types.go
@@ -0,0 +1,64 @@
+package validator
+
+// namespaceResults: [{
+// name: "kube-system",
+// resourceResults: [{
+// name: "example-deployment",
+// type: "DaemonSet",
+// summary: {
+// successes: 28,
+// warnings: 12,
+// failures: 18,
+// },
+// messages: [{
+// message: "Resource requests are not set",
+// type: "failure",
+// }]
+// }]
+// }]
+
+type NamespacedResult struct {
+ Namespace string
+ Results []ResourceResult
+}
+
+type ResourceResult struct {
+ Name string
+ Type string
+ Summary *ResultSummary
+ Messages []ResultMessage
+}
+
+type ResultSummary struct {
+ Successes uint
+ Warnings uint
+ Failures uint
+}
+
+type ResultMessage struct {
+ Message string
+ Type string
+}
+
+func (rs *ResultSummary) Score() uint {
+ return uint(float64(rs.Successes) / float64(rs.Successes+rs.Warnings+rs.Failures) * 100)
+}
+
+func (rs *ResultSummary) WarningWidth(fullWidth uint) uint {
+ return uint(float64(rs.Successes+rs.Warnings) / float64(rs.Successes+rs.Warnings+rs.Failures) * float64(fullWidth))
+}
+
+func (rs *ResultSummary) SuccessWidth(fullWidth uint) uint {
+ return uint(float64(rs.Successes) / float64(rs.Successes+rs.Warnings+rs.Failures) * float64(fullWidth))
+}
+
+func (rm *ResultMessage) HTMLSpecialCharCode() string {
+ switch rm.Type {
+ case "success":
+ return "9745"
+ case "warning":
+ return "9888"
+ default:
+ return "9746"
+ }
+}
diff --git a/public/charts.html b/public/charts.html
new file mode 100644
index 00000000..c42add4a
--- /dev/null
+++ b/public/charts.html
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+ Fairwinds
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Scores By Namespace:
+
+
+
+
+
+
Namespace: kube-system
+
+
+
+ |
+ DaemonSet: datadog-agent
+ |
+
+
+ |
+
+
+ |
+ Deployment: tiller-deployment
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
diff --git a/public/css/charts.css b/public/css/charts.css
new file mode 100644
index 00000000..72e5d8bf
--- /dev/null
+++ b/public/css/charts.css
@@ -0,0 +1,193 @@
+body {
+ margin: 0;
+ font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
+ background: #eee;
+}
+
+.header {
+ background-color: #fff;
+ color: #006369;
+ padding: 20px 30px;
+ box-shadow: 0 2px 5px rgba(0,0,0,0.3);
+}
+
+.header h1 {
+ font-family: 'Lobster', sans-serif;
+ font-size: 60px;
+ font-weight: normal;
+ margin: 0 auto;
+ width: 900px;
+}
+
+.dashboard-content {
+ width: 960px;
+ margin: 0 auto;
+}
+
+.charts {
+ height: 400px;
+}
+
+.chart-section {
+ float: left;
+ margin: 20px;
+ padding: 30px;
+ width: 300px;
+ height: 320px;
+ color: #333;
+ background-color: #fff;
+ box-shadow: 0 2px 5px rgba(0,0,0,0.3);
+ border-radius: 5px;
+}
+
+.chart-section.namespace-score {
+ margin-left: 0px;
+ width: 480px;
+}
+
+.chart-section h3 {
+ margin: 0 0 15px;
+ padding: 0 0 15px;
+ font-weight: 300;
+ font-size: 30px;
+ border-bottom: 1px solid #eee;
+}
+
+#clusterScoreChart {
+ width: 260px;
+ height: 260px;
+}
+
+#namespaceScoreChart {
+ width: 520px;
+ height: 260px;
+}
+
+.namespace {
+ margin: 20px;
+ padding: 10px 20px;
+ color: #333;
+ background-color: #fff;
+ box-shadow: 0 2px 5px rgba(0,0,0,0.3);
+ border-radius: 5px;
+}
+
+.namespace h3 {
+ margin: 0;
+ font-weight: 300;
+ font-size: 30px;
+ padding: 20px;
+}
+
+.namespace h3 strong {
+ margin: 0;
+ font-weight: bold;
+ font-size: 30px;
+}
+
+.cluster-score .status {
+ width: 400px;
+ height: 30px;
+ margin: 30px auto;
+}
+
+.namespace-content {
+ width: 100%;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+
+.namespace-content tr {
+ height: 50px;
+}
+
+.namespace-content td {
+ padding: 15px 20px;
+ margin: 0;
+ font-size: 18px;
+ border-top: 1px solid #eee;
+}
+
+.namespace-content .caret-expander {
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+ margin-right: 10px;
+ background-image: url('../images/caret-right.svg');
+ background-size: 15px auto;
+ background-repeat: no-repeat;
+ background-position: 2px center;
+}
+
+.namespace-content .caret-expander.expanded {
+ background-image: url('../images/caret-bottom.svg');
+ background-position: center center;
+}
+
+.namespace-content .extra {
+ list-style-type: none;
+ font-size: 14px;
+ line-height: 19px;
+ margin: 10px 30px;
+ padding: 0;
+}
+
+.namespace-content .extra span {
+ display: inline-block;
+ text-align: center;
+ width: 20px;
+ font-size: 20px;
+}
+
+.namespace-content .extra .success {
+ color: #006469;
+}
+
+.namespace-content .extra .warning {
+ color: #AE7500;
+}
+
+.namespace-content .extra .warning span {
+ font-size: 15px;
+}
+
+.namespace-content .extra .failure {
+ color: #AE0400;
+}
+
+.namespace-content td.status-bar {
+ vertical-align: top;
+ padding-top: 18px;
+}
+
+.namespace-content .status {
+ float: right;
+ width: 200px;
+}
+
+.namespace-content .status div {
+ height: 15px;
+ border-radius: 10px;
+}
+
+.namespace-content .status .passing {
+ background-color: #006469;
+ float: left;
+}
+
+.namespace-content .status .warning {
+ background-color: #AE7500;
+ float: left;
+}
+
+@keyframes fadeIn {
+ 0% {opacity: 0;}
+ 100% {opacity: 1;}
+}
+
+.namespace-content .status .failing {
+ background-color: #AE0400;
+ width: 200px;
+ animation: fadeIn 2s;
+}
+
diff --git a/public/css/main.css b/public/css/main.css
new file mode 100644
index 00000000..d587aa48
--- /dev/null
+++ b/public/css/main.css
@@ -0,0 +1,198 @@
+body {
+ margin: 0;
+ font-family: 'Helvetica', 'Arial', sans-serif;
+}
+
+.header {
+ background-color: #006369;
+ color: #fff;
+ padding: 50px;
+}
+
+.header h1 {
+ font-family: 'Lobster', sans-serif;
+ font-size: 100px;
+ font-weight: normal;
+ text-align: center;
+ margin: 0;
+}
+
+.cluster-score {
+ margin: 0;
+ padding: 30px;
+ color: #003339;
+ background-color: #eaf3f9;
+ text-align: center;
+}
+
+.cluster-score h2 {
+ margin: 0;
+ font-size: 80px;
+}
+
+.cluster-score .status {
+ width: 400px;
+ height: 30px;
+ margin: 30px auto;
+}
+
+.cluster-score .status div {
+ height: 30px;
+ border-radius: 8px;
+}
+
+.cluster-score .status .passing {
+ background-color: #4ab977;
+ float: left;
+}
+
+.cluster-score .status .warning {
+ background-color: #bdbd63;
+ float: left;
+}
+
+.cluster-score .status .failing {
+ background-color: #c37575;
+ width: 400px;
+}
+
+.cluster-score p {
+ margin: 10px 0;
+ font-weight: 300;
+ font-size: 24px;
+}
+
+.cluster-score .summary {
+ margin: 30px auto;
+ font-weight: 300;
+ font-size: 24px;
+ width: 300px;
+ text-align: left;
+ line-height: 40px;
+}
+
+.cluster-score .summary .value {
+ float: right;
+ font-size: 28px;
+}
+
+.namespace-header {
+ background-color: #006369;
+ color: #fff;
+ font-size: 50px;
+ font-weight: normal;
+ padding: 20px;
+}
+
+.namespace-header h3 {
+ margin: 0;
+ font-weight: 300;
+ font-size: 30px;
+}
+
+.namespace-header h3 strong {
+ margin: 0;
+ font-weight: bold;
+ font-size: 30px;
+}
+
+.cluster-score .status {
+ width: 400px;
+ height: 30px;
+ margin: 30px auto;
+}
+
+.namespace-content {
+ width: 100%;
+ background-color: #eaf3f9;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+
+.namespace-content tr {
+ height: 50px;
+}
+
+.namespace-content td {
+ padding: 15px 20px;
+ margin: 0;
+ font-size: 18px;
+ border-bottom: 1px solid #aac3c9;
+}
+
+.namespace-content .caret-expander {
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+ margin-right: 10px;
+ background-image: url('../images/caret-right.svg');
+ background-size: 15px auto;
+ background-repeat: no-repeat;
+ background-position: 2px center;
+}
+
+.namespace-content .caret-expander.expanded {
+ background-image: url('../images/caret-bottom.svg');
+ background-position: center center;
+}
+
+.namespace-content .extra {
+ list-style-type: none;
+ font-size: 14px;
+ line-height: 19px;
+ margin: 10px 30px;
+ padding: 0;
+}
+
+.namespace-content .extra span {
+ display: inline-block;
+ text-align: center;
+ width: 20px;
+}
+
+.namespace-content .extra .success {
+ color: #2a9957;
+}
+
+.namespace-content .extra .warning {
+ color: #adad43;
+}
+
+.namespace-content .extra .warning span {
+ font-size: 11px;
+}
+
+.namespace-content .extra .failure {
+ color: #a35555;
+}
+
+.namespace-content td.status-bar {
+ vertical-align: top;
+ padding-top: 18px;
+}
+
+.namespace-content .status {
+ float: right;
+ width: 200px;
+}
+
+.namespace-content .status div {
+ height: 15px;
+ border-radius: 4px;
+}
+
+.namespace-content .status .passing {
+ background-color: #4ab977;
+ float: left;
+}
+
+.namespace-content .status .warning {
+ background-color: #bdbd63;
+ float: left;
+}
+
+.namespace-content .status .failing {
+ background-color: #c37575;
+ width: 200px;
+}
+
diff --git a/public/css/normalize.css b/public/css/normalize.css
new file mode 100644
index 00000000..c4699894
--- /dev/null
+++ b/public/css/normalize.css
@@ -0,0 +1,349 @@
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+ ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+ html {
+ line-height: 1.15; /* 1 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/* Sections
+ ========================================================================== */
+
+/**
+ * Remove the margin in all browsers.
+ */
+
+body {
+ margin: 0;
+}
+
+/**
+ * Render the `main` element consistently in IE.
+ */
+
+main {
+ display: block;
+}
+
+/**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+hr {
+ box-sizing: content-box; /* 1 */
+ height: 0; /* 1 */
+ overflow: visible; /* 2 */
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+pre {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Remove the gray background on active links in IE 10.
+ */
+
+a {
+ background-color: transparent;
+}
+
+/**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+abbr[title] {
+ border-bottom: none; /* 1 */
+ text-decoration: underline; /* 2 */
+ text-decoration: underline dotted; /* 2 */
+}
+
+/**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+b,
+strong {
+ font-weight: bolder;
+}
+
+/**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+code,
+kbd,
+samp {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+}
+
+/**
+ * Add the correct font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+sup {
+ top: -0.5em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove the border on images inside links in IE 10.
+ */
+
+img {
+ border-style: none;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ font-family: inherit; /* 1 */
+ font-size: 100%; /* 1 */
+ line-height: 1.15; /* 1 */
+ margin: 0; /* 2 */
+}
+
+/**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+button,
+input { /* 1 */
+ overflow: visible;
+}
+
+/**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+button,
+select { /* 1 */
+ text-transform: none;
+}
+
+/**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+button,
+[type="button"],
+[type="reset"],
+[type="submit"] {
+ -webkit-appearance: button;
+}
+
+/**
+ * Remove the inner border and padding in Firefox.
+ */
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0;
+}
+
+/**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText;
+}
+
+/**
+ * Correct the padding in Firefox.
+ */
+
+fieldset {
+ padding: 0.35em 0.75em 0.625em;
+}
+
+/**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ * `fieldset` elements in all browsers.
+ */
+
+legend {
+ box-sizing: border-box; /* 1 */
+ color: inherit; /* 2 */
+ display: table; /* 1 */
+ max-width: 100%; /* 1 */
+ padding: 0; /* 3 */
+ white-space: normal; /* 1 */
+}
+
+/**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+progress {
+ vertical-align: baseline;
+}
+
+/**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+[type="checkbox"],
+[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ outline-offset: -2px; /* 2 */
+}
+
+/**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button; /* 1 */
+ font: inherit; /* 2 */
+}
+
+/* Interactive
+ ========================================================================== */
+
+/*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+details {
+ display: block;
+}
+
+/*
+ * Add the correct display in all browsers.
+ */
+
+summary {
+ display: list-item;
+}
+
+/* Misc
+ ========================================================================== */
+
+/**
+ * Add the correct display in IE 10+.
+ */
+
+template {
+ display: none;
+}
+
+/**
+ * Add the correct display in IE 10.
+ */
+
+[hidden] {
+ display: none;
+}
diff --git a/public/images/caret-bottom.svg b/public/images/caret-bottom.svg
new file mode 100755
index 00000000..2b4c5253
--- /dev/null
+++ b/public/images/caret-bottom.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/public/images/caret-right.svg b/public/images/caret-right.svg
new file mode 100755
index 00000000..23b33a08
--- /dev/null
+++ b/public/images/caret-right.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/public/images/circle-check.svg b/public/images/circle-check.svg
new file mode 100755
index 00000000..5df0f156
--- /dev/null
+++ b/public/images/circle-check.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/public/images/circle-x.svg b/public/images/circle-x.svg
new file mode 100755
index 00000000..0244752c
--- /dev/null
+++ b/public/images/circle-x.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/public/images/warning.svg b/public/images/warning.svg
new file mode 100755
index 00000000..e3594a88
--- /dev/null
+++ b/public/images/warning.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 00000000..97ac32ef
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+ Fairwinds
+
+
+
+
+
+
+
+
+
+
+
+
+
Overall Score:
+
64%
+
+
+
+ Successes:
+ 118
+
+
+ Warnings:
+ 34
+
+
+ Failures:
+ 28
+
+
+
+
+
+
+
+
+ |
+ DaemonSet: datadog-agent
+ |
+
+
+ |
+
+
+ |
+ Deployment: tiller-deployment
+
+ |
+
+
+ |
+
+
+
+
+
+