Skip to content

Commit 5ea606c

Browse files
committed
"Implement retry logic for API requests and improve error handling in Sophos plugin."
Signed-off-by: Osmany Montero <osmontero@icloud.com>
1 parent d3ee8c8 commit 5ea606c

2 files changed

Lines changed: 140 additions & 17 deletions

File tree

plugins/sophos/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package main
22

33
import (
4-
"os"
54
"runtime"
65
"strings"
76
"sync"
@@ -20,7 +19,8 @@ const delayCheck = 300
2019
func main() {
2120
mode := plugins.GetCfg().Env.Mode
2221
if mode != "manager" {
23-
os.Exit(0)
22+
// Don't exit, just return
23+
return
2424
}
2525

2626
pCfg := plugins.PluginCfg("com.utmstack", false)
@@ -53,6 +53,8 @@ func main() {
5353

5454
for _, group := range moduleConfig.ConfigurationGroups {
5555
go func(group types.ModuleGroup) {
56+
defer wg.Done()
57+
5658
var skip bool
5759

5860
for _, cnf := range group.Configurations {
@@ -65,7 +67,6 @@ func main() {
6567
if !skip {
6668
pullLogs(group)
6769
}
68-
wg.Done()
6970
}(group)
7071
}
7172

plugins/sophos/processor.go

Lines changed: 136 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,53 @@ func (p *SophosCentralProcessor) getAccessToken() (string, error) {
5050
"Content-Type": "application/x-www-form-urlencoded",
5151
}
5252

53-
response, _, err := utils.DoReq[map[string]any](authURL, []byte(data.Encode()), http.MethodPost, headers)
53+
// Retry logic for getting access token
54+
maxRetries := 3
55+
retryDelay := 2 * time.Second
56+
57+
var response map[string]any
58+
var err error
59+
60+
for retry := 0; retry < maxRetries; retry++ {
61+
response, _, err = utils.DoReq[map[string]any](authURL, []byte(data.Encode()), http.MethodPost, headers)
62+
if err == nil {
63+
accessToken, ok := response["access_token"].(string)
64+
if ok && accessToken != "" {
65+
expiresIn, ok := response["expires_in"].(float64)
66+
if ok {
67+
p.AccessToken = accessToken
68+
p.ExpiresAt = time.Now().Add(time.Duration(expiresIn) * time.Second)
69+
return accessToken, nil
70+
}
71+
}
72+
}
73+
74+
_ = catcher.Error("error getting access token, retrying", err, map[string]any{
75+
"retry": retry + 1,
76+
"maxRetries": maxRetries,
77+
})
78+
79+
if retry < maxRetries-1 {
80+
time.Sleep(retryDelay)
81+
// Increase delay for next retry
82+
retryDelay *= 2
83+
}
84+
}
85+
5486
if err != nil {
55-
return "", catcher.Error("error making auth request", err, map[string]any{})
87+
return "", catcher.Error("all retries failed when getting access token", err, nil)
5688
}
5789

5890
accessToken, ok := response["access_token"].(string)
5991
if !ok || accessToken == "" {
60-
return "", catcher.Error("access_token not found in response", nil, map[string]any{
92+
return "", catcher.Error("access_token not found in response after all retries", nil, map[string]any{
6193
"response": response,
6294
})
6395
}
6496

6597
expiresIn, ok := response["expires_in"].(float64)
6698
if !ok {
67-
return "", catcher.Error("expires_in not found in response", nil, map[string]any{
99+
return "", catcher.Error("expires_in not found in response after all retries", nil, map[string]any{
68100
"response": response,
69101
})
70102
}
@@ -90,20 +122,48 @@ func (p *SophosCentralProcessor) getTenantInfo(accessToken string) error {
90122
"Authorization": "Bearer " + accessToken,
91123
}
92124

93-
response, _, err := utils.DoReq[WhoamiResponse](whoamiURL, nil, http.MethodGet, headers)
125+
// Retry logic for getting tenant info
126+
maxRetries := 3
127+
retryDelay := 2 * time.Second
128+
129+
var response WhoamiResponse
130+
var err error
131+
132+
for retry := 0; retry < maxRetries; retry++ {
133+
response, _, err = utils.DoReq[WhoamiResponse](whoamiURL, nil, http.MethodGet, headers)
134+
if err == nil {
135+
if response.ID != "" && response.ApiHosts.DataRegion != "" {
136+
p.TenantID = response.ID
137+
p.DataRegion = response.ApiHosts.DataRegion
138+
return nil
139+
}
140+
}
141+
142+
_ = catcher.Error("error getting tenant info, retrying", err, map[string]any{
143+
"retry": retry + 1,
144+
"maxRetries": maxRetries,
145+
})
146+
147+
if retry < maxRetries-1 {
148+
time.Sleep(retryDelay)
149+
// Increase delay for next retry
150+
retryDelay *= 2
151+
}
152+
}
153+
94154
if err != nil {
95-
return catcher.Error("error making whoami request", err, map[string]any{})
155+
return catcher.Error("all retries failed when getting tenant info", err, nil)
96156
}
97157

98158
if response.ID == "" {
99-
return catcher.Error("tenant ID not found in whoami response", nil, map[string]any{
159+
return catcher.Error("tenant ID not found in whoami response after all retries", nil, map[string]any{
100160
"response": response,
101161
})
102162
}
103163
p.TenantID = response.ID
104164

105165
if response.ApiHosts.DataRegion == "" {
106-
return catcher.Error("dataRegion not found in whoami response", nil, map[string]any{
166+
return catcher.Error("dataRegion not found in whoami response after all retries", nil, map[string]any{
107167
"response": response,
108168
})
109169
}
@@ -132,14 +192,57 @@ type Pages struct {
132192
}
133193

134194
func (p *SophosCentralProcessor) getLogs(fromTime int, nextKey string) ([]string, string, error) {
135-
accessToken, err := p.getValidAccessToken()
195+
// Retry logic for getting access token
196+
maxRetries := 3
197+
retryDelay := 2 * time.Second
198+
199+
var accessToken string
200+
var err error
201+
202+
for retry := 0; retry < maxRetries; retry++ {
203+
accessToken, err = p.getValidAccessToken()
204+
if err == nil {
205+
break
206+
}
207+
208+
_ = catcher.Error("error getting access token, retrying", err, map[string]any{
209+
"retry": retry + 1,
210+
"maxRetries": maxRetries,
211+
})
212+
213+
if retry < maxRetries-1 {
214+
time.Sleep(retryDelay)
215+
// Increase delay for next retry
216+
retryDelay *= 2
217+
}
218+
}
219+
136220
if err != nil {
137-
return nil, "", fmt.Errorf("error getting access token: %v", err)
221+
return nil, "", catcher.Error("all retries failed when getting access token", err, nil)
138222
}
139223

140224
if p.TenantID == "" || p.DataRegion == "" {
141-
if err := p.getTenantInfo(accessToken); err != nil {
142-
return nil, "", fmt.Errorf("error getting tenant information: %v", err)
225+
// Retry logic for getting tenant info
226+
for retry := 0; retry < maxRetries; retry++ {
227+
err = p.getTenantInfo(accessToken)
228+
if err == nil {
229+
break
230+
}
231+
232+
_ = catcher.Error("error getting tenant info, retrying", err, map[string]any{
233+
"retry": retry + 1,
234+
"maxRetries": maxRetries,
235+
})
236+
237+
if retry < maxRetries-1 {
238+
time.Sleep(retryDelay)
239+
// Increase delay for next retry
240+
retryDelay *= 2
241+
}
242+
}
243+
244+
if err != nil {
245+
return nil, "", catcher.Error("all retries failed when getting tenant info", err, nil)
143246
}
144247
}
145248

@@ -157,9 +260,28 @@ func (p *SophosCentralProcessor) getLogs(fromTime int, nextKey string) ([]string
157260
"X-Tenant-ID": p.TenantID,
158261
}
159262

160-
response, _, err := utils.DoReq[EventAggregate](u.String(), nil, http.MethodGet, headers)
263+
// Retry logic for getting logs
264+
var response EventAggregate
265+
for retry := 0; retry < maxRetries; retry++ {
266+
response, _, err = utils.DoReq[EventAggregate](u.String(), nil, http.MethodGet, headers)
267+
if err == nil {
268+
break
269+
}
270+
271+
_ = catcher.Error("error getting logs, retrying", err, map[string]any{
272+
"retry": retry + 1,
273+
"maxRetries": maxRetries,
274+
})
275+
276+
if retry < maxRetries-1 {
277+
time.Sleep(retryDelay)
278+
// Increase delay for next retry
279+
retryDelay *= 2
280+
}
281+
}
282+
161283
if err != nil {
162-
return nil, "", fmt.Errorf("error getting logs: %v", err)
284+
return nil, "", catcher.Error("all retries failed when getting logs", err, nil)
163285
}
164286

165287
for _, item := range response.Items {

0 commit comments

Comments
 (0)