@@ -15,6 +15,7 @@ import (
1515 "github.com/zalando/postgres-operator/pkg/util/config"
1616 "github.com/zalando/postgres-operator/pkg/util/k8sutil"
1717 "github.com/zalando/postgres-operator/pkg/util/patroni"
18+ v1 "k8s.io/api/core/v1"
1819)
1920
2021func TestGetSwitchoverCandidate (t * testing.T ) {
@@ -112,3 +113,302 @@ func TestGetSwitchoverCandidate(t *testing.T) {
112113 }
113114 }
114115}
116+
117+ func TestPodIsNotRunning (t * testing.T ) {
118+ tests := []struct {
119+ subtest string
120+ pod v1.Pod
121+ expected bool
122+ }{
123+ {
124+ subtest : "pod with no status reported yet" ,
125+ pod : v1.Pod {
126+ Status : v1.PodStatus {},
127+ },
128+ expected : false ,
129+ },
130+ {
131+ subtest : "pod running with all containers ready" ,
132+ pod : v1.Pod {
133+ Status : v1.PodStatus {
134+ Phase : v1 .PodRunning ,
135+ ContainerStatuses : []v1.ContainerStatus {
136+ {
137+ State : v1.ContainerState {
138+ Running : & v1.ContainerStateRunning {},
139+ },
140+ },
141+ },
142+ },
143+ },
144+ expected : false ,
145+ },
146+ {
147+ subtest : "pod in pending phase" ,
148+ pod : v1.Pod {
149+ Status : v1.PodStatus {
150+ Phase : v1 .PodPending ,
151+ },
152+ },
153+ expected : true ,
154+ },
155+ {
156+ subtest : "pod running but container in CreateContainerConfigError" ,
157+ pod : v1.Pod {
158+ Status : v1.PodStatus {
159+ Phase : v1 .PodRunning ,
160+ ContainerStatuses : []v1.ContainerStatus {
161+ {
162+ State : v1.ContainerState {
163+ Waiting : & v1.ContainerStateWaiting {
164+ Reason : "CreateContainerConfigError" ,
165+ Message : `secret "some-secret" not found` ,
166+ },
167+ },
168+ },
169+ },
170+ },
171+ },
172+ expected : true ,
173+ },
174+ {
175+ subtest : "pod running but container in CrashLoopBackOff" ,
176+ pod : v1.Pod {
177+ Status : v1.PodStatus {
178+ Phase : v1 .PodRunning ,
179+ ContainerStatuses : []v1.ContainerStatus {
180+ {
181+ State : v1.ContainerState {
182+ Waiting : & v1.ContainerStateWaiting {
183+ Reason : "CrashLoopBackOff" ,
184+ },
185+ },
186+ },
187+ },
188+ },
189+ },
190+ expected : true ,
191+ },
192+ {
193+ subtest : "pod running but container terminated" ,
194+ pod : v1.Pod {
195+ Status : v1.PodStatus {
196+ Phase : v1 .PodRunning ,
197+ ContainerStatuses : []v1.ContainerStatus {
198+ {
199+ State : v1.ContainerState {
200+ Terminated : & v1.ContainerStateTerminated {
201+ ExitCode : 137 ,
202+ },
203+ },
204+ },
205+ },
206+ },
207+ },
208+ expected : true ,
209+ },
210+ {
211+ subtest : "pod running with mixed container states - one healthy one broken" ,
212+ pod : v1.Pod {
213+ Status : v1.PodStatus {
214+ Phase : v1 .PodRunning ,
215+ ContainerStatuses : []v1.ContainerStatus {
216+ {
217+ State : v1.ContainerState {
218+ Running : & v1.ContainerStateRunning {},
219+ },
220+ },
221+ {
222+ State : v1.ContainerState {
223+ Waiting : & v1.ContainerStateWaiting {
224+ Reason : "CreateContainerConfigError" ,
225+ },
226+ },
227+ },
228+ },
229+ },
230+ },
231+ expected : true ,
232+ },
233+ {
234+ subtest : "pod in failed phase" ,
235+ pod : v1.Pod {
236+ Status : v1.PodStatus {
237+ Phase : v1 .PodFailed ,
238+ },
239+ },
240+ expected : true ,
241+ },
242+ {
243+ subtest : "pod running with multiple healthy containers" ,
244+ pod : v1.Pod {
245+ Status : v1.PodStatus {
246+ Phase : v1 .PodRunning ,
247+ ContainerStatuses : []v1.ContainerStatus {
248+ {
249+ State : v1.ContainerState {
250+ Running : & v1.ContainerStateRunning {},
251+ },
252+ },
253+ {
254+ State : v1.ContainerState {
255+ Running : & v1.ContainerStateRunning {},
256+ },
257+ },
258+ },
259+ },
260+ },
261+ expected : false ,
262+ },
263+ {
264+ subtest : "pod running with ImagePullBackOff" ,
265+ pod : v1.Pod {
266+ Status : v1.PodStatus {
267+ Phase : v1 .PodRunning ,
268+ ContainerStatuses : []v1.ContainerStatus {
269+ {
270+ State : v1.ContainerState {
271+ Waiting : & v1.ContainerStateWaiting {
272+ Reason : "ImagePullBackOff" ,
273+ },
274+ },
275+ },
276+ },
277+ },
278+ },
279+ expected : true ,
280+ },
281+ }
282+
283+ for _ , tt := range tests {
284+ t .Run (tt .subtest , func (t * testing.T ) {
285+ result := podIsNotRunning (& tt .pod )
286+ if result != tt .expected {
287+ t .Errorf ("podIsNotRunning() = %v, expected %v" , result , tt .expected )
288+ }
289+ })
290+ }
291+ }
292+
293+ func TestAllPodsRunning (t * testing.T ) {
294+ client , _ := newFakeK8sSyncClient ()
295+
296+ var cluster = New (
297+ Config {
298+ OpConfig : config.Config {
299+ Resources : config.Resources {
300+ ClusterLabels : map [string ]string {"application" : "spilo" },
301+ ClusterNameLabel : "cluster-name" ,
302+ PodRoleLabel : "spilo-role" ,
303+ },
304+ },
305+ }, client , acidv1.Postgresql {}, logger , eventRecorder )
306+
307+ tests := []struct {
308+ subtest string
309+ pods []v1.Pod
310+ expected bool
311+ }{
312+ {
313+ subtest : "all pods running" ,
314+ pods : []v1.Pod {
315+ {
316+ Status : v1.PodStatus {
317+ Phase : v1 .PodRunning ,
318+ ContainerStatuses : []v1.ContainerStatus {
319+ {State : v1.ContainerState {Running : & v1.ContainerStateRunning {}}},
320+ },
321+ },
322+ },
323+ {
324+ Status : v1.PodStatus {
325+ Phase : v1 .PodRunning ,
326+ ContainerStatuses : []v1.ContainerStatus {
327+ {State : v1.ContainerState {Running : & v1.ContainerStateRunning {}}},
328+ },
329+ },
330+ },
331+ },
332+ expected : true ,
333+ },
334+ {
335+ subtest : "one pod not running" ,
336+ pods : []v1.Pod {
337+ {
338+ Status : v1.PodStatus {
339+ Phase : v1 .PodRunning ,
340+ ContainerStatuses : []v1.ContainerStatus {
341+ {State : v1.ContainerState {Running : & v1.ContainerStateRunning {}}},
342+ },
343+ },
344+ },
345+ {
346+ Status : v1.PodStatus {
347+ Phase : v1 .PodRunning ,
348+ ContainerStatuses : []v1.ContainerStatus {
349+ {
350+ State : v1.ContainerState {
351+ Waiting : & v1.ContainerStateWaiting {
352+ Reason : "CreateContainerConfigError" ,
353+ },
354+ },
355+ },
356+ },
357+ },
358+ },
359+ },
360+ expected : false ,
361+ },
362+ {
363+ subtest : "all pods not running" ,
364+ pods : []v1.Pod {
365+ {
366+ Status : v1.PodStatus {
367+ Phase : v1 .PodPending ,
368+ },
369+ },
370+ {
371+ Status : v1.PodStatus {
372+ Phase : v1 .PodRunning ,
373+ ContainerStatuses : []v1.ContainerStatus {
374+ {
375+ State : v1.ContainerState {
376+ Waiting : & v1.ContainerStateWaiting {
377+ Reason : "CrashLoopBackOff" ,
378+ },
379+ },
380+ },
381+ },
382+ },
383+ },
384+ },
385+ expected : false ,
386+ },
387+ {
388+ subtest : "empty pod list" ,
389+ pods : []v1.Pod {},
390+ expected : true ,
391+ },
392+ {
393+ subtest : "pods with no status reported yet" ,
394+ pods : []v1.Pod {
395+ {
396+ Status : v1.PodStatus {},
397+ },
398+ {
399+ Status : v1.PodStatus {},
400+ },
401+ },
402+ expected : true ,
403+ },
404+ }
405+
406+ for _ , tt := range tests {
407+ t .Run (tt .subtest , func (t * testing.T ) {
408+ result := cluster .allPodsRunning (tt .pods )
409+ if result != tt .expected {
410+ t .Errorf ("allPodsRunning() = %v, expected %v" , result , tt .expected )
411+ }
412+ })
413+ }
414+ }
0 commit comments