Skip to content

Commit abb3bd7

Browse files
authored
fix: GitHub downloader should do a GET and retry, trying to discover the correct URL (#171)
Co-authored-by: Kemal Hadimli <[email protected]>
1 parent f382c2c commit abb3bd7

File tree

1 file changed

+46
-21
lines changed

1 file changed

+46
-21
lines changed

managedplugin/download.go

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,50 @@ func getURLLocation(ctx context.Context, org string, name string, version string
6767
}
6868
}
6969

70+
var (
71+
err404 = errors.New("404")
72+
err401 = errors.New("401")
73+
err429 = errors.New("429")
74+
)
75+
7076
for _, downloadURL := range urls {
71-
req, err := http.NewRequestWithContext(ctx, http.MethodHead, downloadURL, nil)
72-
if err != nil {
73-
return "", fmt.Errorf("failed create request %s: %w", downloadURL, err)
74-
}
75-
resp, err := http.DefaultClient.Do(req)
76-
if err != nil {
77-
return "", fmt.Errorf("failed to get url %s: %w", downloadURL, err)
78-
}
79-
// Check server response
80-
if resp.StatusCode == http.StatusNotFound {
77+
err := retry.Do(func() error {
78+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadURL, nil)
79+
if err != nil {
80+
return fmt.Errorf("failed create request %s: %w", downloadURL, err)
81+
}
82+
resp, err := http.DefaultClient.Do(req)
83+
if err != nil {
84+
return fmt.Errorf("failed to get url %s: %w", downloadURL, err)
85+
}
8186
resp.Body.Close()
87+
// Check server response
88+
switch {
89+
case resp.StatusCode == http.StatusNotFound:
90+
return err404
91+
case resp.StatusCode == http.StatusUnauthorized:
92+
fmt.Printf("Failed downloading %s with status code %d. Retrying\n", downloadURL, resp.StatusCode)
93+
return err401
94+
case resp.StatusCode == http.StatusTooManyRequests:
95+
fmt.Printf("Failed downloading %s with status code %d. Retrying\n", downloadURL, resp.StatusCode)
96+
return err429
97+
case resp.StatusCode >= http.StatusBadRequest: // anything that's not 200 or 30*
98+
fmt.Printf("Failed downloading %s with status code %d\n", downloadURL, resp.StatusCode)
99+
return fmt.Errorf("statusCode %d", resp.StatusCode)
100+
}
101+
return nil
102+
}, retry.RetryIf(func(err error) bool {
103+
return err == err401 || err == err429
104+
}),
105+
retry.Context(ctx),
106+
retry.Attempts(RetryAttempts),
107+
retry.Delay(RetryWaitTime),
108+
retry.LastErrorOnly(true),
109+
)
110+
if err == err404 {
82111
continue
83-
} else if resp.StatusCode != http.StatusOK {
84-
resp.Body.Close()
85-
fmt.Printf("Failed downloading %s with status code %d. Retrying\n", downloadURL, resp.StatusCode)
86-
return "", errors.New("statusCode != 200")
87112
}
88-
resp.Body.Close()
89-
return downloadURL, nil
113+
return downloadURL, err
90114
}
91115

92116
return "", fmt.Errorf("failed to find plugin %s/%s version %s", org, name, version)
@@ -114,7 +138,7 @@ func DownloadPluginFromHub(ctx context.Context, ops HubDownloadOptions) error {
114138

115139
pluginAsset, statusCode, err := downloadPluginAssetFromHub(ctx, ops)
116140
if err != nil {
117-
return fmt.Errorf("failed to get plugin url: %w", err)
141+
return fmt.Errorf("failed to get plugin metadata from hub: %w", err)
118142
}
119143
switch statusCode {
120144
case http.StatusOK:
@@ -129,11 +153,11 @@ func DownloadPluginFromHub(ctx context.Context, ops HubDownloadOptions) error {
129153
return fmt.Errorf("failed to download plugin %v %v/%v@%v: unexpected status code %v", ops.PluginKind, ops.PluginTeam, ops.PluginName, ops.PluginVersion, statusCode)
130154
}
131155
if pluginAsset == nil {
132-
return fmt.Errorf("failed to get plugin url for %v %v/%v@%v: missing json response", ops.PluginKind, ops.PluginTeam, ops.PluginName, ops.PluginVersion)
156+
return fmt.Errorf("failed to get plugin metadata from hub for %v %v/%v@%v: missing json response", ops.PluginKind, ops.PluginTeam, ops.PluginName, ops.PluginVersion)
133157
}
134158
location := pluginAsset.Location
135159
if len(location) == 0 {
136-
return fmt.Errorf("failed to get plugin url: empty location from response")
160+
return fmt.Errorf("failed to get plugin metadata from hub: empty location from response")
137161
}
138162
pluginZipPath := ops.LocalPath + ".zip"
139163
writtenChecksum, err := downloadFile(ctx, pluginZipPath, location)
@@ -201,7 +225,7 @@ func downloadPluginAssetFromHub(ctx context.Context, ops HubDownloadOptions) (*c
201225
&cloudquery_api.DownloadPluginAssetByTeamParams{Accept: &aj},
202226
)
203227
if err != nil {
204-
return nil, -1, fmt.Errorf("failed to get plugin url with team: %w", err)
228+
return nil, -1, fmt.Errorf("failed to request with team: %w", err)
205229
}
206230
return resp.JSON200, resp.StatusCode(), nil
207231
default:
@@ -215,7 +239,7 @@ func downloadPluginAssetFromHub(ctx context.Context, ops HubDownloadOptions) (*c
215239
&cloudquery_api.DownloadPluginAssetParams{Accept: &aj},
216240
)
217241
if err != nil {
218-
return nil, -1, fmt.Errorf("failed to get plugin url: %w", err)
242+
return nil, -1, fmt.Errorf("failed to request: %w", err)
219243
}
220244
return resp.JSON200, resp.StatusCode(), nil
221245
}
@@ -341,6 +365,7 @@ func downloadFileFromURL(ctx context.Context, out *os.File, downloadURL string)
341365
}, retry.RetryIf(func(err error) bool {
342366
return err.Error() == "statusCode != 200"
343367
}),
368+
retry.Context(ctx),
344369
retry.Attempts(RetryAttempts),
345370
retry.Delay(RetryWaitTime),
346371
)

0 commit comments

Comments
 (0)