github.com/a4a881d4/docker@v1.9.0-rc2/graph/history.go (about)

     1  package graph
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/docker/docker/api/types"
     8  	"github.com/docker/docker/image"
     9  	"github.com/docker/docker/utils"
    10  )
    11  
    12  // WalkHistory calls the handler function for each image in the
    13  // provided images lineage starting from immediate parent.
    14  func (graph *Graph) WalkHistory(img *image.Image, handler func(image.Image) error) (err error) {
    15  	currentImg := img
    16  	for currentImg != nil {
    17  		if handler != nil {
    18  			if err := handler(*currentImg); err != nil {
    19  				return err
    20  			}
    21  		}
    22  		currentImg, err = graph.GetParent(currentImg)
    23  		if err != nil {
    24  			return fmt.Errorf("Error while getting parent image: %v", err)
    25  		}
    26  	}
    27  	return nil
    28  }
    29  
    30  // depth returns the number of parents for the current image
    31  func (graph *Graph) depth(img *image.Image) (int, error) {
    32  	var (
    33  		count  = 0
    34  		parent = img
    35  		err    error
    36  	)
    37  
    38  	for parent != nil {
    39  		count++
    40  		if parent, err = graph.GetParent(parent); err != nil {
    41  			return -1, err
    42  		}
    43  	}
    44  	return count, nil
    45  }
    46  
    47  // Set the max depth to the aufs default that most
    48  // kernels are compiled with
    49  // For more information see: http://sourceforge.net/p/aufs/aufs3-standalone/ci/aufs3.12/tree/config.mk
    50  const MaxImageDepth = 127
    51  
    52  // CheckDepth returns an error if the depth of an image, as returned
    53  // by ImageDepth, is too large to support creating a container from it
    54  // on this daemon.
    55  func (graph *Graph) CheckDepth(img *image.Image) error {
    56  	// We add 2 layers to the depth because the container's rw and
    57  	// init layer add to the restriction
    58  	depth, err := graph.depth(img)
    59  	if err != nil {
    60  		return err
    61  	}
    62  	if depth+2 >= MaxImageDepth {
    63  		return fmt.Errorf("Cannot create container with more than %d parents", MaxImageDepth)
    64  	}
    65  	return nil
    66  }
    67  
    68  // History returns a slice of ImageHistory structures for the specified image
    69  // name by walking the image lineage.
    70  func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
    71  	foundImage, err := s.LookupImage(name)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	lookupMap := make(map[string][]string)
    77  	for name, repository := range s.Repositories {
    78  		for tag, id := range repository {
    79  			// If the ID already has a reverse lookup, do not update it unless for "latest"
    80  			if _, exists := lookupMap[id]; !exists {
    81  				lookupMap[id] = []string{}
    82  			}
    83  			lookupMap[id] = append(lookupMap[id], utils.ImageReference(name, tag))
    84  		}
    85  	}
    86  
    87  	history := []*types.ImageHistory{}
    88  
    89  	err = s.graph.WalkHistory(foundImage, func(img image.Image) error {
    90  		history = append(history, &types.ImageHistory{
    91  			ID:        img.ID,
    92  			Created:   img.Created.Unix(),
    93  			CreatedBy: strings.Join(img.ContainerConfig.Cmd.Slice(), " "),
    94  			Tags:      lookupMap[img.ID],
    95  			Size:      img.Size,
    96  			Comment:   img.Comment,
    97  		})
    98  		return nil
    99  	})
   100  
   101  	return history, err
   102  }
   103  
   104  // GetParent returns the parent image for the specified image.
   105  func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) {
   106  	if img.Parent == "" {
   107  		return nil, nil
   108  	}
   109  	return graph.Get(img.Parent)
   110  }
   111  
   112  // GetParentsSize returns the combined size of all parent images. If there is
   113  // no parent image or it's unavailable, it returns 0.
   114  func (graph *Graph) GetParentsSize(img *image.Image) int64 {
   115  	parentImage, err := graph.GetParent(img)
   116  	if err != nil || parentImage == nil {
   117  		return 0
   118  	}
   119  	return parentImage.Size + graph.GetParentsSize(parentImage)
   120  }