Skip to content

Commit 5c057b4

Browse files
use http get to download file from GitHub
1 parent 82eff49 commit 5c057b4

File tree

1 file changed

+57
-8
lines changed

1 file changed

+57
-8
lines changed

cmd/clusterctl/client/repository/repository_github.go

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func (g *gitHubRepository) GetVersions(ctx context.Context) ([]string, error) {
109109
return versions, nil
110110
}
111111

112-
goProxyClient, err := g.getGoproxyClient()
112+
goProxyClient, err := g.getGoproxyClient(ctx)
113113
if err != nil {
114114
return nil, errors.Wrap(err, "get versions client")
115115
}
@@ -156,6 +156,27 @@ func (g *gitHubRepository) ComponentsPath() string {
156156

157157
// GetFile returns a file for a given provider version.
158158
func (g *gitHubRepository) GetFile(ctx context.Context, version, path string) ([]byte, error) {
159+
log := logf.Log
160+
161+
cacheID := fmt.Sprintf("%s/%s:%s:%s", g.owner, g.repository, version, path)
162+
if content, ok := cacheFiles[cacheID]; ok {
163+
return content, nil
164+
}
165+
166+
// Try to get the file using http get.
167+
// NOTE: this can be disabled by setting GORPOXY to `direct` or `off` (same knobs used for skipping goproxy requests).
168+
if goProxyClient, _ := g.getGoproxyClient(ctx); goProxyClient != nil {
169+
files, err := g.httpGetFilesFromRelease(ctx, version, path)
170+
if err != nil {
171+
log.V(5).Info("error using httpGet to get file from GitHub releases, falling back to github client", "owner", g.owner, "repository", g.repository, "version", version, "path", path, "error", err)
172+
} else {
173+
cacheFiles[cacheID] = files
174+
return files, nil
175+
}
176+
}
177+
178+
// If the http get request failed (or it is disabled) falls back on using the GITHUB api to download the file
179+
159180
release, err := g.getReleaseByTag(ctx, version)
160181
if err != nil {
161182
if errors.Is(err, errNotFound) {
@@ -172,6 +193,7 @@ func (g *gitHubRepository) GetFile(ctx context.Context, version, path string) ([
172193
return nil, errors.Wrapf(err, "failed to download files from GitHub release %s", version)
173194
}
174195

196+
cacheFiles[cacheID] = files
175197
return files, nil
176198
}
177199

@@ -259,7 +281,7 @@ func (g *gitHubRepository) getClient() *github.Client {
259281
// getGoproxyClient returns a go proxy client.
260282
// It returns nil, nil if the environment variable is set to `direct` or `off`
261283
// to skip goproxy requests.
262-
func (g *gitHubRepository) getGoproxyClient() (*goproxy.Client, error) {
284+
func (g *gitHubRepository) getGoproxyClient(_ context.Context) (*goproxy.Client, error) {
263285
if g.injectGoproxyClient != nil {
264286
return g.injectGoproxyClient, nil
265287
}
@@ -379,13 +401,41 @@ func (g *gitHubRepository) getReleaseByTag(ctx context.Context, tag string) (*gi
379401
return release, nil
380402
}
381403

382-
// downloadFilesFromRelease download a file from release.
383-
func (g *gitHubRepository) downloadFilesFromRelease(ctx context.Context, release *github.RepositoryRelease, fileName string) ([]byte, error) {
384-
cacheID := fmt.Sprintf("%s/%s:%s:%s", g.owner, g.repository, *release.TagName, fileName)
385-
if content, ok := cacheFiles[cacheID]; ok {
386-
return content, nil
404+
// httpGetFilesFromRelease gets a file from github using http get.
405+
func (g *gitHubRepository) httpGetFilesFromRelease(ctx context.Context, version, fileName string) ([]byte, error) {
406+
downloadURL := fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/%s", g.owner, g.repository, version, fileName)
407+
var retryError error
408+
var content []byte
409+
_ = wait.PollUntilContextTimeout(ctx, retryableOperationInterval, retryableOperationTimeout, true, func(ctx context.Context) (bool, error) {
410+
resp, err := http.Get(downloadURL) //nolint:gosec,noctx
411+
if err != nil {
412+
retryError = errors.Wrap(err, "error sending request")
413+
return false, nil
414+
}
415+
defer resp.Body.Close()
416+
417+
if resp.StatusCode != http.StatusOK {
418+
retryError = errors.Errorf("error getting file, status code: %d", resp.StatusCode)
419+
return false, nil
420+
}
421+
422+
content, err = io.ReadAll(resp.Body)
423+
if err != nil {
424+
retryError = errors.Wrap(err, "error reading response body")
425+
return false, nil
426+
}
427+
428+
retryError = nil
429+
return true, nil
430+
})
431+
if retryError != nil {
432+
return nil, retryError
387433
}
434+
return content, nil
435+
}
388436

437+
// downloadFilesFromRelease download a file from release.
438+
func (g *gitHubRepository) downloadFilesFromRelease(ctx context.Context, release *github.RepositoryRelease, fileName string) ([]byte, error) {
389439
client := g.getClient()
390440
absoluteFileName := filepath.Join(g.rootPath, fileName)
391441

@@ -439,7 +489,6 @@ func (g *gitHubRepository) downloadFilesFromRelease(ctx context.Context, release
439489
return nil, retryError
440490
}
441491

442-
cacheFiles[cacheID] = content
443492
return content, nil
444493
}
445494

0 commit comments

Comments
 (0)