github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/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  				if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) {
   112  					continue
   113  				}
   114  				if filtTagged {
   115  					newImage := new(types.Image)
   116  					newImage.ParentID = image.Parent
   117  					newImage.ID = image.ID
   118  					newImage.Created = image.Created.Unix()
   119  					newImage.Size = image.Size
   120  					newImage.VirtualSize = s.graph.GetParentsSize(image) + image.Size
   121  					newImage.Labels = image.ContainerConfig.Labels
   122  
   123  					if utils.DigestReference(ref) {
   124  						newImage.RepoTags = []string{}
   125  						newImage.RepoDigests = []string{imgRef}
   126  					} else {
   127  						newImage.RepoTags = []string{imgRef}
   128  						newImage.RepoDigests = []string{}
   129  					}
   130  
   131  					lookup[id] = newImage
   132  				}
   133  			}
   134  
   135  		}
   136  	}
   137  	s.Unlock()
   138  
   139  	images := []*types.Image{}
   140  	for _, value := range lookup {
   141  		images = append(images, value)
   142  	}
   143  
   144  	// Display images which aren't part of a repository/tag
   145  	if filter == "" || filtLabel {
   146  		for _, image := range allImages {
   147  			if !imageFilters.MatchKVList("label", image.ContainerConfig.Labels) {
   148  				continue
   149  			}
   150  			newImage := new(types.Image)
   151  			newImage.ParentID = image.Parent
   152  			newImage.RepoTags = []string{"<none>:<none>"}
   153  			newImage.RepoDigests = []string{"<none>@<none>"}
   154  			newImage.ID = image.ID
   155  			newImage.Created = image.Created.Unix()
   156  			newImage.Size = image.Size
   157  			newImage.VirtualSize = s.graph.GetParentsSize(image) + image.Size
   158  			newImage.Labels = image.ContainerConfig.Labels
   159  
   160  			images = append(images, newImage)
   161  		}
   162  	}
   163  
   164  	sort.Sort(sort.Reverse(byCreated(images)))
   165  
   166  	return images, nil
   167  }