mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
daemon/images: move SquashImage to its own file
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
6b70975efc
commit
046b3fc5dd
2 changed files with 95 additions and 88 deletions
95
daemon/images/image_squash.go
Normal file
95
daemon/images/image_squash.go
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
package images // import "github.com/docker/docker/daemon/images"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/docker/image"
|
||||||
|
"github.com/docker/docker/layer"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SquashImage creates a new image with the diff of the specified image and the specified parent.
|
||||||
|
// This new image contains only the layers from it's parent + 1 extra layer which contains the diff of all the layers in between.
|
||||||
|
// The existing image(s) is not destroyed.
|
||||||
|
// If no parent is specified, a new image with the diff of all the specified image's layers merged into a new layer that has no parents.
|
||||||
|
func (i *ImageService) SquashImage(id, parent string) (string, error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
img *image.Image
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if img, err = i.imageStore.Get(image.ID(id)); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var parentImg *image.Image
|
||||||
|
var parentChainID layer.ChainID
|
||||||
|
if len(parent) != 0 {
|
||||||
|
parentImg, err = i.imageStore.Get(image.ID(parent))
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "error getting specified parent layer")
|
||||||
|
}
|
||||||
|
parentChainID = parentImg.RootFS.ChainID()
|
||||||
|
} else {
|
||||||
|
rootFS := image.NewRootFS()
|
||||||
|
parentImg = &image.Image{RootFS: rootFS}
|
||||||
|
}
|
||||||
|
l, err := i.layerStore.Get(img.RootFS.ChainID())
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "error getting image layer")
|
||||||
|
}
|
||||||
|
defer i.layerStore.Release(l)
|
||||||
|
|
||||||
|
ts, err := l.TarStreamFrom(parentChainID)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrapf(err, "error getting tar stream to parent")
|
||||||
|
}
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
newL, err := i.layerStore.Register(ts, parentChainID)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "error registering layer")
|
||||||
|
}
|
||||||
|
defer i.layerStore.Release(newL)
|
||||||
|
|
||||||
|
newImage := *img
|
||||||
|
newImage.RootFS = nil
|
||||||
|
|
||||||
|
rootFS := *parentImg.RootFS
|
||||||
|
rootFS.DiffIDs = append(rootFS.DiffIDs, newL.DiffID())
|
||||||
|
newImage.RootFS = &rootFS
|
||||||
|
|
||||||
|
for i, hi := range newImage.History {
|
||||||
|
if i >= len(parentImg.History) {
|
||||||
|
hi.EmptyLayer = true
|
||||||
|
}
|
||||||
|
newImage.History[i] = hi
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
var historyComment string
|
||||||
|
if len(parent) > 0 {
|
||||||
|
historyComment = fmt.Sprintf("merge %s to %s", id, parent)
|
||||||
|
} else {
|
||||||
|
historyComment = fmt.Sprintf("create new from %s", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
newImage.History = append(newImage.History, image.History{
|
||||||
|
Created: now,
|
||||||
|
Comment: historyComment,
|
||||||
|
})
|
||||||
|
newImage.Created = now
|
||||||
|
|
||||||
|
b, err := json.Marshal(&newImage)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "error marshalling image config")
|
||||||
|
}
|
||||||
|
|
||||||
|
newImgID, err := i.imageStore.Create(b)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "error creating new image after squash")
|
||||||
|
}
|
||||||
|
return string(newImgID), nil
|
||||||
|
}
|
|
@ -2,12 +2,8 @@ package images // import "github.com/docker/docker/daemon/images"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
@ -247,90 +243,6 @@ func (i *ImageService) Images(_ context.Context, opts types.ImageListOptions) ([
|
||||||
return summaries, nil
|
return summaries, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SquashImage creates a new image with the diff of the specified image and the specified parent.
|
|
||||||
// This new image contains only the layers from it's parent + 1 extra layer which contains the diff of all the layers in between.
|
|
||||||
// The existing image(s) is not destroyed.
|
|
||||||
// If no parent is specified, a new image with the diff of all the specified image's layers merged into a new layer that has no parents.
|
|
||||||
func (i *ImageService) SquashImage(id, parent string) (string, error) {
|
|
||||||
|
|
||||||
var (
|
|
||||||
img *image.Image
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if img, err = i.imageStore.Get(image.ID(id)); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var parentImg *image.Image
|
|
||||||
var parentChainID layer.ChainID
|
|
||||||
if len(parent) != 0 {
|
|
||||||
parentImg, err = i.imageStore.Get(image.ID(parent))
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "error getting specified parent layer")
|
|
||||||
}
|
|
||||||
parentChainID = parentImg.RootFS.ChainID()
|
|
||||||
} else {
|
|
||||||
rootFS := image.NewRootFS()
|
|
||||||
parentImg = &image.Image{RootFS: rootFS}
|
|
||||||
}
|
|
||||||
l, err := i.layerStore.Get(img.RootFS.ChainID())
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "error getting image layer")
|
|
||||||
}
|
|
||||||
defer i.layerStore.Release(l)
|
|
||||||
|
|
||||||
ts, err := l.TarStreamFrom(parentChainID)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrapf(err, "error getting tar stream to parent")
|
|
||||||
}
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
newL, err := i.layerStore.Register(ts, parentChainID)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "error registering layer")
|
|
||||||
}
|
|
||||||
defer i.layerStore.Release(newL)
|
|
||||||
|
|
||||||
newImage := *img
|
|
||||||
newImage.RootFS = nil
|
|
||||||
|
|
||||||
rootFS := *parentImg.RootFS
|
|
||||||
rootFS.DiffIDs = append(rootFS.DiffIDs, newL.DiffID())
|
|
||||||
newImage.RootFS = &rootFS
|
|
||||||
|
|
||||||
for i, hi := range newImage.History {
|
|
||||||
if i >= len(parentImg.History) {
|
|
||||||
hi.EmptyLayer = true
|
|
||||||
}
|
|
||||||
newImage.History[i] = hi
|
|
||||||
}
|
|
||||||
|
|
||||||
now := time.Now()
|
|
||||||
var historyComment string
|
|
||||||
if len(parent) > 0 {
|
|
||||||
historyComment = fmt.Sprintf("merge %s to %s", id, parent)
|
|
||||||
} else {
|
|
||||||
historyComment = fmt.Sprintf("create new from %s", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
newImage.History = append(newImage.History, image.History{
|
|
||||||
Created: now,
|
|
||||||
Comment: historyComment,
|
|
||||||
})
|
|
||||||
newImage.Created = now
|
|
||||||
|
|
||||||
b, err := json.Marshal(&newImage)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "error marshalling image config")
|
|
||||||
}
|
|
||||||
|
|
||||||
newImgID, err := i.imageStore.Create(b)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "error creating new image after squash")
|
|
||||||
}
|
|
||||||
return string(newImgID), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newImageSummary(image *image.Image, size int64) *types.ImageSummary {
|
func newImageSummary(image *image.Image, size int64) *types.ImageSummary {
|
||||||
summary := &types.ImageSummary{
|
summary := &types.ImageSummary{
|
||||||
ParentID: image.Parent.String(),
|
ParentID: image.Parent.String(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue