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 }