github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/daemon/images.go (about)

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