Add node name check: Checks for pods which use node name in the node selector.

varsha/versions
Varsha Varadarajan 2019-06-14 15:22:17 -04:00 committed by Varsha Varadarajan
parent 8d1893c06d
commit baa0bf739c
3 changed files with 117 additions and 0 deletions

View File

@ -4,5 +4,6 @@ package all
import (
_ "github.com/digitalocean/clusterlint/checks/basic"
_ "github.com/digitalocean/clusterlint/checks/doks"
_ "github.com/digitalocean/clusterlint/checks/noop"
)

View File

@ -0,0 +1,45 @@
package doks
import (
"fmt"
"github.com/digitalocean/clusterlint/checks"
"github.com/digitalocean/clusterlint/kube"
corev1 "k8s.io/api/core/v1"
)
func init() {
checks.Register(&podSelectorCheck{})
}
type podSelectorCheck struct{}
// Name returns a unique name for this check.
func (nc *podSelectorCheck) Name() string {
return "node-name-pod-selector"
}
// Groups returns a list of group names this check should be part of.
func (nc *podSelectorCheck) Groups() []string {
return []string{"doks"}
}
// Description returns a detailed human-readable description of what this check
// does.
func (nc *podSelectorCheck) Description() string {
return "Checks if there are pods which use kubernetes.io/hostname label in the node selector."
}
// 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 (nc *podSelectorCheck) Run(objects *kube.Objects) (warnings []error, errors []error, err error) {
var e []error
for _, pod := range objects.Pods.Items {
nodeSelectorMap := pod.Spec.NodeSelector
if _, ok := nodeSelectorMap[corev1.LabelHostname]; ok {
e = append(e, fmt.Errorf("pod '%s' in namespace '%s' uses the node name for node selector", pod.GetName(), pod.GetNamespace()))
}
}
return nil, e, nil
}

View File

@ -0,0 +1,71 @@
package doks
import (
"fmt"
"testing"
"github.com/digitalocean/clusterlint/kube"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestGroup(t *testing.T) {
podSelectorCheck := podSelectorCheck{}
assert.Equal(t, []string{"doks"}, podSelectorCheck.Groups())
}
func TestNodeNameError(t *testing.T) {
scenarios := []struct {
name string
arg *kube.Objects
expected []error
}{
{
name: "no node name selector",
arg: empty(),
expected: nil,
},
{
name: "node name used in node selector",
arg: invalidPod(),
expected: errors(),
},
}
podSelectorCheck := podSelectorCheck{}
for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) {
_, e, _ := podSelectorCheck.Run(scenario.arg)
assert.ElementsMatch(t, scenario.expected, e)
})
}
}
func empty() *kube.Objects {
objs := &kube.Objects{
Pods: &corev1.PodList{},
}
return objs
}
func invalidPod() *kube.Objects {
objs := empty()
objs.Pods = &corev1.PodList{
Items: []corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "pod_foo", Namespace: "k8s"},
Spec: corev1.PodSpec{NodeSelector: map[string]string{corev1.LabelHostname: "foo"}},
},
},
}
return objs
}
func errors() []error {
e := []error{
fmt.Errorf("pod 'pod_foo' in namespace 'k8s' uses the node name for node selector"),
}
return e
}