Pod state check: Checks the cluster for pods in unknown or failed state.
parent
b77cf1ea42
commit
4a3e055e13
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue