Skip to content

Commit

Permalink
fix(actions,docker): add status to tagging operation
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Schlesinger committed Jun 9, 2016
1 parent 3ac5132 commit 1dfba28
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 20 deletions.
10 changes: 5 additions & 5 deletions actions/docker/retag.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ func retag(ghClient *github.Client, dockerCl *dlib.Client) func(c *cli.Context)
}
}
fmt.Println("Re-tagging images...")
taggedCh, errCh, doneCh := docker.Retag(dockerCl, allReposAndShas, newTag)
statusCh, errCh, doneCh := docker.Retag(dockerCl, allReposAndShas, newTag)
errFound := false
newImages := []*docker.Image{}
for {
shouldBreak := false
select {
case img := <-taggedCh:
fmt.Printf("Tagged image %s\n", *img)
newImages = append(newImages, img)
case st := <-statusCh:
fmt.Println(st.String())
newImages = append(newImages, st.Image())
case retErr := <-errCh:
fmt.Printf("Error tagging image: %s", retErr)
fmt.Printf("Error tagging image: %s\n", retErr)
errFound = true
case <-doneCh:
shouldBreak = true
Expand Down
36 changes: 21 additions & 15 deletions docker/retag.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ func listWithFilter(dockerCl *dlib.Client, img *Image) ([]dlib.APIImages, error)
})
}

func pullIfMissing(dockerCl *dlib.Client, img *Image) error {
if _, err := listWithFilter(dockerCl, img); err != nil {
return nil
}
func pullImage(dockerCl *dlib.Client, img *Image) error {
return dockerCl.PullImage(dlib.PullImageOptions{
Repository: img.FullWithoutTag(),
Tag: img.tag,
Expand All @@ -45,16 +42,16 @@ func fullImageName(ras git.RepoAndSha) string {
return fmt.Sprintf("quay.io/deisci/%s:git-%s", ras.Name, ras.SHA)
}

// Retag re-tags images from tags based on items in rasl, pulling existing images if necessary, to target. It returns a channel indicating the progress of the tagging (which may be out of order) and a channel of errors which indicates any errors encountered during the entire process. Some images may be successfully tagged and some may not, but at the end of execution, the final channel (<-chan struct{}) will be closed
func Retag(dockerCl *dlib.Client, rasl []git.RepoAndSha, target string) (<-chan *Image, <-chan error, <-chan struct{}) {
imagesCh := make(chan *Image)
// Retag re-tags images from tags based on items in rasl, pulling existing images if necessary, to target. It returns a channel indicating the progress of the tagging (which may be out of order across different images) and a channel of errors which indicates any errors encountered during the entire process. Some images may be successfully tagged and some may not, but at the end of execution, the final channel (<-chan struct{}) will be closed
func Retag(dockerCl *dlib.Client, rasl []git.RepoAndSha, target string) (<-chan TagStatus, <-chan error, <-chan struct{}) {
statusCh := make(chan TagStatus)
errCh := make(chan error)
doneCh := make(chan struct{})

var wg sync.WaitGroup
for i, ras := range rasl {
wg.Add(1)
iCh := make(chan *Image)
sCh := make(chan TagStatus)
eCh := make(chan error)
go func(i int, ras git.RepoAndSha) {
fullName := fullImageName(ras)
Expand All @@ -63,22 +60,31 @@ func Retag(dockerCl *dlib.Client, rasl []git.RepoAndSha, target string) (<-chan
eCh <- err
return
}
if pullErr := pullIfMissing(dockerCl, img); pullErr != nil {
eCh <- pullErr
return
sCh <- TagStartStatus{Img: img}
isMissing := false
if _, listErr := listWithFilter(dockerCl, img); listErr != nil {
isMissing = true
}
if isMissing {
sCh <- TagPullStatus{Img: img}
if pullErr := pullImage(dockerCl, img); pullErr != nil {
eCh <- pullErr
return
}
}

newImg, err := retagOne(dockerCl, img, target)
if err != nil {
eCh <- err
return
}
iCh <- newImg
sCh <- TagFinishStatus{Img: newImg}
}(i, ras)
go func() {
defer wg.Done()
select {
case img := <-iCh:
imagesCh <- img
case st := <-sCh:
statusCh <- st
case err := <-eCh:
errCh <- err
}
Expand All @@ -90,5 +96,5 @@ func Retag(dockerCl *dlib.Client, rasl []git.RepoAndSha, target string) (<-chan
close(doneCh)
}()

return imagesCh, errCh, doneCh
return statusCh, errCh, doneCh
}
50 changes: 50 additions & 0 deletions docker/tag_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package docker

import (
"fmt"
)

// TagStatus represents the status of an image tagging process
type TagStatus interface {
fmt.Stringer
Image() *Image
}

// TagStartStatus is the tag status that represents starting to tag an image
type TagStartStatus struct {
Img *Image
}

// String is the fmt.Stringer interface implementation
func (t TagStartStatus) String() string {
return fmt.Sprintf("Starting tag operation on %s", *t.Img)
}

// Image is the TagStatus interface implementation
func (t TagStartStatus) Image() *Image { return t.Img }

// TagPullStatus is the tag status that represents starting to pull an image for tagging
type TagPullStatus struct {
Img *Image
}

// String is the fmt.Stringer interface implementation
func (t TagPullStatus) String() string {
return fmt.Sprintf("Starting pull operation on image %s", *t.Img)
}

// Image is the TagStatus interface implementation
func (t TagPullStatus) Image() *Image { return t.Img }

// TagFinishStatus is the tag status that represents the tag operation finishing
type TagFinishStatus struct {
Img *Image
}

// String is the fmt.Stringer interface implementation
func (t TagFinishStatus) String() string {
return fmt.Sprintf("Finished tag operation on %s", *t.Img)
}

// Image is the TagStatus interface implementation
func (t TagFinishStatus) Image() *Image { return t.Img }

0 comments on commit 1dfba28

Please sign in to comment.