history.go 2.9 KB

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