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  }