github.com/shiroyuki/docker@v1.9.0/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 // byCreated is a temporary type used to sort a list of images by creation 22 // time. 23 type byCreated []*types.Image 24 25 func (r byCreated) Len() int { return len(r) } 26 func (r byCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 27 func (r byCreated) Less(i, j int) bool { return r[i].Created < r[j].Created } 28 29 // Images returns a filtered list of images. filterArgs is a JSON-encoded set 30 // of filter arguments which will be interpreted by pkg/parsers/filters. 31 // filter is a shell glob string applied to repository names. The argument 32 // named all controls whether all images in the graph are filtered, or just 33 // the heads. 34 func (s *TagStore) Images(filterArgs, filter string, all bool) ([]*types.Image, error) { 35 var ( 36 allImages map[string]*image.Image 37 err error 38 filtTagged = true 39 filtLabel = false 40 ) 41 42 imageFilters, err := filters.FromParam(filterArgs) 43 if err != nil { 44 return nil, err 45 } 46 for name := range imageFilters { 47 if _, ok := acceptedImageFilterTags[name]; !ok { 48 return nil, fmt.Errorf("Invalid filter '%s'", name) 49 } 50 } 51 52 if i, ok := imageFilters["dangling"]; ok { 53 for _, value := range i { 54 if v := strings.ToLower(value); v == "true" { 55 filtTagged = false 56 } else if v != "false" { 57 return nil, fmt.Errorf("Invalid filter 'dangling=%s'", v) 58 } 59 } 60 } 61 62 _, filtLabel = imageFilters["label"] 63 64 if all && filtTagged { 65 allImages = s.graph.Map() 66 } else { 67 allImages = s.graph.Heads() 68 } 69 70 lookup := make(map[string]*types.Image) 71 s.Lock() 72 for repoName, repository := range s.Repositories { 73 filterTagName := "" 74 if filter != "" { 75 filterName := filter 76 // Test if the tag was in there, if yes, get the name 77 if strings.Contains(filterName, ":") { 78 filterWithTag := strings.Split(filter, ":") 79 filterName = filterWithTag[0] 80 filterTagName = filterWithTag[1] 81 } 82 if match, _ := path.Match(filterName, repoName); !match { 83 continue 84 } 85 if filterTagName != "" { 86 if _, ok := repository[filterTagName]; !ok { 87 continue 88 } 89 } 90 } 91 for ref, id := range repository { 92 imgRef := utils.ImageReference(repoName, ref) 93 if !strings.Contains(imgRef, filterTagName) { 94 continue 95 } 96 image, err := s.graph.Get(id) 97 if err != nil { 98 logrus.Warnf("couldn't load %s from %s: %s", id, imgRef, err) 99 continue 100 } 101 102 if lImage, exists := lookup[id]; exists { 103 if filtTagged { 104 if utils.DigestReference(ref) { 105 lImage.RepoDigests = append(lImage.RepoDigests, imgRef) 106 } else { // Tag Ref. 107 lImage.RepoTags = append(lImage.RepoTags, imgRef) 108 } 109 } 110 } else { 111 // get the boolean list for if only the untagged images are requested 112 delete(allImages, id) 113 114 if len(imageFilters["label"]) > 0 { 115 if image.Config == nil { 116 // Very old image that do not have image.Config (or even labels) 117 continue 118 } 119 // We are now sure image.Config is not nil 120 if !imageFilters.MatchKVList("label", image.Config.Labels) { 121 continue 122 } 123 } 124 if filtTagged { 125 newImage := newImage(image, s.graph.GetParentsSize(image)) 126 127 if utils.DigestReference(ref) { 128 newImage.RepoTags = []string{} 129 newImage.RepoDigests = []string{imgRef} 130 } else { 131 newImage.RepoTags = []string{imgRef} 132 newImage.RepoDigests = []string{} 133 } 134 135 lookup[id] = newImage 136 } 137 } 138 139 } 140 } 141 s.Unlock() 142 143 images := []*types.Image{} 144 for _, value := range lookup { 145 images = append(images, value) 146 } 147 148 // Display images which aren't part of a repository/tag 149 if filter == "" || filtLabel { 150 for _, image := range allImages { 151 if len(imageFilters["label"]) > 0 { 152 if image.Config == nil { 153 // Very old image that do not have image.Config (or even labels) 154 continue 155 } 156 // We are now sure image.Config is not nil 157 if !imageFilters.MatchKVList("label", image.Config.Labels) { 158 continue 159 } 160 } 161 newImage := newImage(image, s.graph.GetParentsSize(image)) 162 newImage.RepoTags = []string{"<none>:<none>"} 163 newImage.RepoDigests = []string{"<none>@<none>"} 164 165 images = append(images, newImage) 166 } 167 } 168 169 sort.Sort(sort.Reverse(byCreated(images))) 170 171 return images, nil 172 } 173 174 func newImage(image *image.Image, parentSize int64) *types.Image { 175 newImage := new(types.Image) 176 newImage.ParentID = image.Parent 177 newImage.ID = image.ID 178 newImage.Created = image.Created.Unix() 179 newImage.Size = image.Size 180 newImage.VirtualSize = parentSize + image.Size 181 if image.Config != nil { 182 newImage.Labels = image.Config.Labels 183 } 184 return newImage 185 }