Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 51 additions & 28 deletions internal/fetch/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,47 +17,70 @@ import (

// Download handles direct binary releases
type Download struct {
url string
urls []string
headers map[string]string
}

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

args := tpl.New(v, mapper)

url, err := args.Render(d.url)
if err != nil {
return "", err
}

logger.Debug().Msgf("fetching version %q for arch %q and OS %q at %s", v, runtime.GOARCH, runtime.GOOS, url)

req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", err
}

for k, v := range d.headers {
req.Header.Add(k, v)
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("unable to download binary at %s: %s", url, resp.Status)
var resp *http.Response

for i, u := range d.urls {

args := tpl.New(v, mapper)

url, err := args.Render(u)
if err != nil {
if len(d.urls)-1 > i {
continue
} else {
return "", err
}
}

logger.Debug().Msgf("fetching version %q for arch %q and OS %q at %s", v, runtime.GOARCH, runtime.GOOS, url)

req, err := http.NewRequest("GET", url, nil)
if err != nil {
if len(d.urls)-1 > i {
continue
} else {
return "", err
}
}

for k, v := range d.headers {
req.Header.Add(k, v)
}

resp, err = http.DefaultClient.Do(req)
if err != nil {
if len(d.urls)-1 > i {
continue
} else {
return "", err
}
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
if len(d.urls)-1 > i {
logger.Debug().Msgf("unable to download binary at %s: %s, %d urls left to try...", url, resp.Status, len(d.urls)-1-i)
continue
} else {
return "", fmt.Errorf("unable to download binary at %s: %s", url, resp.Status)
}
}
// if we reach this point, download was successful, let's move on
break
}

tmpfile, err := os.CreateTemp("", v)
if err != nil {
logger.Fatal().Err(err)
}

defer tmpfile.Close()

bar := progressbar.DefaultBytes(
Expand Down
14 changes: 9 additions & 5 deletions internal/fetch/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ type Fetcher interface {

// Fetch contains fetch configuration
type Fetch struct {
Type string `yaml:"type"`
URL string `yaml:"url"`
TokenEnv string `yaml:"token_env"`
Type string `yaml:"type"`
URL string `yaml:"url"`
URLs []string `yaml:"urls"`
TokenEnv string `yaml:"token_env"`
}

// Factory returns instances that comply to Fetcher interface
Expand All @@ -37,10 +38,13 @@ func (r Fetch) Factory() (Fetcher, error) {
}
headers["PRIVATE-TOKEN"] = token
}

return Download{
url: r.URL,
urls: []string{r.URL},
headers: headers,
}, nil
case "download_list":
return Download{
urls: r.URLs,
}, nil
}
}