Merge pull request #12 from digitalocean/varsha/pod-state

Pod state check: Checks the cluster for pods in unknown or failed state.
varsha/versions
Varsha Varadarajan 2019-06-20 15:32:15 -04:00 committed by GitHub
commit 787fc63030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 125 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{"workload-health"}
}
// 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,79 @@
package basic
import (
"fmt"
"testing"
"github.com/digitalocean/clusterlint/kube"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/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{"workload-health"}, 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 status(status corev1.PodPhase) *kube.Objects {
objs := initPod()
objs.Pods.Items[0].Status = corev1.PodStatus{
Phase: status,
}
return objs
}