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