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  }