1
16
17 package pleg
18
19 import (
20 "fmt"
21 "reflect"
22 "strings"
23 "testing"
24 "time"
25
26 "github.com/stretchr/testify/assert"
27 "github.com/stretchr/testify/require"
28
29 "k8s.io/apimachinery/pkg/types"
30 "k8s.io/component-base/metrics/testutil"
31 v1 "k8s.io/cri-api/pkg/apis/runtime/v1"
32 critest "k8s.io/cri-api/pkg/apis/testing"
33 kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
34 containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
35 "k8s.io/kubernetes/pkg/kubelet/metrics"
36 testingclock "k8s.io/utils/clock/testing"
37 )
38
39 func newTestEventedPLEG() *EventedPLEG {
40 return &EventedPLEG{
41 runtime: &containertest.FakeRuntime{},
42 clock: testingclock.NewFakeClock(time.Time{}),
43 cache: kubecontainer.NewCache(),
44 runtimeService: critest.NewFakeRuntimeService(),
45 eventChannel: make(chan *PodLifecycleEvent, 100),
46 }
47 }
48
49 func TestHealthyEventedPLEG(t *testing.T) {
50 metrics.Register()
51 pleg := newTestEventedPLEG()
52
53 _, _, events := createTestPodsStatusesAndEvents(100)
54 for _, event := range events[:5] {
55 pleg.eventChannel <- event
56 }
57
58
59 isHealthy, err := pleg.Healthy()
60 require.NoError(t, err)
61 assert.Equal(t, true, isHealthy)
62
63
64 for _, event := range events[5:] {
65 pleg.eventChannel <- event
66 }
67
68 isHealthy, err = pleg.Healthy()
69 require.Error(t, err)
70 assert.Equal(t, false, isHealthy)
71 }
72
73 func TestUpdateRunningPodMetric(t *testing.T) {
74 metrics.Register()
75 pleg := newTestEventedPLEG()
76
77 podStatuses := make([]*kubecontainer.PodStatus, 5)
78 for i := range podStatuses {
79 id := fmt.Sprintf("test-pod-%d", i)
80 podStatuses[i] = &kubecontainer.PodStatus{
81 ID: types.UID(id),
82 SandboxStatuses: []*v1.PodSandboxStatus{
83 {Id: id},
84 },
85 ContainerStatuses: []*kubecontainer.Status{
86 {ID: kubecontainer.ContainerID{ID: id}, State: kubecontainer.ContainerStateRunning},
87 },
88 }
89
90 pleg.updateRunningPodMetric(podStatuses[i])
91 pleg.cache.Set(podStatuses[i].ID, podStatuses[i], nil, time.Now())
92
93 }
94 pleg.cache.UpdateTime(time.Now())
95
96 expectedMetric := `
97 # HELP kubelet_running_pods [ALPHA] Number of pods that have a running pod sandbox
98 # TYPE kubelet_running_pods gauge
99 kubelet_running_pods 5
100 `
101 testMetric(t, expectedMetric, metrics.RunningPodCount.FQName())
102
103
104 for _, podStatus := range podStatuses[:2] {
105 podId := string(podStatus.ID)
106 newPodStatus := kubecontainer.PodStatus{
107 ID: podStatus.ID,
108 SandboxStatuses: []*v1.PodSandboxStatus{
109 {Id: podId},
110 },
111 ContainerStatuses: []*kubecontainer.Status{
112
113 {ID: kubecontainer.ContainerID{ID: podId}, State: kubecontainer.ContainerStateExited},
114 },
115 }
116
117 pleg.updateRunningPodMetric(&newPodStatus)
118 pleg.cache.Set(newPodStatus.ID, &newPodStatus, nil, time.Now())
119 }
120 pleg.cache.UpdateTime(time.Now())
121
122 expectedMetric = `
123 # HELP kubelet_running_pods [ALPHA] Number of pods that have a running pod sandbox
124 # TYPE kubelet_running_pods gauge
125 kubelet_running_pods 3
126 `
127 testMetric(t, expectedMetric, metrics.RunningPodCount.FQName())
128 }
129
130 func testMetric(t *testing.T, expectedMetric string, metricName string) {
131 err := testutil.GatherAndCompare(metrics.GetGather(), strings.NewReader(expectedMetric), metricName)
132 if err != nil {
133 t.Fatal(err)
134 }
135 }
136
137 func TestEventedPLEG_getPodIPs(t *testing.T) {
138 cache := kubecontainer.NewCache()
139 type args struct {
140 pid types.UID
141 status *kubecontainer.PodStatus
142 }
143 tests := []struct {
144 name string
145 args args
146 oldstatus *kubecontainer.PodStatus
147 expected []string
148 }{
149 {
150 name: "status ips is not empty",
151 args: args{
152 pid: "62212",
153 status: &kubecontainer.PodStatus{
154 IPs: []string{"10.0.0.10", "10.23.0.1"},
155 },
156 },
157 oldstatus: &kubecontainer.PodStatus{
158 IPs: []string{"192.168.0.10", "192.168.0.1"},
159 },
160 expected: []string{"10.0.0.10", "10.23.0.1"},
161 },
162 {
163 name: "status ips is empty and SandboxStatuses has PodSandboxState_SANDBOX_READY state",
164 args: args{
165 pid: "62212",
166 status: &kubecontainer.PodStatus{
167 SandboxStatuses: []*v1.PodSandboxStatus{
168 {
169 Id: "sandboxID2",
170 Metadata: &v1.PodSandboxMetadata{Attempt: uint32(1)},
171 State: v1.PodSandboxState_SANDBOX_READY,
172 },
173 {
174 Id: "sandboxID1",
175 Metadata: &v1.PodSandboxMetadata{Attempt: uint32(0)},
176 State: v1.PodSandboxState_SANDBOX_NOTREADY,
177 },
178 },
179 },
180 },
181 oldstatus: &kubecontainer.PodStatus{
182 IPs: []string{"192.168.0.10", "192.168.0.1"},
183 },
184 expected: nil,
185 },
186 {
187 name: "status and cache ips are empty",
188 args: args{
189 pid: "62212",
190 status: &kubecontainer.PodStatus{},
191 },
192 oldstatus: &kubecontainer.PodStatus{
193 IPs: []string{},
194 },
195 expected: nil,
196 },
197 {
198 name: "sandbox state is no PodSandboxState_SANDBOX_READY",
199 args: args{
200 pid: "62212",
201 status: &kubecontainer.PodStatus{
202 SandboxStatuses: []*v1.PodSandboxStatus{
203 {
204 Id: "sandboxID2",
205 Metadata: &v1.PodSandboxMetadata{Attempt: uint32(1)},
206 State: v1.PodSandboxState_SANDBOX_NOTREADY,
207 },
208 {
209 Id: "sandboxID1",
210 Metadata: &v1.PodSandboxMetadata{Attempt: uint32(0)},
211 State: v1.PodSandboxState_SANDBOX_NOTREADY,
212 },
213 },
214 },
215 },
216 oldstatus: &kubecontainer.PodStatus{
217 IPs: []string{"192.168.0.10", "192.168.0.1"},
218 },
219 expected: []string{"192.168.0.10", "192.168.0.1"},
220 },
221 }
222 for _, test := range tests {
223 cache.Set(test.args.pid, test.oldstatus, nil, time.Time{})
224 e := &EventedPLEG{
225 cache: cache,
226 }
227 t.Run(test.name, func(t *testing.T) {
228 if got := e.getPodIPs(test.args.pid, test.args.status); !reflect.DeepEqual(got, test.expected) {
229 t.Errorf("EventedPLEG.getPodIPs() = %v, expected %v", got, test.expected)
230 }
231 })
232 }
233 }
234
View as plain text