mirror of https://github.com/docker/docs.git
				
				
				
			
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
| package graph
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/docker/docker/api/types"
 | |
| 	"github.com/docker/docker/image"
 | |
| 	"github.com/docker/docker/utils"
 | |
| )
 | |
| 
 | |
| // WalkHistory calls the handler function for each image in the
 | |
| // provided images lineage starting from immediate parent.
 | |
| func (graph *Graph) WalkHistory(img *image.Image, handler func(image.Image) error) (err error) {
 | |
| 	currentImg := img
 | |
| 	for currentImg != nil {
 | |
| 		if handler != nil {
 | |
| 			if err := handler(*currentImg); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 		}
 | |
| 		currentImg, err = graph.GetParent(currentImg)
 | |
| 		if err != nil {
 | |
| 			return fmt.Errorf("Error while getting parent image: %v", err)
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // depth returns the number of parents for a
 | |
| // current image
 | |
| func (graph *Graph) depth(img *image.Image) (int, error) {
 | |
| 	var (
 | |
| 		count  = 0
 | |
| 		parent = img
 | |
| 		err    error
 | |
| 	)
 | |
| 
 | |
| 	for parent != nil {
 | |
| 		count++
 | |
| 		parent, err = graph.GetParent(parent)
 | |
| 		if err != nil {
 | |
| 			return -1, err
 | |
| 		}
 | |
| 	}
 | |
| 	return count, nil
 | |
| }
 | |
| 
 | |
| // Set the max depth to the aufs default that most
 | |
| // kernels are compiled with
 | |
| // For more information see: http://sourceforge.net/p/aufs/aufs3-standalone/ci/aufs3.12/tree/config.mk
 | |
| const MaxImageDepth = 127
 | |
| 
 | |
| // CheckDepth returns an error if the depth of an image, as returned
 | |
| // by ImageDepth, is too large to support creating a container from it
 | |
| // on this daemon.
 | |
| func (graph *Graph) CheckDepth(img *image.Image) error {
 | |
| 	// We add 2 layers to the depth because the container's rw and
 | |
| 	// init layer add to the restriction
 | |
| 	depth, err := graph.depth(img)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if depth+2 >= MaxImageDepth {
 | |
| 		return fmt.Errorf("Cannot create container with more than %d parents", MaxImageDepth)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // History returns a slice of ImageHistory structures for the specified image
 | |
| // name by walking the image lineage.
 | |
| func (s *TagStore) History(name string) ([]*types.ImageHistory, error) {
 | |
| 	foundImage, err := s.LookupImage(name)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	lookupMap := make(map[string][]string)
 | |
| 	for name, repository := range s.Repositories {
 | |
| 		for tag, id := range repository {
 | |
| 			// If the ID already has a reverse lookup, do not update it unless for "latest"
 | |
| 			if _, exists := lookupMap[id]; !exists {
 | |
| 				lookupMap[id] = []string{}
 | |
| 			}
 | |
| 			lookupMap[id] = append(lookupMap[id], utils.ImageReference(name, tag))
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	history := []*types.ImageHistory{}
 | |
| 
 | |
| 	err = s.graph.WalkHistory(foundImage, func(img image.Image) error {
 | |
| 		history = append(history, &types.ImageHistory{
 | |
| 			ID:        img.ID,
 | |
| 			Created:   img.Created.Unix(),
 | |
| 			CreatedBy: strings.Join(img.ContainerConfig.Cmd.Slice(), " "),
 | |
| 			Tags:      lookupMap[img.ID],
 | |
| 			Size:      img.Size,
 | |
| 			Comment:   img.Comment,
 | |
| 		})
 | |
| 		return nil
 | |
| 	})
 | |
| 
 | |
| 	return history, err
 | |
| }
 | |
| 
 | |
| // GetParent returns the parent image for the specified image.
 | |
| func (graph *Graph) GetParent(img *image.Image) (*image.Image, error) {
 | |
| 	if img.Parent == "" {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 	return graph.Get(img.Parent)
 | |
| }
 | |
| 
 | |
| // GetParentsSize returns the combined size of all parent images. If there is
 | |
| // no parent image or it's unavailable, it returns 0.
 | |
| func (graph *Graph) GetParentsSize(img *image.Image) int64 {
 | |
| 	parentImage, err := graph.GetParent(img)
 | |
| 	if err != nil || parentImage == nil {
 | |
| 		return 0
 | |
| 	}
 | |
| 	return parentImage.Size + graph.GetParentsSize(parentImage)
 | |
| }
 |