github.com/baris/docker@v1.7.0/graph/list.go (about) 1 package graph 2 3 import ( 4 "fmt" 5 "log" 6 "path" 7 "sort" 8 "strings" 9 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, err = s.graph.Map() 63 } else { 64 allImages, err = s.graph.Heads() 65 } 66 if err != nil { 67 return nil, err 68 } 69 70 lookup := make(map[string]*types.Image) 71 s.Lock() 72 for repoName, repository := range s.Repositories { 73 if config.Filter != "" { 74 if match, _ := path.Match(config.Filter, repoName); !match { 75 continue 76 } 77 } 78 for ref, id := range repository { 79 imgRef := utils.ImageReference(repoName, ref) 80 image, err := s.graph.Get(id) 81 if err != nil { 82 log.Printf("Warning: couldn't load %s from %s: %s", id, imgRef, err) 83 continue 84 } 85 86 if lImage, exists := lookup[id]; exists { 87 if filtTagged { 88 if utils.DigestReference(ref) { 89 lImage.RepoDigests = append(lImage.RepoDigests, imgRef) 90 } else { // Tag Ref. 91 lImage.RepoTags = append(lImage.RepoTags, imgRef) 92 } 93 } 94 } else { 95 // get the boolean list for if only the untagged images are requested 96 delete(allImages, id) 97 if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) { 98 continue 99 } 100 if filtTagged { 101 newImage := new(types.Image) 102 newImage.ParentId = image.Parent 103 newImage.ID = image.ID 104 newImage.Created = int(image.Created.Unix()) 105 newImage.Size = int(image.Size) 106 newImage.VirtualSize = int(image.GetParentsSize(0) + image.Size) 107 newImage.Labels = image.ContainerConfig.Labels 108 109 if utils.DigestReference(ref) { 110 newImage.RepoTags = []string{} 111 newImage.RepoDigests = []string{imgRef} 112 } else { 113 newImage.RepoTags = []string{imgRef} 114 newImage.RepoDigests = []string{} 115 } 116 117 lookup[id] = newImage 118 } 119 } 120 121 } 122 } 123 s.Unlock() 124 125 images := []*types.Image{} 126 for _, value := range lookup { 127 images = append(images, value) 128 } 129 130 // Display images which aren't part of a repository/tag 131 if config.Filter == "" || filtLabel { 132 for _, image := range allImages { 133 if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) { 134 continue 135 } 136 newImage := new(types.Image) 137 newImage.ParentId = image.Parent 138 newImage.RepoTags = []string{"<none>:<none>"} 139 newImage.RepoDigests = []string{"<none>@<none>"} 140 newImage.ID = image.ID 141 newImage.Created = int(image.Created.Unix()) 142 newImage.Size = int(image.Size) 143 newImage.VirtualSize = int(image.GetParentsSize(0) + image.Size) 144 newImage.Labels = image.ContainerConfig.Labels 145 146 images = append(images, newImage) 147 } 148 } 149 150 sort.Sort(sort.Reverse(ByCreated(images))) 151 152 return images, nil 153 }