Repository: zegl/kube-score (go)

Issue:
Container image pull policy is asking for an invalid value
My YAML container image pull policy says:
 imagePullPolicy: Always

and kube-core is recommending "PullAlways" value
[CRITICAL] Container Image Pull Policy
        * esp -> 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.

however, that is not a valid value according to latest API definition:
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.12/

Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images

Pull request description:
pullpolicy: handle containers without a explicit imagePullPolicy set
A typo in the issue description that recommended the policy "PullAlways" instead of "Always" was also fixed

Fixes #39

Patch:
diff --git a/score/container/container.go b/score/container/container.go
index 7a4221c..3e35865 100644
--- a/score/container/container.go
+++ b/score/container/container.go
@@ -68,10 +68,8 @@ func ScoreContainerImageTag(podTemplate corev1.PodTemplateSpec) (score scorecard
 	hasTagLatest := false
 
 	for _, container := range allContainers {
-		imageParts := strings.Split(container.Image, ":")
-		imageVersion := imageParts[len(imageParts)-1]
-
-		if imageVersion == "latest" {
+		tag := containerTag(container.Image)
+		if tag == "" || tag == "latest" {
 			score.AddComment(container.Name, "Image with latest tag", "Using a fixed tag is recommended to avoid accidental upgrades")
 			hasTagLatest = true
 		}
@@ -98,9 +96,18 @@ func ScoreContainerImagePullPolicy(podTemplate corev1.PodTemplateSpec) (score sc
 	hasNonAlways := false
 
 	for _, container := range allContainers {
-		if container.ImagePullPolicy != corev1.PullAlways {
-			score.AddComment(container.Name, "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
+
+		// No defined pull policy
+		if container.ImagePullPolicy == corev1.PullPolicy("") {
+			tag := containerTag(container.Image)
+			if tag != "" && tag != "latest" {
+				hasNonAlways = true
+			}
+		} else {
+			if container.ImagePullPolicy != corev1.PullAlways {
+				score.AddComment(container.Name, "ImagePullPolicy is not set to Always", "It's recommended to always set the ImagePullPolicy to Always, to make sure that the imagePullSecrets are always correct, and to always get the image you want.")
+				hasNonAlways = true
+			}
 		}
 	}
 
@@ -112,3 +119,14 @@ func ScoreContainerImagePullPolicy(podTemplate corev1.PodTemplateSpec) (score sc
 
 	return
 }
+
+// containerTag returns the image tag
+// An empty string is returned if the image has no tag
+func containerTag(image string) string {
+	imageParts := strings.Split(image, ":")
+	if len(imageParts) > 1 {
+		imageVersion := imageParts[len(imageParts)-1]
+		return imageVersion
+	}
+	return ""
+}


Test patch:
diff --git a/score/score_test.go b/score/score_test.go
index 05abf67..b1a4e16 100644
--- a/score/score_test.go
+++ b/score/score_test.go
@@ -81,6 +81,14 @@ func TestPodContainerPullPolicyUndefined(t *testing.T) {
 	testExpectedScore(t, "pod-image-pullpolicy-undefined.yaml", "Container Image Pull Policy", 0)
 }
 
+func TestPodContainerPullPolicyUndefinedLatestTag(t *testing.T) {
+	testExpectedScore(t, "pod-image-pullpolicy-undefined-latest-tag.yaml", "Container Image Pull Policy", 10)
+}
+
+func TestPodContainerPullPolicyUndefinedNoTag(t *testing.T) {
+	testExpectedScore(t, "pod-image-pullpolicy-undefined-no-tag.yaml", "Container Image Pull Policy", 10)
+}
+
 func TestPodContainerPullPolicyNever(t *testing.T) {
 	testExpectedScore(t, "pod-image-pullpolicy-never.yaml", "Container Image Pull Policy", 0)
 }
diff --git a/score/testdata/pod-image-pullpolicy-undefined-latest-tag.yaml b/score/testdata/pod-image-pullpolicy-undefined-latest-tag.yaml
new file mode 100644
index 0000000..3a1508b
--- /dev/null
+++ b/score/testdata/pod-image-pullpolicy-undefined-latest-tag.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: pod-test-1
+spec:
+  containers:
+  - name: foobar
+    image: foo/bar:latest
diff --git a/score/testdata/pod-image-pullpolicy-undefined-no-tag.yaml b/score/testdata/pod-image-pullpolicy-undefined-no-tag.yaml
new file mode 100644
index 0000000..23fb3c7
--- /dev/null
+++ b/score/testdata/pod-image-pullpolicy-undefined-no-tag.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: pod-test-1
+spec:
+  containers:
+  - name: foobar
+    image: foo/bar