diff --git a/Makefile b/Makefile index a2a1e6ad82..aff2359cf9 100644 --- a/Makefile +++ b/Makefile @@ -143,4 +143,5 @@ swagger-gen: docker run --rm -v $(PWD):/work -w /work quay.io/goswagger/swagger \ generate model -m "types" -f api/swagger.yaml -t api/ --skip-validator \ -n Volume \ - -n Port + -n Port \ + -n ImageSummary diff --git a/api/server/router/image/backend.go b/api/server/router/image/backend.go index aed2ded22a..c5be1dfc14 100644 --- a/api/server/router/image/backend.go +++ b/api/server/router/image/backend.go @@ -25,7 +25,7 @@ type containerBackend interface { type imageBackend interface { ImageDelete(imageRef string, force, prune bool) ([]types.ImageDelete, error) ImageHistory(imageName string) ([]*types.ImageHistory, error) - Images(filterArgs string, filter string, all bool, withExtraAttrs bool) ([]*types.Image, error) + Images(filterArgs string, filter string, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) LookupImage(name string) (*types.ImageInspect, error) TagImage(imageName, repository, tag string) error ImagesPrune(config *types.ImagesPruneConfig) (*types.ImagesPruneReport, error) diff --git a/api/swagger.yaml b/api/swagger.yaml index 3e63fc2db0..897312b2f6 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -762,6 +762,58 @@ definitions: type: "string" BaseLayer: type: "string" + + ImageSummary: + type: "object" + required: + - Id + - ParentId + - RepoTags + - RepoDigests + - Created + - Size + - SharedSize + - VirtualSize + - Labels + - Containers + properties: + Id: + type: "string" + x-nullable: false + ParentId: + type: "string" + x-nullable: false + RepoTags: + type: "array" + x-nullable: false + items: + type: "string" + RepoDigests: + type: "array" + x-nullable: false + items: + type: "string" + Created: + type: "integer" + x-nullable: false + Size: + type: "integer" + x-nullable: false + SharedSize: + type: "integer" + x-nullable: false + VirtualSize: + type: "integer" + x-nullable: false + Labels: + type: "object" + x-nullable: false + additionalProperties: + type: "string" + Containers: + x-nullable: false + type: "integer" + AuthConfig: type: "object" properties: @@ -3829,37 +3881,11 @@ paths: - "application/json" responses: 200: - description: "no error" + description: "Summary image data for the images matching the query" schema: type: "array" items: - type: "object" - properties: - Id: - type: "string" - ParentId: - type: "string" - RepoTags: - type: "array" - items: - type: "string" - RepoDigests: - type: "array" - items: - type: "string" - Created: - type: "integer" - format: "int64" - Size: - type: "integer" - format: "int64" - VirtualSize: - type: "integer" - format: "int64" - Labels: - type: "object" - additionalProperties: - type: "string" + $ref: "#/definitions/ImageSummary" examples: application/json: - RepoTags: diff --git a/api/types/image_summary.go b/api/types/image_summary.go new file mode 100644 index 0000000000..e145b3dcfc --- /dev/null +++ b/api/types/image_summary.go @@ -0,0 +1,49 @@ +package types + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +// ImageSummary image summary +// swagger:model ImageSummary +type ImageSummary struct { + + // containers + // Required: true + Containers int64 `json:"Containers"` + + // created + // Required: true + Created int64 `json:"Created"` + + // Id + // Required: true + ID string `json:"Id"` + + // labels + // Required: true + Labels map[string]string `json:"Labels"` + + // parent Id + // Required: true + ParentID string `json:"ParentId"` + + // repo digests + // Required: true + RepoDigests []string `json:"RepoDigests"` + + // repo tags + // Required: true + RepoTags []string `json:"RepoTags"` + + // shared size + // Required: true + SharedSize int64 `json:"SharedSize"` + + // size + // Required: true + Size int64 `json:"Size"` + + // virtual size + // Required: true + VirtualSize int64 `json:"VirtualSize"` +} diff --git a/api/types/types.go b/api/types/types.go index 42df042394..afb3e8bc91 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -86,21 +86,6 @@ type ImageDelete struct { Deleted string `json:",omitempty"` } -// Image contains response of Remote API: -// GET "/images/json" -type Image struct { - ID string `json:"Id"` - ParentID string `json:"ParentId"` - RepoTags []string - RepoDigests []string - Created int64 - Size int64 - SharedSize int64 - VirtualSize int64 - Labels map[string]string - Containers int64 -} - // GraphDriverData returns Image's graph driver config info // when calling inspect command type GraphDriverData struct { @@ -516,7 +501,7 @@ type Runtime struct { // GET "/system/df" type DiskUsage struct { LayersSize int64 - Images []*Image + Images []*ImageSummary Containers []*Container Volumes []*Volume } diff --git a/cli/command/formatter/disk_usage.go b/cli/command/formatter/disk_usage.go index acb210dbff..6f97d3b0f9 100644 --- a/cli/command/formatter/disk_usage.go +++ b/cli/command/formatter/disk_usage.go @@ -31,7 +31,7 @@ type DiskUsageContext struct { Context Verbose bool LayersSize int64 - Images []*types.Image + Images []*types.ImageSummary Containers []*types.Container Volumes []*types.Volume } @@ -155,7 +155,7 @@ func (ctx *DiskUsageContext) Write() { type diskUsageImagesContext struct { HeaderContext totalSize int64 - images []*types.Image + images []*types.ImageSummary } func (c *diskUsageImagesContext) Type() string { diff --git a/cli/command/formatter/image.go b/cli/command/formatter/image.go index 1e71bda3aa..594b2f3926 100644 --- a/cli/command/formatter/image.go +++ b/cli/command/formatter/image.go @@ -26,7 +26,7 @@ type ImageContext struct { Digest bool } -func isDangling(image types.Image) bool { +func isDangling(image types.ImageSummary) bool { return len(image.RepoTags) == 1 && image.RepoTags[0] == ":" && len(image.RepoDigests) == 1 && image.RepoDigests[0] == "@" } @@ -72,14 +72,14 @@ virtual_size: {{.Size}} } // ImageWrite writes the formatter images using the ImageContext -func ImageWrite(ctx ImageContext, images []types.Image) error { +func ImageWrite(ctx ImageContext, images []types.ImageSummary) error { render := func(format func(subContext subContext) error) error { return imageFormat(ctx, images, format) } return ctx.Write(&imageContext{}, render) } -func imageFormat(ctx ImageContext, images []types.Image, format func(subContext subContext) error) error { +func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subContext subContext) error) error { for _, image := range images { images := []*imageContext{} if isDangling(image) { @@ -184,7 +184,7 @@ func imageFormat(ctx ImageContext, images []types.Image, format func(subContext type imageContext struct { HeaderContext trunc bool - i types.Image + i types.ImageSummary repo string tag string digest string diff --git a/cli/command/formatter/image_test.go b/cli/command/formatter/image_test.go index 73b3c3f2e9..ffe77f6677 100644 --- a/cli/command/formatter/image_test.go +++ b/cli/command/formatter/image_test.go @@ -24,36 +24,36 @@ func TestImageContext(t *testing.T) { call func() string }{ {imageContext{ - i: types.Image{ID: imageID}, + i: types.ImageSummary{ID: imageID}, trunc: true, }, stringid.TruncateID(imageID), imageIDHeader, ctx.ID}, {imageContext{ - i: types.Image{ID: imageID}, + i: types.ImageSummary{ID: imageID}, trunc: false, }, imageID, imageIDHeader, ctx.ID}, {imageContext{ - i: types.Image{Size: 10, VirtualSize: 10}, + i: types.ImageSummary{Size: 10, VirtualSize: 10}, trunc: true, }, "10 B", sizeHeader, ctx.Size}, {imageContext{ - i: types.Image{Created: unix}, + i: types.ImageSummary{Created: unix}, trunc: true, }, time.Unix(unix, 0).String(), createdAtHeader, ctx.CreatedAt}, // FIXME // {imageContext{ - // i: types.Image{Created: unix}, + // i: types.ImageSummary{Created: unix}, // trunc: true, // }, units.HumanDuration(time.Unix(unix, 0)), createdSinceHeader, ctx.CreatedSince}, {imageContext{ - i: types.Image{}, + i: types.ImageSummary{}, repo: "busybox", }, "busybox", repositoryHeader, ctx.Repository}, {imageContext{ - i: types.Image{}, + i: types.ImageSummary{}, tag: "latest", }, "latest", tagHeader, ctx.Tag}, {imageContext{ - i: types.Image{}, + i: types.ImageSummary{}, digest: "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", }, "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", digestHeader, ctx.Digest}, } @@ -262,7 +262,7 @@ image_id: imageID3 } for _, testcase := range cases { - images := []types.Image{ + images := []types.ImageSummary{ {ID: "imageID1", RepoTags: []string{"image:tag1"}, RepoDigests: []string{"image@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf"}, Created: unixTime}, {ID: "imageID2", RepoTags: []string{"image:tag2"}, Created: unixTime}, {ID: "imageID3", RepoTags: []string{":"}, RepoDigests: []string{"@"}, Created: unixTime}, @@ -280,7 +280,7 @@ image_id: imageID3 func TestImageContextWriteWithNoImage(t *testing.T) { out := bytes.NewBufferString("") - images := []types.Image{} + images := []types.ImageSummary{} contexts := []struct { context ImageContext diff --git a/client/image_list.go b/client/image_list.go index 00f27dc0c9..6ebb460541 100644 --- a/client/image_list.go +++ b/client/image_list.go @@ -10,8 +10,8 @@ import ( ) // ImageList returns a list of images in the docker host. -func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error) { - var images []types.Image +func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) { + var images []types.ImageSummary query := url.Values{} if options.Filters.Len() > 0 { diff --git a/client/image_list_test.go b/client/image_list_test.go index 2a52279081..1ea6f1f05a 100644 --- a/client/image_list_test.go +++ b/client/image_list_test.go @@ -93,7 +93,7 @@ func TestImageList(t *testing.T) { return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual) } } - content, err := json.Marshal([]types.Image{ + content, err := json.Marshal([]types.ImageSummary{ { ID: "image_id2", }, diff --git a/client/interface.go b/client/interface.go index de06b848ae..4d450d8316 100644 --- a/client/interface.go +++ b/client/interface.go @@ -71,7 +71,7 @@ type ImageAPIClient interface { ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error) - ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error) + ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) diff --git a/daemon/images.go b/daemon/images.go index a127b00264..aa66b0cc1d 100644 --- a/daemon/images.go +++ b/daemon/images.go @@ -22,7 +22,7 @@ var acceptedImageFilterTags = map[string]bool{ // byCreated is a temporary type used to sort a list of images by creation // time. -type byCreated []*types.Image +type byCreated []*types.ImageSummary func (r byCreated) Len() int { return len(r) } func (r byCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] } @@ -38,7 +38,7 @@ func (daemon *Daemon) Map() map[image.ID]*image.Image { // filter is a shell glob string applied to repository names. The argument // named all controls whether all images in the graph are filtered, or just // the heads. -func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs bool) ([]*types.Image, error) { +func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) { var ( allImages map[image.ID]*image.Image err error @@ -83,8 +83,8 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs return nil, err } - images := []*types.Image{} - var imagesMap map[*image.Image]*types.Image + images := []*types.ImageSummary{} + var imagesMap map[*image.Image]*types.ImageSummary var layerRefs map[layer.ChainID]int var allLayers map[layer.ChainID]layer.Layer var allContainers []*container.Container @@ -181,7 +181,7 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs if imagesMap == nil { allContainers = daemon.List() allLayers = daemon.layerStore.Map() - imagesMap = make(map[*image.Image]*types.Image) + imagesMap = make(map[*image.Image]*types.ImageSummary) layerRefs = make(map[layer.ChainID]int) } @@ -241,8 +241,8 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool, withExtraAttrs return images, nil } -func newImage(image *image.Image, virtualSize int64) *types.Image { - newImage := new(types.Image) +func newImage(image *image.Image, virtualSize int64) *types.ImageSummary { + newImage := new(types.ImageSummary) newImage.ParentID = image.Parent.String() newImage.ID = image.ID().String() newImage.Created = image.Created.Unix() diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index 75ed2b0188..cde8a7765c 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -18,7 +18,7 @@ func (s *DockerSuite) TestAPIImagesFilter(c *check.C) { for _, n := range []string{name, name2, name3} { dockerCmd(c, "tag", "busybox", n) } - type image types.Image + type image types.ImageSummary getImages := func(filter string) []image { v := url.Values{} v.Set("filter", filter)