Skip to content

Commit

Permalink
use http get to download file from GitHub
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziopandini committed Aug 18, 2023
1 parent 1b66879 commit 24c4d18
Showing 1 changed file with 75 additions and 6 deletions.
81 changes: 75 additions & 6 deletions cmd/clusterctl/client/repository/repository_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,22 @@ func (g *gitHubRepository) ComponentsPath() string {

// GetFile returns a file for a given provider version.
func (g *gitHubRepository) GetFile(version, path string) ([]byte, error) {
cacheID := fmt.Sprintf("%s/%s:%s:%s", g.owner, g.repository, version, path)
if content, ok := cacheFiles[cacheID]; ok {
return content, nil
}

// Try to get the file using http get.
// NOTE: this can be disabled by setting GORPOXY to `direct` or `off` (same knobs used for skipping goproxy requests).
if goProxyClient, _ := g.getGoproxyClient(); goProxyClient != nil {
if files, err := g.httpGetFilesFromRelease(version, path); err == nil {
cacheFiles[cacheID] = files
return files, nil
}
}

// If the http get request failed (or it is disabled) falls back on using the GITHUB api to download the file

release, err := g.getReleaseByTag(version)
if err != nil {
if errors.Is(err, errNotFound) {
Expand All @@ -172,6 +188,7 @@ func (g *gitHubRepository) GetFile(version, path string) ([]byte, error) {
return nil, errors.Wrapf(err, "failed to download files from GitHub release %s", version)
}

cacheFiles[cacheID] = files
return files, nil
}

Expand Down Expand Up @@ -379,14 +396,28 @@ func (g *gitHubRepository) getReleaseByTag(tag string) (*github.RepositoryReleas
return release, nil
}

// downloadFilesFromRelease download a file from release.
func (g *gitHubRepository) downloadFilesFromRelease(release *github.RepositoryRelease, fileName string) ([]byte, error) {
// httpGetFilesFromRelease gets a file from github using http get.
func (g *gitHubRepository) httpGetFilesFromRelease(version, fileName string) ([]byte, error) {
ctx := context.TODO()

cacheID := fmt.Sprintf("%s/%s:%s:%s", g.owner, g.repository, *release.TagName, fileName)
if content, ok := cacheFiles[cacheID]; ok {
return content, nil
downloadURL := fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/%s", g.owner, g.repository, version, fileName)
var retryError error
var content []byte
_ = wait.PollUntilContextTimeout(ctx, retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) {
if content, retryError = httpGetFile(downloadURL); retryError != nil {
return false, retryError
}
return true, nil
})
if retryError != nil {
return content, retryError
}
return content, nil
}

// downloadFilesFromRelease download a file from release.
func (g *gitHubRepository) downloadFilesFromRelease(release *github.RepositoryRelease, fileName string) ([]byte, error) {
ctx := context.TODO()

client := g.getClient()
absoluteFileName := filepath.Join(g.rootPath, fileName)
Expand Down Expand Up @@ -441,7 +472,6 @@ func (g *gitHubRepository) downloadFilesFromRelease(release *github.RepositoryRe
return nil, retryError
}

cacheFiles[cacheID] = content
return content, nil
}

Expand All @@ -457,3 +487,42 @@ func (g *gitHubRepository) handleGithubErr(err error, message string, args ...in
}
return errors.Wrapf(err, message, args...)
}

func httpGetFile(url string) ([]byte, error) {
// create a new HTTP client
client := &http.Client{}

// create a new GET request
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, http.NoBody)
if err != nil {
return nil, errors.Wrap(err, "error creating request")
}

// send the request and get the response
resp, err := client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "error sending request")
}
defer resp.Body.Close()

// check if the response was a redirect
if resp.StatusCode >= 300 && resp.StatusCode <= 399 {
redirectURL, err := resp.Location()
if err != nil {
return nil, errors.Wrap(err, "error getting redirect location")
}

// Follow the redirect
return httpGetFile(redirectURL.String())
}

if resp.StatusCode != http.StatusOK {
return nil, errors.Errorf("error getting file, status code: %d", resp.StatusCode)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "error reading response body")
}
return body, nil
}

0 comments on commit 24c4d18

Please sign in to comment.