github.com/arunkumar7540/cli@v6.45.0+incompatible/api/cloudcontroller/ccv3/job.go (about)

     1  package ccv3
     2  
     3  import (
     4  	"time"
     5  
     6  	"code.cloudfoundry.org/cli/api/cloudcontroller"
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
     9  )
    10  
    11  // Job represents a Cloud Controller Job.
    12  type Job struct {
    13  	// RawErrors is a list of errors that occurred while processing the job.
    14  	RawErrors []JobErrorDetails `json:"errors"`
    15  	// GUID is a unique identifier for the job.
    16  	GUID string `json:"guid"`
    17  	// State is the state of the job.
    18  	State constant.JobState `json:"state"`
    19  }
    20  
    21  // Errors returns back a list of
    22  func (job Job) Errors() []error {
    23  	var errs []error
    24  	for _, errDetails := range job.RawErrors {
    25  		switch errDetails.Code {
    26  		case constant.JobErrorCodeBuildpackAlreadyExistsForStack:
    27  			errs = append(errs, ccerror.BuildpackAlreadyExistsForStackError{Message: errDetails.Detail})
    28  		case constant.JobErrorCodeBuildpackAlreadyExistsWithoutStack:
    29  			errs = append(errs, ccerror.BuildpackAlreadyExistsWithoutStackError{Message: errDetails.Detail})
    30  		case constant.JobErrorCodeBuildpackStacksDontMatch:
    31  			errs = append(errs, ccerror.BuildpackStacksDontMatchError{Message: errDetails.Detail})
    32  		case constant.JobErrorCodeBuildpackStackDoesNotExist:
    33  			errs = append(errs, ccerror.BuildpackStackDoesNotExistError{Message: errDetails.Detail})
    34  		case constant.JobErrorCodeBuildpackZipInvalid:
    35  			errs = append(errs, ccerror.BuildpackZipInvalidError{Message: errDetails.Detail})
    36  		default:
    37  			errs = append(errs, ccerror.V3JobFailedError{
    38  				JobGUID: job.GUID,
    39  				Code:    errDetails.Code,
    40  				Detail:  errDetails.Detail,
    41  				Title:   errDetails.Title,
    42  			})
    43  		}
    44  	}
    45  	return errs
    46  }
    47  
    48  // HasFailed returns true when the job has completed with an error/failure.
    49  func (job Job) HasFailed() bool {
    50  	return job.State == constant.JobFailed
    51  }
    52  
    53  // IsComplete returns true when the job has completed successfully.
    54  func (job Job) IsComplete() bool {
    55  	return job.State == constant.JobComplete
    56  }
    57  
    58  // JobErrorDetails provides information regarding a job's error.
    59  type JobErrorDetails struct {
    60  	// Code is a numeric code for this error.
    61  	Code constant.JobErrorCode `json:"code"`
    62  	// Detail is a verbose description of the error.
    63  	Detail string `json:"detail"`
    64  	// Title is a short description of the error.
    65  	Title string `json:"title"`
    66  }
    67  
    68  // GetJob returns a job for the provided GUID.
    69  func (client *Client) GetJob(jobURL JobURL) (Job, Warnings, error) {
    70  	request, err := client.newHTTPRequest(requestOptions{URL: string(jobURL)})
    71  	if err != nil {
    72  		return Job{}, nil, err
    73  	}
    74  
    75  	var job Job
    76  	response := cloudcontroller.Response{
    77  		DecodeJSONResponseInto: &job,
    78  	}
    79  
    80  	err = client.connection.Make(request, &response)
    81  	return job, response.Warnings, err
    82  }
    83  
    84  // PollJob will keep polling the given job until the job has terminated, an
    85  // error is encountered, or config.OverallPollingTimeout is reached. In the
    86  // last case, a JobTimeoutError is returned.
    87  func (client *Client) PollJob(jobURL JobURL) (Warnings, error) {
    88  	var (
    89  		err         error
    90  		warnings    Warnings
    91  		allWarnings Warnings
    92  		job         Job
    93  	)
    94  
    95  	startTime := client.clock.Now()
    96  	for client.clock.Now().Sub(startTime) < client.jobPollingTimeout {
    97  		job, warnings, err = client.GetJob(jobURL)
    98  		allWarnings = append(allWarnings, warnings...)
    99  		if err != nil {
   100  			return allWarnings, err
   101  		}
   102  
   103  		if job.HasFailed() {
   104  			firstError := job.Errors()[0]
   105  			return allWarnings, firstError
   106  		}
   107  
   108  		if job.IsComplete() {
   109  			return allWarnings, nil
   110  		}
   111  
   112  		time.Sleep(client.jobPollingInterval)
   113  	}
   114  
   115  	return allWarnings, ccerror.JobTimeoutError{
   116  		JobGUID: job.GUID,
   117  		Timeout: client.jobPollingTimeout,
   118  	}
   119  }