c8d: add support for docker diff
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
This commit is contained in:
parent
e85c69e1b7
commit
4c459ddabd
6 changed files with 96 additions and 13 deletions
|
@ -48,7 +48,7 @@ type stateBackend interface {
|
|||
|
||||
// monitorBackend includes functions to implement to provide containers monitoring functionality.
|
||||
type monitorBackend interface {
|
||||
ContainerChanges(name string) ([]archive.Change, error)
|
||||
ContainerChanges(ctx context.Context, name string) ([]archive.Change, error)
|
||||
ContainerInspect(ctx context.Context, name string, size bool, version string) (interface{}, error)
|
||||
ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
|
||||
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
|
||||
|
|
|
@ -401,7 +401,7 @@ func (s *containerRouter) postContainersWait(ctx context.Context, w http.Respons
|
|||
}
|
||||
|
||||
func (s *containerRouter) getContainersChanges(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
changes, err := s.backend.ContainerChanges(vars["name"])
|
||||
changes, err := s.backend.ContainerChanges(ctx, vars["name"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
// ContainerChanges returns a list of container fs changes
|
||||
func (daemon *Daemon) ContainerChanges(name string) ([]archive.Change, error) {
|
||||
func (daemon *Daemon) ContainerChanges(ctx context.Context, name string) ([]archive.Change, error) {
|
||||
start := time.Now()
|
||||
|
||||
container, err := daemon.GetContainer(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -20,15 +21,7 @@ func (daemon *Daemon) ContainerChanges(name string) ([]archive.Change, error) {
|
|||
return nil, errors.New("Windows does not support diff of a running container")
|
||||
}
|
||||
|
||||
if daemon.UsesSnapshotter() {
|
||||
return nil, errdefs.NotImplemented(errors.New("not implemented"))
|
||||
}
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
if container.RWLayer == nil {
|
||||
return nil, errors.New("RWLayer of container " + name + " is unexpectedly nil")
|
||||
}
|
||||
c, err := container.RWLayer.Changes()
|
||||
c, err := daemon.imageService.Changes(ctx, container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
69
daemon/containerd/image_changes.go
Normal file
69
daemon/containerd/image_changes.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package containerd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/google/uuid"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (i *ImageService) Changes(ctx context.Context, container *container.Container) ([]archive.Change, error) {
|
||||
cs := i.client.ContentStore()
|
||||
|
||||
imageManifestBytes, err := content.ReadBlob(ctx, cs, *container.ImageManifest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var manifest ocispec.Manifest
|
||||
if err := json.Unmarshal(imageManifestBytes, &manifest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
imageConfigBytes, err := content.ReadBlob(ctx, cs, manifest.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var image ocispec.Image
|
||||
if err := json.Unmarshal(imageConfigBytes, &image); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rnd, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
snapshotter := i.client.SnapshotService(i.snapshotter)
|
||||
|
||||
diffIDs := image.RootFS.DiffIDs
|
||||
parent, err := snapshotter.View(ctx, rnd.String(), identity.ChainID(diffIDs).String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := snapshotter.Remove(ctx, rnd.String()); err != nil {
|
||||
logrus.WithError(err).WithField("key", rnd.String()).Warn("remove temporary snapshot")
|
||||
}
|
||||
}()
|
||||
|
||||
mounts, err := snapshotter.Mounts(ctx, container.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var changes []archive.Change
|
||||
err = mount.WithReadonlyTempMount(ctx, mounts, func(fs string) error {
|
||||
return mount.WithTempMount(ctx, parent, func(root string) error {
|
||||
changes, err = archive.ChangesDirs(fs, root)
|
||||
return err
|
||||
})
|
||||
})
|
||||
return changes, err
|
||||
}
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/docker/docker/daemon/images"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
|
@ -60,6 +61,7 @@ type ImageService interface {
|
|||
GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error)
|
||||
Mount(ctx context.Context, container *container.Container) error
|
||||
Unmount(ctx context.Context, container *container.Container) error
|
||||
Changes(ctx context.Context, container *container.Container) ([]archive.Change, error)
|
||||
|
||||
// Windows specific
|
||||
|
||||
|
|
19
daemon/images/image_changes.go
Normal file
19
daemon/images/image_changes.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package images
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
func (i *ImageService) Changes(ctx context.Context, container *container.Container) ([]archive.Change, error) {
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
|
||||
if container.RWLayer == nil {
|
||||
return nil, errors.New("RWLayer of container " + container.Name + " is unexpectedly nil")
|
||||
}
|
||||
return container.RWLayer.Changes()
|
||||
}
|
Loading…
Reference in a new issue