1/*
2Copyright 2019 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package job
18
19import (
20	"context"
21	"time"
22
23	batchv1 "k8s.io/api/batch/v1"
24	"k8s.io/api/core/v1"
25	apierrors "k8s.io/apimachinery/pkg/api/errors"
26	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27	"k8s.io/apimachinery/pkg/util/wait"
28	clientset "k8s.io/client-go/kubernetes"
29	"k8s.io/kubernetes/test/e2e/framework"
30)
31
32// WaitForAllJobPodsRunning wait for all pods for the Job named JobName in namespace ns to become Running.  Only use
33// when pods will run for a long time, or it will be racy.
34func WaitForAllJobPodsRunning(c clientset.Interface, ns, jobName string, parallelism int32) error {
35	return wait.Poll(framework.Poll, JobTimeout, func() (bool, error) {
36		pods, err := GetJobPods(c, ns, jobName)
37		if err != nil {
38			return false, err
39		}
40		count := int32(0)
41		for _, p := range pods.Items {
42			if p.Status.Phase == v1.PodRunning {
43				count++
44			}
45		}
46		return count == parallelism, nil
47	})
48}
49
50// WaitForJobComplete uses c to wait for completions to complete for the Job jobName in namespace ns.
51func WaitForJobComplete(c clientset.Interface, ns, jobName string, completions int32) error {
52	return wait.Poll(framework.Poll, JobTimeout, func() (bool, error) {
53		curr, err := c.BatchV1().Jobs(ns).Get(context.TODO(), jobName, metav1.GetOptions{})
54		if err != nil {
55			return false, err
56		}
57		return curr.Status.Succeeded == completions, nil
58	})
59}
60
61// WaitForJobFinish uses c to wait for the Job jobName in namespace ns to finish (either Failed or Complete).
62func WaitForJobFinish(c clientset.Interface, ns, jobName string) error {
63	return wait.PollImmediate(framework.Poll, JobTimeout, func() (bool, error) {
64		curr, err := c.BatchV1().Jobs(ns).Get(context.TODO(), jobName, metav1.GetOptions{})
65		if err != nil {
66			return false, err
67		}
68
69		return isJobFinished(curr), nil
70	})
71}
72
73func isJobFinished(j *batchv1.Job) bool {
74	for _, c := range j.Status.Conditions {
75		if (c.Type == batchv1.JobComplete || c.Type == batchv1.JobFailed) && c.Status == v1.ConditionTrue {
76			return true
77		}
78	}
79
80	return false
81}
82
83// WaitForJobGone uses c to wait for up to timeout for the Job named jobName in namespace ns to be removed.
84func WaitForJobGone(c clientset.Interface, ns, jobName string, timeout time.Duration) error {
85	return wait.Poll(framework.Poll, timeout, func() (bool, error) {
86		_, err := c.BatchV1().Jobs(ns).Get(context.TODO(), jobName, metav1.GetOptions{})
87		if apierrors.IsNotFound(err) {
88			return true, nil
89		}
90		return false, err
91	})
92}
93
94// WaitForAllJobPodsGone waits for all pods for the Job named jobName in namespace ns
95// to be deleted.
96func WaitForAllJobPodsGone(c clientset.Interface, ns, jobName string) error {
97	return wait.PollImmediate(framework.Poll, JobTimeout, func() (bool, error) {
98		pods, err := GetJobPods(c, ns, jobName)
99		if err != nil {
100			return false, err
101		}
102		return len(pods.Items) == 0, nil
103	})
104}
105