2b58b677a5
Move graph related functions in image to graph package. Consolidating graph functionality is the first step in refactoring graph into an image store model. Subsequent refactors will involve breaking up graph into multiple types with a strongly defined interface. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
153 lines
3.7 KiB
Go
153 lines
3.7 KiB
Go
package graph
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"path"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/image"
|
|
"github.com/docker/docker/pkg/parsers/filters"
|
|
"github.com/docker/docker/utils"
|
|
)
|
|
|
|
var acceptedImageFilterTags = map[string]struct{}{
|
|
"dangling": {},
|
|
"label": {},
|
|
}
|
|
|
|
type ImagesConfig struct {
|
|
Filters string
|
|
Filter string
|
|
All bool
|
|
}
|
|
|
|
type ByCreated []*types.Image
|
|
|
|
func (r ByCreated) Len() int { return len(r) }
|
|
func (r ByCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
|
func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created }
|
|
|
|
func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) {
|
|
var (
|
|
allImages map[string]*image.Image
|
|
err error
|
|
filtTagged = true
|
|
filtLabel = false
|
|
)
|
|
|
|
imageFilters, err := filters.FromParam(config.Filters)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for name := range imageFilters {
|
|
if _, ok := acceptedImageFilterTags[name]; !ok {
|
|
return nil, fmt.Errorf("Invalid filter '%s'", name)
|
|
}
|
|
}
|
|
|
|
if i, ok := imageFilters["dangling"]; ok {
|
|
for _, value := range i {
|
|
if strings.ToLower(value) == "true" {
|
|
filtTagged = false
|
|
}
|
|
}
|
|
}
|
|
|
|
_, filtLabel = imageFilters["label"]
|
|
|
|
if config.All && filtTagged {
|
|
allImages, err = s.graph.Map()
|
|
} else {
|
|
allImages, err = s.graph.Heads()
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
lookup := make(map[string]*types.Image)
|
|
s.Lock()
|
|
for repoName, repository := range s.Repositories {
|
|
if config.Filter != "" {
|
|
if match, _ := path.Match(config.Filter, repoName); !match {
|
|
continue
|
|
}
|
|
}
|
|
for ref, id := range repository {
|
|
imgRef := utils.ImageReference(repoName, ref)
|
|
image, err := s.graph.Get(id)
|
|
if err != nil {
|
|
log.Printf("Warning: couldn't load %s from %s: %s", id, imgRef, err)
|
|
continue
|
|
}
|
|
|
|
if lImage, exists := lookup[id]; exists {
|
|
if filtTagged {
|
|
if utils.DigestReference(ref) {
|
|
lImage.RepoDigests = append(lImage.RepoDigests, imgRef)
|
|
} else { // Tag Ref.
|
|
lImage.RepoTags = append(lImage.RepoTags, imgRef)
|
|
}
|
|
}
|
|
} else {
|
|
// get the boolean list for if only the untagged images are requested
|
|
delete(allImages, id)
|
|
if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) {
|
|
continue
|
|
}
|
|
if filtTagged {
|
|
newImage := new(types.Image)
|
|
newImage.ParentId = image.Parent
|
|
newImage.ID = image.ID
|
|
newImage.Created = int(image.Created.Unix())
|
|
newImage.Size = int(image.Size)
|
|
newImage.VirtualSize = int(s.graph.GetParentsSize(image, 0) + image.Size)
|
|
newImage.Labels = image.ContainerConfig.Labels
|
|
|
|
if utils.DigestReference(ref) {
|
|
newImage.RepoTags = []string{}
|
|
newImage.RepoDigests = []string{imgRef}
|
|
} else {
|
|
newImage.RepoTags = []string{imgRef}
|
|
newImage.RepoDigests = []string{}
|
|
}
|
|
|
|
lookup[id] = newImage
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
s.Unlock()
|
|
|
|
images := []*types.Image{}
|
|
for _, value := range lookup {
|
|
images = append(images, value)
|
|
}
|
|
|
|
// Display images which aren't part of a repository/tag
|
|
if config.Filter == "" || filtLabel {
|
|
for _, image := range allImages {
|
|
if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) {
|
|
continue
|
|
}
|
|
newImage := new(types.Image)
|
|
newImage.ParentId = image.Parent
|
|
newImage.RepoTags = []string{"<none>:<none>"}
|
|
newImage.RepoDigests = []string{"<none>@<none>"}
|
|
newImage.ID = image.ID
|
|
newImage.Created = int(image.Created.Unix())
|
|
newImage.Size = int(image.Size)
|
|
newImage.VirtualSize = int(s.graph.GetParentsSize(image, 0) + image.Size)
|
|
newImage.Labels = image.ContainerConfig.Labels
|
|
|
|
images = append(images, newImage)
|
|
}
|
|
}
|
|
|
|
sort.Sort(sort.Reverse(ByCreated(images)))
|
|
|
|
return images, nil
|
|
}
|