Add node name check: Checks for pods which use node name in the node selector.
parent
8d1893c06d
commit
baa0bf739c
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue