github.com/crquan/docker@v1.8.1/graph/list.go (about) 1 package graph 2 3 import ( 4 "fmt" 5 "path" 6 "sort" 7 "strings" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/image" 12 "github.com/docker/docker/pkg/parsers/filters" 13 "github.com/docker/docker/utils" 14 ) 15 16 var acceptedImageFilterTags = map[string]struct{}{ 17 "dangling": {}, 18 "label": {}, 19 } 20 21 type ImagesConfig struct { 22 Filters string 23 Filter string 24 All bool 25 } 26 27 type ByCreated []*types.Image 28 29 func (r ByCreated) Len() int { return len(r) } 30 func (r ByCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 31 func (r ByCreated) Less(i, j int) bool { return r[i].Created < r[j].Created } 32 33 func (s *TagStore) Images(config *ImagesConfig) ([]*types.Image, error) { 34 var ( 35 allImages map[string]*image.Image 36 err error 37 filtTagged = true 38 filtLabel = false 39 ) 40 41 imageFilters, err := filters.FromParam(config.Filters) 42 if err != nil { 43 return nil, err 44 } 45 for name := range imageFilters { 46 if _, ok := acceptedImageFilterTags[name]; !ok { 47 return nil, fmt.Errorf("Invalid filter '%s'", name) 48 } 49 } 50 51 if i, ok := imageFilters["dangling"]; ok { 52 for _, value := range i { 53 if strings.ToLower(value) == "true" { 54 filtTagged = false 55 } 56 } 57 } 58 59 _, filtLabel = imageFilters["label"] 60 61 if config.All && filtTagged { 62 allImages = s.graph.Map() 63 } else { 64 allImages = s.graph.Heads() 65 } 66 67 lookup := make(map[string]*types.Image) 68 s.Lock() 69 for repoName, repository := range s.Repositories { 70 if config.Filter != "" { 71 if match, _ := path.Match(config.Filter, repoName); !match { 72 continue 73 } 74 } 75 for ref, id := range repository { 76 imgRef := utils.ImageReference(repoName, ref) 77 image, err := s.graph.Get(id) 78 if err != nil { 79 logrus.Warnf("couldn't load %s from %s: %s", id, imgRef, err) 80 continue 81 } 82 83 if lImage, exists := lookup[id]; exists { 84 if filtTagged { 85 if utils.DigestReference(ref) { 86 lImage.RepoDigests = append(lImage.RepoDigests, imgRef) 87 } else { // Tag Ref. 88 lImage.RepoTags = append(lImage.RepoTags, imgRef) 89 } 90 } 91 } else { 92 // get the boolean list for if only the untagged images are requested 93 delete(allImages, id) 94 if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) { 95 continue 96 } 97 if filtTagged { 98 newImage := new(types.Image) 99 newImage.ParentId = image.Parent 100 newImage.ID = image.ID 101 newImage.Created = int(image.Created.Unix()) 102 newImage.Size = int(image.Size) 103 newImage.VirtualSize = int(s.graph.GetParentsSize(image, 0) + image.Size) 104 newImage.Labels = image.ContainerConfig.Labels 105 106 if utils.DigestReference(ref) { 107 newImage.RepoTags = []string{} 108 newImage.RepoDigests = []string{imgRef} 109 } else { 110 newImage.RepoTags = []string{imgRef} 111 newImage.RepoDigests = []string{} 112 } 113 114 lookup[id] = newImage 115 } 116 } 117 118 } 119 } 120 s.Unlock() 121 122 images := []*types.Image{} 123 for _, value := range lookup { 124 images = append(images, value) 125 } 126 127 // Display images which aren't part of a repository/tag 128 if config.Filter == "" || filtLabel { 129 for _, image := range allImages { 130 if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) { 131 continue 132 } 133 newImage := new(types.Image) 134 newImage.ParentId = image.Parent 135 newImage.RepoTags = []string{"<none>:<none>"} 136 newImage.RepoDigests = []string{"<none>@<none>"} 137 newImage.ID = image.ID 138 newImage.Created = int(image.Created.Unix()) 139 newImage.Size = int(image.Size) 140 newImage.VirtualSize = int(s.graph.GetParentsSize(image, 0) + image.Size) 141 newImage.Labels = image.ContainerConfig.Labels 142 143 images = append(images, newImage) 144 } 145 } 146 147 sort.Sort(sort.Reverse(ByCreated(images))) 148 149 return images, nil 150 }