Repository: zegl/kube-score
Pull request #515 (2023-02-20 12:53:18)

Generic pod speccer


Patch:
diff --git a/score/checks/checks.go b/score/checks/checks.go
index 20a709c..758f829 100644
--- a/score/checks/checks.go
+++ b/score/checks/checks.go
@@ -3,14 +3,12 @@ package checks
 import (
 	"strings"
 
-	appsv1 "k8s.io/api/apps/v1"
-	corev1 "k8s.io/api/core/v1"
-	networkingv1 "k8s.io/api/networking/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
 	"github.com/zegl/kube-score/config"
 	ks "github.com/zegl/kube-score/domain"
 	"github.com/zegl/kube-score/scorecard"
+	appsv1 "k8s.io/api/apps/v1"
+	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 )
 
 func New(cnf config.Configuration) *Checks {
@@ -19,7 +17,7 @@ func New(cnf config.Configuration) *Checks {
 
 		all:                      make([]ks.Check, 0),
 		metas:                    make(map[string]GenCheck[ks.BothMeta]),
-		pods:                     make(map[string]PodCheck),
+		pods:                     make(map[string]GenCheck[ks.PodSpecer]),
 		services:                 make(map[string]GenCheck[corev1.Service]),
 		statefulsets:             make(map[string]GenCheck[appsv1.StatefulSet]),
 		deployments:              make(map[string]GenCheck[appsv1.Deployment]),
@@ -53,12 +51,6 @@ type MetaCheck struct {
 	Fn MetaCheckFn
 }
 
-type PodCheckFn = func(corev1.PodTemplateSpec, metav1.TypeMeta) scorecard.TestScore
-type PodCheck struct {
-	ks.Check
-	Fn PodCheckFn
-}
-
 type CheckFunc[T any] func(T) (scorecard.TestScore, error)
 
 type GenCheck[T any] struct {
@@ -69,7 +61,7 @@ type GenCheck[T any] struct {
 type Checks struct {
 	all                      []ks.Check
 	metas                    map[string]GenCheck[ks.BothMeta]
-	pods                     map[string]PodCheck
+	pods                     map[string]GenCheck[ks.PodSpecer]
 	services                 map[string]GenCheck[corev1.Service]
 	statefulsets             map[string]GenCheck[appsv1.StatefulSet]
 	deployments              map[string]GenCheck[appsv1.Deployment]
@@ -110,46 +102,34 @@ func (c *Checks) Metas() map[string]GenCheck[ks.BothMeta] {
 	return c.metas
 }
 
-func (c *Checks) RegisterPodCheck(name, comment string, fn PodCheckFn) {
-	ch := NewCheck(name, "Pod", comment, false)
-	c.registerPodCheck(PodCheck{ch, fn})
+func reg[T any](c *Checks, targetType, name, comment string, optional bool, fn CheckFunc[T], mp map[string]GenCheck[T]) {
+	ch := NewCheck(name, targetType, comment, optional)
+	check := GenCheck[T]{Check: ch, Fn: fn}
+	c.all = append(c.all, check.Check)
+	if !c.isEnabled(check.Check) {
+		return
+	}
+	mp[machineFriendlyName(ch.Name)] = check
 }
 
-func (c *Checks) RegisterOptionalPodCheck(name, comment string, fn PodCheckFn) {
-	ch := NewCheck(name, "Pod", comment, true)
-	c.registerPodCheck(PodCheck{ch, fn})
+func (c *Checks) RegisterPodCheck(name, comment string, fn CheckFunc[ks.PodSpecer]) {
+	reg(c, "Pod", name, comment, false, fn, c.pods)
 }
 
-func (c *Checks) registerPodCheck(ch PodCheck) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.pods[machineFriendlyName(ch.Name)] = ch
+func (c *Checks) RegisterOptionalPodCheck(name, comment string, fn CheckFunc[ks.PodSpecer]) {
+	reg(c, "Pod", name, comment, true, fn, c.pods)
 }
 
-func (c *Checks) Pods() map[string]PodCheck {
+func (c *Checks) Pods() map[string]GenCheck[ks.PodSpecer] {
 	return c.pods
 }
 
 func (c *Checks) RegisterHorizontalPodAutoscalerCheck(name, comment string, fn CheckFunc[ks.HpaTargeter]) {
-	ch := NewCheck(name, "HorizontalPodAutoscaler", comment, false)
-	c.registerHorizontalPodAutoscalerCheck(GenCheck[ks.HpaTargeter]{ch, fn})
+	reg(c, "HorizontalPodAutoscaler", name, comment, false, fn, c.horizontalPodAutoscalers)
 }
 
 func (c *Checks) RegisterOptionalHorizontalPodAutoscalerCheck(name, comment string, fn CheckFunc[ks.HpaTargeter]) {
-	ch := NewCheck(name, "HorizontalPodAutoscaler", comment, true)
-	c.registerHorizontalPodAutoscalerCheck(GenCheck[ks.HpaTargeter]{ch, fn})
-}
-
-func (c *Checks) registerHorizontalPodAutoscalerCheck(ch GenCheck[ks.HpaTargeter]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.horizontalPodAutoscalers[machineFriendlyName(ch.Name)] = ch
+	reg(c, "HorizontalPodAutoscaler", name, comment, true, fn, c.horizontalPodAutoscalers)
 }
 
 func (c *Checks) HorizontalPodAutoscalers() map[string]GenCheck[ks.HpaTargeter] {
@@ -157,22 +137,11 @@ func (c *Checks) HorizontalPodAutoscalers() map[string]GenCheck[ks.HpaTargeter]
 }
 
 func (c *Checks) RegisterCronJobCheck(name, comment string, fn CheckFunc[ks.CronJob]) {
-	ch := NewCheck(name, "CronJob", comment, false)
-	c.registerCronJobCheck(GenCheck[ks.CronJob]{ch, fn})
+	reg(c, "CronJob", name, comment, false, fn, c.cronjobs)
 }
 
 func (c *Checks) RegisterOptionalCronJobCheck(name, comment string, fn CheckFunc[ks.CronJob]) {
-	ch := NewCheck(name, "CronJob", comment, true)
-	c.registerCronJobCheck(GenCheck[ks.CronJob]{ch, fn})
-}
-
-func (c *Checks) registerCronJobCheck(ch GenCheck[ks.CronJob]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.cronjobs[machineFriendlyName(ch.Name)] = ch
+	reg(c, "CronJob", name, comment, true, fn, c.cronjobs)
 }
 
 func (c *Checks) CronJobs() map[string]GenCheck[ks.CronJob] {
@@ -180,22 +149,11 @@ func (c *Checks) CronJobs() map[string]GenCheck[ks.CronJob] {
 }
 
 func (c *Checks) RegisterStatefulSetCheck(name, comment string, fn CheckFunc[appsv1.StatefulSet]) {
-	ch := NewCheck(name, "StatefulSet", comment, false)
-	c.registerStatefulSetCheck(GenCheck[appsv1.StatefulSet]{ch, fn})
+	reg(c, "StatefulSet", name, comment, false, fn, c.statefulsets)
 }
 
 func (c *Checks) RegisterOptionalStatefulSetCheck(name, comment string, fn CheckFunc[appsv1.StatefulSet]) {
-	ch := NewCheck(name, "StatefulSet", comment, true)
-	c.registerStatefulSetCheck(GenCheck[appsv1.StatefulSet]{ch, fn})
-}
-
-func (c *Checks) registerStatefulSetCheck(ch GenCheck[appsv1.StatefulSet]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.statefulsets[machineFriendlyName(ch.Name)] = ch
+	reg(c, "StatefulSet", name, comment, true, fn, c.statefulsets)
 }
 
 func (c *Checks) StatefulSets() map[string]GenCheck[appsv1.StatefulSet] {
@@ -203,22 +161,11 @@ func (c *Checks) StatefulSets() map[string]GenCheck[appsv1.StatefulSet] {
 }
 
 func (c *Checks) RegisterDeploymentCheck(name, comment string, fn CheckFunc[appsv1.Deployment]) {
-	ch := NewCheck(name, "Deployment", comment, false)
-	c.registerDeploymentCheck(GenCheck[appsv1.Deployment]{ch, fn})
+	reg(c, "Deployment", name, comment, false, fn, c.deployments)
 }
 
 func (c *Checks) RegisterOptionalDeploymentCheck(name, comment string, fn CheckFunc[appsv1.Deployment]) {
-	ch := NewCheck(name, "Deployment", comment, true)
-	c.registerDeploymentCheck(GenCheck[appsv1.Deployment]{ch, fn})
-}
-
-func (c *Checks) registerDeploymentCheck(ch GenCheck[appsv1.Deployment]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.deployments[machineFriendlyName(ch.Name)] = ch
+	reg(c, "Deployment", name, comment, true, fn, c.deployments)
 }
 
 func (c *Checks) Deployments() map[string]GenCheck[appsv1.Deployment] {
@@ -226,22 +173,11 @@ func (c *Checks) Deployments() map[string]GenCheck[appsv1.Deployment] {
 }
 
 func (c *Checks) RegisterIngressCheck(name, comment string, fn CheckFunc[ks.Ingress]) {
-	ch := NewCheck(name, "Ingress", comment, false)
-	c.registerIngressCheck(GenCheck[ks.Ingress]{ch, fn})
+	reg(c, "Ingress", name, comment, false, fn, c.ingresses)
 }
 
 func (c *Checks) RegisterOptionalIngressCheck(name, comment string, fn CheckFunc[ks.Ingress]) {
-	ch := NewCheck(name, "Ingress", comment, true)
-	c.registerIngressCheck(GenCheck[ks.Ingress]{ch, fn})
-}
-
-func (c *Checks) registerIngressCheck(ch GenCheck[ks.Ingress]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.ingresses[machineFriendlyName(ch.Name)] = ch
+	reg(c, "Ingress", name, comment, true, fn, c.ingresses)
 }
 
 func (c *Checks) Ingresses() map[string]GenCheck[ks.Ingress] {
@@ -249,22 +185,11 @@ func (c *Checks) Ingresses() map[string]GenCheck[ks.Ingress] {
 }
 
 func (c *Checks) RegisterNetworkPolicyCheck(name, comment string, fn CheckFunc[networkingv1.NetworkPolicy]) {
-	ch := NewCheck(name, "NetworkPolicy", comment, false)
-	c.registerNetworkPolicyCheck(GenCheck[networkingv1.NetworkPolicy]{ch, fn})
+	reg(c, "NetworkPolicy", name, comment, false, fn, c.networkpolicies)
 }
 
 func (c *Checks) RegisterOptionalNetworkPolicyCheck(name, comment string, fn CheckFunc[networkingv1.NetworkPolicy]) {
-	ch := NewCheck(name, "NetworkPolicy", comment, true)
-	c.registerNetworkPolicyCheck(GenCheck[networkingv1.NetworkPolicy]{ch, fn})
-}
-
-func (c *Checks) registerNetworkPolicyCheck(ch GenCheck[networkingv1.NetworkPolicy]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.networkpolicies[machineFriendlyName(ch.Name)] = ch
+	reg(c, "NetworkPolicy", name, comment, true, fn, c.networkpolicies)
 }
 
 func (c *Checks) NetworkPolicies() map[string]GenCheck[networkingv1.NetworkPolicy] {
@@ -272,18 +197,7 @@ func (c *Checks) NetworkPolicies() map[string]GenCheck[networkingv1.NetworkPolic
 }
 
 func (c *Checks) RegisterPodDisruptionBudgetCheck(name, comment string, fn CheckFunc[ks.PodDisruptionBudget]) {
-	ch := NewCheck(name, "PodDisruptionBudget", comment, false)
-	c.registerPodDisruptionBudgetCheck(GenCheck[ks.PodDisruptionBudget]{ch, fn})
-}
-
-func (c *Checks) registerPodDisruptionBudgetCheck(ch GenCheck[ks.PodDisruptionBudget]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-
-	c.poddisruptionbudgets[machineFriendlyName(ch.Name)] = ch
+	reg(c, "PodDisruptionBudget", name, comment, false, fn, c.poddisruptionbudgets)
 }
 
 func (c *Checks) PodDisruptionBudgets() map[string]GenCheck[ks.PodDisruptionBudget] {
@@ -291,22 +205,11 @@ func (c *Checks) PodDisruptionBudgets() map[string]GenCheck[ks.PodDisruptionBudg
 }
 
 func (c *Checks) RegisterServiceCheck(name, comment string, fn CheckFunc[corev1.Service]) {
-	ch := NewCheck(name, "Service", comment, false)
-	c.registerServiceCheck(GenCheck[corev1.Service]{ch, fn})
+	reg(c, "Service", name, comment, false, fn, c.services)
 }
 
 func (c *Checks) RegisterOptionalServiceCheck(name, comment string, fn CheckFunc[corev1.Service]) {
-	ch := NewCheck(name, "Service", comment, true)
-	c.registerServiceCheck(GenCheck[corev1.Service]{ch, fn})
-}
-
-func (c *Checks) registerServiceCheck(ch GenCheck[corev1.Service]) {
-	c.all = append(c.all, ch.Check)
-
-	if !c.isEnabled(ch.Check) {
-		return
-	}
-	c.services[machineFriendlyName(ch.Name)] = ch
+	reg(c, "Service", name, comment, true, fn, c.services)
 }
 
 func (c *Checks) Services() map[string]GenCheck[corev1.Service] {
diff --git a/score/container/container.go b/score/container/container.go
index b612598..5b30c92 100644
--- a/score/container/container.go
+++ b/score/container/container.go
@@ -5,10 +5,10 @@ import (
 	"strings"
 
 	"github.com/zegl/kube-score/config"
+	ks "github.com/zegl/kube-score/domain"
 	"github.com/zegl/kube-score/score/checks"
 	"github.com/zegl/kube-score/scorecard"
 	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 func Register(allChecks *checks.Checks, cnf config.Configuration) {
@@ -26,9 +26,9 @@ func Register(allChecks *checks.Checks, cnf config.Configuration) {
 
 // containerResources makes sure that the container has resource requests and limits set
 // The check for a CPU limit requirement can be enabled via the requireCPULimit flag parameter
-func containerResources(requireCPULimit bool, requireMemoryLimit bool) func(corev1.PodTemplateSpec, metav1.TypeMeta) scorecard.TestScore {
-	return func(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-		pod := podTemplate.Spec
+func containerResources(requireCPULimit bool, requireMemoryLimit bool) func(ks.PodSpecer) (scorecard.TestScore, error) {
+	return func(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+		pod := ps.GetPodTemplateSpec().Spec
 
 		allContainers := pod.InitContainers
 		allContainers = append(allContainers, pod.Containers...)
@@ -72,9 +72,9 @@ func containerResources(requireCPULimit bool, requireMemoryLimit bool) func(core
 }
 
 // containerResourceRequestsEqualLimits checks that all containers have equal requests and limits for CPU and memory resources
-func containerResourceRequestsEqualLimits(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	cpuScore := containerCPURequestsEqualLimits(podTemplate, typeMeta)
-	memoryScore := containerMemoryRequestsEqualLimits(podTemplate, typeMeta)
+func containerResourceRequestsEqualLimits(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	cpuScore, _ := containerCPURequestsEqualLimits(ps)
+	memoryScore, _ := containerMemoryRequestsEqualLimits(ps)
 
 	score.Grade = scorecard.GradeAllOK
 	if cpuScore.Grade == scorecard.GradeCritical {
@@ -86,12 +86,12 @@ func containerResourceRequestsEqualLimits(podTemplate corev1.PodTemplateSpec, ty
 		score.Comments = append(score.Comments, memoryScore.Comments...)
 	}
 
-	return score
+	return
 }
 
 // containerCPURequestsEqualLimits checks that all containers have equal requests and limits for CPU resources
-func containerCPURequestsEqualLimits(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	pod := podTemplate.Spec
+func containerCPURequestsEqualLimits(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	pod := ps.GetPodTemplateSpec().Spec
 
 	allContainers := pod.InitContainers
 	allContainers = append(allContainers, pod.Containers...)
@@ -117,8 +117,8 @@ func containerCPURequestsEqualLimits(podTemplate corev1.PodTemplateSpec, typeMet
 }
 
 // containerMemoryRequestsEqualLimits checks that all containers have equal requests and limits for memory resources
-func containerMemoryRequestsEqualLimits(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	pod := podTemplate.Spec
+func containerMemoryRequestsEqualLimits(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	pod := ps.GetPodTemplateSpec().Spec
 
 	allContainers := pod.InitContainers
 	allContainers = append(allContainers, pod.Containers...)
@@ -144,8 +144,8 @@ func containerMemoryRequestsEqualLimits(podTemplate corev1.PodTemplateSpec, type
 }
 
 // containerImageTag checks that no container is using the ":latest" tag
-func containerImageTag(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	pod := podTemplate.Spec
+func containerImageTag(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	pod := ps.GetPodTemplateSpec().Spec
 
 	allContainers := pod.InitContainers
 	allContainers = append(allContainers, pod.Containers...)
@@ -170,8 +170,8 @@ func containerImageTag(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeM
 }
 
 // containerImagePullPolicy checks if the containers ImagePullPolicy is set to PullAlways
-func containerImagePullPolicy(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	pod := podTemplate.Spec
+func containerImagePullPolicy(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	pod := ps.GetPodTemplateSpec().Spec
 
 	allContainers := pod.InitContainers
 	allContainers = append(allContainers, pod.Containers...)
@@ -209,10 +209,9 @@ func containerTag(image string) string {
 	return ""
 }
 
-func containerStorageEphemeralRequestAndLimit(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-
-	allContainers := podTemplate.Spec.InitContainers
-	allContainers = append(allContainers, podTemplate.Spec.Containers...)
+func containerStorageEphemeralRequestAndLimit(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	allContainers := ps.GetPodTemplateSpec().Spec.InitContainers
+	allContainers = append(allContainers, ps.GetPodTemplateSpec().Spec.Containers...)
 
 	score.Grade = scorecard.GradeAllOK
 
@@ -231,10 +230,9 @@ func containerStorageEphemeralRequestAndLimit(podTemplate corev1.PodTemplateSpec
 	return
 }
 
-func containerStorageEphemeralRequestEqualsLimit(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-
-	allContainers := podTemplate.Spec.InitContainers
-	allContainers = append(allContainers, podTemplate.Spec.Containers...)
+func containerStorageEphemeralRequestEqualsLimit(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	allContainers := ps.GetPodTemplateSpec().Spec.InitContainers
+	allContainers = append(allContainers, ps.GetPodTemplateSpec().Spec.Containers...)
 
 	score.Grade = scorecard.GradeAllOK
 
@@ -254,12 +252,12 @@ func containerStorageEphemeralRequestEqualsLimit(podTemplate corev1.PodTemplateS
 
 // List of ports to expose from the container. This is primarily informational. Not specifying a port here
 // does not prevent it from being exposed. Specifying it does not expose the port outside the cluster; that
-// requires a Service object. However misspecifying elements of this optional Container
-func containerPortsCheck(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
+// requires a Service object.
+func containerPortsCheck(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
 	const maxPortNameLength = 15
 
-	allContainers := podTemplate.Spec.InitContainers
-	allContainers = append(allContainers, podTemplate.Spec.Containers...)
+	allContainers := ps.GetPodTemplateSpec().Spec.InitContainers
+	allContainers = append(allContainers, ps.GetPodTemplateSpec().Spec.Containers...)
 
 	score.Grade = scorecard.GradeAllOK
 
@@ -289,8 +287,8 @@ func containerPortsCheck(podTemplate corev1.PodTemplateSpec, typeMeta metav1.Typ
 }
 
 // environmentVariableKeyDuplication checks that no duplicated environment variable keys.
-func environmentVariableKeyDuplication(podTemplate corev1.PodTemplateSpec, _ metav1.TypeMeta) (score scorecard.TestScore) {
-	pod := podTemplate.Spec
+func environmentVariableKeyDuplication(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	pod := ps.GetPodTemplateSpec().Spec
 
 	allContainers := pod.InitContainers
 	allContainers = append(allContainers, pod.Containers...)
diff --git a/score/networkpolicy/networkpolicy.go b/score/networkpolicy/networkpolicy.go
index 2a8bfba..f5630a1 100644
--- a/score/networkpolicy/networkpolicy.go
+++ b/score/networkpolicy/networkpolicy.go
@@ -1,7 +1,6 @@
 package networkpolicy
 
 import (
-	corev1 "k8s.io/api/core/v1"
 	networkingv1 "k8s.io/api/networking/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
@@ -18,8 +17,8 @@ func Register(allChecks *checks.Checks, netpols ks.NetworkPolicies, pods ks.Pods
 
 // podHasNetworkPolicy returns a function that tests that all pods have matching NetworkPolicies
 // podHasNetworkPolicy takes a list of all defined NetworkPolicies as input
-func podHasNetworkPolicy(allNetpols []ks.NetworkPolicy) func(spec corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) scorecard.TestScore {
-	return func(podSpec corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
+func podHasNetworkPolicy(allNetpols []ks.NetworkPolicy) func(ks.PodSpecer) (scorecard.TestScore, error) {
+	return func(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
 		hasMatchingEgressNetpol := false
 		hasMatchingIngressNetpol := false
 
@@ -27,12 +26,12 @@ func podHasNetworkPolicy(allNetpols []ks.NetworkPolicy) func(spec corev1.PodTemp
 			netPol := n.NetworkPolicy()
 
 			// Make sure that the pod and networkpolicy is in the same namespace
-			if podSpec.Namespace != netPol.Namespace {
+			if ps.GetPodTemplateSpec().Namespace != netPol.Namespace {
 				continue
 			}
 
 			if selector, err := metav1.LabelSelectorAsSelector(&netPol.Spec.PodSelector); err == nil {
-				if selector.Matches(internal.MapLabels(podSpec.Labels)) {
+				if selector.Matches(internal.MapLabels(ps.GetPodTemplateSpec().Labels)) {
 
 					// Documentation of PolicyTypes
 					//
diff --git a/score/probes/probes.go b/score/probes/probes.go
index a683101..f5ede4c 100644
--- a/score/probes/probes.go
+++ b/score/probes/probes.go
@@ -1,13 +1,11 @@
 package probes
 
 import (
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
 	ks "github.com/zegl/kube-score/domain"
 	"github.com/zegl/kube-score/score/checks"
 	"github.com/zegl/kube-score/score/internal"
 	"github.com/zegl/kube-score/scorecard"
+	corev1 "k8s.io/api/core/v1"
 )
 
 func Register(allChecks *checks.Checks, services ks.Services) {
@@ -19,13 +17,15 @@ func Register(allChecks *checks.Checks, services ks.Services) {
 // ReadinessProbes are not required if the pod is not targeted by a Service.
 //
 // containerProbes takes a slice of all defined Services as input.
-func containerProbes(allServices []ks.Service) func(corev1.PodTemplateSpec, metav1.TypeMeta) scorecard.TestScore {
-	return func(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
+func containerProbes(allServices []ks.Service) func(ks.PodSpecer) (scorecard.TestScore, error) {
+	return func(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+		typeMeta := ps.GetTypeMeta()
 		if typeMeta.Kind == "CronJob" && typeMeta.GroupVersionKind().Group == "batch" || typeMeta.Kind == "Job" && typeMeta.GroupVersionKind().Group == "batch" {
 			score.Grade = scorecard.GradeAllOK
-			return score
+			return score, nil
 		}
 
+		podTemplate := ps.GetPodTemplateSpec()
 		allContainers := podTemplate.Spec.InitContainers
 		allContainers = append(allContainers, podTemplate.Spec.Containers...)
 
@@ -94,13 +94,13 @@ func containerProbes(allServices []ks.Service) func(corev1.PodTemplateSpec, meta
 				"Using the same probe for liveness and readiness is very likely dangerous. Generally it's better to avoid the livenessProbe than re-using the readinessProbe.",
 				"https://github.com/zegl/kube-score/blob/master/README_PROBES.md",
 			)
-			return score
+			return score, nil
 		}
 
 		if !isTargetedByService {
 			score.Grade = scorecard.GradeAllOK
 			score.AddComment("", "The pod is not targeted by a service, skipping probe checks.", "")
-			return score
+			return score, nil
 		}
 
 		if !hasReadinessProbe {
@@ -111,7 +111,7 @@ func containerProbes(allServices []ks.Service) func(corev1.PodTemplateSpec, meta
 					"It's also used during rollouts, and can prevent downtime if a new version of the application is failing.",
 				"https://github.com/zegl/kube-score/blob/master/README_PROBES.md",
 			)
-			return score
+			return score, nil
 		}
 
 		if !hasLivenessProbe {
@@ -121,12 +121,12 @@ func containerProbes(allServices []ks.Service) func(corev1.PodTemplateSpec, meta
 					"It's only recommended to setup a livenessProbe if you really need one.",
 				"https://github.com/zegl/kube-score/blob/master/README_PROBES.md",
 			)
-			return score
+			return score, nil
 		}
 
 		score.Grade = scorecard.GradeAllOK
 
-		return score
+		return score, nil
 	}
 }
 
diff --git a/score/score.go b/score/score.go
index c8fafcc..8f538a4 100644
--- a/score/score.go
+++ b/score/score.go
@@ -41,6 +41,28 @@ func RegisterAllChecks(allObjects ks.AllTypes, cnf config.Configuration) *checks
 	return allChecks
 }
 
+type podSpeccer struct {
+	typeMeta   metav1.TypeMeta
+	objectMeta metav1.ObjectMeta
+	spec       corev1.PodTemplateSpec
+}
+
+func (p *podSpeccer) GetTypeMeta() metav1.TypeMeta {
+	return p.typeMeta
+}
+
+func (p *podSpeccer) GetObjectMeta() metav1.ObjectMeta {
+	return p.objectMeta
+}
+
+func (p *podSpeccer) GetPodTemplateSpec() corev1.PodTemplateSpec {
+	return p.spec
+}
+
+func (p *podSpeccer) FileLocation() ks.FileLocation {
+	return ks.FileLocation{}
+}
+
 // Score runs a pre-configured list of tests against the files defined in the configuration, and returns a scorecard.
 // Additional configuration and tuning parameters can be provided via the config.
 func Score(allObjects ks.AllTypes, cnf config.Configuration) (*scorecard.Scorecard, error) {
@@ -76,10 +98,17 @@ func Score(allObjects ks.AllTypes, cnf config.Configuration) (*scorecard.Scoreca
 	for _, pod := range allObjects.Pods() {
 		o := newObject(pod.Pod().TypeMeta, pod.Pod().ObjectMeta)
 		for _, test := range allChecks.Pods() {
-			score := test.Fn(corev1.PodTemplateSpec{
+
+			podTemplateSpec := corev1.PodTemplateSpec{
 				ObjectMeta: pod.Pod().ObjectMeta,
 				Spec:       pod.Pod().Spec,
-			}, pod.Pod().TypeMeta)
+			}
+
+			score, _ := test.Fn(&podSpeccer{
+				typeMeta:   pod.Pod().TypeMeta,
+				objectMeta: pod.Pod().ObjectMeta,
+				spec:       podTemplateSpec,
+			})
 			o.Add(score, test.Check, pod, pod.Pod().ObjectMeta.Annotations)
 		}
 	}
@@ -87,7 +116,7 @@ func Score(allObjects ks.AllTypes, cnf config.Configuration) (*scorecard.Scoreca
 	for _, podspecer := range allObjects.PodSpeccers() {
 		o := newObject(podspecer.GetTypeMeta(), podspecer.GetObjectMeta())
 		for _, test := range allChecks.Pods() {
-			score := test.Fn(podspecer.GetPodTemplateSpec(), podspecer.GetTypeMeta())
+			score, _ := test.Fn(podspecer)
 			o.Add(score, test.Check, podspecer,
 				podspecer.GetObjectMeta().Annotations,
 				podspecer.GetPodTemplateSpec().Annotations,
diff --git a/score/security/security.go b/score/security/security.go
index 9ed5504..4262a8d 100644
--- a/score/security/security.go
+++ b/score/security/security.go
@@ -1,11 +1,10 @@
 package security
 
 import (
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
+	ks "github.com/zegl/kube-score/domain"
 	"github.com/zegl/kube-score/score/checks"
 	"github.com/zegl/kube-score/scorecard"
+	corev1 "k8s.io/api/core/v1"
 )
 
 func Register(allChecks *checks.Checks) {
@@ -17,9 +16,9 @@ func Register(allChecks *checks.Checks) {
 }
 
 // containerSecurityContextReadOnlyRootFilesystem checks for pods using writeable root filesystems
-func containerSecurityContextReadOnlyRootFilesystem(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	allContainers := podTemplate.Spec.InitContainers
-	allContainers = append(allContainers, podTemplate.Spec.Containers...)
+func containerSecurityContextReadOnlyRootFilesystem(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	allContainers := ps.GetPodTemplateSpec().Spec.InitContainers
+	allContainers = append(allContainers, ps.GetPodTemplateSpec().Spec.Containers...)
 
 	noContextSet := false
 	hasWritableRootFS := false
@@ -47,9 +46,9 @@ func containerSecurityContextReadOnlyRootFilesystem(podTemplate corev1.PodTempla
 }
 
 // containerSecurityContextPrivileged checks for privileged containers
-func containerSecurityContextPrivileged(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	allContainers := podTemplate.Spec.InitContainers
-	allContainers = append(allContainers, podTemplate.Spec.Containers...)
+func containerSecurityContextPrivileged(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	allContainers := ps.GetPodTemplateSpec().Spec.InitContainers
+	allContainers = append(allContainers, ps.GetPodTemplateSpec().Spec.Containers...)
 	hasPrivileged := false
 	for _, container := range allContainers {
 		if container.SecurityContext != nil && container.SecurityContext.Privileged != nil && *container.SecurityContext.Privileged {
@@ -66,10 +65,10 @@ func containerSecurityContextPrivileged(podTemplate corev1.PodTemplateSpec, type
 }
 
 // containerSecurityContextUserGroupID checks that the user and group are valid ( > 10000) in the security context
-func containerSecurityContextUserGroupID(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	allContainers := podTemplate.Spec.InitContainers
-	allContainers = append(allContainers, podTemplate.Spec.Containers...)
-	podSecurityContext := podTemplate.Spec.SecurityContext
+func containerSecurityContextUserGroupID(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	allContainers := ps.GetPodTemplateSpec().Spec.InitContainers
+	allContainers = append(allContainers, ps.GetPodTemplateSpec().Spec.Containers...)
+	podSecurityContext := ps.GetPodTemplateSpec().Spec.SecurityContext
 	noContextSet := false
 	hasLowUserID := false
 	hasLowGroupID := false
@@ -110,9 +109,9 @@ func containerSecurityContextUserGroupID(podTemplate corev1.PodTemplateSpec, typ
 	return
 }
 
-// podSeccompProfile checks if the any Seccommp profile is configured for the pod
-func podSeccompProfile(podTemplate corev1.PodTemplateSpec, typeMeta metav1.TypeMeta) (score scorecard.TestScore) {
-	metadata := podTemplate.ObjectMeta
+// podSeccompProfile checks that a Seccommp profile is configured for the pod
+func podSeccompProfile(ps ks.PodSpecer) (score scorecard.TestScore, err error) {
+	metadata := ps.GetPodTemplateSpec().ObjectMeta
 
 	seccompAnnotated := false
 	if metadata.Annotations != nil {


Test patch:
diff --git a/score/container/container_test.go b/score/container/container_test.go
index 91322a6..5629bf4 100644
--- a/score/container/container_test.go
+++ b/score/container/container_test.go
@@ -3,6 +3,7 @@ package container
 import (
 	"testing"
 
+	ks "github.com/zegl/kube-score/domain"
 	"k8s.io/apimachinery/pkg/api/resource"
 
 	"github.com/stretchr/testify/assert"
@@ -12,29 +13,53 @@ import (
 	"github.com/zegl/kube-score/scorecard"
 )
 
+type podSpeccer struct {
+	typeMeta   metav1.TypeMeta
+	objectMeta metav1.ObjectMeta
+	spec       corev1.PodTemplateSpec
+}
+
+func (p *podSpeccer) GetTypeMeta() metav1.TypeMeta {
+	return p.typeMeta
+}
+
+func (p *podSpeccer) GetObjectMeta() metav1.ObjectMeta {
+	return p.objectMeta
+}
+
+func (p *podSpeccer) GetPodTemplateSpec() corev1.PodTemplateSpec {
+	return p.spec
+}
+
+func (p *podSpeccer) FileLocation() ks.FileLocation {
+	return ks.FileLocation{}
+}
+
 func TestOkAllTheSameContainerResourceRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerResourceRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
+	s, _ := containerResourceRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -42,55 +67,57 @@ func TestOkAllTheSameContainerResourceRequestsEqualLimits(t *testing.T) {
 
 func TestOkMultipleContainersContainerResourceRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerResourceRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				InitContainers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
+	s, _ := containerResourceRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					InitContainers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
-				},
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
-					},
-					{
-						Name: "foo2",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
+						{
+							Name: "foo2",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -98,27 +125,29 @@ func TestOkMultipleContainersContainerResourceRequestsEqualLimits(t *testing.T)
 
 func TestOkSameQuantityContainerResourceRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerResourceRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1000m"),
-								"memory": resource.MustParse("0.25Gi"),
+	s, _ := containerResourceRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1000m"),
+									"memory": resource.MustParse("0.25Gi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -126,27 +155,28 @@ func TestOkSameQuantityContainerResourceRequestsEqualLimits(t *testing.T) {
 
 func TestFailBothContainerResourceRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerResourceRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("2"),
-								"memory": resource.MustParse("512Mi"),
+	s, _ := containerResourceRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("2"),
+									"memory": resource.MustParse("512Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
-		},
-		metav1.TypeMeta{})
+		})
 
 	assert.Equal(t, scorecard.GradeCritical, s.Grade)
 	assert.Len(t, s.Comments, 2)
@@ -160,42 +190,44 @@ func TestFailBothContainerResourceRequestsEqualLimits(t *testing.T) {
 
 func TestFailCpuInitContainerResourceRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerResourceRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				InitContainers: []corev1.Container{
-					{
-						Name: "init",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("2"),
-								"memory": resource.MustParse("256Mi"),
+	s, _ := containerResourceRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					InitContainers: []corev1.Container{
+						{
+							Name: "init",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("2"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
-				},
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeCritical, s.Grade)
 	assert.Len(t, s.Comments, 1)
@@ -206,25 +238,27 @@ func TestFailCpuInitContainerResourceRequestsEqualLimits(t *testing.T) {
 
 func TestOkAllCPURequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerCPURequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
+	s, _ := containerCPURequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -232,49 +266,51 @@ func TestOkAllCPURequestsEqualLimits(t *testing.T) {
 
 func TestOkMultipleContainersContainerCPURequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerCPURequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				InitContainers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
+	s, _ := containerCPURequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					InitContainers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
 							},
 						},
 					},
-				},
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
 							},
 						},
-					},
-					{
-						Name: "foo2",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
+						{
+							Name: "foo2",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -282,25 +318,27 @@ func TestOkMultipleContainersContainerCPURequestsEqualLimits(t *testing.T) {
 
 func TestOkSameQuantityContainerCPURequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerCPURequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1000m"),
+	s, _ := containerCPURequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1000m"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -308,27 +346,29 @@ func TestOkSameQuantityContainerCPURequestsEqualLimits(t *testing.T) {
 
 func TestFailContainerCPURequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerCPURequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("2"),
-								"memory": resource.MustParse("512Mi"),
+	s, _ := containerCPURequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("2"),
+									"memory": resource.MustParse("512Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeCritical, s.Grade)
 	assert.Len(t, s.Comments, 1)
@@ -340,40 +380,42 @@ func TestFailContainerCPURequestsEqualLimits(t *testing.T) {
 
 func TestFailInitContainerCPURequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerCPURequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				InitContainers: []corev1.Container{
-					{
-						Name: "init",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("1"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu": resource.MustParse("2"),
+	s, _ := containerCPURequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					InitContainers: []corev1.Container{
+						{
+							Name: "init",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("1"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu": resource.MustParse("2"),
+								},
 							},
 						},
 					},
-				},
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeCritical, s.Grade)
 	assert.Len(t, s.Comments, 1)
@@ -384,25 +426,27 @@ func TestFailInitContainerCPURequestsEqualLimits(t *testing.T) {
 
 func TestOkContainerMemoryResourceRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerMemoryRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
+	s, _ := containerMemoryRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -410,49 +454,51 @@ func TestOkContainerMemoryResourceRequestsEqualLimits(t *testing.T) {
 
 func TestOkMultipleContainersContainerMemoryRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerMemoryRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				InitContainers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
+	s, _ := containerMemoryRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					InitContainers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
-				},
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
-					},
-					{
-						Name: "foo2",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
+						{
+							Name: "foo2",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -460,25 +506,27 @@ func TestOkMultipleContainersContainerMemoryRequestsEqualLimits(t *testing.T) {
 
 func TestOkSameQuantityContainerMemoryRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerMemoryRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("0.25Gi"),
+	s, _ := containerMemoryRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("0.25Gi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeAllOK, s.Grade)
 	assert.Len(t, s.Comments, 0)
@@ -486,27 +534,29 @@ func TestOkSameQuantityContainerMemoryRequestsEqualLimits(t *testing.T) {
 
 func TestFailContainerMemoryRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerMemoryRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("2"),
-								"memory": resource.MustParse("512Mi"),
+	s, _ := containerMemoryRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("2"),
+									"memory": resource.MustParse("512Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeCritical, s.Grade)
 	assert.Len(t, s.Comments, 1)
@@ -517,40 +567,42 @@ func TestFailContainerMemoryRequestsEqualLimits(t *testing.T) {
 
 func TestFailInitContainerMemoryRequestsEqualLimits(t *testing.T) {
 	t.Parallel()
-	s := containerMemoryRequestsEqualLimits(
-		corev1.PodTemplateSpec{
-			Spec: corev1.PodSpec{
-				InitContainers: []corev1.Container{
-					{
-						Name: "init",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"memory": resource.MustParse("512Mi"),
+	s, _ := containerMemoryRequestsEqualLimits(
+		&podSpeccer{
+			spec: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					InitContainers: []corev1.Container{
+						{
+							Name: "init",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"memory": resource.MustParse("512Mi"),
+								},
 							},
 						},
 					},
-				},
-				Containers: []corev1.Container{
-					{
-						Name: "foo",
-						Resources: corev1.ResourceRequirements{
-							Requests: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
-							},
-							Limits: map[corev1.ResourceName]resource.Quantity{
-								"cpu":    resource.MustParse("1"),
-								"memory": resource.MustParse("256Mi"),
+					Containers: []corev1.Container{
+						{
+							Name: "foo",
+							Resources: corev1.ResourceRequirements{
+								Requests: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
+								Limits: map[corev1.ResourceName]resource.Quantity{
+									"cpu":    resource.MustParse("1"),
+									"memory": resource.MustParse("256Mi"),
+								},
 							},
 						},
 					},
 				},
 			},
 		},
-		metav1.TypeMeta{})
+	)
 
 	assert.Equal(t, scorecard.GradeCritical, s.Grade)
 	assert.Len(t, s.Comments, 1)
diff --git a/score/networkpolicy/networkpolicy_test.go b/score/networkpolicy/networkpolicy_test.go
index 46721ab..a0ae76a 100644
--- a/score/networkpolicy/networkpolicy_test.go
+++ b/score/networkpolicy/networkpolicy_test.go
@@ -102,7 +102,8 @@ func TestPodHasNetworkPolicy(t *testing.T) {
 		}
 
 		fn := podHasNetworkPolicy([]domain.NetworkPolicy{np{Obj: pol}})
-		score := fn(corev1.PodTemplateSpec{ObjectMeta: pod.ObjectMeta, Spec: pod.Spec}, pod.TypeMeta)
+		spec := corev1.PodTemplateSpec{ObjectMeta: pod.ObjectMeta, Spec: pod.Spec}
+		score, _ := fn(&podSpeccer{spec: spec})
 		assert.Equal(t, tc.expected, score.Grade, "caseID = %d", caseID)
 	}
 }
@@ -118,3 +119,25 @@ func (n np) NetworkPolicy() v1.NetworkPolicy {
 func (np) FileLocation() domain.FileLocation {
 	return domain.FileLocation{}
 }
+
+type podSpeccer struct {
+	typeMeta   metav1.TypeMeta
+	objectMeta metav1.ObjectMeta
+	spec       corev1.PodTemplateSpec
+}
+
+func (p *podSpeccer) GetTypeMeta() metav1.TypeMeta {
+	return p.typeMeta
+}
+
+func (p *podSpeccer) GetObjectMeta() metav1.ObjectMeta {
+	return p.objectMeta
+}
+
+func (p *podSpeccer) GetPodTemplateSpec() corev1.PodTemplateSpec {
+	return p.spec
+}
+
+func (p *podSpeccer) FileLocation() domain.FileLocation {
+	return domain.FileLocation{}
+}