@@ -9,34 +9,53 @@ import (
9
9
"net/http"
10
10
"time"
11
11
12
+ "github.com/cenkalti/backoff/v5"
12
13
log "github.com/sirupsen/logrus"
13
14
"golang.org/x/mod/semver"
14
15
15
16
"github.com/crowdsecurity/go-cs-lib/version"
16
17
18
+ "github.com/crowdsecurity/crowdsec/pkg/apiclient/useragent"
17
19
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
18
20
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
19
21
)
20
22
21
23
// lookupLatest returns the latest crowdsec version based on github
22
24
func lookupLatest (ctx context.Context ) (string , error ) {
23
- ctx , cancel := context .WithTimeout (ctx , 10 * time .Second )
24
- defer cancel ()
25
+ bo := backoff .NewConstantBackOff (1 * time .Second )
25
26
26
27
url := "https://version.crowdsec.net/latest"
27
28
28
- req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , http .NoBody )
29
- if err != nil {
30
- return "" , fmt .Errorf ("unable to create request for %s: %w" , url , err )
31
- }
32
-
33
29
client := & http.Client {}
34
30
35
- resp , err := client .Do (req )
31
+ operation := func () (* http.Response , error ) {
32
+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , url , http .NoBody )
33
+ if err != nil {
34
+ return nil , fmt .Errorf ("unable to create request for %s: %w" , url , err )
35
+ }
36
+
37
+ req .Header .Set ("User-Agent" , useragent .Default ())
38
+
39
+ resp , err := client .Do (req )
40
+ if err != nil {
41
+ return nil , fmt .Errorf ("unable to send request to %s: %w" , url , err )
42
+ }
43
+
44
+ if resp .StatusCode != http .StatusOK {
45
+ resp .Body .Close ()
46
+ return nil , fmt .Errorf ("unexpected status code %d from %s" , resp .StatusCode , url )
47
+ }
48
+
49
+ return resp , nil
50
+ }
51
+
52
+ resp , err := backoff .Retry (ctx , operation ,
53
+ backoff .WithBackOff (bo ),
54
+ backoff .WithMaxElapsedTime (5 * time .Second ),
55
+ )
36
56
if err != nil {
37
- return "" , fmt . Errorf ( "unable to send request to %s: %w" , url , err )
57
+ return "" , err
38
58
}
39
- defer resp .Body .Close ()
40
59
41
60
latest := make (map [string ]any )
42
61
@@ -56,51 +75,53 @@ func lookupLatest(ctx context.Context) (string, error) {
56
75
return name , nil
57
76
}
58
77
59
- func chooseBranch (ctx context.Context , cfg * csconfig.Config ) string {
78
+ func chooseBranch (ctx context.Context , cfg * csconfig.Config ) ( string , error ) {
60
79
// this was set from config.yaml or flag
61
80
if cfg .Cscli .HubBranch != "" {
62
81
log .Debugf ("Hub override from config: branch '%s'" , cfg .Cscli .HubBranch )
63
- return cfg .Cscli .HubBranch
64
- }
65
-
66
- latest , err := lookupLatest (ctx )
67
- if err != nil {
68
- log .Warningf ("Unable to retrieve latest crowdsec version: %s, using hub branch 'master'" , err )
69
- return "master"
82
+ return cfg .Cscli .HubBranch , nil
70
83
}
71
84
72
85
csVersion := cwversion .BaseVersion ()
73
86
if csVersion == "" {
74
87
log .Warning ("Crowdsec version is not set, using hub branch 'master'" )
75
- return "master"
88
+ return "master" , nil
89
+ }
90
+
91
+ latest , err := lookupLatest (ctx )
92
+ if err != nil {
93
+ return "" , fmt .Errorf ("unable to retrieve latest crowdsec version: %w" , err )
76
94
}
77
95
78
96
if csVersion == latest {
79
97
log .Debugf ("Latest crowdsec version (%s), using hub branch 'master'" , version .String ())
80
- return "master"
98
+ return "master" , nil
81
99
}
82
100
83
101
// if current version is greater than the latest we are in pre-release
84
102
if semver .Compare (csVersion , latest ) == 1 {
85
103
log .Debugf ("Your current crowdsec version seems to be a pre-release (%s), using hub branch 'master'" , version .String ())
86
- return "master"
104
+ return "master" , nil
87
105
}
88
106
89
107
log .Warnf ("A new CrowdSec release is available (%s). " +
90
108
"Your version is '%s'. Please update it to use new parsers/scenarios/collections." ,
91
109
latest , csVersion )
92
110
93
- return csVersion
111
+ return csVersion , nil
94
112
}
95
113
96
114
// HubBranch sets the branch (in cscli config) and returns its value
97
115
// It can be "master", or the branch corresponding to the current crowdsec version, or the value overridden in config/flag
98
- func HubBranch (ctx context.Context , cfg * csconfig.Config ) string {
99
- branch := chooseBranch (ctx , cfg )
116
+ func HubBranch (ctx context.Context , cfg * csconfig.Config ) (string , error ) {
117
+ branch , err := chooseBranch (ctx , cfg )
118
+ if err != nil {
119
+ return "" , err
120
+ }
100
121
101
122
cfg .Cscli .HubBranch = branch
102
123
103
- return branch
124
+ return branch , nil
104
125
}
105
126
106
127
func HubURLTemplate (cfg * csconfig.Config ) string {
0 commit comments