Skip to content

Commit 88c545a

Browse files
committed
Add handling for multiple urls in fetch
* change Download struct to list of urls * add URLs to Fetch struct * add new handler for Fetch Type "download_list" in Fetcher * Type "download" and "default" will use list with single url * Fetch will iterate through the urls and try them one by one until one is successful Signed-off-by: Fabian 'xx4h' Sylvester <xx4h@xx4h.de>
1 parent 5029ec6 commit 88c545a

2 files changed

Lines changed: 60 additions & 33 deletions

File tree

internal/fetch/download.go

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,47 +17,70 @@ import (
1717

1818
// Download handles direct binary releases
1919
type Download struct {
20-
url string
20+
urls []string
2121
headers map[string]string
2222
}
2323

2424
// Fetch gets the package and returns location of downloaded file
2525
func (d Download) Fetch(ctx context.Context, dist, v string, mapper mapping.Mapper) (string, error) {
2626
logger := zerolog.Ctx(ctx).With().Str("func", "Download.Fetch").Logger()
2727

28-
args := tpl.New(v, mapper)
29-
30-
url, err := args.Render(d.url)
31-
if err != nil {
32-
return "", err
33-
}
34-
35-
logger.Debug().Msgf("fetching version %q for arch %q and OS %q at %s", v, runtime.GOARCH, runtime.GOOS, url)
36-
37-
req, err := http.NewRequest("GET", url, nil)
38-
if err != nil {
39-
return "", err
40-
}
41-
42-
for k, v := range d.headers {
43-
req.Header.Add(k, v)
44-
}
45-
46-
resp, err := http.DefaultClient.Do(req)
47-
if err != nil {
48-
return "", err
49-
}
50-
defer resp.Body.Close()
51-
52-
if resp.StatusCode != http.StatusOK {
53-
return "", fmt.Errorf("unable to download binary at %s: %s", url, resp.Status)
28+
var resp *http.Response
29+
30+
for i, u := range d.urls {
31+
32+
args := tpl.New(v, mapper)
33+
34+
url, err := args.Render(u)
35+
if err != nil {
36+
if len(d.urls)-1 > i {
37+
continue
38+
} else {
39+
return "", err
40+
}
41+
}
42+
43+
logger.Debug().Msgf("fetching version %q for arch %q and OS %q at %s", v, runtime.GOARCH, runtime.GOOS, url)
44+
45+
req, err := http.NewRequest("GET", url, nil)
46+
if err != nil {
47+
if len(d.urls)-1 > i {
48+
continue
49+
} else {
50+
return "", err
51+
}
52+
}
53+
54+
for k, v := range d.headers {
55+
req.Header.Add(k, v)
56+
}
57+
58+
resp, err = http.DefaultClient.Do(req)
59+
if err != nil {
60+
if len(d.urls)-1 > i {
61+
continue
62+
} else {
63+
return "", err
64+
}
65+
}
66+
defer resp.Body.Close()
67+
68+
if resp.StatusCode != http.StatusOK {
69+
if len(d.urls)-1 > i {
70+
logger.Debug().Msgf("unable to download binary at %s: %s, %d urls left to try...", url, resp.Status, len(d.urls)-1-i)
71+
continue
72+
} else {
73+
return "", fmt.Errorf("unable to download binary at %s: %s", url, resp.Status)
74+
}
75+
}
76+
// if we reach this point, download was successful, let's move on
77+
break
5478
}
5579

5680
tmpfile, err := os.CreateTemp("", v)
5781
if err != nil {
5882
logger.Fatal().Err(err)
5983
}
60-
6184
defer tmpfile.Close()
6285

6386
bar := progressbar.DefaultBytes(

internal/fetch/fetch.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ type Fetcher interface {
1616

1717
// Fetch contains fetch configuration
1818
type Fetch struct {
19-
Type string `yaml:"type"`
20-
URL string `yaml:"url"`
21-
TokenEnv string `yaml:"token_env"`
19+
Type string `yaml:"type"`
20+
URL string `yaml:"url"`
21+
URLs []string `yaml:"urls"`
22+
TokenEnv string `yaml:"token_env"`
2223
}
2324

2425
// Factory returns instances that comply to Fetcher interface
@@ -37,10 +38,13 @@ func (r Fetch) Factory() (Fetcher, error) {
3738
}
3839
headers["PRIVATE-TOKEN"] = token
3940
}
40-
4141
return Download{
42-
url: r.URL,
42+
urls: []string{r.URL},
4343
headers: headers,
4444
}, nil
45+
case "download_list":
46+
return Download{
47+
urls: r.URLs,
48+
}, nil
4549
}
4650
}

0 commit comments

Comments
 (0)