Skip to content

Commit

Permalink
score: add descriptions to all comments
Browse files Browse the repository at this point in the history
  • Loading branch information
zegl committed Sep 27, 2018
1 parent 9892b79 commit 7518b60
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 24 deletions.
2 changes: 1 addition & 1 deletion cmd/kube-score/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func main() {
color.New(col).Printf(" [%s] %s\n", status, card.Name)

for _, comment := range card.Comments {
fmt.Printf(" * %s\n", comment)
fmt.Printf(" * %s (%s)\n", comment.Summary, comment.Description)
}

sumGrade += card.Grade
Expand Down
34 changes: 17 additions & 17 deletions score/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,26 @@ func scoreContainerLimits(podTemplate corev1.PodTemplateSpec) (score scorecard.T

for _, container := range allContainers {
if container.Resources.Limits.Cpu().IsZero() {
score.Comments = append(score.Comments, "CPU limit is not set")
score.AddComment("", "CPU limit is not set", "Resource limits are recommended to avoid resource DDOS")
hasMissingLimit = true
}
if container.Resources.Limits.Memory().IsZero() {
score.Comments = append(score.Comments, "Memory limit is not set")
score.AddComment("", "Memory limit is not set", "Resource limits are recommended to avoid resource DDOS")
hasMissingLimit = true
}
if container.Resources.Requests.Cpu().IsZero() {
score.Comments = append(score.Comments, "CPU request is not set")
score.AddComment("", "CPU request is not set", "Resource requests are recommended to make sure that the application can start and run without crashing")
hasMissingRequest = true
}
if container.Resources.Requests.Memory().IsZero() {
score.Comments = append(score.Comments, "Memory request is not set")
score.AddComment("", "Memory request is not set", "Resource requests are recommended to make sure that the application can start and run without crashing")
hasMissingRequest = true
}
}

if len(allContainers) == 0 {
score.Grade = 0
score.Comments = append(score.Comments, "No containers defined")
score.AddComment("", "No containers defined", "")
} else if hasMissingLimit {
score.Grade = 0
} else if hasMissingRequest {
Expand All @@ -67,7 +67,7 @@ func scoreContainerImageTag(podTemplate corev1.PodTemplateSpec) (score scorecard
imageVersion := imageParts[len(imageParts)-1]

if imageVersion == "latest" {
score.Comments = append(score.Comments, "Image with latest tag")
score.AddComment("", "Image with latest tag", "Using a fixed tag is recommended to avoid accidental upgrades")
hasTagLatest = true
}
}
Expand All @@ -93,7 +93,7 @@ func scoreContainerImagePullPolicy(podTemplate corev1.PodTemplateSpec) (score sc

for _, container := range allContainers{
if container.ImagePullPolicy != corev1.PullAlways {
score.Comments = append(score.Comments, "ImagePullPolicy is not set to PullAlways")
score.AddComment("", "ImagePullPolicy is not set to PullAlways", "It's recommended to always set the ImagePullPolicy to PullAlways, to make sure that the imagePullSecrets are always correct, and to always get the image you want.")
hasNonAlways = true
}
}
Expand Down Expand Up @@ -121,12 +121,12 @@ func scoreContainerProbes(podTemplate corev1.PodTemplateSpec) (score scorecard.T
for _, container := range allContainers {
if container.ReadinessProbe == nil {
hasReadinessProbe = false
score.Comments = append(score.Comments, "Container is missing readinessProbe")
score.AddComment("", "Container is missing a readinessProbe", "Without a readinessProbe Services will start sending traffic to this pod before it's ready")
}

if container.LivenessProbe == nil {
hasLivenessProbe = false
score.Comments = append(score.Comments, "Container is missing livenessProbe")
score.AddComment("", "Container is missing a livenessProbe", "Without a livenessProbe kubelet can not restart the Pod if it has crashed")
}

if container.ReadinessProbe != nil && container.LivenessProbe != nil {
Expand All @@ -137,15 +137,15 @@ func scoreContainerProbes(podTemplate corev1.PodTemplateSpec) (score scorecard.T
if r.HTTPGet != nil && l.HTTPGet != nil {
if r.HTTPGet.Path == l.HTTPGet.Path &&
r.HTTPGet.Port.IntValue() == l.HTTPGet.Port.IntValue() {
probesAreIdentical = true
score.Comments = append(score.Comments, "Container has the same readiness and liveness probe")
probesAreIdentical = true
score.AddComment("", "Container has the same readiness and liveness probe", "It's recommended to have different probes for the two different purposes.")
}
}

if r.TCPSocket != nil && l.TCPSocket != nil {
if r.TCPSocket.Port == l.TCPSocket.Port {
probesAreIdentical = true
score.Comments = append(score.Comments, "Container has the same readiness and liveness probe")
score.AddComment("", "Container has the same readiness and liveness probe", "It's recommended to have different probes for the two different purposes.")
}
}

Expand All @@ -161,7 +161,7 @@ func scoreContainerProbes(podTemplate corev1.PodTemplateSpec) (score scorecard.T

if !hasDifferent {
probesAreIdentical = true
score.Comments = append(score.Comments, "Container has the same readiness and liveness probe")
score.AddComment("", "Container has the same readiness and liveness probe", "It's recommended to have different probes for the two different purposes.")
}
}
}
Expand Down Expand Up @@ -205,22 +205,22 @@ func scoreContainerSecurityContext(podTemplate corev1.PodTemplateSpec) (score sc

if sec.Privileged != nil && *sec.Privileged {
hasPrivileged = true
score.Comments = append(score.Comments, "The pod has a privileged container")
score.AddComment("", "The container is privileged", "")
}

if sec.ReadOnlyRootFilesystem != nil && *sec.ReadOnlyRootFilesystem == false {
hasWritableRootFS = true
score.Comments = append(score.Comments, "The pod has a container with a writable root filesystem")
score.AddComment("", "The pod has a container with a writable root filesystem", "")
}

if sec.RunAsUser != nil && *sec.RunAsUser < 10000 {
hasLowUserID = true
score.Comments = append(score.Comments, "The pod has a container running with a low user ID")
score.AddComment("", "The container is running with a low user ID", "A userid above 10 000 is recommended to avoid conflicts with the host")
}

if sec.RunAsGroup != nil && *sec.RunAsGroup < 10000 {
hasLowGroupID = true
score.Comments = append(score.Comments, "The pod has a container running with a low group ID")
score.AddComment("", "The container running with a low group ID", "A groupid above 10 000 is recommended to avoid conflicts with the host")
}
}

Expand Down
6 changes: 3 additions & 3 deletions score/networkpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ func scorePodHasNetworkPolicy(allNetpols []networkingv1.NetworkPolicy) func(spec
score.Grade = 10
} else if hasMatchingEgressNetpol && !hasMatchingIngressNetpol {
score.Grade = 5
score.Comments = append(score.Comments, "The pod does not have a matching ingress network policy")
score.AddComment("", "The pod does not have a matching ingress network policy", "")
} else if hasMatchingIngressNetpol && !hasMatchingEgressNetpol {
score.Grade = 5
score.Comments = append(score.Comments, "The pod does not have a matching egress network policy")
score.AddComment("", "The pod does not have a matching egress network policy", "")
} else {
score.Grade = 0
score.Comments = append(score.Comments, "The pod does not have a matching network policy")
score.AddComment("", "The pod does not have a matching network policy", "")
}

return
Expand Down
10 changes: 8 additions & 2 deletions score/stableVersion.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package score

import "github.com/zegl/kube-score/scorecard"
import (
"fmt"
"github.com/zegl/kube-score/scorecard"
)
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

func scoreMetaStableAvailable(meta metav1.TypeMeta) (score scorecard.TestScore) {
Expand All @@ -25,7 +28,10 @@ func scoreMetaStableAvailable(meta metav1.TypeMeta) (score scorecard.TestScore)
if inVersion, ok := withStable[meta.APIVersion]; ok {
if recommendedVersion, ok := inVersion[meta.Kind]; ok {
score.Grade = 5
score.Comments = []string{"Recommended replacement: " + recommendedVersion}
score.AddComment("",
fmt.Sprintf("The apiVersion and kind %s/%s is deprecated", meta.APIVersion, meta.Kind),
fmt.Sprintf("It's recommended to use %s instead", recommendedVersion),
)
return
}
}
Expand Down
16 changes: 15 additions & 1 deletion scorecard/scorecard.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,21 @@ type TestScore struct {
}

Grade int
Comments []string
Comments []TestScoreComment
}

type TestScoreComment struct {
Path string
Summary string
Description string
}

func (ts *TestScore) AddComment(path, summary, description string) {
ts.Comments = append(ts.Comments, TestScoreComment{
Path: path,
Summary: summary,
Description: description,
})
}

func (ts *TestScore) AddMeta(typeMeta metav1.TypeMeta, objectMeta metav1.ObjectMeta) {
Expand Down

0 comments on commit 7518b60

Please sign in to comment.