Explorar o código

Merge pull request #43831 from thaJeztah/containerd_restructure

containerd-integration: restructure code to match existing implementation
Sebastiaan van Stijn %!s(int64=3) %!d(string=hai) anos
pai
achega
992961c56c

+ 10 - 0
daemon/containerd/cache.go

@@ -0,0 +1,10 @@
+package containerd
+
+import (
+	"github.com/docker/docker/builder"
+)
+
+// MakeImageCache creates a stateful image cache.
+func (i *ImageService) MakeImageCache(cacheFrom []string) builder.ImageCache {
+	panic("not implemented")
+}

+ 11 - 0
daemon/containerd/image.go

@@ -0,0 +1,11 @@
+package containerd
+
+import (
+	"github.com/docker/docker/image"
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+// GetImage returns an image corresponding to the image referred to by refOrID.
+func (i *ImageService) GetImage(refOrID string, platform *specs.Platform) (retImg *image.Image, retErr error) {
+	panic("not implemented")
+}

+ 22 - 0
daemon/containerd/image_builder.go

@@ -0,0 +1,22 @@
+package containerd
+
+import (
+	"context"
+
+	"github.com/docker/docker/api/types/backend"
+	"github.com/docker/docker/builder"
+)
+
+// GetImageAndReleasableLayer returns an image and releaseable layer for a
+// reference or ID. Every call to GetImageAndReleasableLayer MUST call
+// releasableLayer.Release() to prevent leaking of layers.
+func (i *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
+	panic("not implemented")
+}
+
+// CreateImage creates a new image by adding a config and ID to the image store.
+// This is similar to LoadImage() except that it receives JSON encoded bytes of
+// an image instead of a tar archive.
+func (i *ImageService) CreateImage(config []byte, parent string) (builder.Image, error) {
+	panic("not implemented")
+}

+ 24 - 0
daemon/containerd/image_commit.go

@@ -0,0 +1,24 @@
+package containerd
+
+import (
+	"github.com/docker/docker/api/types/backend"
+	"github.com/docker/docker/image"
+)
+
+// CommitImage creates a new image from a commit config.
+func (i *ImageService) CommitImage(c backend.CommitConfig) (image.ID, error) {
+	panic("not implemented")
+}
+
+// CommitBuildStep is used by the builder to create an image for each step in
+// the build.
+//
+// This method is different from CreateImageFromContainer:
+//   - it doesn't attempt to validate container state
+//   - it doesn't send a commit action to metrics
+//   - it doesn't log a container commit event
+//
+// This is a temporary shim. Should be removed when builder stops using commit.
+func (i *ImageService) CommitBuildStep(c backend.CommitConfig) (image.ID, error) {
+	panic("not implemented")
+}

+ 40 - 0
daemon/containerd/image_delete.go

@@ -0,0 +1,40 @@
+package containerd
+
+import "github.com/docker/docker/api/types"
+
+// ImageDelete deletes the image referenced by the given imageRef from this
+// daemon. The given imageRef can be an image ID, ID prefix, or a repository
+// reference (with an optional tag or digest, defaulting to the tag name
+// "latest"). There is differing behavior depending on whether the given
+// imageRef is a repository reference or not.
+//
+// If the given imageRef is a repository reference then that repository
+// reference will be removed. However, if there exists any containers which
+// were created using the same image reference then the repository reference
+// cannot be removed unless either there are other repository references to the
+// same image or force is true. Following removal of the repository reference,
+// the referenced image itself will attempt to be deleted as described below
+// but quietly, meaning any image delete conflicts will cause the image to not
+// be deleted and the conflict will not be reported.
+//
+// There may be conflicts preventing deletion of an image and these conflicts
+// are divided into two categories grouped by their severity:
+//
+// Hard Conflict:
+//   - a pull or build using the image.
+//   - any descendant image.
+//   - any running container using the image.
+//
+// Soft Conflict:
+//   - any stopped container using the image.
+//   - any repository tag or digest references to the image.
+//
+// The image cannot be removed if there are any hard conflicts and can be
+// removed if there are soft conflicts only if force is true.
+//
+// If prune is true, ancestor images will each attempt to be deleted quietly,
+// meaning any delete conflicts will cause the image to not be deleted and the
+// conflict will not be reported.
+func (i *ImageService) ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error) {
+	panic("not implemented")
+}

+ 13 - 0
daemon/containerd/image_events.go

@@ -0,0 +1,13 @@
+package containerd
+
+// LogImageEvent generates an event related to an image with only the
+// default attributes.
+func (i *ImageService) LogImageEvent(imageID, refName, action string) {
+	panic("not implemented")
+}
+
+// LogImageEventWithAttributes generates an event related to an image with
+// specific given attributes.
+func (i *ImageService) LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) {
+	panic("not implemented")
+}

+ 19 - 0
daemon/containerd/image_exporter.go

@@ -0,0 +1,19 @@
+package containerd
+
+import "io"
+
+// ExportImage exports a list of images to the given output stream. The
+// exported images are archived into a tar when written to the output
+// stream. All images with the given tag and all versions containing
+// the same tag are exported. names is the set of tags to export, and
+// outStream is the writer which the images are written to.
+func (i *ImageService) ExportImage(names []string, outStream io.Writer) error {
+	panic("not implemented")
+}
+
+// LoadImage uploads a set of images into the repository. This is the
+// complement of ExportImage.  The input stream is an uncompressed tar
+// ball containing images and metadata.
+func (i *ImageService) LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error {
+	panic("not implemented")
+}

+ 9 - 0
daemon/containerd/image_history.go

@@ -0,0 +1,9 @@
+package containerd
+
+import imagetype "github.com/docker/docker/api/types/image"
+
+// ImageHistory returns a slice of ImageHistory structures for the specified
+// image name by walking the image lineage.
+func (i *ImageService) ImageHistory(name string) ([]*imagetype.HistoryResponseItem, error) {
+	panic("not implemented")
+}

+ 15 - 0
daemon/containerd/image_import.go

@@ -0,0 +1,15 @@
+package containerd
+
+import (
+	"io"
+
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+// ImportImage imports an image, getting the archived layer data either from
+// inConfig (if src is "-"), or from a URI specified in src. Progress output is
+// written to outStream. Repository and tag names can optionally be given in
+// the repo and tag arguments, respectively.
+func (i *ImageService) ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
+	panic("not implemented")
+}

+ 37 - 0
daemon/containerd/image_list.go

@@ -0,0 +1,37 @@
+package containerd
+
+import (
+	"context"
+
+	"github.com/docker/docker/api/types"
+)
+
+// Images returns a filtered list of images.
+func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error) {
+	imgs, err := i.client.ListImages(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	var ret []*types.ImageSummary
+	for _, img := range imgs {
+		size, err := img.Size(ctx)
+		if err != nil {
+			return nil, err
+		}
+
+		ret = append(ret, &types.ImageSummary{
+			RepoDigests: []string{img.Name() + "@" + img.Target().Digest.String()}, // "hello-world@sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38"},
+			RepoTags:    []string{img.Name()},
+			Containers:  -1,
+			ParentID:    "",
+			SharedSize:  -1,
+			VirtualSize: 10,
+			ID:          img.Target().Digest.String(),
+			Created:     img.Metadata().CreatedAt.Unix(),
+			Size:        size,
+		})
+	}
+
+	return ret, nil
+}

+ 13 - 0
daemon/containerd/image_prune.go

@@ -0,0 +1,13 @@
+package containerd
+
+import (
+	"context"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+)
+
+// ImagesPrune removes unused images
+func (i *ImageService) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) {
+	panic("not implemented")
+}

+ 51 - 0
daemon/containerd/image_pull.go

@@ -0,0 +1,51 @@
+package containerd
+
+import (
+	"context"
+	"io"
+
+	"github.com/containerd/containerd"
+	"github.com/containerd/containerd/platforms"
+	"github.com/docker/distribution"
+	"github.com/docker/distribution/reference"
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/errdefs"
+	"github.com/opencontainers/go-digest"
+	specs "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+// PullImage initiates a pull operation. image is the repository name to pull, and
+// tagOrDigest may be either empty, or indicate a specific tag or digest to pull.
+func (i *ImageService) PullImage(ctx context.Context, image, tagOrDigest string, platform *specs.Platform, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
+	var opts []containerd.RemoteOpt
+	if platform != nil {
+		opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
+	}
+	ref, err := reference.ParseNormalizedNamed(image)
+	if err != nil {
+		return errdefs.InvalidParameter(err)
+	}
+
+	// TODO(thaJeztah) this could use a WithTagOrDigest() utility
+	if tagOrDigest != "" {
+		// The "tag" could actually be a digest.
+		var dgst digest.Digest
+		dgst, err = digest.Parse(tagOrDigest)
+		if err == nil {
+			ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
+		} else {
+			ref, err = reference.WithTag(ref, tagOrDigest)
+		}
+		if err != nil {
+			return errdefs.InvalidParameter(err)
+		}
+	}
+
+	_, err = i.client.Pull(ctx, ref.String(), opts...)
+	return err
+}
+
+// GetRepository returns a repository from the registry.
+func (i *ImageService) GetRepository(ctx context.Context, ref reference.Named, authConfig *types.AuthConfig) (distribution.Repository, error) {
+	panic("not implemented")
+}

+ 13 - 0
daemon/containerd/image_push.go

@@ -0,0 +1,13 @@
+package containerd
+
+import (
+	"context"
+	"io"
+
+	"github.com/docker/docker/api/types"
+)
+
+// PushImage initiates a push operation on the repository named localName.
+func (i *ImageService) PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
+	panic("not implemented")
+}

+ 18 - 0
daemon/containerd/image_search.go

@@ -0,0 +1,18 @@
+package containerd
+
+import (
+	"context"
+
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	registrytypes "github.com/docker/docker/api/types/registry"
+)
+
+// SearchRegistryForImages queries the registry for images matching
+// term. authConfig is used to login.
+//
+// TODO: this could be implemented in a registry service instead of the image
+// service.
+func (i *ImageService) SearchRegistryForImages(ctx context.Context, searchFilters filters.Args, term string, limit int, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registrytypes.SearchResults, error) {
+	panic("not implemented")
+}

+ 11 - 0
daemon/containerd/image_squash.go

@@ -0,0 +1,11 @@
+package containerd
+
+// SquashImage creates a new image with the diff of the specified image and
+// the specified parent. This new image contains only the layers from its
+// 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) {
+	panic("not implemented")
+}

+ 17 - 0
daemon/containerd/image_tag.go

@@ -0,0 +1,17 @@
+package containerd
+
+import (
+	"github.com/docker/distribution/reference"
+	"github.com/docker/docker/image"
+)
+
+// TagImage creates the tag specified by newTag, pointing to the image named
+// imageName (alternatively, imageName can also be an image ID).
+func (i *ImageService) TagImage(imageName, repository, tag string) (string, error) {
+	panic("not implemented")
+}
+
+// TagImageWithReference adds the given reference to the image ID provided.
+func (i *ImageService) TagImageWithReference(imageID image.ID, newTag reference.Named) error {
+	panic("not implemented")
+}

+ 40 - 279
daemon/containerd/service.go

@@ -2,25 +2,13 @@ package containerd
 
 import (
 	"context"
-	"io"
 
 	"github.com/containerd/containerd"
-	"github.com/containerd/containerd/platforms"
-	"github.com/docker/distribution"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/backend"
-	"github.com/docker/docker/api/types/filters"
-	imagetype "github.com/docker/docker/api/types/image"
-	registrytypes "github.com/docker/docker/api/types/registry"
-	"github.com/docker/docker/builder"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/daemon/images"
-	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
-	"github.com/opencontainers/go-digest"
-	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 )
 
 // ImageService implements daemon.ImageService
@@ -35,100 +23,58 @@ func NewService(c *containerd.Client) *ImageService {
 	}
 }
 
-// PullImage initiates a pull operation. image is the repository name to pull, and
-// tagOrDigest may be either empty, or indicate a specific tag or digest to pull.
-func (cs *ImageService) PullImage(ctx context.Context, image, tagOrDigest string, platform *ocispec.Platform, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
-	var opts []containerd.RemoteOpt
-	if platform != nil {
-		opts = append(opts, containerd.WithPlatform(platforms.Format(*platform)))
-	}
-	ref, err := reference.ParseNormalizedNamed(image)
-	if err != nil {
-		return errdefs.InvalidParameter(err)
-	}
-
-	// TODO(thaJeztah) this could use a WithTagOrDigest() utility
-	if tagOrDigest != "" {
-		// The "tag" could actually be a digest.
-		var dgst digest.Digest
-		dgst, err = digest.Parse(tagOrDigest)
-		if err == nil {
-			ref, err = reference.WithDigest(reference.TrimNamed(ref), dgst)
-		} else {
-			ref, err = reference.WithTag(ref, tagOrDigest)
-		}
-		if err != nil {
-			return errdefs.InvalidParameter(err)
-		}
-	}
-
-	_, err = cs.client.Pull(ctx, ref.String(), opts...)
-	return err
+// DistributionServices return services controlling daemon image storage.
+func (i *ImageService) DistributionServices() images.DistributionServices {
+	return images.DistributionServices{}
 }
 
-// Images returns a filtered list of images.
-func (cs *ImageService) Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error) {
-	imgs, err := cs.client.ListImages(ctx)
+// CountImages returns the number of images stored by ImageService
+// called from info.go
+func (i *ImageService) CountImages() int {
+	imgs, err := i.client.ListImages(context.TODO())
 	if err != nil {
-		return nil, err
-	}
-
-	var ret []*types.ImageSummary
-	for _, img := range imgs {
-		size, err := img.Size(ctx)
-		if err != nil {
-			return nil, err
-		}
-
-		ret = append(ret, &types.ImageSummary{
-			RepoDigests: []string{img.Name() + "@" + img.Target().Digest.String()}, // "hello-world@sha256:bfea6278a0a267fad2634554f4f0c6f31981eea41c553fdf5a83e95a41d40c38"},
-			RepoTags:    []string{img.Name()},
-			Containers:  -1,
-			ParentID:    "",
-			SharedSize:  -1,
-			VirtualSize: 10,
-			ID:          img.Target().Digest.String(),
-			Created:     img.Metadata().CreatedAt.Unix(),
-			Size:        size,
-		})
+		return 0
 	}
 
-	return ret, nil
-}
-
-// LogImageEvent generates an event related to an image with only the
-// default attributes.
-func (cs *ImageService) LogImageEvent(imageID, refName, action string) {
-	panic("not implemented")
+	return len(imgs)
 }
 
-// LogImageEventWithAttributes generates an event related to an image with
-// specific given attributes.
-func (cs *ImageService) LogImageEventWithAttributes(imageID, refName, action string, attributes map[string]string) {
+// Children returns the children image.IDs for a parent image.
+// called from list.go to filter containers
+// TODO: refactor to expose an ancestry for image.ID?
+func (i *ImageService) Children(id image.ID) []image.ID {
 	panic("not implemented")
 }
 
-// GetLayerFolders returns the layer folders from an image RootFS.
-func (cs *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error) {
+// CreateLayer creates a filesystem layer for a container.
+// called from create.go
+// TODO: accept an opt struct instead of container?
+func (i *ImageService) CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error) {
 	panic("not implemented")
 }
 
 // GetLayerByID returns a layer by ID
 // called from daemon.go Daemon.restore(), and Daemon.containerExport().
-func (cs *ImageService) GetLayerByID(string) (layer.RWLayer, error) {
+func (i *ImageService) GetLayerByID(cid string) (layer.RWLayer, error) {
 	panic("not implemented")
 }
 
+// LayerStoreStatus returns the status for each layer store
+// called from info.go
+func (i *ImageService) LayerStoreStatus() [][2]string {
+	return [][2]string{}
+}
+
 // GetLayerMountID returns the mount ID for a layer
 // called from daemon.go Daemon.Shutdown(), and Daemon.Cleanup() (cleanup is actually continerCleanup)
 // TODO: needs to be refactored to Unmount (see callers), or removed and replaced with GetLayerByID
-func (cs *ImageService) GetLayerMountID(string) (string, error) {
+func (i *ImageService) GetLayerMountID(cid string) (string, error) {
 	panic("not implemented")
 }
 
 // Cleanup resources before the process is shutdown.
 // called from daemon.go Daemon.Shutdown()
-func (cs *ImageService) Cleanup() error {
+func (i *ImageService) Cleanup() error {
 	return nil
 }
 
@@ -136,225 +82,40 @@ func (cs *ImageService) Cleanup() error {
 // moved from Daemon.GraphDriverName, used by:
 // - newContainer
 // - to report an error in Daemon.Mount(container)
-func (cs *ImageService) GraphDriverName() string {
+func (i *ImageService) GraphDriverName() string {
 	return ""
 }
 
-// CommitBuildStep is used by the builder to create an image for each step in
-// the build.
-//
-// This method is different from CreateImageFromContainer:
-//   - it doesn't attempt to validate container state
-//   - it doesn't send a commit action to metrics
-//   - it doesn't log a container commit event
-//
-// This is a temporary shim. Should be removed when builder stops using commit.
-func (cs *ImageService) CommitBuildStep(c backend.CommitConfig) (image.ID, error) {
-	panic("not implemented")
-}
-
-// CreateImage creates a new image by adding a config and ID to the image store.
-// This is similar to LoadImage() except that it receives JSON encoded bytes of
-// an image instead of a tar archive.
-func (cs *ImageService) CreateImage(config []byte, parent string) (builder.Image, error) {
-	panic("not implemented")
-}
-
-// GetImageAndReleasableLayer returns an image and releaseable layer for a
-// eference or ID. Every call to GetImageAndReleasableLayer MUST call
-// releasableLayer.Release() to prevent leaking of layers.
-func (cs *ImageService) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ROLayer, error) {
-	panic("not implemented")
-}
-
-// MakeImageCache creates a stateful image cache.
-func (cs *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
-	panic("not implemented")
-}
-
-// TagImageWithReference adds the given reference to the image ID provided.
-func (cs *ImageService) TagImageWithReference(imageID image.ID, newTag reference.Named) error {
-	panic("not implemented")
-}
-
-// SquashImage creates a new image with the diff of the specified image and
-// the specified parent. This new image contains only the layers from its
-// 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 (cs *ImageService) SquashImage(id, parent string) (string, error) {
-	panic("not implemented")
-}
-
-// ExportImage exports a list of images to the given output stream. The
-// exported images are archived into a tar when written to the output
-// stream. All images with the given tag and all versions containing
-// the same tag are exported. names is the set of tags to export, and
-// outStream is the writer which the images are written to.
-func (cs *ImageService) ExportImage(names []string, outStream io.Writer) error {
-	panic("not implemented")
-}
-
-// ImageDelete deletes the image referenced by the given imageRef from this
-// daemon. The given imageRef can be an image ID, ID prefix, or a repository
-// reference (with an optional tag or digest, defaulting to the tag name
-// "latest"). There is differing behavior depending on whether the given
-// imageRef is a repository reference or not.
-//
-// If the given imageRef is a repository reference then that repository
-// reference will be removed. However, if there exists any containers which
-// were created using the same image reference then the repository reference
-// cannot be removed unless either there are other repository references to the
-// same image or force is true. Following removal of the repository reference,
-// the referenced image itself will attempt to be deleted as described below
-// but quietly, meaning any image delete conflicts will cause the image to not
-// be deleted and the conflict will not be reported.
-//
-// There may be conflicts preventing deletion of an image and these conflicts
-// are divided into two categories grouped by their severity:
-//
-// Hard Conflict:
-//   - a pull or build using the image.
-//   - any descendant image.
-//   - any running container using the image.
-//
-// Soft Conflict:
-//   - any stopped container using the image.
-//   - any repository tag or digest references to the image.
-//
-// The image cannot be removed if there are any hard conflicts and can be
-// removed if there are soft conflicts only if force is true.
-//
-// If prune is true, ancestor images will each attempt to be deleted quietly,
-// meaning any delete conflicts will cause the image to not be deleted and the
-// conflict will not be reported.
-func (cs *ImageService) ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error) {
-	panic("not implemented")
-}
-
-// ImageHistory returns a slice of ImageHistory structures for the specified
-// image name by walking the image lineage.
-func (cs *ImageService) ImageHistory(name string) ([]*imagetype.HistoryResponseItem, error) {
-	panic("not implemented")
-}
-
-// ImagesPrune removes unused images
-func (cs *ImageService) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) {
-	panic("not implemented")
-}
-
-// ImportImage imports an image, getting the archived layer data either from
-// inConfig (if src is "-"), or from a URI specified in src. Progress output is
-// written to outStream. Repository and tag names can optionally be given in
-// the repo and tag arguments, respectively.
-func (cs *ImageService) ImportImage(src string, repository string, platform *ocispec.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
-	panic("not implemented")
-}
-
-// LoadImage uploads a set of images into the repository. This is the
-// complement of ExportImage.  The input stream is an uncompressed tar
-// ball containing images and metadata.
-func (cs *ImageService) LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error {
-	panic("not implemented")
-}
-
-// PushImage initiates a push operation on the repository named localName.
-func (cs *ImageService) PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
-	panic("not implemented")
-}
-
-// SearchRegistryForImages queries the registry for images matching
-// term. authConfig is used to login.
-//
-// TODO: this could be implemented in a registry service instead of the image
-// service.
-func (cs *ImageService) SearchRegistryForImages(ctx context.Context, searchFilters filters.Args, term string, limit int, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registrytypes.SearchResults, error) {
-	panic("not implemented")
-}
-
-// TagImage creates the tag specified by newTag, pointing to the image named
-// imageName (alternatively, imageName can also be an image ID).
-func (cs *ImageService) TagImage(imageName, repository, tag string) (string, error) {
-	panic("not implemented")
-}
-
-// GetRepository returns a repository from the registry.
-func (cs *ImageService) GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, error) {
-	panic("not implemented")
-}
-
-// ImageDiskUsage returns information about image data disk usage.
-func (cs *ImageService) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) {
+// ReleaseLayer releases a layer allowing it to be removed
+// called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport()
+func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error {
 	panic("not implemented")
 }
 
 // LayerDiskUsage returns the number of bytes used by layer stores
 // called from disk_usage.go
-func (cs *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) {
-	panic("not implemented")
-}
-
-// ReleaseLayer releases a layer allowing it to be removed
-// called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport()
-func (cs *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error {
+func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) {
 	panic("not implemented")
 }
 
-// CommitImage creates a new image from a commit config.
-func (cs *ImageService) CommitImage(c backend.CommitConfig) (image.ID, error) {
+// ImageDiskUsage returns information about image data disk usage.
+func (i *ImageService) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) {
 	panic("not implemented")
 }
 
-// GetImage returns an image corresponding to the image referred to by refOrID.
-func (cs *ImageService) GetImage(refOrID string, platform *ocispec.Platform) (retImg *image.Image, retErr error) {
+// UpdateConfig values
+//
+// called from reload.go
+func (i *ImageService) UpdateConfig(maxDownloads, maxUploads int) {
 	panic("not implemented")
 }
 
-// CreateLayer creates a filesystem layer for a container.
-// called from create.go
-// TODO: accept an opt struct instead of container?
-func (cs *ImageService) CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error) {
+// GetLayerFolders returns the layer folders from an image RootFS.
+func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error) {
 	panic("not implemented")
 }
 
-// DistributionServices return services controlling daemon image storage.
-func (cs *ImageService) DistributionServices() images.DistributionServices {
-	return images.DistributionServices{}
-}
-
-// CountImages returns the number of images stored by ImageService
-// called from info.go
-func (cs *ImageService) CountImages() int {
-	imgs, err := cs.client.ListImages(context.TODO())
-	if err != nil {
-		return 0
-	}
-
-	return len(imgs)
-}
-
-// LayerStoreStatus returns the status for each layer store
-// called from info.go
-func (cs *ImageService) LayerStoreStatus() [][2]string {
-	return [][2]string{}
-}
-
 // GetContainerLayerSize returns the real size & virtual size of the container.
-func (cs *ImageService) GetContainerLayerSize(containerID string) (int64, int64) {
-	panic("not implemented")
-}
-
-// UpdateConfig values
-//
-// called from reload.go
-func (cs *ImageService) UpdateConfig(maxDownloads, maxUploads int) {
-	panic("not implemented")
-}
-
-// Children returns the children image.IDs for a parent image.
-// called from list.go to filter containers
-// TODO: refactor to expose an ancestry for image.ID?
-func (cs *ImageService) Children(id image.ID) []image.ID {
+func (i *ImageService) GetContainerLayerSize(containerID string) (int64, int64) {
 	panic("not implemented")
 }

+ 0 - 88
daemon/images/images.go → daemon/images/image_list.go

@@ -2,12 +2,8 @@ package images // import "github.com/docker/docker/daemon/images"
 
 import (
 	"context"
-	"encoding/json"
 	"fmt"
 	"sort"
-	"time"
-
-	"github.com/pkg/errors"
 
 	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
@@ -247,90 +243,6 @@ func (i *ImageService) Images(_ context.Context, opts types.ImageListOptions) ([
 	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 {
 	summary := &types.ImageSummary{
 		ParentID:    image.Parent.String(),

+ 95 - 0
daemon/images/image_squash.go

@@ -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
+}

+ 6 - 5
daemon/images/service.go

@@ -24,10 +24,11 @@ import (
 )
 
 type containerStore interface {
-	// used by image delete
+	// First is used by image delete
 	First(container.StoreFilter) *container.Container
-	// used by image prune, and image list
+	// List is used by image prune, and image list
 	List() []*container.Container
+	// Get is used by CommitBuildStep
 	// TODO: remove, only used for CommitBuildStep
 	Get(string) *container.Container
 }
@@ -144,7 +145,7 @@ func (i *ImageService) CreateLayer(container *container.Container, initFunc laye
 }
 
 // GetLayerByID returns a layer by ID
-// called from daemon.go Daemon.restore(), and Daemon.containerExport()
+// called from daemon.go Daemon.restore(), and Daemon.containerExport().
 func (i *ImageService) GetLayerByID(cid string) (layer.RWLayer, error) {
 	return i.layerStore.GetRWLayer(cid)
 }
@@ -182,8 +183,8 @@ func (i *ImageService) GraphDriverName() string {
 // ReleaseLayer releases a layer allowing it to be removed
 // called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport()
 func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error {
-	metadata, err := i.layerStore.ReleaseRWLayer(rwlayer)
-	layer.LogReleaseMetadata(metadata)
+	metaData, err := i.layerStore.ReleaseRWLayer(rwlayer)
+	layer.LogReleaseMetadata(metaData)
 	if err != nil && !errors.Is(err, layer.ErrMountDoesNotExist) && !errors.Is(err, os.ErrNotExist) {
 		return errors.Wrapf(err, "driver %q failed to remove root filesystem",
 			i.layerStore.DriverName())