| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- package wait
- import (
- "context"
- "fmt"
- "strconv"
- "time"
- "github.com/fatih/color"
- api "github.com/porter-dev/porter/api/client"
- v1 "k8s.io/api/batch/v1"
- )
- type WaitOpts struct {
- ProjectID, ClusterID uint
- Namespace, Name string
- }
- // WaitForJob waits for a job with a given name/namespace to complete its run
- func WaitForJob(client *api.Client, opts *WaitOpts) error {
- // get the job release
- jobRelease, err := client.GetRelease(context.Background(), opts.ProjectID, opts.ClusterID, opts.Namespace, opts.Name)
- if err != nil {
- return err
- }
- // make sure the job chart has a manual job running
- pausedVal, ok := jobRelease.Release.Config["paused"]
- pausedErr := fmt.Errorf("this job template is not currently running a manual job")
- if !ok {
- return pausedErr
- }
- if pausedValBool, ok := pausedVal.(bool); ok && pausedValBool {
- return pausedErr
- }
- // attempt to parse out the timeout value for the job, given by `sidecar.timeout`
- // if it does not exist, we set the default to 30 minutes
- timeoutVal := getJobTimeoutValue(jobRelease.Release.Config)
- color.New(color.FgYellow).Printf("Waiting for timeout seconds %.1f\n", timeoutVal.Seconds())
- // if no job exists with the given revision, wait for the timeout value
- timeWait := time.Now().Add(timeoutVal)
- for time.Now().Before(timeWait) {
- // get the jobs for that job chart
- jobs, err := client.GetJobs(context.Background(), opts.ProjectID, opts.ClusterID, opts.Namespace, opts.Name)
- if err != nil {
- return err
- }
- job := getJobMatchingRevision(uint(jobRelease.Release.Version), jobs)
- if job == nil {
- time.Sleep(10 * time.Second)
- continue
- }
- // once job is running, wait for status to be completed, or failed
- // if failed, exit with non-zero exit code
- if job.Status.Failed > 0 {
- return fmt.Errorf("job failed")
- }
- if job.Status.Succeeded > 0 {
- return nil
- }
- // otherwise, return no error
- time.Sleep(10 * time.Second)
- }
- return fmt.Errorf("timed out waiting for job")
- }
- func getJobMatchingRevision(revision uint, jobs []v1.Job) *v1.Job {
- for _, job := range jobs {
- revisionLabel, revisionLabelExists := job.Labels["helm.sh/revision"]
- if !revisionLabelExists {
- continue
- }
- jobRevision, err := strconv.ParseUint(revisionLabel, 10, 64)
- if err != nil {
- continue
- }
- if uint(jobRevision) == revision {
- return &job
- }
- }
- return nil
- }
- func getJobTimeoutValue(values map[string]interface{}) time.Duration {
- defaultTimeout := time.Minute * 60
- sidecarInter, ok := values["sidecar"]
- if !ok {
- return defaultTimeout
- }
- sidecarVal, ok := sidecarInter.(map[string]interface{})
- if !ok {
- return defaultTimeout
- }
- timeoutInter, ok := sidecarVal["timeout"]
- if !ok {
- return defaultTimeout
- }
- timeoutVal, ok := timeoutInter.(float64)
- if !ok {
- return defaultTimeout
- }
- return time.Second * time.Duration(timeoutVal)
- }
|