Skip to content

Commit

Permalink
including successes in dashboard output
Browse files Browse the repository at this point in the history
  • Loading branch information
robscott committed Jan 29, 2019
1 parent 5c5eefa commit 9d3f78e
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 76 deletions.
11 changes: 10 additions & 1 deletion config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
resources:
requests:
cpu:
min: 100m
min: 50m
max: 1
memory:
min: 100M
Expand All @@ -13,3 +13,12 @@ resources:
memory:
min: 150M
max: 4G
healthChecks:
readiness:
require: true
liveness:
require: true
images:
tagRequired: true
whitelistRepos:
- gcr.io
62 changes: 31 additions & 31 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,43 @@ import (
"k8s.io/apimachinery/pkg/util/yaml"
)

// ResourceMinMax sets a range for a min and max setting for a resource.
type ResourceMinMax struct {
Min *resource.Quantity
Max *resource.Quantity
// Configuration contains all of the config for the validation checks.
type Configuration struct {
Resources RequestsAndLimits `json:"resources"`
HealthChecks Probes `json:"healthChecks"`
Images Images `json:"images"`
}

// RequestsAndLimits contains config for resource requests and limits.
type RequestsAndLimits struct {
Requests ResourceList `json:"requests"`
Limits ResourceList `json:"limits"`
}

// ResourceList maps the resource name to a range on min and max values.
type ResourceList map[corev1.ResourceName]ResourceMinMax

// RequestsAndLimits contains config for resource requests and limits.
type RequestsAndLimits struct {
Requests ResourceList
Limits ResourceList
// ResourceMinMax sets a range for a min and max setting for a resource.
type ResourceMinMax struct {
Min *resource.Quantity `json:"min"`
Max *resource.Quantity `json:"max"`
}

// Configuration contains all of the config for the validation checks.
type Configuration struct {
Resources RequestsAndLimits
HealthChecks Probes
Images Images
// Probes contains config for the readiness and liveness probes.
type Probes struct {
Readiness ResourceRequire `json:"readiness"`
Liveness ResourceRequire `json:"liveness"`
}

// ResourceRequire indicates if this resource should be validated.
type ResourceRequire struct {
Require bool `json:"require"`
}

// Images contains the config for images.
type Images struct {
TagRequired bool `json:"tagRequired"`
WhitelistRepos []string `json:"whitelistRepos"`
}

// ParseFile parses config from a file.
Expand All @@ -52,24 +69,7 @@ func Parse(rawBytes []byte) (Configuration, error) {
if err == io.EOF {
return conf, nil
}
return Configuration{}, fmt.Errorf("Decoding config failed: %v", err)
return conf, fmt.Errorf("Decoding config failed: %v", err)
}
}
}

// Probes contains config for the readiness and liveness probes.
type Probes struct {
Readiness ResourceRequire
Liveness ResourceRequire
}

// ResourceRequire indicates if this resource should be validated.
type ResourceRequire struct {
Require bool
}

// Images contains the config for images.
type Images struct {
TagRequired bool
WhitelistRepos []string
}
37 changes: 16 additions & 21 deletions pkg/dashboard/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ func getDashboardData(c conf.Configuration) (DashboardData, error) {

dashboardData := DashboardData{
ClusterSummary: &validator.ResultSummary{
Successes: 46,
Warnings: 8,
Failures: 5,
Successes: 0,
Warnings: 4,
Failures: 0,
},
NamespacedResults: map[string]*validator.NamespacedResult{},
}
Expand All @@ -67,36 +67,31 @@ func getDashboardData(c conf.Configuration) (DashboardData, error) {
Name: deploy.Name,
Type: "Deployment",
Summary: &validator.ResultSummary{
Successes: 16,
Warnings: 4,
Failures: 2,
Successes: 0,
Warnings: 2,
Failures: 0,
},
}

if dashboardData.NamespacedResults[deploy.Namespace] == nil {
dashboardData.NamespacedResults[deploy.Namespace] = &validator.NamespacedResult{
Results: []validator.ResourceResult{},
Summary: &validator.ResultSummary{
Successes: 16,
Warnings: 4,
Failures: 2,
Successes: 0,
Warnings: 3,
Failures: 0,
},
}
}

for _, containerValidation := range validationFailures.InitContainerValidations {
for _, failure := range containerValidation.Failures {
dashboardData.ClusterSummary.Failures++
dashboardData.NamespacedResults[deploy.Namespace].Summary.Failures++
resResult.Summary.Failures++
resResult.Messages = append(resResult.Messages, validator.ResultMessage{
Message: failure.Reason(),
Type: "failure",
})
containerValidations := append(validationFailures.InitContainerValidations, validationFailures.ContainerValidations...)
for _, containerValidation := range containerValidations {
for _, success := range containerValidation.Successes {
dashboardData.ClusterSummary.Successes++
dashboardData.NamespacedResults[deploy.Namespace].Summary.Successes++
resResult.Summary.Successes++
resResult.Messages = append(resResult.Messages, success)
}
}

for _, containerValidation := range validationFailures.ContainerValidations {
for _, failure := range containerValidation.Failures {
dashboardData.ClusterSummary.Failures++
dashboardData.NamespacedResults[deploy.Namespace].Summary.Failures++
Expand Down
2 changes: 1 addition & 1 deletion pkg/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Failure struct {

// Reason returns a string that describes the reason for a Failure.
func (f *Failure) Reason() string {
return fmt.Sprintf("- %s: Expected: %s, Actual: %s.\n",
return fmt.Sprintf("%s: Expected: %s, Actual: %s.",
f.Name,
f.Expected,
f.Actual,
Expand Down
30 changes: 26 additions & 4 deletions pkg/validator/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package validator

import (
"fmt"
"strings"

conf "github.com/reactiveops/fairwinds/pkg/config"
Expand All @@ -27,6 +28,7 @@ import (
type ContainerValidation struct {
Container corev1.Container
Failures []types.Failure
Successes []ResultMessage
}

func validateContainer(conf conf.Configuration, container corev1.Container) ContainerValidation {
Expand All @@ -49,6 +51,13 @@ func (cv *ContainerValidation) addFailure(name, expected, actual string) {
})
}

func (cv *ContainerValidation) addSuccess(message string) {
cv.Successes = append(cv.Successes, ResultMessage{
Message: message,
Type: "success",
})
}

func (cv *ContainerValidation) validateResources(conf conf.RequestsAndLimits) {
actualRes := cv.Container.Resources
cv.withinRange("requests.cpu", conf.Requests["cpu"], actualRes.Requests.Cpu())
Expand All @@ -64,15 +73,26 @@ func (cv *ContainerValidation) withinRange(resourceName string, expectedRange co
cv.addFailure(resourceName, expectedMin.String(), actual.String())
} else if expectedMax != nil && expectedMax.MilliValue() < actual.MilliValue() {
cv.addFailure(resourceName, expectedMax.String(), actual.String())
} else {
cv.addSuccess(fmt.Sprintf("Resource %s within expected range", resourceName))
}
}

func (cv *ContainerValidation) validateHealthChecks(conf conf.Probes) {
if conf.Readiness.Require && cv.Container.ReadinessProbe == nil {
cv.addFailure("readiness", "probe needs to be configured", "nil")
if conf.Readiness.Require {
if cv.Container.ReadinessProbe == nil {
cv.addFailure("readiness", "probe needs to be configured", "nil")
} else {
cv.addSuccess("Readiness probe configured")
}
}
if conf.Liveness.Require && cv.Container.LivenessProbe == nil {
cv.addFailure("liveness", "probe needs to be configured", "nil")

if conf.Liveness.Require {
if cv.Container.LivenessProbe == nil {
cv.addFailure("liveness", "probe needs to be configured", "nil")
} else {
cv.addSuccess("Liveness probe configured")
}
}
}

Expand All @@ -81,6 +101,8 @@ func (cv *ContainerValidation) validateImage(conf conf.Images) {
img := strings.Split(cv.Container.Image, ":")
if len(img) == 1 || img[1] == "latest" {
cv.addFailure("Image Tag", "not latest", "latest")
} else {
cv.addSuccess("Image tag specified")
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/validator/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func validContainer(sb *strings.Builder, cv *ContainerValidation) bool {
s := fmt.Sprintf("\nContainer: %s\n Failure/s:\n", cv.Container.Name)
sb.WriteString(s)
for _, failure := range cv.Failures {
sb.WriteString(failure.Reason())
sb.WriteString(fmt.Sprintf("- %s\n", failure.Reason()))
}
return false
}
17 changes: 0 additions & 17 deletions pkg/validator/types.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
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 {
Summary *ResultSummary
Results []ResourceResult
Expand Down

0 comments on commit 9d3f78e

Please sign in to comment.