mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #43680 from rumpl/move-image-inspect
Move the inspect code away from the image service
This commit is contained in:
commit
0861539571
8 changed files with 117 additions and 106 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue