diff --git a/api/types/types.go b/api/types/types.go index 9ceabcc531..b1aefd7d15 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -96,6 +96,7 @@ type GraphDriverData struct { // GET "/images/{name:.*}/json" type ImageInspect struct { ID string `json:"Id"` + Tags []string Parent string Comment string Created string diff --git a/docs/reference/api/docker_remote_api.md b/docs/reference/api/docker_remote_api.md index f3b3e279a9..1e1ff2d5c8 100644 --- a/docs/reference/api/docker_remote_api.md +++ b/docs/reference/api/docker_remote_api.md @@ -81,6 +81,7 @@ This section lists each version from latest to oldest. Each listing includes a * `GET /volumes/(name)` get low-level information about a volume. * `DELETE /volumes/(name)`remove a volume with the specified name. * `VolumeDriver` has been moved from config to hostConfig to make the configuration portable. +* `GET /images/(name)/json` now returns information about tags of the image. ### v1.20 API changes diff --git a/docs/reference/api/docker_remote_api_v1.21.md b/docs/reference/api/docker_remote_api_v1.21.md index ee178cc7a1..6a9e37faf1 100644 --- a/docs/reference/api/docker_remote_api_v1.21.md +++ b/docs/reference/api/docker_remote_api_v1.21.md @@ -1433,7 +1433,7 @@ Return low-level information on the image `name` **Example request**: - GET /images/ubuntu/json HTTP/1.1 + GET /images/example/json HTTP/1.1 **Example response**: @@ -1441,34 +1441,90 @@ Return low-level information on the image `name` Content-Type: application/json { - "Created": "2013-03-23T22:24:18.818426-07:00", - "Container": "3d67245a8d72ecf13f33dffac9f79dcdf70f75acb84d308770391510e0c23ad0", - "ContainerConfig": - { - "Hostname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": false, - "AttachStderr": false, - "Tty": true, - "OpenStdin": true, - "StdinOnce": false, - "Env": null, - "Cmd": ["/bin/bash"], - "Dns": null, - "Image": "ubuntu", - "Labels": { - "com.example.vendor": "Acme", - "com.example.license": "GPL", - "com.example.version": "1.0" - }, - "Volumes": null, - "VolumesFrom": "", - "WorkingDir": "" - }, - "Id": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc", - "Parent": "27cf784147099545", - "Size": 6824592 + "Id" : "85f05633ddc1c50679be2b16a0479ab6f7637f8884e0cfe0f4d20e1ebb3d6e7c", + "Container" : "cb91e48a60d01f1e27028b4fc6819f4f290b3cf12496c8176ec714d0d390984a", + "Comment" : "", + "Os" : "linux", + "Architecture" : "amd64", + "Parent" : "91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c", + "ContainerConfig" : { + "Tty" : false, + "Hostname" : "e611e15f9c9d", + "Volumes" : null, + "Domainname" : "", + "AttachStdout" : false, + "PublishService" : "", + "AttachStdin" : false, + "OpenStdin" : false, + "StdinOnce" : false, + "NetworkDisabled" : false, + "OnBuild" : [], + "Image" : "91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c", + "User" : "", + "WorkingDir" : "", + "Entrypoint" : null, + "MacAddress" : "", + "AttachStderr" : false, + "Labels" : { + "com.example.license" : "GPL", + "com.example.version" : "1.0", + "com.example.vendor" : "Acme" + }, + "Env" : [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "ExposedPorts" : null, + "Cmd" : [ + "/bin/sh", + "-c", + "#(nop) LABEL com.example.vendor=Acme com.example.license=GPL com.example.version=1.0" + ] + }, + "DockerVersion" : "1.9.0-dev", + "VirtualSize" : 188359297, + "Size" : 0, + "Author" : "", + "Created" : "2015-09-10T08:30:53.26995814Z", + "GraphDriver" : { + "Name" : "aufs", + "Data" : null + }, + "Tags" : [ + "example:1.0", + "example:latest", + "example:stable" + ], + "Config" : { + "Image" : "91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c", + "NetworkDisabled" : false, + "OnBuild" : [], + "StdinOnce" : false, + "PublishService" : "", + "AttachStdin" : false, + "OpenStdin" : false, + "Domainname" : "", + "AttachStdout" : false, + "Tty" : false, + "Hostname" : "e611e15f9c9d", + "Volumes" : null, + "Cmd" : [ + "/bin/bash" + ], + "ExposedPorts" : null, + "Env" : [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Labels" : { + "com.example.vendor" : "Acme", + "com.example.version" : "1.0", + "com.example.license" : "GPL" + }, + "Entrypoint" : null, + "MacAddress" : "", + "AttachStderr" : false, + "WorkingDir" : "", + "User" : "" + } } Status Codes: diff --git a/graph/service.go b/graph/service.go index 1b347d0b5a..1ecc08ccab 100644 --- a/graph/service.go +++ b/graph/service.go @@ -8,6 +8,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" + "github.com/docker/docker/utils" ) // lookupRaw looks up an image by name in a TagStore and returns the raw JSON @@ -34,8 +35,22 @@ func (s *TagStore) Lookup(name string) (*types.ImageInspect, error) { return nil, fmt.Errorf("No such image: %s", name) } + var tags = make([]string, 0) + + s.Lock() + for repoName, repository := range s.Repositories { + for ref, id := range repository { + if id == image.ID { + imgRef := utils.ImageReference(repoName, ref) + tags = append(tags, imgRef) + } + } + } + s.Unlock() + imageInspect := &types.ImageInspect{ ID: image.ID, + Tags: tags, Parent: image.Parent, Comment: image.Comment, Created: image.Created.Format(time.RFC3339Nano), diff --git a/integration-cli/docker_api_inspect_test.go b/integration-cli/docker_api_inspect_test.go index 56f5eb052f..d6054a9bbf 100644 --- a/integration-cli/docker_api_inspect_test.go +++ b/integration-cli/docker_api_inspect_test.go @@ -6,6 +6,8 @@ import ( "net/http" "strings" + "github.com/docker/docker/api/types" + "github.com/docker/docker/pkg/stringutils" "github.com/go-check/check" ) @@ -111,3 +113,23 @@ func (s *DockerSuite) TestInspectApiContainerVolumeDriver(c *check.C) { c.Fatal("Api version 1.21 expected to include VolumeDriver in 'HostConfig'") } } + +func (s *DockerSuite) TestInspectApiImageResponse(c *check.C) { + dockerCmd(c, "tag", "busybox:latest", "busybox:mytag") + + endpoint := "/images/busybox/json" + status, body, err := sockRequest("GET", endpoint, nil) + + c.Assert(err, check.IsNil) + c.Assert(status, check.Equals, http.StatusOK) + + var imageJSON types.ImageInspect + if err = json.Unmarshal(body, &imageJSON); err != nil { + c.Fatalf("unable to unmarshal body for latest version: %v", err) + } + + c.Assert(len(imageJSON.Tags), check.Equals, 2) + + c.Assert(stringutils.InSlice(imageJSON.Tags, "busybox:latest"), check.Equals, true) + c.Assert(stringutils.InSlice(imageJSON.Tags, "busybox:mytag"), check.Equals, true) +}