Separate messages for malformed image and fully qualified image.

varsha/versions
Varsha Varadarajan 2019-06-20 15:13:43 -04:00
parent d1469a006c
commit e8223d9204
4 changed files with 76 additions and 34 deletions

View File

@ -34,27 +34,36 @@ func (fq *fullyQualifiedImageCheck) Description() string {
// Run runs this check on a set of Kubernetes objects. It can return warnings
// (low-priority problems) and errors (high-priority problems) as well as an
// error value indicating that the check failed to run.
func (fq *fullyQualifiedImageCheck) Run(objects *kube.Objects) (warnings []error, errors []error, err error) {
var w []error
func (fq *fullyQualifiedImageCheck) Run(objects *kube.Objects) ([]error, []error, error) {
var warnings, errors []error
for _, pod := range objects.Pods.Items {
podName := pod.GetName()
namespace := pod.GetNamespace()
w = append(w, checkImage(pod.Spec.Containers, podName, namespace)...)
w = append(w, checkImage(pod.Spec.InitContainers, podName, namespace)...)
w, e := checkImage(pod.Spec.Containers, podName, namespace)
warnings = append(warnings, w...)
errors = append(errors, e...)
w, e = checkImage(pod.Spec.InitContainers, podName, namespace)
warnings = append(warnings, w...)
errors = append(errors, e...)
}
return w, nil, nil
return warnings, errors, nil
}
// checkImage checks if the image name is fully qualified
// Adds a warning if the container does not use a fully qualified image name
func checkImage(containers []corev1.Container, podName string, namespace string) []error {
var w []error
func checkImage(containers []corev1.Container, podName string, namespace string) ([]error, []error) {
var w, e []error
for _, container := range containers {
if value, err := reference.ParseAnyReference(container.Image); err != nil || value.String() != container.Image {
w = append(w, fmt.Errorf("[Best Practice] Use fully qualified image for container '%s' in pod '%s' in namespace '%s'", container.Name, podName, namespace))
value, err := reference.ParseAnyReference(container.Image)
if err != nil {
e = append(e, fmt.Errorf("[Error] Malformed image name for container '%s' in pod '%s' in namespace '%s'", container.Name, podName, namespace))
} else {
if value.String() != container.Image {
w = append(w, fmt.Errorf("[Best Practice] Use fully qualified image for container '%s' in pod '%s' in namespace '%s'", container.Name, podName, namespace))
}
}
}
return w
return w, e
}

View File

@ -43,7 +43,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox:latest",
arg: container("busybox:latest"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - k8s.gcr.io/busybox",
@ -53,7 +53,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox",
arg: container("busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - test:5000/repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -63,7 +63,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: container("repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - test:5000/repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -73,7 +73,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: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - k8s.gcr.io/busybox:latest",
@ -83,7 +83,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox:latest",
arg: initContainer("busybox:latest"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - k8s.gcr.io/busybox",
@ -93,7 +93,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - busybox",
arg: initContainer("busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - test:5000/repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -103,7 +103,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{
name: "pod with container image - repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: initContainer("repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - test:5000/repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@ -113,7 +113,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: warnings(warning),
expected: issues(warning),
},
}
@ -122,9 +122,42 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) {
w, e, err := fullyQualifiedImageCheck.Run(scenario.arg)
assert.NoError(t, err)
assert.ElementsMatch(t, scenario.expected, w)
assert.Empty(t, e)
assert.Nil(t, err)
})
}
}
func TestMalformedImageError(t *testing.T) {
const e string = "[Error] Malformed image name for container 'bar' in pod 'pod_foo' in namespace 'k8s'"
scenarios := []struct {
name string
arg *kube.Objects
expected []error
}{
{
name: "container with image : test:5000/repo/image@sha256:digest",
arg: container("test:5000/repo/image@sha256:digest"),
expected: issues(e),
},
{
name: "init container with image : test:5000/repo/image@sha256:digest",
arg: initContainer("test:5000/repo/image@sha256:digest"),
expected: issues(e),
},
}
fullyQualifiedImageCheck := fullyQualifiedImageCheck{}
for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) {
w, e, err := fullyQualifiedImageCheck.Run(scenario.arg)
assert.NoError(t, err)
assert.ElementsMatch(t, scenario.expected, e)
assert.Empty(t, w)
})
}
}

View File

@ -45,9 +45,9 @@ func initContainer(image string) *kube.Objects {
return objs
}
func warnings(s string) []error {
w := []error{
func issues(s string) []error {
issue := []error{
fmt.Errorf(s),
}
return w
return issue
}

View File

@ -37,32 +37,32 @@ func TestLatestTagWarning(t *testing.T) {
{
name: "pod with container image - k8s.gcr.io/busybox:latest",
arg: container("k8s.gcr.io/busybox:latest"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - busybox:latest",
arg: container("busybox:latest"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - k8s.gcr.io/busybox",
arg: container("k8s.gcr.io/busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - busybox",
arg: container("busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - private:5000/repo/busybox",
arg: container("http://private:5000/repo/busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - private:5000/repo/busybox:latest",
arg: container("http://private:5000/repo/busybox:latest"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - test:5000/repo@sha256:digest",
@ -88,32 +88,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: warnings(warning),
expected: issues(warning),
},
{
name: "pod with init container image - busybox:latest",
arg: initContainer("busybox:latest"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with init container image - k8s.gcr.io/busybox",
arg: initContainer("k8s.gcr.io/busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with init container image - busybox",
arg: initContainer("busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - http://private:5000/repo/busybox",
arg: container("http://private:5000/repo/busybox"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - http://private:5000/repo/busybox:latest",
arg: container("http://private:5000/repo/busybox:latest"),
expected: warnings(warning),
expected: issues(warning),
},
{
name: "pod with container image - test:5000/repo@sha256:digest",