소스 검색

Move the inspect code away from the image service

The LoopkupImage method is only used by the inspect image route and
returns an api/type struct. The depenency to api/types of the
daemon/images package is wrong, the daemon doesn't need to know about
the api types.

Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
Djordje Lukic 3 년 전
부모
커밋
b4ffe3a9fb

+ 2 - 1
api/server/router/image/backend.go

@@ -8,6 +8,7 @@ import (
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/image"
 	"github.com/docker/docker/api/types/registry"
+	dockerimage "github.com/docker/docker/image"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
 )
 
@@ -23,7 +24,7 @@ type imageBackend interface {
 	ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)
 	ImageHistory(imageName string) ([]*image.HistoryResponseItem, error)
 	Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error)
-	LookupImage(name string) (*types.ImageInspect, error)
+	GetImage(refOrID string, platform *specs.Platform) (retImg *dockerimage.Image, retErr error)
 	TagImage(imageName, repository, tag string) (string, error)
 	ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error)
 }

+ 15 - 4
api/server/router/image/image.go

@@ -2,17 +2,28 @@ package image // import "github.com/docker/docker/api/server/router/image"
 
 import (
 	"github.com/docker/docker/api/server/router"
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/layer"
+	"github.com/docker/docker/reference"
 )
 
 // imageRouter is a router to talk with the image controller
 type imageRouter struct {
-	backend Backend
-	routes  []router.Route
+	backend          Backend
+	referenceBackend reference.Store
+	imageStore       image.Store
+	layerStore       layer.Store
+	routes           []router.Route
 }
 
 // NewRouter initializes a new image router
-func NewRouter(backend Backend) router.Router {
-	r := &imageRouter{backend: backend}
+func NewRouter(backend Backend, referenceBackend reference.Store, imageStore image.Store, layerStore layer.Store) router.Router {
+	r := &imageRouter{
+		backend:          backend,
+		referenceBackend: referenceBackend,
+		imageStore:       imageStore,
+		layerStore:       layerStore,
+	}
 	r.initRoutes()
 	return r
 }

+ 89 - 1
api/server/router/image/image_routes.go

@@ -7,13 +7,17 @@ import (
 	"net/http"
 	"strconv"
 	"strings"
+	"time"
 
 	"github.com/containerd/containerd/platforms"
+	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/errdefs"
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/streamformatter"
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -200,7 +204,12 @@ func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r
 }
 
 func (s *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
-	imageInspect, err := s.backend.LookupImage(vars["name"])
+	image, err := s.backend.GetImage(vars["name"], nil)
+	if err != nil {
+		return err
+	}
+
+	imageInspect, err := s.toImageInspect(image)
 	if err != nil {
 		return err
 	}
@@ -208,6 +217,85 @@ func (s *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter
 	return httputils.WriteJSON(w, http.StatusOK, imageInspect)
 }
 
+func (s *imageRouter) toImageInspect(img *image.Image) (*types.ImageInspect, error) {
+	refs := s.referenceBackend.References(img.ID().Digest())
+	repoTags := []string{}
+	repoDigests := []string{}
+	for _, ref := range refs {
+		switch ref.(type) {
+		case reference.NamedTagged:
+			repoTags = append(repoTags, reference.FamiliarString(ref))
+		case reference.Canonical:
+			repoDigests = append(repoDigests, reference.FamiliarString(ref))
+		}
+	}
+
+	var size int64
+	var layerMetadata map[string]string
+	layerID := img.RootFS.ChainID()
+	if layerID != "" {
+		l, err := s.layerStore.Get(layerID)
+		if err != nil {
+			return nil, err
+		}
+		defer layer.ReleaseAndLog(s.layerStore, l)
+		size = l.Size()
+		layerMetadata, err = l.Metadata()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	comment := img.Comment
+	if len(comment) == 0 && len(img.History) > 0 {
+		comment = img.History[len(img.History)-1].Comment
+	}
+
+	lastUpdated, err := s.imageStore.GetLastUpdated(img.ID())
+	if err != nil {
+		return nil, err
+	}
+
+	return &types.ImageInspect{
+		ID:              img.ID().String(),
+		RepoTags:        repoTags,
+		RepoDigests:     repoDigests,
+		Parent:          img.Parent.String(),
+		Comment:         comment,
+		Created:         img.Created.Format(time.RFC3339Nano),
+		Container:       img.Container,
+		ContainerConfig: &img.ContainerConfig,
+		DockerVersion:   img.DockerVersion,
+		Author:          img.Author,
+		Config:          img.Config,
+		Architecture:    img.Architecture,
+		Variant:         img.Variant,
+		Os:              img.OperatingSystem(),
+		OsVersion:       img.OSVersion,
+		Size:            size,
+		VirtualSize:     size, // TODO: field unused, deprecate
+		GraphDriver: types.GraphDriverData{
+			Name: s.layerStore.DriverName(),
+			Data: layerMetadata,
+		},
+		RootFS: rootFSToAPIType(img.RootFS),
+		Metadata: types.ImageMetadata{
+			LastTagTime: lastUpdated,
+		},
+	}, nil
+}
+
+func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
+	var layers []string
+	for _, l := range rootfs.DiffIDs {
+		layers = append(layers, l.String())
+	}
+	return types.RootFS{
+		Type:   rootfs.Type,
+		Layers: layers,
+	}
+}
+
 func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := httputils.ParseForm(r); err != nil {
 		return err

+ 6 - 1
cmd/dockerd/daemon.go

@@ -529,7 +529,12 @@ func initRouter(opts routerOptions) {
 		// we need to add the checkpoint router before the container router or the DELETE gets masked
 		checkpointrouter.NewRouter(opts.daemon, decoder),
 		container.NewRouter(opts.daemon, decoder, opts.daemon.RawSysInfo().CgroupUnified),
-		image.NewRouter(opts.daemon.ImageService()),
+		image.NewRouter(
+			opts.daemon.ImageService(),
+			opts.daemon.ReferenceStore,
+			opts.daemon.ImageService().DistributionServices().ImageStore,
+			opts.daemon.ImageService().DistributionServices().LayerStore,
+		),
 		systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildkit, opts.features),
 		volume.NewRouter(opts.daemon.VolumesService(), opts.cluster),
 		build.NewRouter(opts.buildBackend, opts.daemon, opts.features),

+ 2 - 1
daemon/cluster/executor/backend.go

@@ -18,6 +18,7 @@ import (
 	containerpkg "github.com/docker/docker/container"
 	clustertypes "github.com/docker/docker/daemon/cluster/provider"
 	networkSettings "github.com/docker/docker/daemon/network"
+	"github.com/docker/docker/image"
 	"github.com/docker/docker/libnetwork"
 	"github.com/docker/docker/libnetwork/cluster"
 	networktypes "github.com/docker/docker/libnetwork/types"
@@ -74,5 +75,5 @@ type VolumeBackend interface {
 type ImageBackend interface {
 	PullImage(ctx context.Context, image, tag string, platform *specs.Platform, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
 	GetRepository(context.Context, reference.Named, *types.AuthConfig) (distribution.Repository, error)
-	LookupImage(name string) (*types.ImageInspect, error)
+	GetImage(refOrID string, platform *specs.Platform) (retImg *image.Image, retErr error)
 }

+ 1 - 1
daemon/cluster/executor/container/adapter.go

@@ -74,7 +74,7 @@ func (c *containerAdapter) pullImage(ctx context.Context) error {
 	named, err := reference.ParseNormalizedNamed(spec.Image)
 	if err == nil {
 		if _, ok := named.(reference.Canonical); ok {
-			_, err := c.imageBackend.LookupImage(spec.Image)
+			_, err := c.imageBackend.GetImage(spec.Image, nil)
 			if err == nil {
 				return nil
 			}

+ 2 - 0
daemon/daemon.go

@@ -105,6 +105,7 @@ type Daemon struct {
 	cluster               Cluster
 	genericResources      []swarm.GenericResource
 	metricsPluginListener net.Listener
+	ReferenceStore        refstore.Store
 
 	machineMemory uint64
 
@@ -999,6 +1000,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
 	if err != nil {
 		return nil, fmt.Errorf("Couldn't create reference store repository: %s", err)
 	}
+	d.ReferenceStore = rs
 
 	distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution"))
 	if err != nil {

+ 0 - 97
daemon/images/image_inspect.go

@@ -1,97 +0,0 @@
-package images // import "github.com/docker/docker/daemon/images"
-
-import (
-	"time"
-
-	"github.com/docker/distribution/reference"
-	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/image"
-	"github.com/docker/docker/layer"
-	"github.com/pkg/errors"
-)
-
-// LookupImage looks up an image by name and returns it as an ImageInspect
-// structure.
-func (i *ImageService) LookupImage(name string) (*types.ImageInspect, error) {
-	img, err := i.GetImage(name, nil)
-	if err != nil {
-		return nil, errors.Wrapf(err, "no such image: %s", name)
-	}
-
-	refs := i.referenceStore.References(img.ID().Digest())
-	repoTags := []string{}
-	repoDigests := []string{}
-	for _, ref := range refs {
-		switch ref.(type) {
-		case reference.NamedTagged:
-			repoTags = append(repoTags, reference.FamiliarString(ref))
-		case reference.Canonical:
-			repoDigests = append(repoDigests, reference.FamiliarString(ref))
-		}
-	}
-
-	var size int64
-	var layerMetadata map[string]string
-	layerID := img.RootFS.ChainID()
-	if layerID != "" {
-		l, err := i.layerStore.Get(layerID)
-		if err != nil {
-			return nil, err
-		}
-		defer layer.ReleaseAndLog(i.layerStore, l)
-		size = l.Size()
-		layerMetadata, err = l.Metadata()
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	comment := img.Comment
-	if len(comment) == 0 && len(img.History) > 0 {
-		comment = img.History[len(img.History)-1].Comment
-	}
-
-	lastUpdated, err := i.imageStore.GetLastUpdated(img.ID())
-	if err != nil {
-		return nil, err
-	}
-
-	return &types.ImageInspect{
-		ID:              img.ID().String(),
-		RepoTags:        repoTags,
-		RepoDigests:     repoDigests,
-		Parent:          img.Parent.String(),
-		Comment:         comment,
-		Created:         img.Created.Format(time.RFC3339Nano),
-		Container:       img.Container,
-		ContainerConfig: &img.ContainerConfig,
-		DockerVersion:   img.DockerVersion,
-		Author:          img.Author,
-		Config:          img.Config,
-		Architecture:    img.Architecture,
-		Variant:         img.Variant,
-		Os:              img.OperatingSystem(),
-		OsVersion:       img.OSVersion,
-		Size:            size,
-		VirtualSize:     size, // TODO: field unused, deprecate
-		GraphDriver: types.GraphDriverData{
-			Name: i.layerStore.DriverName(),
-			Data: layerMetadata,
-		},
-		RootFS: rootFSToAPIType(img.RootFS),
-		Metadata: types.ImageMetadata{
-			LastTagTime: lastUpdated,
-		},
-	}, nil
-}
-
-func rootFSToAPIType(rootfs *image.RootFS) types.RootFS {
-	var layers []string
-	for _, l := range rootfs.DiffIDs {
-		layers = append(layers, l.String())
-	}
-	return types.RootFS{
-		Type:   rootfs.Type,
-		Layers: layers,
-	}
-}