Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Refactor available image functions
Browse files Browse the repository at this point in the history
  • Loading branch information
aaron7 committed May 18, 2018
1 parent 90d5c6b commit 25d9aaf
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 68 deletions.
39 changes: 20 additions & 19 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,25 +580,26 @@ func getServiceContainers(service cluster.Controller, imageRepos update.ImageRep

imageRepo := c.Image.Name
tagPattern := getTagPattern(policyResourceMap, service.ID, c.Name)
currentImage := imageRepos.FindImageInfo(imageRepo, c.Image)

// All available images
availableImages := imageRepos.Available(imageRepo)
availableImagesCount := len(availableImages)
availableImagesErr := ""
if availableImages == nil {
availableImagesErr = registry.ErrNoImageData.Error()

images := imageRepos.GetRepoImages(imageRepo)
currentImage := images.FindWithRef(c.Image)

// All images
imagesCount := len(images)
imagesErr := ""
if images == nil {
imagesErr = registry.ErrNoImageData.Error()
}
var newAvailableImages []image.Info
for _, img := range availableImages {
var newImages []image.Info
for _, img := range images {
if img.CreatedAt.After(currentImage.CreatedAt) {
newAvailableImages = append(newAvailableImages, img)
newImages = append(newImages, img)
}
}
newAvailableImagesCount := len(newAvailableImages)
newImagesCount := len(newImages)

// Filtered available images
filteredImages := imageRepos.FilteredAvailable(imageRepo, tagPattern)
// Filtered images
filteredImages := images.Filter(tagPattern)
filteredImagesCount := len(filteredImages)
var newFilteredImages []image.Info
for _, img := range filteredImages {
Expand All @@ -615,15 +616,15 @@ func getServiceContainers(service cluster.Controller, imageRepos update.ImageRep
case "Current":
container.Current = currentImage
case "LatestFiltered":
container.LatestFiltered, _ = imageRepos.LatestFilteredImage(imageRepo, tagPattern)
container.LatestFiltered, _ = filteredImages.Latest()
case "Available":
container.Available = availableImages
container.Available = images
case "AvailableError":
container.AvailableError = availableImagesErr
container.AvailableError = imagesErr
case "AvailableImagesCount":
container.AvailableImagesCount = availableImagesCount
container.AvailableImagesCount = imagesCount
case "NewAvailableImagesCount":
container.NewAvailableImagesCount = newAvailableImagesCount
container.NewAvailableImagesCount = newImagesCount
case "FilteredImagesCount":
container.FilteredImagesCount = filteredImagesCount
case "NewFilteredImagesCount":
Expand Down
4 changes: 3 additions & 1 deletion daemon/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ func (d *Daemon) pollForNewImages(logger log.Logger) {
repo := currentImageID.Name
logger.Log("repo", repo, "pattern", pattern)

if latest, ok := imageRepos.LatestFilteredImage(repo, pattern); ok && latest.ID != currentImageID {
filteredImages := imageRepos.GetRepoImages(repo).Filter(pattern)

if latest, ok := filteredImages.Latest(); ok && latest.ID != currentImageID {
if latest.ID.Tag == "" {
logger.Log("msg", "untagged image in available images", "action", "skip", "available", repo)
continue
Expand Down
79 changes: 36 additions & 43 deletions update/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,74 +14,67 @@ import (
"github.com/weaveworks/flux/resource"
)

type imageReposMap map[image.CanonicalName][]image.Info
type imageReposMap map[image.CanonicalName]ImageInfos

// ImageRepos contains a map of image repositories to their images
type ImageRepos struct {
imageRepos imageReposMap
}

// FindImageInfo returns image.Info given an image ref. If the image cannot be
// found, return the image.Info with only the ID.
func (r ImageRepos) FindImageInfo(repo image.Name, ref image.Ref) image.Info {
images, ok := r.imageRepos[ref.CanonicalName()]
if !ok {
return image.Info{ID: ref}
}
for _, img := range images {
if img.ID == ref {
return img
// GetRepoImages returns image.Info entries for all the images in the
// named image repository.
func (r ImageRepos) GetRepoImages(repo image.Name) ImageInfos {
if canon, ok := r.imageRepos[repo.CanonicalName()]; ok {
infos := make([]image.Info, len(canon))
for i := range canon {
infos[i] = canon[i]
infos[i].ID = repo.ToRef(infos[i].ID.Tag)
}
return infos
}
return image.Info{ID: ref}
return nil
}

// LatestFilteredImage returns the latest releasable image for a repository
// for which the tag matches a given pattern. A releasable image is
// one that is not tagged "latest". (Assumes the available images are
// in descending order of latestness.) If no such image exists,
// returns a zero value and `false`, and the caller can decide whether
// that's an error or not.
func (r ImageRepos) LatestFilteredImage(repo image.Name, tagGlob string) (image.Info, bool) {
filtered := r.FilteredAvailable(repo, tagGlob)
if len(filtered) > 0 {
return filtered[0], true
}
return image.Info{}, false
}
// ImageInfos is a list of image.Info which can be filtered.
type ImageInfos []image.Info

// FilteredAvailable returns image.Info entries for all the images in the
// named image repository which match the tagGlob.
func (r ImageRepos) FilteredAvailable(repo image.Name, tagGlob string) []image.Info {
var filtered []image.Info
for _, available := range r.Available(repo) {
tag := available.ID.Tag
// Filter returns only the images which match the tagGlob.
func (ii ImageInfos) Filter(tagGlob string) ImageInfos {
var filtered ImageInfos
for _, i := range ii {
tag := i.ID.Tag
// Ignore latest if and only if it's not what the user wants.
if !strings.EqualFold(tagGlob, "latest") && strings.EqualFold(tag, "latest") {
continue
}
if glob.Glob(tagGlob, tag) {
var im image.Info
im = available
im.ID = repo.ToRef(tag)
im = i
filtered = append(filtered, im)
}
}
return filtered
}

// Available returns image.Info entries for all the images in the
// named image repository.
func (r ImageRepos) Available(repo image.Name) []image.Info {
if canon, ok := r.imageRepos[repo.CanonicalName()]; ok {
infos := make([]image.Info, len(canon))
for i := range canon {
infos[i] = canon[i]
infos[i].ID = repo.ToRef(infos[i].ID.Tag)
// Latest returns the latest image from ImageInfos. If no such image exists,
// returns a zero value and `false`, and the caller can decide whether
// that's an error or not.
func (ii ImageInfos) Latest() (image.Info, bool) {
if len(ii) > 0 {
return ii[0], true
}
return image.Info{}, false
}

// FindWithRef returns image.Info given an image ref. If the image cannot be
// found, it returns the image.Info with the ID provided.
func (ii ImageInfos) FindWithRef(ref image.Ref) image.Info {
for _, img := range ii {
if img.ID == ref {
return img
}
return infos
}
return nil
return image.Info{ID: ref}
}

// containers represents a collection of things that have containers
Expand Down
10 changes: 6 additions & 4 deletions update/images_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,23 @@ func TestDecanon(t *testing.T) {
name: infos,
}}

latest, ok := m.LatestFilteredImage(mustParseName("weaveworks/helloworld"), "*")
filteredImages := m.GetRepoImages(mustParseName("weaveworks/helloworld")).Filter("*")
latest, ok := filteredImages.Latest()
if !ok {
t.Error("did not find latest image")
} else if latest.ID.Name != mustParseName("weaveworks/helloworld") {
t.Error("name did not match what was asked")
}

latest, ok = m.LatestFilteredImage(mustParseName("index.docker.io/weaveworks/helloworld"), "*")
filteredImages = m.GetRepoImages(mustParseName("index.docker.io/weaveworks/helloworld")).Filter("*")
latest, ok = filteredImages.Latest()
if !ok {
t.Error("did not find latest image")
} else if latest.ID.Name != mustParseName("index.docker.io/weaveworks/helloworld") {
t.Error("name did not match what was asked")
}

avail := m.Available(mustParseName("weaveworks/helloworld"))
avail := m.GetRepoImages(mustParseName("weaveworks/helloworld"))
if len(avail) != len(infos) {
t.Errorf("expected %d available images, got %d", len(infos), len(avail))
}
Expand All @@ -51,7 +53,7 @@ func TestDecanon(t *testing.T) {

func TestAvail(t *testing.T) {
m := ImageRepos{imageReposMap{name: infos}}
avail := m.Available(mustParseName("weaveworks/goodbyeworld"))
avail := m.GetRepoImages(mustParseName("weaveworks/goodbyeworld"))
if len(avail) > 0 {
t.Errorf("did not expect available images, but got %#v", avail)
}
Expand Down
3 changes: 2 additions & 1 deletion update/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ func (s ReleaseSpec) calculateImageUpdates(rc ReleaseContext, candidates []*Cont
for _, container := range containers {
currentImageID := container.Image

latestImage, ok := imageRepos.LatestFilteredImage(currentImageID.Name, "*")
filteredImages := imageRepos.GetRepoImages(currentImageID.Name).Filter("*")
latestImage, ok := filteredImages.Latest()
if !ok {
if currentImageID.CanonicalName() != singleRepo {
ignoredOrSkipped = ReleaseStatusIgnored
Expand Down

0 comments on commit 25d9aaf

Please sign in to comment.