github.com/darciopacifico/docker@v1.9.0-rc1/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 strings.ToLower(value) == "true" {
    55  				filtTagged = false
    56  			}
    57  		}
    58  	}
    59  
    60  	_, filtLabel = imageFilters["label"]
    61  
    62  	if all && filtTagged {
    63  		allImages = s.graph.Map()
    64  	} else {
    65  		allImages = s.graph.Heads()
    66  	}
    67  
    68  	lookup := make(map[string]*types.Image)
    69  	s.Lock()
    70  	for repoName, repository := range s.Repositories {
    71  		filterTagName := ""
    72  		if filter != "" {
    73  			filterName := filter
    74  			// Test if the tag was in there, if yes, get the name
    75  			if strings.Contains(filterName, ":") {
    76  				filterWithTag := strings.Split(filter, ":")
    77  				filterName = filterWithTag[0]
    78  				filterTagName = filterWithTag[1]
    79  			}
    80  			if match, _ := path.Match(filterName, repoName); !match {
    81  				continue
    82  			}
    83  			if filterTagName != "" {
    84  				if _, ok := repository[filterTagName]; !ok {
    85  					continue
    86  				}
    87  			}
    88  		}
    89  		for ref, id := range repository {
    90  			imgRef := utils.ImageReference(repoName, ref)
    91  			if !strings.Contains(imgRef, filterTagName) {
    92  				continue
    93  			}
    94  			image, err := s.graph.Get(id)
    95  			if err != nil {
    96  				logrus.Warnf("couldn't load %s from %s: %s", id, imgRef, err)
    97  				continue
    98  			}
    99  
   100  			if lImage, exists := lookup[id]; exists {
   101  				if filtTagged {
   102  					if utils.DigestReference(ref) {
   103  						lImage.RepoDigests = append(lImage.RepoDigests, imgRef)
   104  					} else { // Tag Ref.
   105  						lImage.RepoTags = append(lImage.RepoTags, imgRef)
   106  					}
   107  				}
   108  			} else {
   109  				// get the boolean list for if only the untagged images are requested
   110  				delete(allImages, id)
   111  
   112  				if len(imageFilters["label"]) > 0 {
   113  					if image.Config == nil {
   114  						// Very old image that do not have image.Config (or even labels)
   115  						continue
   116  					}
   117  					// We are now sure image.Config is not nil
   118  					if !imageFilters.MatchKVList("label", image.Config.Labels) {
   119  						continue
   120  					}
   121  				}
   122  				if filtTagged {
   123  					newImage := newImage(image, s.graph.GetParentsSize(image))
   124  
   125  					if utils.DigestReference(ref) {
   126  						newImage.RepoTags = []string{}
   127  						newImage.RepoDigests = []string{imgRef}
   128  					} else {
   129  						newImage.RepoTags = []string{imgRef}
   130  						newImage.RepoDigests = []string{}
   131  					}
   132  
   133  					lookup[id] = newImage
   134  				}
   135  			}
   136  
   137  		}
   138  	}
   139  	s.Unlock()
   140  
   141  	images := []*types.Image{}
   142  	for _, value := range lookup {
   143  		images = append(images, value)
   144  	}
   145  
   146  	// Display images which aren't part of a repository/tag
   147  	if filter == "" || filtLabel {
   148  		for _, image := range allImages {
   149  			if len(imageFilters["label"]) > 0 {
   150  				if image.Config == nil {
   151  					// Very old image that do not have image.Config (or even labels)
   152  					continue
   153  				}
   154  				// We are now sure image.Config is not nil
   155  				if !imageFilters.MatchKVList("label", image.Config.Labels) {
   156  					continue
   157  				}
   158  			}
   159  			newImage := newImage(image, s.graph.GetParentsSize(image))
   160  			newImage.RepoTags = []string{"<none>:<none>"}
   161  			newImage.RepoDigests = []string{"<none>@<none>"}
   162  
   163  			images = append(images, newImage)
   164  		}
   165  	}
   166  
   167  	sort.Sort(sort.Reverse(byCreated(images)))
   168  
   169  	return images, nil
   170  }
   171  
   172  func newImage(image *image.Image, parentSize int64) *types.Image {
   173  	newImage := new(types.Image)
   174  	newImage.ParentID = image.Parent
   175  	newImage.ID = image.ID
   176  	newImage.Created = image.Created.Unix()
   177  	newImage.Size = image.Size
   178  	newImage.VirtualSize = parentSize + image.Size
   179  	if image.Config != nil {
   180  		newImage.Labels = image.Config.Labels
   181  	}
   182  	return newImage
   183  }