github.com/rawahars/moby@v24.0.4+incompatible/daemon/containerd/image_history.go (about) 1 package containerd 2 3 import ( 4 "context" 5 "sort" 6 7 cplatforms "github.com/containerd/containerd/platforms" 8 "github.com/docker/distribution/reference" 9 imagetype "github.com/docker/docker/api/types/image" 10 "github.com/docker/docker/errdefs" 11 "github.com/docker/docker/pkg/platforms" 12 "github.com/opencontainers/image-spec/identity" 13 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 14 "github.com/pkg/errors" 15 ) 16 17 // ImageHistory returns a slice of HistoryResponseItem structures for the 18 // specified image name by walking the image lineage. 19 func (i *ImageService) ImageHistory(ctx context.Context, name string) ([]*imagetype.HistoryResponseItem, error) { 20 desc, err := i.resolveImage(ctx, name) 21 if err != nil { 22 return nil, err 23 } 24 25 cs := i.client.ContentStore() 26 // TODO: pass platform in from the CLI 27 platform := platforms.AllPlatformsWithPreference(cplatforms.Default()) 28 29 var presentImages []ocispec.Image 30 err = i.walkImageManifests(ctx, desc, func(img *ImageManifest) error { 31 conf, err := img.Config(ctx) 32 if err != nil { 33 return err 34 } 35 var ociimage ocispec.Image 36 if err := readConfig(ctx, cs, conf, &ociimage); err != nil { 37 return err 38 } 39 presentImages = append(presentImages, ociimage) 40 return nil 41 }) 42 if err != nil { 43 return nil, err 44 } 45 if len(presentImages) == 0 { 46 return nil, errdefs.NotFound(errors.New("failed to find image manifest")) 47 } 48 49 sort.SliceStable(presentImages, func(i, j int) bool { 50 return platform.Less(presentImages[i].Platform, presentImages[j].Platform) 51 }) 52 ociimage := presentImages[0] 53 54 var ( 55 history []*imagetype.HistoryResponseItem 56 sizes []int64 57 ) 58 s := i.client.SnapshotService(i.snapshotter) 59 60 diffIDs := ociimage.RootFS.DiffIDs 61 for i := range diffIDs { 62 chainID := identity.ChainID(diffIDs[0 : i+1]).String() 63 64 use, err := s.Usage(ctx, chainID) 65 if err != nil { 66 return nil, err 67 } 68 69 sizes = append(sizes, use.Size) 70 } 71 72 for _, h := range ociimage.History { 73 size := int64(0) 74 if !h.EmptyLayer { 75 if len(sizes) == 0 { 76 return nil, errors.New("unable to find the size of the layer") 77 } 78 size = sizes[0] 79 sizes = sizes[1:] 80 } 81 82 history = append([]*imagetype.HistoryResponseItem{{ 83 ID: "<missing>", 84 Comment: h.Comment, 85 CreatedBy: h.CreatedBy, 86 Created: h.Created.Unix(), 87 Size: size, 88 Tags: nil, 89 }}, history...) 90 } 91 92 if len(history) != 0 { 93 history[0].ID = desc.Target.Digest.String() 94 95 tagged, err := i.client.ImageService().List(ctx, "target.digest=="+desc.Target.Digest.String()) 96 if err != nil { 97 return nil, err 98 } 99 100 var tags []string 101 for _, t := range tagged { 102 if isDanglingImage(t) { 103 continue 104 } 105 name, err := reference.ParseNamed(t.Name) 106 if err != nil { 107 return nil, err 108 } 109 tags = append(tags, reference.FamiliarString(name)) 110 } 111 history[0].Tags = tags 112 } 113 114 return history, nil 115 }