-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(edge): parse the response body with failed request [EE-7244] #661
base: develop
Are you sure you want to change the base?
Changes from 7 commits
04af5ac
ef4569b
6ac038f
385914a
a9c97e8
46c81c1
9426755
55b9929
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,40 +2,28 @@ package client | |
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"net/http" | ||
|
||
httperror "github.com/portainer/portainer/pkg/libhttp/error" | ||
"github.com/rs/zerolog/log" | ||
) | ||
|
||
type errorData struct { | ||
Details string | ||
Message string | ||
} | ||
|
||
func parseError(resp *http.Response) *errorData { | ||
errorData := &errorData{} | ||
|
||
err := json.NewDecoder(resp.Body).Decode(&errorData) | ||
if err != nil { | ||
log.Debug().CallerSkipFrame(1). | ||
func logPollingError(resp *http.Response, ctxMsg, errMsg string) error { | ||
var respErr httperror.HandlerError | ||
if err := json.NewDecoder(resp.Body).Decode(&respErr); err != nil { | ||
log. | ||
Error(). | ||
Err(err). | ||
Int("status_code", resp.StatusCode). | ||
Msg("failed to decode error response") | ||
|
||
return nil | ||
Str("context", ctxMsg). | ||
Int("response_code", resp.StatusCode). | ||
Msg("PollClient failed to decode server response") | ||
} | ||
|
||
return errorData | ||
} | ||
|
||
func logError(resp *http.Response, errorData *errorData) { | ||
if errorData == nil { | ||
return | ||
} | ||
|
||
log.Debug().CallerSkipFrame(1). | ||
Str("error_response_message", errorData.Message). | ||
Str("error_response_details", errorData.Details). | ||
Int("status_code", resp.StatusCode). | ||
Msg("poll request failure") | ||
log. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we use |
||
Error().Err(respErr.Err). | ||
Str("context", ctxMsg). | ||
Str("response message", respErr.Message). | ||
Int("status code", respErr.StatusCode). | ||
Msg(errMsg) | ||
return errors.New(errMsg) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -415,14 +415,7 @@ func (client *PortainerAsyncClient) executeAsyncRequest(payload AsyncRequest, po | |
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
errorData := parseError(resp) | ||
logError(resp, errorData) | ||
|
||
if errorData != nil { | ||
return nil, errors.New(errorData.Message + ": " + errorData.Details) | ||
} | ||
|
||
return nil, errors.New("short poll request failed") | ||
return nil, logPollingError(resp, "AsyncEdgeAgentExecuteAsyncRequest", fmt.Sprintf("AsyncEdgeAgent [%d] failed to execute async request", client.getEndpointIDFn())) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please try to avoid using |
||
} | ||
|
||
var asyncResponse AsyncResponse | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -51,10 +51,6 @@ type NonOkResponseError struct { | |||||||||||||||||||
msg string | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
func newNonOkResponseError(msg string) *NonOkResponseError { | ||||||||||||||||||||
return &NonOkResponseError{msg: msg} | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
Comment on lines
-54
to
-57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You cannot remove this, we rely on that error type in other parts of the code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The type was not removed, only the constructor function was removed, because I found that it is not used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is technically true but the constructor function is not used anymore because you removed it in this PR. 🤣 You can't do that, we need to return that error because we depend on it in other places, please see: Lines 217 to 225 in 676d62a
|
||||||||||||||||||||
func (e *NonOkResponseError) Error() string { | ||||||||||||||||||||
return e.msg | ||||||||||||||||||||
} | ||||||||||||||||||||
|
@@ -121,9 +117,7 @@ func (client *PortainerEdgeClient) GetEnvironmentID() (portainer.EndpointID, err | |||||||||||||||||||
defer resp.Body.Close() | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode != http.StatusOK { | ||||||||||||||||||||
log.Debug().Int("response_code", resp.StatusCode).Msg("global key request failure") | ||||||||||||||||||||
|
||||||||||||||||||||
return 0, errors.New("global key request failed") | ||||||||||||||||||||
return 0, logPollingError(resp, "EdgeAgentGetEnvironmentID", fmt.Sprintf("EdgeAgent [%d] failed to request global key", client.getEndpointIDFn())) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
var responseData globalKeyResponse | ||||||||||||||||||||
|
@@ -166,14 +160,7 @@ func (client *PortainerEdgeClient) GetEnvironmentStatus(flags ...string) (*PollS | |||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode != http.StatusOK { | ||||||||||||||||||||
errorData := parseError(resp) | ||||||||||||||||||||
logError(resp, errorData) | ||||||||||||||||||||
|
||||||||||||||||||||
if errorData != nil { | ||||||||||||||||||||
return nil, newNonOkResponseError(errorData.Message + ": " + errorData.Details) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
return nil, newNonOkResponseError("short poll request failed") | ||||||||||||||||||||
return nil, logPollingError(resp, "EdgeAgentGetEnvironmentStatus", fmt.Sprintf("EdgeAgent [%d] failed to request edge environment status", client.getEndpointIDFn())) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
var responseData PollStatusResponse | ||||||||||||||||||||
|
@@ -208,9 +195,7 @@ func (client *PortainerEdgeClient) GetEdgeStackConfig(edgeStackID int, version * | |||||||||||||||||||
defer resp.Body.Close() | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode != http.StatusOK { | ||||||||||||||||||||
log.Error().Int("response_code", resp.StatusCode).Msg("GetEdgeStackConfig operation failed") | ||||||||||||||||||||
|
||||||||||||||||||||
return nil, errors.New("GetEdgeStackConfig operation failed") | ||||||||||||||||||||
return nil, logPollingError(resp, "EdgeAgentGetEdgeStackConfig", fmt.Sprintf("EdgeAgent [%d] failed to request edge stack config", client.getEndpointIDFn())) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
var data edge.StackPayload | ||||||||||||||||||||
|
@@ -265,9 +250,7 @@ func (client *PortainerEdgeClient) SetEdgeStackStatus( | |||||||||||||||||||
resp.Body.Close() | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode != http.StatusOK { | ||||||||||||||||||||
log.Error().Int("response_code", resp.StatusCode).Msg("SetEdgeStackStatus operation failed") | ||||||||||||||||||||
|
||||||||||||||||||||
return errors.New("SetEdgeStackStatus operation failed") | ||||||||||||||||||||
return logPollingError(resp, "EdgeAgentSetEdgeStackStatus", fmt.Sprintf("EdgeAgent [%d] failed to set edge stack status", client.getEndpointIDFn())) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
return nil | ||||||||||||||||||||
|
@@ -302,9 +285,7 @@ func (client *PortainerEdgeClient) SetEdgeJobStatus(edgeJobStatus agent.EdgeJobS | |||||||||||||||||||
resp.Body.Close() | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode != http.StatusOK { | ||||||||||||||||||||
log.Error().Int("response_code", resp.StatusCode).Msg("SetEdgeJobStatus operation failed") | ||||||||||||||||||||
|
||||||||||||||||||||
return errors.New("SetEdgeJobStatus operation failed") | ||||||||||||||||||||
return logPollingError(resp, "EdgeAgentSetEdgeJobStatus", fmt.Sprintf("EdgeAgent [%d] failed to set edge job status", client.getEndpointIDFn())) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
return nil | ||||||||||||||||||||
|
@@ -326,13 +307,11 @@ func (client *PortainerEdgeClient) GetEdgeConfig(id EdgeConfigID) (*EdgeConfig, | |||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode != http.StatusOK { | ||||||||||||||||||||
log.Error().Int("response_code", resp.StatusCode).Msg("GetEdgeConfig operation failed") | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode == http.StatusForbidden { | ||||||||||||||||||||
return nil, errors.New("GetEdgeConfig operation forbidden") | ||||||||||||||||||||
return nil, logPollingError(resp, "EdgeAgentGetEdgeConfig", fmt.Sprintf("EdgeAgent [%d] is forbidden to get the info of edge config [%d]", client.getEndpointIDFn(), id)) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
return nil, errors.New("GetEdgeConfig operation failed") | ||||||||||||||||||||
return nil, logPollingError(resp, "EdgeAgentGetEdgeConfig", fmt.Sprintf("EdgeAgent [%d] failed to get the info of edge config [%d]", client.getEndpointIDFn(), id)) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
var data EdgeConfig | ||||||||||||||||||||
|
@@ -362,9 +341,7 @@ func (client *PortainerEdgeClient) SetEdgeConfigState(id EdgeConfigID, state Edg | |||||||||||||||||||
resp.Body.Close() | ||||||||||||||||||||
|
||||||||||||||||||||
if resp.StatusCode != http.StatusOK { | ||||||||||||||||||||
log.Error().Int("edge_config_id", int(id)).Stringer("state", state).Int("response_code", resp.StatusCode).Msg("SetEdgeConfigState operation failed") | ||||||||||||||||||||
|
||||||||||||||||||||
return errors.New("SetEdgeConfigState operation failed") | ||||||||||||||||||||
return logPollingError(resp, "EdgeAgentSetEdgeConfigState", fmt.Sprintf("EdgeAgent [%d] failed to set the state [%s] to edge config [%d]", client.getEndpointIDFn(), state, id)) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
return nil | ||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should mix logging with error handling.