mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
API, daemon/images: add ImageListOptions and pass context
This makes it easier to add more options to the backend without having to change the signature. While we're changing the signature, also adding a context.Context, which is not currently used, but probably should be at some point. Signed-off-by: Roman Volosatovs <roman.volosatovs@docker.com>
This commit is contained in:
parent
bf78e25fe5
commit
bf9c76f0a8
5 changed files with 50 additions and 31 deletions
|
@ -22,7 +22,7 @@ type Backend interface {
|
||||||
type imageBackend interface {
|
type imageBackend interface {
|
||||||
ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)
|
ImageDelete(imageRef string, force, prune bool) ([]types.ImageDeleteResponseItem, error)
|
||||||
ImageHistory(imageName string) ([]*image.HistoryResponseItem, error)
|
ImageHistory(imageName string) ([]*image.HistoryResponseItem, error)
|
||||||
Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error)
|
Images(ctx context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error)
|
||||||
LookupImage(name string) (*types.ImageInspect, error)
|
LookupImage(name string) (*types.ImageInspect, error)
|
||||||
TagImage(imageName, repository, tag string) (string, error)
|
TagImage(imageName, repository, tag string) (string, error)
|
||||||
ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error)
|
ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error)
|
||||||
|
|
|
@ -229,13 +229,17 @@ func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter,
|
||||||
|
|
||||||
version := httputils.VersionFromContext(ctx)
|
version := httputils.VersionFromContext(ctx)
|
||||||
if versions.LessThan(version, "1.41") {
|
if versions.LessThan(version, "1.41") {
|
||||||
|
// NOTE: filter is a shell glob string applied to repository names.
|
||||||
filterParam := r.Form.Get("filter")
|
filterParam := r.Form.Get("filter")
|
||||||
if filterParam != "" {
|
if filterParam != "" {
|
||||||
imageFilters.Add("reference", filterParam)
|
imageFilters.Add("reference", filterParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
images, err := s.backend.Images(imageFilters, httputils.BoolValue(r, "all"), false)
|
images, err := s.backend.Images(ctx, types.ImageListOptions{
|
||||||
|
Filters: imageFilters,
|
||||||
|
All: httputils.BoolValue(r, "all"),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,10 +235,20 @@ type ImageImportOptions struct {
|
||||||
Platform string // Platform is the target platform of the image
|
Platform string // Platform is the target platform of the image
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageListOptions holds parameters to filter the list of images with.
|
// ImageListOptions holds parameters to list images with.
|
||||||
type ImageListOptions struct {
|
type ImageListOptions struct {
|
||||||
All bool
|
// All controls whether all images in the graph are filtered, or just
|
||||||
|
// the heads.
|
||||||
|
All bool
|
||||||
|
|
||||||
|
// Filters is a JSON-encoded set of filter arguments.
|
||||||
Filters filters.Args
|
Filters filters.Args
|
||||||
|
|
||||||
|
// SharedSize indicates whether the shared size of images should be computed.
|
||||||
|
SharedSize bool
|
||||||
|
|
||||||
|
// ContainerCount indicates whether container count should be computed.
|
||||||
|
ContainerCount bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageLoadResponse returns information to the client about a load process.
|
// ImageLoadResponse returns information to the client about a load process.
|
||||||
|
|
|
@ -26,7 +26,11 @@ func (daemon *Daemon) SystemDiskUsage(ctx context.Context) (*types.DiskUsage, er
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all top images with extra attributes
|
// Get all top images with extra attributes
|
||||||
allImages, err := daemon.imageService.Images(filters.NewArgs(), false, true)
|
allImages, err := daemon.imageService.Images(ctx, types.ImageListOptions{
|
||||||
|
Filters: filters.NewArgs(),
|
||||||
|
SharedSize: true,
|
||||||
|
ContainerCount: true,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to retrieve image list: %v", err)
|
return nil, fmt.Errorf("failed to retrieve image list: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package images // import "github.com/docker/docker/daemon/images"
|
package images // import "github.com/docker/docker/daemon/images"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -10,7 +11,6 @@ import (
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/filters"
|
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/image"
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/layer"
|
"github.com/docker/docker/layer"
|
||||||
|
@ -38,22 +38,18 @@ func (i *ImageService) Map() map[image.ID]*image.Image {
|
||||||
return i.imageStore.Map()
|
return i.imageStore.Map()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Images returns a filtered list of images. filterArgs is a JSON-encoded set
|
// Images returns a filtered list of images.
|
||||||
// of filter arguments which will be interpreted by api/types/filters.
|
func (i *ImageService) Images(_ context.Context, opts types.ImageListOptions) ([]*types.ImageSummary, error) {
|
||||||
// filter is a shell glob string applied to repository names. The argument
|
if err := opts.Filters.Validate(acceptedImageFilterTags); err != nil {
|
||||||
// named all controls whether all images in the graph are filtered, or just
|
|
||||||
// the heads.
|
|
||||||
func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) {
|
|
||||||
if err := imageFilters.Validate(acceptedImageFilterTags); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var danglingOnly bool
|
var danglingOnly bool
|
||||||
if imageFilters.Contains("dangling") {
|
if opts.Filters.Contains("dangling") {
|
||||||
if imageFilters.ExactMatch("dangling", "true") {
|
if opts.Filters.ExactMatch("dangling", "true") {
|
||||||
danglingOnly = true
|
danglingOnly = true
|
||||||
} else if !imageFilters.ExactMatch("dangling", "false") {
|
} else if !opts.Filters.ExactMatch("dangling", "false") {
|
||||||
return nil, invalidFilter{"dangling", imageFilters.Get("dangling")}
|
return nil, invalidFilter{"dangling", opts.Filters.Get("dangling")}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +57,7 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
||||||
beforeFilter, sinceFilter *image.Image
|
beforeFilter, sinceFilter *image.Image
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
err = imageFilters.WalkValues("before", func(value string) error {
|
err = opts.Filters.WalkValues("before", func(value string) error {
|
||||||
beforeFilter, err = i.GetImage(value, nil)
|
beforeFilter, err = i.GetImage(value, nil)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -69,7 +65,7 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = imageFilters.WalkValues("since", func(value string) error {
|
err = opts.Filters.WalkValues("since", func(value string) error {
|
||||||
sinceFilter, err = i.GetImage(value, nil)
|
sinceFilter, err = i.GetImage(value, nil)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -102,13 +98,13 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if imageFilters.Contains("label") {
|
if opts.Filters.Contains("label") {
|
||||||
// Very old image that do not have image.Config (or even labels)
|
// Very old image that do not have image.Config (or even labels)
|
||||||
if img.Config == nil {
|
if img.Config == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// We are now sure image.Config is not nil
|
// We are now sure image.Config is not nil
|
||||||
if !imageFilters.MatchKVList("label", img.Config.Labels) {
|
if !opts.Filters.MatchKVList("label", img.Config.Labels) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,10 +138,10 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
||||||
summary := newImageSummary(img, size)
|
summary := newImageSummary(img, size)
|
||||||
|
|
||||||
for _, ref := range i.referenceStore.References(id.Digest()) {
|
for _, ref := range i.referenceStore.References(id.Digest()) {
|
||||||
if imageFilters.Contains("reference") {
|
if opts.Filters.Contains("reference") {
|
||||||
var found bool
|
var found bool
|
||||||
var matchErr error
|
var matchErr error
|
||||||
for _, pattern := range imageFilters.Get("reference") {
|
for _, pattern := range opts.Filters.Get("reference") {
|
||||||
found, matchErr = reference.FamiliarMatch(pattern, ref)
|
found, matchErr = reference.FamiliarMatch(pattern, ref)
|
||||||
if matchErr != nil {
|
if matchErr != nil {
|
||||||
return nil, matchErr
|
return nil, matchErr
|
||||||
|
@ -166,13 +162,13 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if summary.RepoDigests == nil && summary.RepoTags == nil {
|
if summary.RepoDigests == nil && summary.RepoTags == nil {
|
||||||
if all || len(i.imageStore.Children(id)) == 0 {
|
if opts.All || len(i.imageStore.Children(id)) == 0 {
|
||||||
|
|
||||||
if imageFilters.Contains("dangling") && !danglingOnly {
|
if opts.Filters.Contains("dangling") && !danglingOnly {
|
||||||
// dangling=false case, so dangling image is not needed
|
// dangling=false case, so dangling image is not needed
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if imageFilters.Contains("reference") { // skip images with no references if filtering by reference
|
if opts.Filters.Contains("reference") { // skip images with no references if filtering by reference
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
summary.RepoDigests = []string{"<none>@<none>"}
|
summary.RepoDigests = []string{"<none>@<none>"}
|
||||||
|
@ -184,10 +180,9 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if withExtraAttrs {
|
if opts.ContainerCount {
|
||||||
// Lazily init summaryMap and allContainers
|
// Lazily init allContainers.
|
||||||
if summaryMap == nil {
|
if allContainers == nil {
|
||||||
summaryMap = make(map[*image.Image]*types.ImageSummary, len(selectedImages))
|
|
||||||
allContainers = i.containers.List()
|
allContainers = i.containers.List()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,13 +195,19 @@ func (i *ImageService) Images(imageFilters filters.Args, all bool, withExtraAttr
|
||||||
}
|
}
|
||||||
// NOTE: By default, Containers is -1, or "not set"
|
// NOTE: By default, Containers is -1, or "not set"
|
||||||
summary.Containers = containers
|
summary.Containers = containers
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.ContainerCount || opts.SharedSize {
|
||||||
|
// Lazily init summaryMap.
|
||||||
|
if summaryMap == nil {
|
||||||
|
summaryMap = make(map[*image.Image]*types.ImageSummary, len(selectedImages))
|
||||||
|
}
|
||||||
summaryMap[img] = summary
|
summaryMap[img] = summary
|
||||||
}
|
}
|
||||||
summaries = append(summaries, summary)
|
summaries = append(summaries, summary)
|
||||||
}
|
}
|
||||||
|
|
||||||
if withExtraAttrs {
|
if opts.SharedSize {
|
||||||
allLayers := i.layerStore.Map()
|
allLayers := i.layerStore.Map()
|
||||||
layerRefs := make(map[layer.ChainID]int, len(allLayers))
|
layerRefs := make(map[layer.ChainID]int, len(allLayers))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue