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 // 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 // (low-priority problems) and errors (high-priority problems) as well as an
// error value indicating that the check failed to run. // error value indicating that the check failed to run.
func (fq *fullyQualifiedImageCheck) Run(objects *kube.Objects) (warnings []error, errors []error, err error) { func (fq *fullyQualifiedImageCheck) Run(objects *kube.Objects) ([]error, []error, error) {
var w []error var warnings, errors []error
for _, pod := range objects.Pods.Items { for _, pod := range objects.Pods.Items {
podName := pod.GetName() podName := pod.GetName()
namespace := pod.GetNamespace() namespace := pod.GetNamespace()
w = append(w, checkImage(pod.Spec.Containers, podName, namespace)...) w, e := checkImage(pod.Spec.Containers, podName, namespace)
w = append(w, checkImage(pod.Spec.InitContainers, 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 // checkImage checks if the image name is fully qualified
// Adds a warning if the container does not use a fully qualified image name // Adds a warning if the container does not use a fully qualified image name
func checkImage(containers []corev1.Container, podName string, namespace string) []error { func checkImage(containers []corev1.Container, podName string, namespace string) ([]error, []error) {
var w []error var w, e []error
for _, container := range containers { for _, container := range containers {
if value, err := reference.ParseAnyReference(container.Image); err != nil || value.String() != container.Image { 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)) 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", name: "pod with container image - busybox:latest",
arg: container("busybox:latest"), arg: container("busybox:latest"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - k8s.gcr.io/busybox", name: "pod with container image - k8s.gcr.io/busybox",
@ -53,7 +53,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{ {
name: "pod with container image - busybox", name: "pod with container image - busybox",
arg: container("busybox"), arg: container("busybox"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - test:5000/repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 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", name: "pod with container image - repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: container("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", 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", name: "pod with container image - repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: container("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", 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", name: "pod with container image - busybox:latest",
arg: initContainer("busybox:latest"), arg: initContainer("busybox:latest"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - k8s.gcr.io/busybox", name: "pod with container image - k8s.gcr.io/busybox",
@ -93,7 +93,7 @@ func TestFullyQualifiedImageWarning(t *testing.T) {
{ {
name: "pod with container image - busybox", name: "pod with container image - busybox",
arg: initContainer("busybox"), arg: initContainer("busybox"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - test:5000/repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 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", name: "pod with container image - repo/image@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: initContainer("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", 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", name: "pod with container image - repo/image:ignore-tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
arg: initContainer("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 { for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) { t.Run(scenario.name, func(t *testing.T) {
w, e, err := fullyQualifiedImageCheck.Run(scenario.arg) w, e, err := fullyQualifiedImageCheck.Run(scenario.arg)
assert.NoError(t, err)
assert.ElementsMatch(t, scenario.expected, w) assert.ElementsMatch(t, scenario.expected, w)
assert.Empty(t, e) 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 return objs
} }
func warnings(s string) []error { func issues(s string) []error {
w := []error{ issue := []error{
fmt.Errorf(s), 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", name: "pod with container image - k8s.gcr.io/busybox:latest",
arg: container("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", name: "pod with container image - busybox:latest",
arg: container("busybox:latest"), arg: container("busybox:latest"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - k8s.gcr.io/busybox", name: "pod with container image - k8s.gcr.io/busybox",
arg: container("k8s.gcr.io/busybox"), arg: container("k8s.gcr.io/busybox"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - busybox", name: "pod with container image - busybox",
arg: container("busybox"), arg: container("busybox"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - private:5000/repo/busybox", name: "pod with container image - private:5000/repo/busybox",
arg: container("http://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", name: "pod with container image - private:5000/repo/busybox:latest",
arg: container("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", 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", name: "pod with init container image - k8s.gcr.io/busybox:latest",
arg: initContainer("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", name: "pod with init container image - busybox:latest",
arg: initContainer("busybox:latest"), arg: initContainer("busybox:latest"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with init container image - k8s.gcr.io/busybox", name: "pod with init container image - k8s.gcr.io/busybox",
arg: initContainer("k8s.gcr.io/busybox"), arg: initContainer("k8s.gcr.io/busybox"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with init container image - busybox", name: "pod with init container image - busybox",
arg: initContainer("busybox"), arg: initContainer("busybox"),
expected: warnings(warning), expected: issues(warning),
}, },
{ {
name: "pod with container image - http://private:5000/repo/busybox", name: "pod with container image - http://private:5000/repo/busybox",
arg: container("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", name: "pod with container image - http://private:5000/repo/busybox:latest",
arg: container("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", name: "pod with container image - test:5000/repo@sha256:digest",