github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+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  // ErrorDetails provides information regarding a job's error.
    12  type ErrorDetails struct {
    13  	// Code is a numeric code for this error.
    14  	Code int64 `json:"code"`
    15  	// Detail is a verbose description of the error.
    16  	Detail string `json:"detail"`
    17  	// Title is a short description of the error.
    18  	Title string `json:"title"`
    19  }
    20  
    21  // Job represents a Cloud Controller Job.
    22  type Job struct {
    23  	// Errors is a list of errors that occurred while processing the job.
    24  	Errors []ErrorDetails `json:"errors"`
    25  	// GUID is a unique identifier for the job.
    26  	GUID string `json:"guid"`
    27  	// State is the state of the job.
    28  	State constant.JobState `json:"state"`
    29  }
    30  
    31  // HasFailed returns true when the job has completed with an error/failure.
    32  func (job Job) HasFailed() bool {
    33  	return job.State == constant.JobFailed
    34  }
    35  
    36  // IsComplete returns true when the job has completed successfully.
    37  func (job Job) IsComplete() bool {
    38  	return job.State == constant.JobComplete
    39  }
    40  
    41  // GetJob returns a job for the provided GUID.
    42  func (client *Client) GetJob(jobURL JobURL) (Job, Warnings, error) {
    43  	request, err := client.newHTTPRequest(requestOptions{URL: string(jobURL)})
    44  	if err != nil {
    45  		return Job{}, nil, err
    46  	}
    47  
    48  	var job Job
    49  	response := cloudcontroller.Response{
    50  		DecodeJSONResponseInto: &job,
    51  	}
    52  
    53  	err = client.connection.Make(request, &response)
    54  	return job, response.Warnings, err
    55  }
    56  
    57  // PollJob will keep polling the given job until the job has terminated, an
    58  // error is encountered, or config.OverallPollingTimeout is reached. In the
    59  // last case, a JobTimeoutError is returned.
    60  func (client *Client) PollJob(jobURL JobURL) (Warnings, error) {
    61  	var (
    62  		err         error
    63  		warnings    Warnings
    64  		allWarnings Warnings
    65  		job         Job
    66  	)
    67  
    68  	startTime := client.clock.Now()
    69  	for client.clock.Now().Sub(startTime) < client.jobPollingTimeout {
    70  		job, warnings, err = client.GetJob(jobURL)
    71  		allWarnings = append(allWarnings, warnings...)
    72  		if err != nil {
    73  			return allWarnings, err
    74  		}
    75  
    76  		if job.HasFailed() {
    77  			firstError := job.Errors[0]
    78  			return allWarnings, ccerror.V3JobFailedError{
    79  				JobGUID: job.GUID,
    80  				Code:    firstError.Code,
    81  				Detail:  firstError.Detail,
    82  				Title:   firstError.Title,
    83  			}
    84  		}
    85  
    86  		if job.IsComplete() {
    87  			return allWarnings, nil
    88  		}
    89  
    90  		time.Sleep(client.jobPollingInterval)
    91  	}
    92  
    93  	return allWarnings, ccerror.JobTimeoutError{
    94  		JobGUID: job.GUID,
    95  		Timeout: client.jobPollingTimeout,
    96  	}
    97  }