Pod state check: Checks the cluster for pods in unknown or failed state.

varsha/versions
Varsha Varadarajan 2019-06-17 16:02:10 -04:00
parent b77cf1ea42
commit 4a3e055e13
2 changed files with 138 additions and 0 deletions

View File

@ -0,0 +1,46 @@
package basic
import (
"fmt"
"github.com/digitalocean/clusterlint/checks"
"github.com/digitalocean/clusterlint/kube"
corev1 "k8s.io/api/core/v1"
)
func init() {
checks.Register(&podStatusCheck{})
}
type podStatusCheck struct{}
// Name returns a unique name for this check.
func (p *podStatusCheck) Name() string {
return "pod-state"
}
// Groups returns a list of group names this check should be part of.
func (p *podStatusCheck) Groups() []string {
return []string{"basic"}
}
// Description returns a detailed human-readable description of what this check
// does.
func (p *podStatusCheck) Description() string {
return "Check if there are unhealthy pods in the cluster"
}
// 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 (p *podStatusCheck) Run(objects *kube.Objects) (warnings []error, errors []error, err error) {
var e []error
for _, pod := range objects.Pods.Items {
if corev1.PodFailed == pod.Status.Phase || corev1.PodUnknown == pod.Status.Phase {
e = append(e, fmt.Errorf("Pod '%s' in namespace '%s' has state: %s. Pod state should be `Running`, `Pending` or `Succeeded`.", pod.GetName(), pod.GetNamespace(), pod.Status.Phase))
}
}
return nil, e, nil
}

View File

@ -0,0 +1,92 @@
package basic
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 TestMeta(t *testing.T) {
podStatusCheck := podStatusCheck{}
assert.Equal(t, "pod-state", podStatusCheck.Name())
assert.Equal(t, "Check if there are unhealthy pods in the cluster", podStatusCheck.Description())
assert.Equal(t, []string{"basic"}, podStatusCheck.Groups())
}
func TestPodStateError(t *testing.T) {
scenarios := []struct {
name string
arg *kube.Objects
expected []error
}{
{
name: "no pods",
arg: initPod(),
expected: nil,
},
{
name: "pod with running status",
arg: status(corev1.PodRunning),
expected: nil,
},
{
name: "pod with pending status",
arg: status(corev1.PodPending),
expected: nil,
},
{
name: "pod with succeeded status",
arg: status(corev1.PodSucceeded),
expected: nil,
},
{
name: "pod with failed status",
arg: status(corev1.PodFailed),
expected: []error{
fmt.Errorf("Pod 'pod_foo' in namespace 'k8s' has state: Failed. Pod state should be `Running`, `Pending` or `Succeeded`."),
},
},
{
name: "pod with unknown status",
arg: status(corev1.PodUnknown),
expected: []error{
fmt.Errorf("Pod 'pod_foo' in namespace 'k8s' has state: Unknown. Pod state should be `Running`, `Pending` or `Succeeded`."),
},
},
}
podStatusCheck := podStatusCheck{}
for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) {
w, e, err := podStatusCheck.Run(scenario.arg)
assert.ElementsMatch(t, scenario.expected, e)
assert.Empty(t, w)
assert.Nil(t, err)
})
}
}
func initPod() *kube.Objects {
objs := &kube.Objects{
Pods: &corev1.PodList{},
}
return objs
}
func status(status corev1.PodPhase) *kube.Objects {
objs := initPod()
objs.Pods = &corev1.PodList{
Items: []corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{Name: "pod_foo", Namespace: "k8s"},
Status: corev1.PodStatus{Phase: status},
},
},
}
return objs
}