Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
JessicaGreben committed Feb 7, 2019
2 parents 93871e2 + d48d2b8 commit bfcda87
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- checkout
- run: dep ensure
- run: go get -u github.com/golang/lint/golint
- run: go list ./... | grep -v vendor | xargs golint
- run: go list ./... | grep -v vendor | xargs golint -set_exit_status
- run: go list ./... | grep -v vendor | xargs go vet
- run: go test ./pkg/... -v -coverprofile cover.out

Expand Down
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ func main() {

func startDashboardServer(c conf.Configuration) {
http.HandleFunc("/results.json", func(w http.ResponseWriter, r *http.Request) {
dashboard.RenderJSON(w, r, c)
dashboard.EndpointHandler(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)
dashboard.MainHandler(w, r, c)
})
glog.Println("Starting Fairwinds dashboard server on port 8080.")
glog.Fatal(http.ListenAndServe(":8080", nil))
Expand Down
49 changes: 21 additions & 28 deletions pkg/dashboard/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,53 @@ 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"
)

// DashboardData stores validation results organized by namespace and also
// tracks the total cluster count of failed/successed validation checks.
type DashboardData struct {
// TemplateData represents data in a format that's template friendly.
type TemplateData struct {
ClusterSummary *validator.ResultSummary
NamespacedResults validator.NamespacedResults
}

var tmpl = template.Must(template.ParseFiles("pkg/dashboard/templates/dashboard.gohtml"))

// Render populates the dashboard template with validation data.
func Render(w http.ResponseWriter, r *http.Request, c conf.Configuration) {
dashboardData, err := getDashboardData(c)
// MainHandler gets template data and renders the dashboard with it.
func MainHandler(w http.ResponseWriter, r *http.Request, c conf.Configuration) {
templateData, err := getTemplateData(c)
if err != nil {
http.Error(w, "Error Fetching Deploys", 500)
http.Error(w, "Error Fetching Deployments", 500)
return
}

tmpl.Execute(w, dashboardData)
tmpl.Execute(w, templateData)
}

// RenderJSON returns pod validation data in JSON format.
func RenderJSON(w http.ResponseWriter, r *http.Request, c conf.Configuration) {
var clientset = kube.CreateClientset()
pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})
// EndpointHandler gets template data and renders json with it.
func EndpointHandler(w http.ResponseWriter, r *http.Request, c conf.Configuration) {
templateData, err := getTemplateData(c)
if err != nil {
http.Error(w, "Error Fetching Pods", 500)
http.Error(w, "Error Fetching Deployments", 500)
return
}
log.Println("pods count:", len(pods.Items))
res := []validator.ResourceResult{}
for _, pod := range pods.Items {
resResult := validator.ValidatePod(c, &pod.Spec)
resResult.Name = pod.Name
res = append(res, resResult)
}

w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(res)
json.NewEncoder(w).Encode(templateData)
}

func getDashboardData(c conf.Configuration) (DashboardData, error) {
func getTemplateData(c conf.Configuration) (TemplateData, error) {

// TODO: Once we are validating more than deployments,
// we will need to merge the namespaceResults that get returned
// from each validation.
nsResults, _ := validator.ValidateDeploys(c)
nsResults, err := validator.ValidateDeploys(c)
if err != nil {
return TemplateData{}, err
}

var clusterSuccesses, clusterFailures, clusterWarnings uint

Expand All @@ -69,7 +62,7 @@ func getDashboardData(c conf.Configuration) (DashboardData, error) {
}
}

dashboardData := DashboardData{
templateData := TemplateData{
ClusterSummary: &validator.ResultSummary{
Failures: clusterFailures,
Warnings: clusterWarnings,
Expand All @@ -78,5 +71,5 @@ func getDashboardData(c conf.Configuration) (DashboardData, error) {
NamespacedResults: nsResults,
}

return dashboardData, nil
return templateData, nil
}
3 changes: 2 additions & 1 deletion pkg/kube/clientset.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package kube
import (
"fmt"

"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes" // Required for GKE auth.
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)

// CreateClientset returns a new Kubernetes clientset.
func CreateClientset() *kubernetes.Clientset {
kubeConf := config.GetConfigOrDie()

Expand Down
2 changes: 1 addition & 1 deletion pkg/validator/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)

// ContainerValidation tracks validation failures associated with a Container
// ContainerValidation tracks validation failures associated with a Container.
type ContainerValidation struct {
Container corev1.Container
Summary ResultSummary
Expand Down
10 changes: 10 additions & 0 deletions pkg/validator/types.go
Original file line number Diff line number Diff line change
@@ -1,47 +1,57 @@
package validator

// NamespacedResult groups resource results by namespace.
type NamespacedResult struct {
Summary *ResultSummary
Results []ResourceResult
}

// NamespacedResults is a mapping of namespace name to the validation results.
type NamespacedResults map[string]*NamespacedResult

// ResourceResult groups container results by parent resource.
type ResourceResult struct {
Name string
Type string
Summary *ResultSummary
ContainerResults []ContainerResult
}

// ResultSummary provides a high level overview of success, warnings, and failures.
type ResultSummary struct {
Successes uint
Warnings uint
Failures uint
}

// ContainerResult provides a list of validation messages for each container.
type ContainerResult struct {
Name string
Messages []ResultMessage
}

// ResultMessage contains a message and a type indicator (success, warning, or failure).
type ResultMessage struct {
Message string
Type string
}

// Score represents a percentage of validations that were successful.
func (rs *ResultSummary) Score() uint {
return uint(float64(rs.Successes) / float64(rs.Successes+rs.Warnings+rs.Failures) * 100)
}

// WarningWidth is a UI specific helper that helps determine the width of a progress bar.
func (rs *ResultSummary) WarningWidth(fullWidth uint) uint {
return uint(float64(rs.Successes+rs.Warnings) / float64(rs.Successes+rs.Warnings+rs.Failures) * float64(fullWidth))
}

// SuccessWidth is a UI specific helper that helps determine the width of a progress bar.
func (rs *ResultSummary) SuccessWidth(fullWidth uint) uint {
return uint(float64(rs.Successes) / float64(rs.Successes+rs.Warnings+rs.Failures) * float64(fullWidth))
}

// HTMLSpecialCharCode is a UI specific helper that provides an HTML char code.
func (rm *ResultMessage) HTMLSpecialCharCode() string {
switch rm.Type {
case "success":
Expand Down

0 comments on commit bfcda87

Please sign in to comment.