Skip to content

Commit

Permalink
Created fetchTag function to improve testing
Browse files Browse the repository at this point in the history
Signed-off-by: dlaw4608 <[email protected]>
  • Loading branch information
dlaw4608 committed Aug 26, 2024
1 parent 6d02302 commit ddf59ad
Showing 1 changed file with 99 additions and 90 deletions.
189 changes: 99 additions & 90 deletions quay/quay_overflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,110 +17,119 @@ const (
)

var (
robotPass = os.Getenv("ROBOT_PASS")
robotUser = os.Getenv("ROBOT_USER")
accessToken = os.Getenv("ACCESS_TOKEN")
preserveSubstring = "danlaw345"
robotPass = os.Getenv("ROBOT_PASS")
robotUser = os.Getenv("ROBOT_USER")
accessToken = os.Getenv("ACCESS_TOKEN")
preserveSubstring = "danlaw345" // Example Tag name that wont be deleted i.e relevant tags
)

// Tag represents a tag in the repository.
type Tag struct {
Name string `json:"name"`
LastModified string `json:"last_modified"`
}

// TagsResponse represents the structure of the API response that contains tags.
type TagsResponse struct {
Tags []Tag `json:"tags"`
}

func main() {
client := &http.Client{}

// Create the request to get tags
req, err := http.NewRequest("GET", baseURL+repo+"/tag", nil)
if err != nil {
fmt.Println("Error creating request:", err)
return
}

// Prioritize Bearer token for authorization
if accessToken != "" {
req.Header.Add("Authorization", "Bearer "+accessToken)
} else {
// Fallback to Basic Authentication if no access token
auth := base64.StdEncoding.EncodeToString([]byte(robotUser + ":" + robotPass))
req.Header.Add("Authorization", "Basic "+auth)
}

// Execute the request
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error making request:", err)
return
}
defer resp.Body.Close()

// Read the response body
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return
}

// Handle possible non-200 status codes
if resp.StatusCode != http.StatusOK {
fmt.Printf("Error: received status code %d\nBody: %s\n", resp.StatusCode, string(body))
return
}

// Parse the JSON response
var tagsResp TagsResponse
if err := json.Unmarshal(body, &tagsResp); err != nil {
fmt.Println("Error unmarshalling response:", err)
return
}

// Use FilterTags to get tags to delete and remaining tags
tagsToDelete, remainingTags := FilterTags(tagsResp.Tags, preserveSubstring)

// Delete tags and update remainingTags
for tagName := range tagsToDelete {
if deleteTag(client, accessToken, tagName) {
delete(remainingTags, tagName) // Remove deleted tag from remainingTags
}
}

// Print remaining tags
fmt.Println("Remaining tags:")
for tag := range remainingTags {
fmt.Println(tag)
}
client := &http.Client{}

// Fetch tags from the API
tags, err := fetchTags(client)
if err != nil {
fmt.Println("Error fetching tags:", err)
return
}

// Use filterTags to get tags to delete and remaining tags
tagsToDelete, remainingTags := filterTags(tags, preserveSubstring)

// Delete tags and update remainingTags
for tagName := range tagsToDelete {
if deleteTag(client, accessToken, tagName) {
delete(remainingTags, tagName) // Remove deleted tag from remainingTags
}
}

// Print remaining tags
fmt.Println("Remaining tags:")
for tag := range remainingTags {
fmt.Println(tag)
}
}

// FilterTags takes a slice of tags and returns two maps: one for tags to delete and one for remaining tags.
func FilterTags(tags []Tag, preserveSubstring string) (map[string]struct{}, map[string]struct{}) {
// Calculate the cutoff time
cutOffTime := time.Now().AddDate(0, 0, 0).Add(0 * time.Hour).Add(-1 * time.Minute)

tagsToDelete := make(map[string]struct{})
remainingTags := make(map[string]struct{})

for _, tag := range tags {
// Parse the LastModified timestamp
lastModified, err := time.Parse(time.RFC1123, tag.LastModified)
if err != nil {
fmt.Println("Error parsing time:", err)
continue
}

// Check if tag should be deleted
if lastModified.Before(cutOffTime) && !containsSubstring(tag.Name, preserveSubstring) {
tagsToDelete[tag.Name] = struct{}{}
} else {
remainingTags[tag.Name] = struct{}{}
}
}

return tagsToDelete, remainingTags
// fetchTags retrieves the tags from the repository using the Quay.io API.
func fetchTags(client *http.Client) ([]Tag, error) {
req, err := http.NewRequest("GET", baseURL+repo+"/tag", nil)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

// Prioritize Bearer token for authorization
if accessToken != "" {
req.Header.Add("Authorization", "Bearer "+accessToken)
} else {
// Fallback to Basic Authentication if no access token
auth := base64.StdEncoding.EncodeToString([]byte(robotUser + ":" + robotPass))
req.Header.Add("Authorization", "Basic "+auth)
}

// Execute the request
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("error making request: %w", err)
}
defer resp.Body.Close()

// Handle possible non-200 status codes
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("error: received status code %d\nBody: %s", resp.StatusCode, string(body))
}

// Read the response body
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading response body: %w", err)
}

// Parse the JSON response
var tagsResp TagsResponse
if err := json.Unmarshal(body, &tagsResp); err != nil {
return nil, fmt.Errorf("error unmarshalling response: %w", err)
}

return tagsResp.Tags, nil
}

// filterTags takes a slice of tags and returns two maps: one for tags to delete and one for remaining tags.
func filterTags(tags []Tag, preserveSubstring string) (map[string]struct{}, map[string]struct{}) {
// Calculate the cutoff time
cutOffTime := time.Now().AddDate(0, 0, 0).Add(0 * time.Hour).Add(-1 * time.Minute)

tagsToDelete := make(map[string]struct{})
remainingTags := make(map[string]struct{})

for _, tag := range tags {
// Parse the LastModified timestamp
lastModified, err := time.Parse(time.RFC1123, tag.LastModified)
if err != nil {
fmt.Println("Error parsing time:", err)
continue
}

// Check if tag should be deleted
if lastModified.Before(cutOffTime) && !containsSubstring(tag.Name, preserveSubstring) {
tagsToDelete[tag.Name] = struct{}{}
} else {
remainingTags[tag.Name] = struct{}{}
}
}

return tagsToDelete, remainingTags
}

func containsSubstring(tagName, substring string) bool {
Expand Down

0 comments on commit ddf59ad

Please sign in to comment.