Skip to content

Commit

Permalink
adjust to new api (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
alv91 authored Aug 3, 2021
1 parent 8fa2821 commit de51f03
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 54 deletions.
14 changes: 7 additions & 7 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ builds:
- binary: dhlm
env:
- CGO_ENABLED=0
archive:
replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
archives:
- replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
snapshot:
name_template: "{{ .Tag }}-next"
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ GLOBAL OPTIONS:
--username value
--password value
--days value (default: "30")
--dry-run
--help, -h show help
```
49 changes: 36 additions & 13 deletions dhlm.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,25 @@ func main() {
var dhOrg string
var dhRepo string
var days string
var dryRun bool

app.Flags = []cli.Flag {
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "username",
Name: "username",
Destination: &dhUsername,
},
cli.StringFlag{
Name: "password",
Name: "password",
Destination: &dhPassword,
},
cli.StringFlag{
Name: "days",
Name: "days",
Destination: &days,
Value: "30",
Value: "30",
},
cli.BoolFlag{
Name: "dry-run",
Destination: &dryRun,
},
}

Expand All @@ -47,25 +52,43 @@ func main() {
return nil
}

dh := dockerhub.NewClient(dockerhub.Auth {
dh := dockerhub.NewClient(dockerhub.Auth{
Username: dhUsername,
Password: dhPassword,
})

daysInt, _ := strconv.Atoi(days)
timeBefore := time.Now().Add(-time.Hour*24*time.Duration(daysInt))
timeBefore := time.Now().Add(-time.Hour * 24 * time.Duration(daysInt))

pageNumber := 1
for tagsList := dh.GetTags(dhOrg, dhRepo, pageNumber); len(tagsList.Next) > 0; pageNumber++ {
for tagsList := dh.GetImages(dhOrg, dhRepo, pageNumber, timeBefore); len(tagsList.Next) > 0; pageNumber++ {
fmt.Println("Checking page:", pageNumber)
var digests []string
var ignoreList []*dockerhub.IgnoreWarnings
for _, tag := range tagsList.Results {
if tag.LastUpdated.Unix() < timeBefore.Unix() {
fmt.Println("Removing "+dhOrg+"/"+dhRepo+":"+tag.Name+" | "+tag.LastUpdated.Format(time.RFC822))
dh.DeleteTag(dhOrg, dhRepo, tag.Name)
if tag.LastPulled.Unix() < timeBefore.Unix() {
fmt.Println("Removing " + dhOrg + "/" + dhRepo + ":" + tag.Digest + " | " + tag.LastPulled.Format(time.RFC3339) + " | " + tag.LastPushed.Format(time.RFC3339))

digests = append(digests, tag.Digest)

for _, t := range tag.Tags {
if t.IsCurrent == true {
ignoreList = append(ignoreList, &dockerhub.IgnoreWarnings{
Repository: dhRepo,
Digest: tag.Digest,
Warning: "current_tag",
Tags: []string{t.Tag},
})
}
}

}
}
deletedImages := dh.DeleteImages(dhOrg, dhRepo, digests, timeBefore, dryRun, ignoreList)
fmt.Printf("Summary of deleted images ➡ manifest_deletes: %d, manifest_errors: %d, tag_deletes: %d, tag_errors: %d \n",
deletedImages.Metrics.ManifestDeletes, deletedImages.Metrics.ManifestErrors, deletedImages.Metrics.TagDeletes, deletedImages.Metrics.TagDeletes)

tagsList = dh.GetTags(dhOrg, dhRepo, pageNumber)
tagsList = dh.GetImages(dhOrg, dhRepo, pageNumber, timeBefore)
}

return nil
Expand All @@ -75,4 +98,4 @@ func main() {
if err != nil {
panic(err)
}
}
}
57 changes: 50 additions & 7 deletions dockerhub/dockerhub.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import (
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"time"
)

type client struct {
token string
}

const pageSize = "10"

func NewClient(auth Auth) *client {
c := &client{}
c.authorize(auth)
Expand Down Expand Up @@ -46,24 +50,60 @@ func (client *client) authorize(auth Auth) {
client.token = token.Token
}

func (client *client) DeleteTag(organization string, repository string, tag string) {
req, err := http.NewRequest("DELETE", "https://hub.docker.com/v2/repositories/"+organization+"/"+repository+"/tags/"+tag+"/", nil)
func (client *client) DeleteImages(organization string, repository string, digests []string, timeBefore time.Time, dryRun bool, ignoreWarnings []*IgnoreWarnings) (deletedImages *DeletedImagesResponse) {
var manifests []*Manifest

for _, d := range digests {
manifests = append(manifests, &Manifest{
Repository: repository,
Digest: d,
})
}

post := &DeleteImagesRequest{
DryRun: dryRun,
ActiveFrom: timeBefore,
Manifests: manifests,
IgnoreWarnings: ignoreWarnings,
}

body, err := json.Marshal(post)
if err != nil {
panic(err)
}

req, err := http.NewRequest("POST", "https://hub.docker.com/v2/namespaces/"+organization+"/delete-images", bytes.NewReader(body))
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "JWT "+client.token)
req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()

rsp, _ := ioutil.ReadAll(resp.Body)

err = json.Unmarshal(rsp, &deletedImages)
if err != nil {
panic(string(rsp))
}

if resp.StatusCode != http.StatusOK {
panic(string(rsp))
}

return deletedImages
}

func (client *client) GetTags(organization string, repository string, page int) TagsList {
func (client *client) GetImages(organization string, repository string, page int, timeBefore time.Time) (imageList *ImageList) {
pageString := strconv.Itoa(page)
timeFrom := url.QueryEscape(timeBefore.Format(time.RFC3339))

req, err := http.NewRequest("GET", "https://hub.docker.com/v2/repositories/"+organization+"/"+repository+"/tags/?page="+pageString, nil)
req, err := http.NewRequest("GET", "https://hub.docker.com/v2/namespaces/"+organization+"/repositories/"+repository+"/images?page="+pageString+"&page_size="+pageSize+"&ordering=last_activity&status=inactive&active_from="+timeFrom, nil)
if err != nil {
panic(err)
}
Expand All @@ -77,8 +117,11 @@ func (client *client) GetTags(organization string, repository string, page int)

rsp, _ := ioutil.ReadAll(resp.Body)

var tagsList TagsList
json.Unmarshal(rsp, &tagsList)
if resp.StatusCode != http.StatusOK {
panic(string(rsp))
}

json.Unmarshal(rsp, &imageList)

return tagsList
return imageList
}
8 changes: 0 additions & 8 deletions dockerhub/tag.go

This file was deleted.

7 changes: 0 additions & 7 deletions dockerhub/tags_list.go

This file was deleted.

5 changes: 0 additions & 5 deletions dockerhub/token.go

This file was deleted.

55 changes: 55 additions & 0 deletions dockerhub/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package dockerhub

import "time"

type Image struct {
Repository string `json:"repository"`
LastPushed time.Time `json:"last_pushed"`
LastPulled time.Time `json:"last_pulled"`
Digest string `json:"digest"`
Tags []*Tags `json:"tags"`
}

type ImageList struct {
Count int `json:"count"`
Next string `json:"next"`
Results []Image `json:"results"`
}

type DeleteImagesRequest struct {
DryRun bool `json:"dry_run"`
ActiveFrom time.Time `json:"active_from,omitempty"`
Manifests []*Manifest `json:"manifests"`
IgnoreWarnings []*IgnoreWarnings `json:"ignore_warnings"`
}

type Manifest struct {
Repository string `json:"repository"`
Digest string `json:"digest"`
}
type IgnoreWarnings struct {
Repository string `json:"repository"`
Digest string `json:"digest"`
Warning string `json:"warning"`
Tags []string `json:"tags"`
}

type Tags struct {
Tag string `json:"tag"`
IsCurrent bool `json:"is_current"`
}

type DeletedImagesResponse struct {
Metrics *Metrics `json:"metrics"`
}

type Metrics struct {
ManifestDeletes int `json:"manifest_deletes"`
ManifestErrors int `json:"manifest_errors"`
TagDeletes int `json:"tag_deletes"`
TagErrors int `json:"tag_errors"`
}

type Token struct {
Token string `json:"token"`
}
7 changes: 2 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
module dhlm

go 1.12
go 1.16

require (
github.com/urfave/cli v1.20.0
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
)
require github.com/urfave/cli v1.20.0
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=

0 comments on commit de51f03

Please sign in to comment.