Skip to content

Commit dcc8f79

Browse files
committed
refactor: use httptest instead of mocking client
Signed-off-by: KevFan <[email protected]>
1 parent 5f359fe commit dcc8f79

File tree

3 files changed

+97
-102
lines changed

3 files changed

+97
-102
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ require (
3131
k8s.io/klog/v2 v2.120.1
3232
k8s.io/utils v0.0.0-20240423183400-0849a56e8f22
3333
maistra.io/istio-operator v0.0.0-20240217080932-98753cb28cd7
34-
oras.land/oras-go v1.2.4
3534
sigs.k8s.io/controller-runtime v0.18.0
3635
sigs.k8s.io/external-dns v0.14.0
3736
sigs.k8s.io/gateway-api v1.1.0
@@ -173,6 +172,7 @@ require (
173172
k8s.io/component-base v0.30.0 // indirect
174173
k8s.io/kube-openapi v0.0.0-20240423202451-8948a665c108 // indirect
175174
k8s.io/kubectl v0.29.1 // indirect
175+
oras.land/oras-go v1.2.4 // indirect
176176
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
177177
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
178178
sigs.k8s.io/kustomize/kyaml v0.16.0 // indirect

quay/quay_overflow.go

+27-21
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,23 @@ import (
1313
"time"
1414

1515
"golang.org/x/exp/maps"
16-
"oras.land/oras-go/pkg/registry/remote"
1716
)
1817

1918
const (
2019
// Max number of entries returned as specified in Quay API docs for listing tags
21-
pageLimit = 100
20+
pageLimit = 100
21+
accessTokenEnvKey = "ACCESS_TOKEN"
2222
)
2323

2424
var (
25-
accessToken = os.Getenv("ACCESS_TOKEN")
25+
accessToken = os.Getenv(accessTokenEnvKey)
2626
preserveSubstrings = []string{
2727
"latest",
2828
// Preserve semver release branch or semver tag regex - release-vX.Y.Z(-rc1) or vX.Y.Z(-rc1)
2929
// Based on https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
3030
"^(v|release-v)(?P<major>0|[1-9]\\d*)\\.(?P<minor>0|[1-9]\\d*)\\.(?P<patch>0|[1-9]\\d*)(?:-(?P<prerelease>(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$",
3131
}
32+
client = &http.Client{Timeout: 5 * time.Second}
3233
)
3334

3435
// Tag represents a tag in the repository.
@@ -46,12 +47,11 @@ type TagsResponse struct {
4647

4748
func main() {
4849
repo := flag.String("repo", "kuadrant/kuadrant-operator", "Repository name")
49-
baseURL := flag.String("base-url", "https://quay.io/api/v1/repository/", "Base API URL")
50+
baseURL := flag.String("base-url", "https://quay.io/api/v1/repository", "Base API URL")
5051
dryRun := flag.Bool("dry-run", true, "Dry run")
5152
batchSize := flag.Int("batch-size", 50, "Batch size for deletion. API calls might get rate limited at large values")
5253
flag.Parse()
5354

54-
client := &http.Client{}
5555
logger := log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime)
5656

5757
if accessToken == "" {
@@ -62,7 +62,7 @@ func main() {
6262

6363
// Fetch tags from the API
6464
logger.Println("Fetching tags from Quay")
65-
tags, err := fetchTags(client, baseURL, repo)
65+
tags, err := fetchTags(baseURL, repo, accessToken)
6666
if err != nil {
6767
logger.Fatalln("Error fetching tags:", err)
6868
}
@@ -90,18 +90,18 @@ func main() {
9090
go func(tagName string) {
9191
defer wg.Done()
9292

93-
if dryRun != nil && *dryRun {
93+
if *dryRun {
9494
logger.Printf("DRY RUN - Successfully deleted tag: %s\n", tagName)
9595
} else {
96-
if err := deleteTag(client, baseURL, repo, accessToken, tagName); err != nil {
96+
if err := deleteTag(baseURL, repo, accessToken, tagName); err != nil {
9797
logger.Println(err)
98-
} else {
99-
logger.Printf("Successfully deleted tag: %s\n", tagName)
10098
}
99+
100+
logger.Printf("Successfully deleted tag: %s\n", tagName)
101101
}
102102
}(tagName)
103103

104-
delete(tagsToDelete, tagName) // Remove deleted tag from remainingTags
104+
delete(tagsToDelete, tagName) // Remove deleted tag from tagsToDelete
105105
i++
106106
}
107107

@@ -115,7 +115,7 @@ func main() {
115115

116116
// fetchTags retrieves the tags from the repository using the Quay.io API.
117117
// https://docs.quay.io/api/swagger/#!/tag/listRepoTags
118-
func fetchTags(client remote.Client, baseURL, repo *string) ([]Tag, error) {
118+
func fetchTags(baseURL, repo *string, accessToken string) ([]Tag, error) {
119119
if baseURL == nil || repo == nil {
120120
return nil, fmt.Errorf("baseURL or repo required")
121121
}
@@ -124,14 +124,14 @@ func fetchTags(client remote.Client, baseURL, repo *string) ([]Tag, error) {
124124
i := 1
125125

126126
for {
127-
url := fmt.Sprintf("%s%s/tag/?page=%d&limit=%d", *baseURL, *repo, i, pageLimit)
127+
url := fmt.Sprintf("%s/%s/tag/?page=%d&limit=%d", *baseURL, *repo, i, pageLimit)
128128
req, err := http.NewRequest("GET", url, nil)
129129
if err != nil {
130130
return nil, fmt.Errorf("error creating request: %w", err)
131131
}
132132

133133
// Required for private repos
134-
req.Header.Add("Authorization", "Bearer "+accessToken)
134+
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
135135

136136
// Execute the request
137137
resp, err := client.Do(req)
@@ -142,7 +142,10 @@ func fetchTags(client remote.Client, baseURL, repo *string) ([]Tag, error) {
142142

143143
// Handle possible non-200 status codes
144144
if resp.StatusCode != http.StatusOK {
145-
body, _ := io.ReadAll(resp.Body)
145+
body, err := io.ReadAll(resp.Body)
146+
if err != nil {
147+
return nil, fmt.Errorf("error reading response body: %w", err)
148+
}
146149
return nil, fmt.Errorf("error: received status code %d\nBody: %s", resp.StatusCode, string(body))
147150
}
148151

@@ -175,18 +178,18 @@ func fetchTags(client remote.Client, baseURL, repo *string) ([]Tag, error) {
175178
// deleteTag sends a DELETE request to remove the specified tag from the repository
176179
// Returns nil if successful, error otherwise
177180
// https://docs.quay.io/api/swagger/#!/tag/deleteFullTag
178-
func deleteTag(client remote.Client, baseURL, repo *string, accessToken, tagName string) error {
181+
func deleteTag(baseURL, repo *string, accessToken, tagName string) error {
179182
if baseURL == nil || repo == nil {
180183
return fmt.Errorf("baseURL or repo required")
181184
}
182185

183-
url := fmt.Sprintf("%s%s/tag/%s", *baseURL, *repo, tagName)
186+
url := fmt.Sprintf("%s/%s/tag/%s", *baseURL, *repo, tagName)
184187

185188
req, err := http.NewRequest("DELETE", url, nil)
186189
if err != nil {
187190
return fmt.Errorf("error creating DELETE request: %s", err)
188191
}
189-
req.Header.Add("Authorization", "Bearer "+accessToken)
192+
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
190193

191194
resp, err := client.Do(req)
192195
if err != nil {
@@ -198,11 +201,14 @@ func deleteTag(client remote.Client, baseURL, repo *string, accessToken, tagName
198201
return nil
199202
}
200203

201-
body, _ := io.ReadAll(resp.Body)
204+
body, err := io.ReadAll(resp.Body)
205+
if err != nil {
206+
return fmt.Errorf("error reading response body: %w", err)
207+
}
202208
return fmt.Errorf("Failed to delete tag %s: Status code %d\nBody: %s\n", tagName, resp.StatusCode, string(body))
203209
}
204210

205-
// filterTags takes a slice of tags and preserves string regex and returns two maps: one for tags to delete and one for remaining tags.
211+
// filterTags takes a slice of tags and preserves string regex and returns two maps: one for tags to delete and one for preserved tags.
206212
func filterTags(tags []Tag, preserveSubstrings []string) (map[string]struct{}, map[string]struct{}, error) {
207213
tagsToDelete := make(map[string]struct{})
208214
preservedTags := make(map[string]struct{})
@@ -219,7 +225,7 @@ func filterTags(tags []Tag, preserveSubstrings []string) (map[string]struct{}, m
219225

220226
for _, tag := range tags {
221227
// Tags that have an expiration set are ignored as they could be historical tags that have already expired
222-
// i.e. when an existing tag is updated, the previous tag of the same name is expired and is returned when listing
228+
// i.e. when an existing tag is updated, the previous tag of the same name is expired and is still returned when listing
223229
// the tags
224230
if tag.Expiration != "" {
225231
continue

0 commit comments

Comments
 (0)