mirror of https://github.com/linkerd/linkerd2.git
483 lines
8.2 KiB
Go
483 lines
8.2 KiB
Go
package k8s
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
)
|
|
|
|
func TestGetPodStatus(t *testing.T) {
|
|
scenarios := []struct {
|
|
desc string
|
|
pod string
|
|
expected string
|
|
}{
|
|
{
|
|
desc: "Pod is running",
|
|
expected: "Running",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
status:
|
|
phase: Running
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod with proxy native sidecar is running",
|
|
expected: "Running",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
spec:
|
|
initContainers:
|
|
- name: linkerd-proxy
|
|
restartPolicy: Always
|
|
status:
|
|
phase: Running
|
|
initContainerStatuses:
|
|
- name: linkerd-proxy
|
|
ready: true
|
|
started: true
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod's reason is filled",
|
|
expected: "podReason",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
status:
|
|
phase: Pending
|
|
reason: podReason
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod waiting is filled",
|
|
expected: "CrashLoopBackOff",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
status:
|
|
phase: Pending
|
|
reason: podReason
|
|
containerStatuses:
|
|
- state:
|
|
waiting:
|
|
reason: CrashLoopBackOff
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod is terminated",
|
|
expected: "podTerminated",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
status:
|
|
phase: Pending
|
|
reason: podReason
|
|
containerStatuses:
|
|
- state:
|
|
terminated:
|
|
reason: podTerminated
|
|
exitCode: 2
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod terminated with signal",
|
|
expected: "Signal:9",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
status:
|
|
phase: Pending
|
|
reason: podReason
|
|
containerStatuses:
|
|
- state:
|
|
terminated:
|
|
signal: 9
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod terminated with exti code",
|
|
expected: "ExitCode:2",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
status:
|
|
phase: Pending
|
|
reason: podReason
|
|
containerStatuses:
|
|
- state:
|
|
terminated:
|
|
exitCode: 2
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod has a running container",
|
|
expected: "Running",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
status:
|
|
phase: Running
|
|
reason: Completed
|
|
containerStatuses:
|
|
- ready: true
|
|
state:
|
|
running:
|
|
startedAt: 1995-02-10T00:42:42Z
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod init container terminated with exit code 0",
|
|
expected: "Running",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
spec:
|
|
initContainers:
|
|
- name: foo
|
|
status:
|
|
phase: Running
|
|
containerStatuses:
|
|
- state:
|
|
running:
|
|
startedAt: 1995-02-10T00:42:42Z
|
|
initContainerStatuses:
|
|
- name: foo
|
|
state:
|
|
terminated:
|
|
exitCode: 0
|
|
reason: Completed
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod init container terminated with exit code 2",
|
|
expected: "Init:ExitCode:2",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
spec:
|
|
initContainers:
|
|
- name: foo
|
|
containers:
|
|
- name: bar
|
|
status:
|
|
phase: Running
|
|
containerStatuses:
|
|
- name: bar
|
|
state:
|
|
running:
|
|
startedAt: 1995-02-10T00:42:42Z
|
|
initContainerStatuses:
|
|
- name: foo
|
|
state:
|
|
terminated:
|
|
exitCode: 2
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod init container terminated with signal",
|
|
expected: "Init:Signal:9",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
spec:
|
|
initContainers:
|
|
- name: foo
|
|
containers:
|
|
- name: bar
|
|
status:
|
|
phase: Running
|
|
containerStatuses:
|
|
- name: bar
|
|
state:
|
|
running:
|
|
startedAt: 1995-02-10T00:42:42Z
|
|
initContainerStatuses:
|
|
- name: foo
|
|
state:
|
|
terminated:
|
|
signal: 9
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod init container in CrashLooBackOff",
|
|
expected: "Init:CrashLoopBackOff",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
spec:
|
|
initContainers:
|
|
- name: foo
|
|
status:
|
|
phase: Pending
|
|
initContainerStatuses:
|
|
- name: foo
|
|
state:
|
|
terminated:
|
|
exitCode: 2
|
|
reason: CrashLoopBackOff
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod init container waiting for someReason",
|
|
expected: "Init:someReason",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
spec:
|
|
initContainers:
|
|
- name: foo
|
|
status:
|
|
phase: Pending
|
|
initContainerStatuses:
|
|
- name: foo
|
|
state:
|
|
waiting:
|
|
reason: someReason
|
|
`,
|
|
},
|
|
{
|
|
desc: "Pod init container is waiting on PodInitializing",
|
|
expected: "Init:0/1",
|
|
pod: `
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: emoji
|
|
namespace: emojivoto
|
|
labels:
|
|
app: emoji-svc
|
|
linkerd.io/control-plane-ns: linkerd
|
|
spec:
|
|
initContainers:
|
|
- name: foo
|
|
status:
|
|
phase: Pending
|
|
initContainerStatuses:
|
|
- name: foo
|
|
state:
|
|
waiting:
|
|
reason: PodInitializing
|
|
`,
|
|
},
|
|
}
|
|
for _, s := range scenarios {
|
|
obj, err := ToRuntimeObject(s.pod)
|
|
if err != nil {
|
|
t.Fatalf("could not decode yml: %s", err)
|
|
}
|
|
pod, ok := obj.(*corev1.Pod)
|
|
if !ok {
|
|
t.Fatalf("could not convert returned object to pod")
|
|
}
|
|
|
|
got := GetPodStatus(*pod)
|
|
if s.expected != got {
|
|
t.Fatalf("Wrong pod status on '%s'. Expected '%s', got '%s'", s.desc, s.expected, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetPodsFor(t *testing.T) {
|
|
|
|
configs := []string{
|
|
// pod-1
|
|
`apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: pod-1
|
|
namespace: ns
|
|
uid: pod-1
|
|
labels:
|
|
app: foo
|
|
ownerReferences:
|
|
- apiVersion: apps/v1
|
|
controller: true
|
|
kind: ReplicaSet
|
|
name: rs-1
|
|
uid: rs-1
|
|
`,
|
|
// rs-1
|
|
`apiVersion: apps/v1
|
|
kind: ReplicaSet
|
|
metadata:
|
|
name: rs-1
|
|
namespace: ns
|
|
uid: rs-1
|
|
labels:
|
|
app: foo
|
|
ownerReferences:
|
|
- apiVersion: apps/v1
|
|
controller: true
|
|
kind: Deployment
|
|
name: deploy-1
|
|
uid: deploy-1
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: foo
|
|
`,
|
|
// deploy-1
|
|
`apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: deploy-1
|
|
namespace: ns
|
|
uid: deploy-1
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: foo
|
|
`,
|
|
// pod-2
|
|
`apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: pod-2
|
|
namespace: ns
|
|
uid: pod-2
|
|
labels:
|
|
app: foo
|
|
ownerReferences:
|
|
- apiVersion: apps/v1
|
|
controller: true
|
|
kind: ReplicaSet
|
|
name: rs-2
|
|
uid: rs-2
|
|
`,
|
|
// rs-2
|
|
`apiVersion: apps/v1
|
|
kind: ReplicaSet
|
|
metadata:
|
|
name: rs-2
|
|
namespace: ns
|
|
uid: rs-2
|
|
labels:
|
|
app: foo
|
|
ownerReferences:
|
|
- apiVersion: apps/v1
|
|
controller: true
|
|
kind: Deployment
|
|
name: deploy-2
|
|
uid: deploy-2
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: foo
|
|
`,
|
|
// deploy-2
|
|
`apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: deploy-2
|
|
namespace: ns
|
|
uid: deploy-2
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
app: foo
|
|
`}
|
|
|
|
k8sClient, err := NewFakeAPI(configs...)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error %s", err)
|
|
}
|
|
|
|
// Both pod-1 and pod-2 have labels which match deploy-1's selector.
|
|
// However, only pod-1 is owned by deploy-1 according to the owner references.
|
|
// Owner references should be considered authoritative to resolve ambiguity
|
|
// when deployments have overlapping seletors.
|
|
pods, err := GetPodsFor(context.Background(), k8sClient, "ns", "deploy/deploy-1")
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error %s", err)
|
|
}
|
|
|
|
if len(pods) != 1 {
|
|
for _, p := range pods {
|
|
t.Logf("%s/%s", p.Namespace, p.Name)
|
|
}
|
|
t.Fatalf("Expected 1 pod, got %d", len(pods))
|
|
}
|
|
}
|