github.com/kobeld/docker@v1.12.0-rc1/daemon/images.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "path" 6 "sort" 7 8 "github.com/docker/docker/image" 9 "github.com/docker/docker/layer" 10 "github.com/docker/docker/reference" 11 "github.com/docker/engine-api/types" 12 "github.com/docker/engine-api/types/filters" 13 ) 14 15 var acceptedImageFilterTags = map[string]bool{ 16 "dangling": true, 17 "label": true, 18 "before": true, 19 "since": true, 20 } 21 22 // byCreated is a temporary type used to sort a list of images by creation 23 // time. 24 type byCreated []*types.Image 25 26 func (r byCreated) Len() int { return len(r) } 27 func (r byCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 28 func (r byCreated) Less(i, j int) bool { return r[i].Created < r[j].Created } 29 30 // Map returns a map of all images in the ImageStore 31 func (daemon *Daemon) Map() map[image.ID]*image.Image { 32 return daemon.imageStore.Map() 33 } 34 35 // Images returns a filtered list of images. filterArgs is a JSON-encoded set 36 // of filter arguments which will be interpreted by api/types/filters. 37 // filter is a shell glob string applied to repository names. The argument 38 // named all controls whether all images in the graph are filtered, or just 39 // the heads. 40 func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Image, error) { 41 var ( 42 allImages map[image.ID]*image.Image 43 err error 44 danglingOnly = false 45 ) 46 47 imageFilters, err := filters.FromParam(filterArgs) 48 if err != nil { 49 return nil, err 50 } 51 if err := imageFilters.Validate(acceptedImageFilterTags); err != nil { 52 return nil, err 53 } 54 55 if imageFilters.Include("dangling") { 56 if imageFilters.ExactMatch("dangling", "true") { 57 danglingOnly = true 58 } else if !imageFilters.ExactMatch("dangling", "false") { 59 return nil, fmt.Errorf("Invalid filter 'dangling=%s'", imageFilters.Get("dangling")) 60 } 61 } 62 if danglingOnly { 63 allImages = daemon.imageStore.Heads() 64 } else { 65 allImages = daemon.imageStore.Map() 66 } 67 68 var beforeFilter, sinceFilter *image.Image 69 err = imageFilters.WalkValues("before", func(value string) error { 70 beforeFilter, err = daemon.GetImage(value) 71 return err 72 }) 73 if err != nil { 74 return nil, err 75 } 76 77 err = imageFilters.WalkValues("since", func(value string) error { 78 sinceFilter, err = daemon.GetImage(value) 79 return err 80 }) 81 if err != nil { 82 return nil, err 83 } 84 85 images := []*types.Image{} 86 87 var filterTagged bool 88 if filter != "" { 89 filterRef, err := reference.ParseNamed(filter) 90 if err == nil { // parse error means wildcard repo 91 if _, ok := filterRef.(reference.NamedTagged); ok { 92 filterTagged = true 93 } 94 } 95 } 96 97 for id, img := range allImages { 98 if beforeFilter != nil { 99 if img.Created.Equal(beforeFilter.Created) || img.Created.After(beforeFilter.Created) { 100 continue 101 } 102 } 103 104 if sinceFilter != nil { 105 if img.Created.Equal(sinceFilter.Created) || img.Created.Before(sinceFilter.Created) { 106 continue 107 } 108 } 109 110 if imageFilters.Include("label") { 111 // Very old image that do not have image.Config (or even labels) 112 if img.Config == nil { 113 continue 114 } 115 // We are now sure image.Config is not nil 116 if !imageFilters.MatchKVList("label", img.Config.Labels) { 117 continue 118 } 119 } 120 121 layerID := img.RootFS.ChainID() 122 var size int64 123 if layerID != "" { 124 l, err := daemon.layerStore.Get(layerID) 125 if err != nil { 126 return nil, err 127 } 128 129 size, err = l.Size() 130 layer.ReleaseAndLog(daemon.layerStore, l) 131 if err != nil { 132 return nil, err 133 } 134 } 135 136 newImage := newImage(img, size) 137 138 for _, ref := range daemon.referenceStore.References(id) { 139 if filter != "" { // filter by tag/repo name 140 if filterTagged { // filter by tag, require full ref match 141 if ref.String() != filter { 142 continue 143 } 144 } else if matched, err := path.Match(filter, ref.Name()); !matched || err != nil { // name only match, FIXME: docs say exact 145 continue 146 } 147 } 148 if _, ok := ref.(reference.Canonical); ok { 149 newImage.RepoDigests = append(newImage.RepoDigests, ref.String()) 150 } 151 if _, ok := ref.(reference.NamedTagged); ok { 152 newImage.RepoTags = append(newImage.RepoTags, ref.String()) 153 } 154 } 155 if newImage.RepoDigests == nil && newImage.RepoTags == nil { 156 if all || len(daemon.imageStore.Children(id)) == 0 { 157 158 if imageFilters.Include("dangling") && !danglingOnly { 159 //dangling=false case, so dangling image is not needed 160 continue 161 } 162 if filter != "" { // skip images with no references if filtering by tag 163 continue 164 } 165 newImage.RepoDigests = []string{"<none>@<none>"} 166 newImage.RepoTags = []string{"<none>:<none>"} 167 } else { 168 continue 169 } 170 } else if danglingOnly { 171 continue 172 } 173 174 images = append(images, newImage) 175 } 176 177 sort.Sort(sort.Reverse(byCreated(images))) 178 179 return images, nil 180 } 181 182 func newImage(image *image.Image, size int64) *types.Image { 183 newImage := new(types.Image) 184 newImage.ParentID = image.Parent.String() 185 newImage.ID = image.ID().String() 186 newImage.Created = image.Created.Unix() 187 newImage.Size = size 188 newImage.VirtualSize = size 189 if image.Config != nil { 190 newImage.Labels = image.Config.Labels 191 } 192 return newImage 193 }