Remove TypeMeta from Diagnostic.

* The k8s API does not set TypeMeta on objects when the list API is used
varsha/versions
Varsha Varadarajan 2019-06-25 10:35:34 -04:00
parent 4be81f8fca
commit 171ba02f4e
14 changed files with 84 additions and 62 deletions

View File

@ -57,7 +57,8 @@ func checkImage(containers []corev1.Container, pod corev1.Pod) []checks.Diagnost
d := checks.Diagnostic{
Severity: checks.Error,
Message: fmt.Sprintf("Malformed image name for container '%s' in pod '%s'", container.Name, pod.GetName()),
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
}
diagnostics = append(diagnostics, d)
@ -66,7 +67,8 @@ func checkImage(containers []corev1.Container, pod corev1.Pod) []checks.Diagnost
d := checks.Diagnostic{
Severity: checks.Warning,
Message: fmt.Sprintf("Use fully qualified image for container '%s' in pod '%s'", container.Name, pod.GetName()),
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
}
diagnostics = append(diagnostics, d)

View File

@ -44,7 +44,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox:latest",
arg: container("busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - k8s.gcr.io/busybox",
@ -54,7 +54,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox",
arg: container("busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - test:5000/repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -64,7 +64,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: container("repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - test:5000/repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -74,7 +74,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: container("repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - k8s.gcr.io/busybox:latest",
@ -84,7 +84,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox:latest",
arg: initContainer("busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - k8s.gcr.io/busybox",
@ -94,7 +94,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox",
arg: initContainer("busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - test:5000/repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -104,7 +104,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: initContainer("repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - test:5000/repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -114,7 +114,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: initContainer("repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
}
@ -140,12 +140,12 @@ func TestMalformedImageError(t *testing.T) {
{
name: "container with image : test:5000/repo/image@sha256:digest",
arg: container("test:5000/repo/image@sha256:digest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "init container with image : test:5000/repo/image@sha256:digest",
arg: initContainer("test:5000/repo/image@sha256:digest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
}
fullyQualifiedImageCheck := fullyQualifiedImageCheck{}

View File

@ -21,11 +21,6 @@ func initPod() *kube.Objects {
return objs
}
func GetTypeMeta() *metav1.TypeMeta {
objs := initPod()
return &objs.Pods.Items[0].TypeMeta
}
func GetObjectMeta() *metav1.ObjectMeta {
objs := initPod()
return &objs.Pods.Items[0].ObjectMeta
@ -60,12 +55,13 @@ func initContainer(image string) *kube.Objects {
return objs
}
func issues(severity checks.Severity, message string) []checks.Diagnostic {
func issues(severity checks.Severity, message string, kind checks.Kind) []checks.Diagnostic {
d := []checks.Diagnostic{
{
Severity: severity,
Message: message,
Object: kube.Object{TypeInfo: GetTypeMeta(), ObjectInfo: GetObjectMeta()},
Kind: kind,
Object: GetObjectMeta(),
Owners: GetOwners(),
},
}

View File

@ -56,7 +56,8 @@ func checkTags(containers []corev1.Container, pod corev1.Pod) []checks.Diagnosti
d := checks.Diagnostic{
Severity: checks.Warning,
Message: fmt.Sprintf("Avoid using latest tag for container '%s' in pod '%s'", container.Name, pod.GetName()),
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
}
diagnostics = append(diagnostics, d)

View File

@ -39,32 +39,32 @@ func TestLatestTagWarning(t *testing.T) {
{
name: "pod with container image - k8s.gcr.io/busybox:latest",
arg: container("k8s.gcr.io/busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - busybox:latest",
arg: container("busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - k8s.gcr.io/busybox",
arg: container("k8s.gcr.io/busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - busybox",
arg: container("busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - private:5000/busybox",
arg: container("private:5000/repo/busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - private:5000/busybox:latest",
arg: container("private:5000/repo/busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - test:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -90,32 +90,32 @@ func TestLatestTagWarning(t *testing.T) {
{
name: "pod with init container image - k8s.gcr.io/busybox:latest",
arg: initContainer("k8s.gcr.io/busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with init container image - busybox:latest",
arg: initContainer("busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with init container image - k8s.gcr.io/busybox",
arg: initContainer("k8s.gcr.io/busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with init container image - busybox",
arg: initContainer("busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - private:5000/busybox",
arg: container("private:5000/repo/busybox"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - private:5000/busybox:latest",
arg: container("private:5000/repo/busybox:latest"),
expected: issues(severity, message),
expected: issues(severity, message, checks.Pod),
},
{
name: "pod with container image - test:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",

View File

@ -34,11 +34,12 @@ func (alert *alert) SetDiagnostics(d []checks.Diagnostic) {
}
// warn adds warnings for k8s objects that should not be in the default namespace
func (alert *alert) warn(k8stype string, itemMeta metav1.ObjectMeta, itemType metav1.TypeMeta) {
func (alert *alert) warn(k8stype checks.Kind, itemMeta metav1.ObjectMeta) {
d := checks.Diagnostic{
Severity: checks.Warning,
Message: fmt.Sprintf("Avoid using the default namespace for %s '%s'", k8stype, itemMeta.GetName()),
Object: kube.Object{TypeInfo: &itemType, ObjectInfo: &itemMeta},
Kind: k8stype,
Object: &itemMeta,
Owners: itemMeta.GetOwnerReferences(),
}
alert.mu.Lock()
@ -66,7 +67,7 @@ func (nc *defaultNamespaceCheck) Description() string {
func checkPods(items *corev1.PodList, alert *alert) {
for _, item := range items.Items {
if corev1.NamespaceDefault == item.GetNamespace() {
alert.warn("pod", item.ObjectMeta, item.TypeMeta)
alert.warn(checks.Pod, item.ObjectMeta)
}
}
}
@ -75,7 +76,7 @@ func checkPods(items *corev1.PodList, alert *alert) {
func checkPodTemplates(items *corev1.PodTemplateList, alert *alert) {
for _, item := range items.Items {
if corev1.NamespaceDefault == item.GetNamespace() {
alert.warn("pod template", item.ObjectMeta, item.TypeMeta)
alert.warn(checks.PodTemplate, item.ObjectMeta)
}
}
}
@ -84,7 +85,7 @@ func checkPodTemplates(items *corev1.PodTemplateList, alert *alert) {
func checkPVCs(items *corev1.PersistentVolumeClaimList, alert *alert) {
for _, item := range items.Items {
if corev1.NamespaceDefault == item.GetNamespace() {
alert.warn("persistent volume claim", item.ObjectMeta, item.TypeMeta)
alert.warn(checks.PVC, item.ObjectMeta)
}
}
}
@ -93,7 +94,7 @@ func checkPVCs(items *corev1.PersistentVolumeClaimList, alert *alert) {
func checkConfigMaps(items *corev1.ConfigMapList, alert *alert) {
for _, item := range items.Items {
if corev1.NamespaceDefault == item.GetNamespace() {
alert.warn("config map", item.ObjectMeta, item.TypeMeta)
alert.warn(checks.ConfigMap, item.ObjectMeta)
}
}
}
@ -102,7 +103,7 @@ func checkConfigMaps(items *corev1.ConfigMapList, alert *alert) {
func checkServices(items *corev1.ServiceList, alert *alert) {
for _, item := range items.Items {
if corev1.NamespaceDefault == item.GetNamespace() && item.GetName() != "kubernetes" {
alert.warn("service", item.ObjectMeta, item.TypeMeta)
alert.warn(checks.Service, item.ObjectMeta)
}
}
}
@ -111,7 +112,7 @@ func checkServices(items *corev1.ServiceList, alert *alert) {
func checkSecrets(items *corev1.SecretList, alert *alert) {
for _, item := range items.Items {
if corev1.NamespaceDefault == item.GetNamespace() && !strings.Contains(item.GetName(), "default-token-") {
alert.warn("secret", item.ObjectMeta, item.TypeMeta)
alert.warn(checks.Secret, item.ObjectMeta)
}
}
}
@ -120,7 +121,7 @@ func checkSecrets(items *corev1.SecretList, alert *alert) {
func checkSA(items *corev1.ServiceAccountList, alert *alert) {
for _, item := range items.Items {
if corev1.NamespaceDefault == item.GetNamespace() && item.GetName() != "default" {
alert.warn("service account", item.ObjectMeta, item.TypeMeta)
alert.warn(checks.SA, item.ObjectMeta)
}
}
}

View File

@ -86,43 +86,50 @@ func errors() []checks.Diagnostic {
{
Severity: checks.Warning,
Message: "Avoid using the default namespace for pod 'pod_foo'",
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
},
{
Severity: checks.Warning,
Message: "Avoid using the default namespace for pod template 'template_foo'",
Object: kube.Object{TypeInfo: &template.TypeMeta, ObjectInfo: &template.ObjectMeta},
Kind: checks.PodTemplate,
Object: &template.ObjectMeta,
Owners: template.ObjectMeta.GetOwnerReferences(),
},
{
Severity: checks.Warning,
Message: "Avoid using the default namespace for persistent volume claim 'pvc_foo'",
Object: kube.Object{TypeInfo: &pvc.TypeMeta, ObjectInfo: &pvc.ObjectMeta},
Kind: checks.PVC,
Object: &pvc.ObjectMeta,
Owners: pvc.ObjectMeta.GetOwnerReferences(),
},
{
Severity: checks.Warning,
Message: "Avoid using the default namespace for config map 'cm_foo'",
Object: kube.Object{TypeInfo: &cm.TypeMeta, ObjectInfo: &cm.ObjectMeta},
Kind: checks.ConfigMap,
Object: &cm.ObjectMeta,
Owners: cm.ObjectMeta.GetOwnerReferences(),
},
{
Severity: checks.Warning,
Message: "Avoid using the default namespace for service 'svc_foo'",
Object: kube.Object{TypeInfo: &service.TypeMeta, ObjectInfo: &service.ObjectMeta},
Kind: checks.Service,
Object: &service.ObjectMeta,
Owners: service.ObjectMeta.GetOwnerReferences(),
},
{
Severity: checks.Warning,
Message: "Avoid using the default namespace for secret 'secret_foo'",
Object: kube.Object{TypeInfo: &secret.TypeMeta, ObjectInfo: &secret.ObjectMeta},
Kind: checks.Secret,
Object: &secret.ObjectMeta,
Owners: secret.ObjectMeta.GetOwnerReferences(),
},
{
Severity: checks.Warning,
Message: "Avoid using the default namespace for service account 'sa_foo'",
Object: kube.Object{TypeInfo: &sa.TypeMeta, ObjectInfo: &sa.ObjectMeta},
Kind: checks.SA,
Object: &sa.ObjectMeta,
Owners: sa.ObjectMeta.GetOwnerReferences(),
},
}

View File

@ -41,7 +41,8 @@ func (p *podStatusCheck) Run(objects *kube.Objects) ([]checks.Diagnostic, error)
d := checks.Diagnostic{
Severity: checks.Warning,
Message: fmt.Sprintf("Pod '%s' in namespace '%s' has state: %s. Pod state should be `Running`, `Pending` or `Succeeded`.", pod.GetName(), pod.GetNamespace(), pod.Status.Phase),
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
}
diagnostics = append(diagnostics, d)

View File

@ -49,7 +49,8 @@ func TestPodStateError(t *testing.T) {
{
Severity: checks.Warning,
Message: "Pod 'pod_foo' in namespace 'k8s' has state: Failed. Pod state should be `Running`, `Pending` or `Succeeded`.",
Object: kube.Object{TypeInfo: GetTypeMeta(), ObjectInfo: GetObjectMeta()},
Kind: checks.Pod,
Object: GetObjectMeta(),
Owners: GetOwners(),
},
},
@ -61,7 +62,8 @@ func TestPodStateError(t *testing.T) {
{
Severity: checks.Warning,
Message: "Pod 'pod_foo' in namespace 'k8s' has state: Unknown. Pod state should be `Running`, `Pending` or `Succeeded`.",
Object: kube.Object{TypeInfo: GetTypeMeta(), ObjectInfo: GetObjectMeta()},
Kind: checks.Pod,
Object: GetObjectMeta(),
Owners: GetOwners(),
},
},

View File

@ -3,7 +3,6 @@ package checks
import (
"fmt"
"github.com/digitalocean/clusterlint/kube"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -11,19 +10,28 @@ import (
type Diagnostic struct {
Severity Severity
Message string
Object kube.Object
Kind Kind
Object *metav1.ObjectMeta
Owners []metav1.OwnerReference
}
func (d Diagnostic) String() string {
return fmt.Sprintf("[%s] %s/%s/%s: %s", d.Severity, d.Object.ObjectInfo.Namespace,
d.Object.TypeInfo.Kind, d.Object.ObjectInfo.Name, d.Message)
return fmt.Sprintf("[%s] %s/%s/%s: %s", d.Severity, d.Object.Namespace,
d.Kind, d.Object.Name, d.Message)
}
type Severity string
type Kind string
const (
Error Severity = "error"
Warning Severity = "warning"
Suggestion Severity = "suggestion"
Error Severity = "error"
Warning Severity = "warning"
Suggestion Severity = "suggestion"
Pod Kind = "pod"
PodTemplate Kind = "pod template"
PVC Kind = "persistent volume claim"
ConfigMap Kind = "config map"
Service Kind = "service"
Secret Kind = "secret"
SA Kind = "service account"
)

View File

@ -41,7 +41,8 @@ func (nc *podSelectorCheck) Run(objects *kube.Objects) ([]checks.Diagnostic, err
d := checks.Diagnostic{
Severity: checks.Error,
Message: fmt.Sprintf("Avoid node name label for node selector in pod: %s", pod.GetName()),
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
}
diagnostics = append(diagnostics, d)

View File

@ -79,7 +79,8 @@ func errors(objs *kube.Objects) []checks.Diagnostic {
{
Severity: checks.Error,
Message: "Avoid node name label for node selector in pod: pod_foo",
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
},
}

View File

@ -53,7 +53,8 @@ func checkPrivileged(containers []corev1.Container, pod corev1.Pod) []checks.Dia
d := checks.Diagnostic{
Severity: checks.Warning,
Message: fmt.Sprintf("[Best Practice] Privileged container '%s' found in pod '%s'", container.Name, pod.GetName()),
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
}
diagnostics = append(diagnostics, d)

View File

@ -178,7 +178,8 @@ func warnings(objs *kube.Objects) []checks.Diagnostic {
{
Severity: checks.Warning,
Message: "[Best Practice] Privileged container 'bar' found in pod 'pod_foo'",
Object: kube.Object{TypeInfo: &pod.TypeMeta, ObjectInfo: &pod.ObjectMeta},
Kind: checks.Pod,
Object: &pod.ObjectMeta,
Owners: pod.ObjectMeta.GetOwnerReferences(),
},
}