Skip to content

Commit

Permalink
Add commit tag support
Browse files Browse the repository at this point in the history
  • Loading branch information
zugao committed Jan 3, 2020
1 parent ebeca4f commit f50fb5a
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 12 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

## General

The image cleanup client is used to clean up Docker images in a Docker Registry when they are tagged using git SHA.
The image cleanup client is used to clean up Docker images in a Docker Registry when they are tagged using git SHA. The cleaning is done either using git commit hashes or tags. Defaults to hashes otherwise ```-t``` flag should be used.

This helps to save space because obsolete images are being removed from the registry.

Expand Down
22 changes: 17 additions & 5 deletions cmd/imagestream.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type ImageStreamCleanupOptions struct {
Keep int
ImageStream string
Namespace string
Tag bool
}

// NewImageStreamCleanupCommand creates a cobra command to clean up an imagestream based on commits
Expand All @@ -35,14 +36,15 @@ func NewImageStreamCleanupCommand() *cobra.Command {
cmd.Flags().StringVarP(&o.RepoPath, "git-repo-path", "p", ".", "absolute path to Git repository (for current dir use: $PWD)")
cmd.Flags().StringVarP(&o.Namespace, "namespace", "n", "", "Kubernetes namespace")
cmd.Flags().IntVarP(&o.Keep, "keep", "k", 10, "keep most current <n> images")
cmd.Flags().BoolVarP(&o.Tag, "tag", "t", false, "use tags instead of commit hashes")
return cmd
}

func (o *ImageStreamCleanupOptions) cleanupImageStreamTags(cmd *cobra.Command, args []string) {
if len(args) > 0 {
o.ImageStream = args[0]
}

if len(o.Namespace) == 0 {
namespace, err := kubernetes.Namespace()
if err != nil {
Expand All @@ -63,17 +65,27 @@ func (o *ImageStreamCleanupOptions) cleanupImageStreamTags(cmd *cobra.Command, a
return
}

commitHashes, err := git.GetCommitHashes(o.RepoPath, o.CommitLimit)
if err != nil {
log.WithError(err).WithField("RepoPath", o.RepoPath).WithField("CommitLimit", o.CommitLimit).Fatal("Retrieving commit hashes failed.")
var commits []string
if o.Tag {
var err error
commits, err = git.GetCommitTags(o.RepoPath, o.CommitLimit)
if err != nil {
log.WithError(err).WithField("RepoPath", o.RepoPath).WithField("CommitLimit", o.CommitLimit).Fatal("Retrieving commit tags failed.")
}
} else {
var err error
commits, err = git.GetCommitHashes(o.RepoPath, o.CommitLimit)
if err != nil {
log.WithError(err).WithField("RepoPath", o.RepoPath).WithField("CommitLimit", o.CommitLimit).Fatal("Retrieving commit hashes failed.")
}
}

imageStreamTags, err := openshift.GetImageStreamTags(o.Namespace, o.ImageStream)
if err != nil {
log.WithError(err).WithField("Namespace", o.Namespace).WithField("ImageStream", o.ImageStream).Fatal("Could not retrieve image stream.")
}

matchingTags := cleanup.GetTagsMatchingPrefixes(&commitHashes, &imageStreamTags)
matchingTags := cleanup.GetTagsMatchingPrefixes(&commits, &imageStreamTags, o.Tag)

activeImageStreamTags, err := openshift.GetActiveImageStreamTags(o.Namespace, o.ImageStream, imageStreamTags)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
Expand Down
17 changes: 13 additions & 4 deletions pkg/cleanup/cleanup.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package cleanup

import (
log "github.com/sirupsen/logrus"
"strings"

log "github.com/sirupsen/logrus"
)

// GetTagsMatchingPrefixes returns all tags matching one of the provided prefixes
func GetTagsMatchingPrefixes(prefixes, tags *[]string) []string {
func GetTagsMatchingPrefixes(prefixes, tags *[]string, commitTag bool) []string {
var matchingTags []string

log.Debugf("GetTagsMatchingPrefixes | Prefixes: %s", prefixes)
Expand All @@ -15,9 +16,9 @@ func GetTagsMatchingPrefixes(prefixes, tags *[]string) []string {
if len(*prefixes) > 0 && len(*tags) > 0 {
for _, prefix := range *prefixes {
for _, tag := range *tags {
if strings.HasPrefix(tag, prefix) {
if match(tag, prefix, commitTag) {
matchingTags = append(matchingTags, tag)
log.Debugf("GetTagsMatchingPrefixes | Tag %s has prefix %s", tag, prefix)
log.Debugf("GetTagsMatchingPrefixes | Tag %s matched with %s", tag, prefix)
}
}
}
Expand Down Expand Up @@ -59,3 +60,11 @@ func LimitTags(tags *[]string, keep int) []string {

return []string{}
}

//Depending on commit type (hash or tag) use different matching logic
func match(tag, prefix string, commitTag bool) bool {
if commitTag {
return tag == prefix
}
return strings.HasPrefix(tag, prefix)
}
34 changes: 32 additions & 2 deletions pkg/cleanup/cleanup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type LimitTagsTestCase struct {
limit int
}

func Test_GetTagsMatchingPrefixes(t *testing.T) {
func Test_GetTagsMatchingPrefixesCommitHashes(t *testing.T) {
testcases := []GetTagsMatchingPrefixesTestCase{
GetTagsMatchingPrefixesTestCase{
prefixes: []string{
Expand Down Expand Up @@ -48,7 +48,37 @@ func Test_GetTagsMatchingPrefixes(t *testing.T) {
}

for _, testcase := range testcases {
assert.Equal(t, testcase.expected, GetTagsMatchingPrefixes(&testcase.prefixes, &testcase.tags))
assert.Equal(t, testcase.expected, GetTagsMatchingPrefixes(&testcase.prefixes, &testcase.tags, false))
}
}

func Test_GetTagsMatchingPrefixesCommitTags(t *testing.T) {
testcases := []GetTagsMatchingPrefixesTestCase{
GetTagsMatchingPrefixesTestCase{
prefixes: []string{
"v1.0.2",
"2.3",
"1.0",
"v3.1.2",
"v2",
},
tags: []string{
"1.0",
"3.4",
"v1.0.2",
"0.0.1",
"0.0.2",
"v2.3.0",
},
expected: []string{
"v1.0.2",
"1.0",
},
},
}

for _, testcase := range testcases {
assert.Equal(t, testcase.expected, GetTagsMatchingPrefixes(&testcase.prefixes, &testcase.tags, true))
}
}

Expand Down
38 changes: 38 additions & 0 deletions pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package git

import (
"io"
"sort"
"strings"

"gopkg.in/src-d/go-git.v4"
)
Expand Down Expand Up @@ -34,3 +36,39 @@ func GetCommitHashes(repoPath string, commitLimit int) ([]string, error) {

return commitHashes, nil
}

// GetCommitTags returns the commit tags of a given repository ordered by the creation date. If `commitLimit` is -1 all tags will be returned.
func GetCommitTags(repoPath string, tagLimit int) ([]string, error) {
var commitTags []string

repository, err := git.PlainOpen(repoPath)
if err != nil {
return nil, err
}

tagIter, err := repository.Tags()
defer tagIter.Close()
if err != nil {
return nil, err
}

for i := 0; i < tagLimit || tagLimit < 0; i++ {
tag, err := tagIter.Next()

if err != nil {
if err == io.EOF {
break
}
return nil, err
}

splittedPath := strings.Split(tag.Name().String(), "/")
tagName := splittedPath[len(splittedPath)-1]

commitTags = append(commitTags, tagName)
}

sort.Sort(sort.Reverse(sort.StringSlice(commitTags)))

return commitTags, nil
}
25 changes: 25 additions & 0 deletions pkg/git/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,28 @@ func Test_GetCommitHashesFail(t *testing.T) {

assert.Error(t, err)
}

func Test_GetCommitTags(t *testing.T) {
commitLimit := 2
commitHashes, err := GetCommitTags("../..", commitLimit) // Open repository from root dir

expectInOrder := []string{"v0.1.0", "0.0.1"}

assert.NoError(t, err)
assert.Len(t, commitHashes, commitLimit)
assert.EqualValues(t, commitHashes, expectInOrder)
}

func Test_GetCommitTagsAll(t *testing.T) {
commitLimit := -1
_, err := GetCommitTags("../..", commitLimit) // Open repository from root dir

assert.NoError(t, err)
}

func Test_GetCommitTagsFail(t *testing.T) {
commitLimit := 2
_, err := GetCommitTags("not-a-repo", commitLimit)

assert.Error(t, err)
}

0 comments on commit f50fb5a

Please sign in to comment.