Skip to content

Commit 95a8b47

Browse files
authored
cscli: don't assume master hub branch if version check fails (after retrying) (#3732)
* cscli: don't assume master hub branch if version check fails (after retrying) * lint
1 parent 136be31 commit 95a8b47

File tree

7 files changed

+93
-43
lines changed

7 files changed

+93
-43
lines changed

cmd/crowdsec-cli/clihub/hub.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,12 @@ func (cli *cliHub) newBranchCmd() *cobra.Command {
9595
Args: args.NoArgs,
9696
DisableAutoGenTag: true,
9797
RunE: func(cmd *cobra.Command, _ []string) error {
98-
branch := require.HubBranch(cmd.Context(), cli.cfg())
99-
fmt.Println(branch)
98+
branch, err := require.HubBranch(cmd.Context(), cli.cfg())
99+
if err != nil {
100+
return err
101+
}
102+
103+
fmt.Fprintln(os.Stdout, branch)
100104
return nil
101105
},
102106
}
@@ -139,15 +143,18 @@ func (cli *cliHub) update(ctx context.Context, withContent bool) error {
139143
return err
140144
}
141145

142-
indexProvider := require.HubDownloader(ctx, cli.cfg())
146+
indexProvider, err := require.HubDownloader(ctx, cli.cfg())
147+
if err != nil {
148+
return err
149+
}
143150

144151
updated, err := hub.Update(ctx, indexProvider, withContent)
145152
if err != nil {
146153
return fmt.Errorf("failed to update hub: %w", err)
147154
}
148155

149156
if !updated && (log.StandardLogger().Level >= log.InfoLevel) {
150-
fmt.Println("Nothing to do, the hub index is up to date.")
157+
fmt.Fprintln(os.Stdout, "Nothing to do, the hub index is up to date.")
151158
}
152159

153160
if err := hub.Load(); err != nil {
@@ -201,7 +208,10 @@ func (cli *cliHub) upgrade(ctx context.Context, interactive bool, dryRun bool, f
201208

202209
plan := hubops.NewActionPlan(hub)
203210

204-
contentProvider := require.HubDownloader(ctx, cfg)
211+
contentProvider, err := require.HubDownloader(ctx, cfg)
212+
if err != nil {
213+
return err
214+
}
205215

206216
for _, itemType := range cwhub.ItemTypes {
207217
for _, item := range hub.GetInstalledByType(itemType, true) {
@@ -223,7 +233,7 @@ func (cli *cliHub) upgrade(ctx context.Context, interactive bool, dryRun bool, f
223233
}
224234

225235
if msg := reload.UserMessage(); msg != "" && plan.ReloadNeeded {
226-
fmt.Println("\n" + msg)
236+
fmt.Fprintln(os.Stdout, "\n"+msg)
227237
}
228238

229239
return nil
@@ -275,17 +285,17 @@ func (cli *cliHub) types() error {
275285
return err
276286
}
277287

278-
fmt.Print(string(s))
288+
fmt.Fprint(os.Stdout, string(s))
279289
case "json":
280290
jsonStr, err := json.Marshal(cwhub.ItemTypes)
281291
if err != nil {
282292
return err
283293
}
284294

285-
fmt.Println(string(jsonStr))
295+
fmt.Fprintln(os.Stdout, string(jsonStr))
286296
case "raw":
287297
for _, itemType := range cwhub.ItemTypes {
288-
fmt.Println(itemType)
298+
fmt.Fprintln(os.Stdout, itemType)
289299
}
290300
}
291301

cmd/crowdsec-cli/cliitem/cmdinspect.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,16 @@ func (cli *cliItem) inspect(ctx context.Context, args []string, url string, diff
3333
cfg.Cscli.PrometheusUrl = url
3434
}
3535

36-
var contentProvider cwhub.ContentProvider
36+
var (
37+
contentProvider cwhub.ContentProvider
38+
err error
39+
)
3740

3841
if diff {
39-
contentProvider = require.HubDownloader(ctx, cfg)
42+
contentProvider, err = require.HubDownloader(ctx, cfg)
43+
if err != nil {
44+
return err
45+
}
4046
}
4147

4248
hub, err := require.Hub(cfg, log.StandardLogger())
@@ -226,7 +232,7 @@ func inspectItem(hub *cwhub.Hub, item *cwhub.Item, wantMetrics bool, output stri
226232
}
227233

228234
if wantMetrics {
229-
fmt.Fprintf(os.Stdout, "\nCurrent metrics: \n")
235+
fmt.Fprint(os.Stdout, "\nCurrent metrics: \n")
230236

231237
if err := showMetrics(prometheusURL, hub, item, wantColor); err != nil {
232238
return err

cmd/crowdsec-cli/cliitem/cmdinstall.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ func (cli *cliItem) install(ctx context.Context, args []string, interactive bool
5454

5555
plan := hubops.NewActionPlan(hub)
5656

57-
contentProvider := require.HubDownloader(ctx, cfg)
57+
contentProvider, err := require.HubDownloader(ctx, cfg)
58+
if err != nil {
59+
return err
60+
}
5861

5962
for _, name := range args {
6063
item := hub.GetItem(cli.name, name)

cmd/crowdsec-cli/cliitem/cmdupgrade.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ func (cli *cliItem) upgrade(ctx context.Context, args []string, interactive bool
5454
return err
5555
}
5656

57-
contentProvider := require.HubDownloader(ctx, cfg)
57+
contentProvider, err := require.HubDownloader(ctx, cfg)
58+
if err != nil {
59+
return err
60+
}
5861

5962
plan, err := cli.upgradePlan(hub, contentProvider, args, force, all)
6063
if err != nil {

cmd/crowdsec-cli/clisetup/setup.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,10 @@ func (cli *cliSetup) install(ctx context.Context, interactive bool, dryRun bool,
295295
return err
296296
}
297297

298-
contentProvider := require.HubDownloader(ctx, cfg)
298+
contentProvider, err := require.HubDownloader(ctx, cfg)
299+
if err != nil {
300+
return err
301+
}
299302

300303
showPlan := (log.StandardLogger().Level >= log.InfoLevel)
301304
verbosePlan := (cfg.Cscli.Output == "raw")

cmd/crowdsec-cli/require/branch.go

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,53 @@ import (
99
"net/http"
1010
"time"
1111

12+
"github.com/cenkalti/backoff/v5"
1213
log "github.com/sirupsen/logrus"
1314
"golang.org/x/mod/semver"
1415

1516
"github.com/crowdsecurity/go-cs-lib/version"
1617

18+
"github.com/crowdsecurity/crowdsec/pkg/apiclient/useragent"
1719
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
1820
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
1921
)
2022

2123
// lookupLatest returns the latest crowdsec version based on github
2224
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)
2526

2627
url := "https://version.crowdsec.net/latest"
2728

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-
3329
client := &http.Client{}
3430

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+
)
3656
if err != nil {
37-
return "", fmt.Errorf("unable to send request to %s: %w", url, err)
57+
return "", err
3858
}
39-
defer resp.Body.Close()
4059

4160
latest := make(map[string]any)
4261

@@ -56,51 +75,53 @@ func lookupLatest(ctx context.Context) (string, error) {
5675
return name, nil
5776
}
5877

59-
func chooseBranch(ctx context.Context, cfg *csconfig.Config) string {
78+
func chooseBranch(ctx context.Context, cfg *csconfig.Config) (string, error) {
6079
// this was set from config.yaml or flag
6180
if cfg.Cscli.HubBranch != "" {
6281
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
7083
}
7184

7285
csVersion := cwversion.BaseVersion()
7386
if csVersion == "" {
7487
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)
7694
}
7795

7896
if csVersion == latest {
7997
log.Debugf("Latest crowdsec version (%s), using hub branch 'master'", version.String())
80-
return "master"
98+
return "master", nil
8199
}
82100

83101
// if current version is greater than the latest we are in pre-release
84102
if semver.Compare(csVersion, latest) == 1 {
85103
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
87105
}
88106

89107
log.Warnf("A new CrowdSec release is available (%s). "+
90108
"Your version is '%s'. Please update it to use new parsers/scenarios/collections.",
91109
latest, csVersion)
92110

93-
return csVersion
111+
return csVersion, nil
94112
}
95113

96114
// HubBranch sets the branch (in cscli config) and returns its value
97115
// 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+
}
100121

101122
cfg.Cscli.HubBranch = branch
102123

103-
return branch
124+
return branch, nil
104125
}
105126

106127
func HubURLTemplate(cfg *csconfig.Config) string {

cmd/crowdsec-cli/require/require.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,20 @@ func DB(c *csconfig.Config) error {
8383
return nil
8484
}
8585

86-
func HubDownloader(ctx context.Context, c *csconfig.Config) *cwhub.Downloader {
86+
func HubDownloader(ctx context.Context, c *csconfig.Config) (*cwhub.Downloader, error) {
8787
// set branch in config, and log if necessary
88-
branch := HubBranch(ctx, c)
88+
branch, err := HubBranch(ctx, c)
89+
if err != nil {
90+
return nil, err
91+
}
92+
8993
urlTemplate := HubURLTemplate(c)
9094
remote := &cwhub.Downloader{
9195
Branch: branch,
9296
URLTemplate: urlTemplate,
9397
}
9498

95-
return remote
99+
return remote, nil
96100
}
97101

98102
// Hub initializes the hub. If a remote configuration is provided, it can be used to download the index and items.

0 commit comments

Comments
 (0)