github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/job.go (about) 1 package kube 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/ghodss/yaml" 8 "github.com/jenkins-x/jx-logging/pkg/log" 9 10 "context" 11 12 batchv1 "k8s.io/api/batch/v1" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 "k8s.io/apimachinery/pkg/fields" 15 "k8s.io/apimachinery/pkg/util/wait" 16 "k8s.io/apimachinery/pkg/watch" 17 "k8s.io/client-go/kubernetes" 18 tools_watch "k8s.io/client-go/tools/watch" 19 ) 20 21 // waits for the job to complete 22 func WaitForJobToSucceeded(client kubernetes.Interface, namespace, jobName string, timeout time.Duration) error { 23 job, err := client.BatchV1().Jobs(namespace).Get(jobName, metav1.GetOptions{}) 24 if err != nil { 25 return err 26 } 27 28 options := metav1.ListOptions{FieldSelector: fields.OneTermEqualSelector("metadata.name", job.Name).String()} 29 30 w, err := client.BatchV1().Jobs(namespace).Watch(options) 31 if err != nil { 32 return err 33 } 34 35 defer w.Stop() 36 37 condition := func(event watch.Event) (bool, error) { 38 job := event.Object.(*batchv1.Job) 39 return job.Status.Succeeded == 1, nil 40 } 41 42 ctx, _ := context.WithTimeout(context.Background(), timeout) 43 _, err = tools_watch.UntilWithoutRetry(ctx, w, condition) 44 45 if err == wait.ErrWaitTimeout { 46 return fmt.Errorf("job %s never succeeded", jobName) 47 } 48 return nil 49 } 50 51 // WaitForJobToComplete waits for the job to complete 52 func WaitForJobToComplete(client kubernetes.Interface, namespace, jobName string, timeout time.Duration, verbose bool) error { 53 job, err := client.BatchV1().Jobs(namespace).Get(jobName, metav1.GetOptions{}) 54 if err != nil { 55 return err 56 } 57 58 options := metav1.ListOptions{FieldSelector: fields.OneTermEqualSelector("metadata.name", job.Name).String()} 59 60 w, err := client.BatchV1().Jobs(namespace).Watch(options) 61 if err != nil { 62 return err 63 } 64 65 defer w.Stop() 66 67 condition := func(event watch.Event) (bool, error) { 68 job := event.Object.(*batchv1.Job) 69 completionTime := job.Status.CompletionTime 70 complete := completionTime != nil && !completionTime.IsZero() 71 if complete && verbose { 72 data, _ := yaml.Marshal(job) 73 log.Logger().Infof("Job %s is complete: %s", jobName, string(data)) 74 } 75 return complete, nil 76 } 77 78 ctx, _ := context.WithTimeout(context.Background(), timeout) 79 _, err = tools_watch.UntilWithoutRetry(ctx, w, condition) 80 if err == wait.ErrWaitTimeout { 81 return fmt.Errorf("job %s never terminated", jobName) 82 } 83 return nil 84 } 85 86 // WaitForJobToFinish waits for the job to finish 87 func WaitForJobToFinish(client kubernetes.Interface, namespace, jobName string, timeout time.Duration, verbose bool) error { 88 job, err := client.BatchV1().Jobs(namespace).Get(jobName, metav1.GetOptions{}) 89 if err != nil { 90 return err 91 } 92 93 options := metav1.ListOptions{FieldSelector: fields.OneTermEqualSelector("metadata.name", job.Name).String()} 94 95 w, err := client.BatchV1().Jobs(namespace).Watch(options) 96 if err != nil { 97 return err 98 } 99 100 defer w.Stop() 101 102 condition := func(event watch.Event) (bool, error) { 103 job := event.Object.(*batchv1.Job) 104 complete := IsJobFinished(job) 105 if complete && verbose { 106 data, _ := yaml.Marshal(job) 107 log.Logger().Infof("Job %s is complete: %s", jobName, string(data)) 108 } 109 return complete, nil 110 } 111 112 ctx, _ := context.WithTimeout(context.Background(), timeout) 113 _, err = tools_watch.UntilWithoutRetry(ctx, w, condition) 114 if err == wait.ErrWaitTimeout { 115 return fmt.Errorf("job %s never terminated", jobName) 116 } 117 return nil 118 } 119 120 // IsJobSucceeded returns true if the job completed and did not fail 121 func IsJobSucceeded(job *batchv1.Job) bool { 122 return IsJobFinished(job) && job.Status.Succeeded > 0 123 } 124 125 // IsJobFinished returns true if the job has completed 126 func IsJobFinished(job *batchv1.Job) bool { 127 BackoffLimit := job.Spec.BackoffLimit 128 return job.Status.CompletionTime != nil || (job.Status.Active == 0 && BackoffLimit != nil && job.Status.Failed >= *BackoffLimit) 129 } 130 131 func DeleteJob(client kubernetes.Interface, namespace, name string) error { 132 err := client.BatchV1().Jobs(namespace).Delete(name, metav1.NewDeleteOptions(0)) 133 if err != nil { 134 return fmt.Errorf("error deleting job %s. error: %v", name, err) 135 } 136 return nil 137 }