client: send error events if update check or ping fails

Does not report errors when sending events since that would be cyclic.
This commit is contained in:
Michael Marineau 2017-06-08 14:28:48 -07:00
parent 41143a9d17
commit 2d48f3a029
3 changed files with 54 additions and 11 deletions

View file

@ -209,11 +209,16 @@ func (ac *AppClient) UpdateCheck() (*omaha.UpdateResponse, error) {
ac.sentPing = true ac.sentPing = true
appResp, err := ac.doReq(ac.apiEndpoint, req) appResp, err := ac.doReq(ac.apiEndpoint, req)
if err != nil { if err, ok := err.(ErrorEvent); ok {
ac.Event(err.ErrorEvent())
return nil, err
} else if err != nil {
ac.Event(NewErrorEvent(ExitCodeOmahaRequestError))
return nil, err return nil, err
} }
if appResp.Ping == nil { if appResp.Ping == nil {
ac.Event(NewErrorEvent(ExitCodeOmahaResponseInvalid))
return nil, fmt.Errorf("omaha: ping status missing from response") return nil, fmt.Errorf("omaha: ping status missing from response")
} }
@ -222,6 +227,7 @@ func (ac *AppClient) UpdateCheck() (*omaha.UpdateResponse, error) {
} }
if appResp.UpdateCheck == nil { if appResp.UpdateCheck == nil {
ac.Event(NewErrorEvent(ExitCodeOmahaResponseInvalid))
return nil, fmt.Errorf("omaha: update check missing from response") return nil, fmt.Errorf("omaha: update check missing from response")
} }
@ -240,11 +246,16 @@ func (ac *AppClient) Ping() error {
ac.sentPing = true ac.sentPing = true
appResp, err := ac.doReq(ac.apiEndpoint, req) appResp, err := ac.doReq(ac.apiEndpoint, req)
if err != nil { if err, ok := err.(ErrorEvent); ok {
ac.Event(err.ErrorEvent())
return err
} else if err != nil {
ac.Event(NewErrorEvent(ExitCodeOmahaRequestError))
return err return err
} }
if appResp.Ping == nil { if appResp.Ping == nil {
ac.Event(NewErrorEvent(ExitCodeOmahaResponseInvalid))
return fmt.Errorf("omaha: ping status missing from response") return fmt.Errorf("omaha: ping status missing from response")
} }
@ -325,7 +336,10 @@ func (ac *AppClient) doReq(url string, req *omaha.Request) (*omaha.AppResponse,
appResp := resp.GetApp(appID) appResp := resp.GetApp(appID)
if appResp == nil { if appResp == nil {
return nil, fmt.Errorf("omaha: app %s missing from response", appID) return nil, &omahaError{
Err: fmt.Errorf("app %s missing from response", appID),
Code: ExitCodeOmahaResponseInvalid,
}
} }
if appResp.Status != omaha.AppOK { if appResp.Status != omaha.AppOK {

View file

@ -21,11 +21,19 @@ import (
"net" "net"
"net/http" "net/http"
"time" "time"
"github.com/coreos/go-omaha/omaha"
) )
var ( var (
bodySizeError = errors.New("http response exceeded 1MB") bodySizeError = &omahaError{
bodyEmptyError = errors.New("http response was empty") Err: errors.New("http response exceeded 1MB"),
Code: ExitCodeOmahaResponseInvalid,
}
bodyEmptyError = &omahaError{
Err: errors.New("http response was empty"),
Code: ExitCodeOmahaRequestEmptyResponseError,
}
// default parameters for expNetBackoff // default parameters for expNetBackoff
backoffStart = time.Second backoffStart = time.Second
@ -60,7 +68,21 @@ func isUnexpectedEOF(err error) bool {
return err == io.ErrUnexpectedEOF return err == io.ErrUnexpectedEOF
} }
// httpError implements error and net.Error for http responses. // omahaError implements error and ErrorEvent for omaha requests/responses.
type omahaError struct {
Err error
Code ExitCode
}
func (oe *omahaError) Error() string {
return "omaha: request failed: " + oe.Err.Error()
}
func (oe *omahaError) ErrorEvent() *omaha.EventRequest {
return NewErrorEvent(oe.Code)
}
// httpError implements error, net.Error, and ErrorEvent for http responses.
type httpError struct { type httpError struct {
*http.Response *http.Response
} }
@ -69,6 +91,14 @@ func (he *httpError) Error() string {
return "http error: " + he.Status return "http error: " + he.Status
} }
func (he *httpError) ErrorEvent() *omaha.EventRequest {
code := ExitCodeOmahaRequestError
if he.StatusCode > 0 && he.StatusCode < 1000 {
code = ExitCodeOmahaRequestHTTPResponseBase + ExitCode(he.StatusCode)
}
return NewErrorEvent(code)
}
func (he *httpError) Timeout() bool { func (he *httpError) Timeout() bool {
switch he.StatusCode { switch he.StatusCode {
case http.StatusRequestTimeout: // 408 case http.StatusRequestTimeout: // 408

View file

@ -45,7 +45,7 @@ func newHTTPClient() *httpClient {
func (hc *httpClient) doPost(url string, reqBody []byte) (*omaha.Response, error) { func (hc *httpClient) doPost(url string, reqBody []byte) (*omaha.Response, error) {
resp, err := hc.Post(url, "text/xml; charset=utf-8", bytes.NewReader(reqBody)) resp, err := hc.Post(url, "text/xml; charset=utf-8", bytes.NewReader(reqBody))
if err != nil { if err != nil {
return nil, err return nil, &omahaError{err, ExitCodeOmahaRequestError}
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -59,6 +59,8 @@ func (hc *httpClient) doPost(url string, reqBody []byte) (*omaha.Response, error
err = bodySizeError err = bodySizeError
} else if err == io.EOF { } else if err == io.EOF {
err = bodyEmptyError err = bodyEmptyError
} else if err != nil {
err = &omahaError{err, ExitCodeOmahaRequestXMLParseError}
} }
// Prefer reporting HTTP errors over XML parsing errors. // Prefer reporting HTTP errors over XML parsing errors.
@ -81,9 +83,6 @@ func (hc *httpClient) Omaha(url string, req *omaha.Request) (resp *omaha.Respons
resp, err = hc.doPost(url, buf.Bytes()) resp, err = hc.doPost(url, buf.Bytes())
return err return err
}) })
if err != nil {
return nil, fmt.Errorf("omaha: request failed: %v", err)
}
return resp, nil return resp, err
} }