diff options
-rw-r--r-- | OWNERS | 2 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_push.go | 1 | ||||
-rw-r--r-- | pkg/api/handlers/types.go | 16 | ||||
-rw-r--r-- | pkg/domain/entities/images.go | 22 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images_list.go | 2 | ||||
-rw-r--r-- | test/apiv2/rest_api/test_rest_v2_0_0.py | 96 |
6 files changed, 102 insertions, 37 deletions
@@ -8,6 +8,7 @@ approvers: - TomSweeneyRedHat - vrothberg - umohnani8 + - Luap99 reviewers: - baude - edsantiago @@ -20,3 +21,4 @@ reviewers: - ashley-cui - QiWang19 - umohnani8 + - Luap99 diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go index 12593a68c..0f3da53e8 100644 --- a/pkg/api/handlers/compat/images_push.go +++ b/pkg/api/handlers/compat/images_push.go @@ -81,5 +81,4 @@ func PushImage(w http.ResponseWriter, r *http.Request) { } utils.WriteResponse(w, http.StatusOK, "") - } diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 40cf16807..25e7640b6 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -145,13 +145,14 @@ type PodCreateConfig struct { Share string `json:"share"` } +// HistoryResponse provides details on image layers type HistoryResponse struct { - ID string `json:"Id"` - Created int64 `json:"Created"` - CreatedBy string `json:"CreatedBy"` - Tags []string `json:"Tags"` - Size int64 `json:"Size"` - Comment string `json:"Comment"` + ID string `json:"Id"` + Created int64 + CreatedBy string + Tags []string + Size int64 + Comment string } type ImageLayer struct{} @@ -213,6 +214,7 @@ func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) { ID: l.ID(), ParentId: l.Parent, RepoTags: repoTags, + RepoDigests: digests, Created: l.Created().Unix(), Size: int64(*size), SharedSize: 0, @@ -223,7 +225,6 @@ func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) { Dangling: l.Dangling(), Names: l.Names(), Digest: string(l.Digest()), - Digests: digests, ConfigDigest: string(l.ConfigDigest), History: l.NamesHistory(), } @@ -329,7 +330,6 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI dockerImageInspect.Parent = d.Parent.String() } return &ImageInspect{dockerImageInspect}, nil - } // portsToPortSet converts libpods exposed ports to dockers structs diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go index ab545d882..81f12bff7 100644 --- a/pkg/domain/entities/images.go +++ b/pkg/domain/entities/images.go @@ -51,22 +51,22 @@ func (i *Image) Id() string { // nolint } type ImageSummary struct { - ID string `json:"Id"` - ParentId string // nolint - RepoTags []string `json:",omitempty"` + ID string `json:"Id"` + ParentId string // nolint + RepoTags []string + RepoDigests []string Created int64 - Size int64 `json:",omitempty"` - SharedSize int `json:",omitempty"` - VirtualSize int64 `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Containers int `json:",omitempty"` - ReadOnly bool `json:",omitempty"` - Dangling bool `json:",omitempty"` + Size int64 + SharedSize int + VirtualSize int64 + Labels map[string]string + Containers int + ReadOnly bool `json:",omitempty"` + Dangling bool `json:",omitempty"` // Podman extensions Names []string `json:",omitempty"` Digest string `json:",omitempty"` - Digests []string `json:",omitempty"` ConfigDigest string `json:",omitempty"` History []string `json:",omitempty"` } diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go index 281b04294..20ae0d0f6 100644 --- a/pkg/domain/infra/abi/images_list.go +++ b/pkg/domain/infra/abi/images_list.go @@ -35,7 +35,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) Created: img.Created().Unix(), Dangling: img.Dangling(), Digest: string(img.Digest()), - Digests: digests, + RepoDigests: digests, History: img.NamesHistory(), Names: img.Names(), ParentId: img.Parent, diff --git a/test/apiv2/rest_api/test_rest_v2_0_0.py b/test/apiv2/rest_api/test_rest_v2_0_0.py index 52348d4f4..dc92a2966 100644 --- a/test/apiv2/rest_api/test_rest_v2_0_0.py +++ b/test/apiv2/rest_api/test_rest_v2_0_0.py @@ -179,15 +179,19 @@ class TestApi(unittest.TestCase): "NetworkDisabled": False, # FIXME adding these 2 lines cause: (This is sampled from docker-py) # "network already exists","message":"container - # 01306e499df5441560d70071a54342611e422a94de20865add50a9565fd79fb9 is already connected to CNI network \"TestDefaultNetwork\": network already exists" + # 01306e499df5441560d70071a54342611e422a94de20865add50a9565fd79fb9 is already connected to CNI + # network \"TestDefaultNetwork\": network already exists" # "HostConfig": {"NetworkMode": "TestDefaultNetwork"}, # "NetworkingConfig": {"EndpointsConfig": {"TestDefaultNetwork": None}}, # FIXME These two lines cause: - # CNI network \"TestNetwork\" not found","message":"error configuring network namespace for container 369ddfa7d3211ebf1fbd5ddbff91bd33fa948858cea2985c133d6b6507546dff: CNI network \"TestNetwork\" not found" + # CNI network \"TestNetwork\" not found","message":"error configuring network namespace for container + # 369ddfa7d3211ebf1fbd5ddbff91bd33fa948858cea2985c133d6b6507546dff: CNI network \"TestNetwork\" not + # found" # "HostConfig": {"NetworkMode": "TestNetwork"}, # "NetworkingConfig": {"EndpointsConfig": {"TestNetwork": None}}, # FIXME no networking defined cause: (note this error is from the container inspect below) - # "internal libpod error","message":"network inspection mismatch: asked to join 2 CNI network(s) [TestDefaultNetwork podman], but have information on 1 network(s): internal libpod error" + # "internal libpod error","message":"network inspection mismatch: asked to join 2 CNI network(s) [ + # TestDefaultNetwork podman], but have information on 1 network(s): internal libpod error" }, ) self.assertEqual(create.status_code, 201, create.text) @@ -255,23 +259,68 @@ class TestApi(unittest.TestCase): def test_commit(self): r = requests.post(_url(ctnr("/commit?container={}"))) self.assertEqual(r.status_code, 200, r.text) - validateObjectFields(r.text) - def test_images(self): - r = requests.get(_url("/images/json")) + obj = json.loads(r.content) + self.assertIsInstance(obj, dict) + self.assertIn("Id", obj) + + def test_images_compat(self): + r = requests.get(PODMAN_URL + "/v1.40/images/json") self.assertEqual(r.status_code, 200, r.text) - validateObjectFields(r.content) - def test_inspect_image(self): - r = requests.get(_url("/images/alpine/json")) + # See https://docs.docker.com/engine/api/v1.40/#operation/ImageList + required_keys = ( + "Id", + "ParentId", + "RepoTags", + "RepoDigests", + "Created", + "Size", + "SharedSize", + "VirtualSize", + "Labels", + "Containers", + ) + objs = json.loads(r.content) + self.assertIn(type(objs), (list,)) + for o in objs: + self.assertIsInstance(o, dict) + for k in required_keys: + self.assertIn(k, o) + + def test_inspect_image_compat(self): + r = requests.get(PODMAN_URL + "/v1.40/images/alpine/json") self.assertEqual(r.status_code, 200, r.text) - obj = validateObjectFields(r.content) + + # See https://docs.docker.com/engine/api/v1.40/#operation/ImageInspect + required_keys = ( + "Id", + "Parent", + "Comment", + "Created", + "Container", + "DockerVersion", + "Author", + "Architecture", + "Os", + "Size", + "VirtualSize", + "GraphDriver", + "RootFS", + "Metadata", + ) + + obj = json.loads(r.content) + self.assertIn(type(obj), (dict,)) + for k in required_keys: + self.assertIn(k, obj) _ = parse(obj["Created"]) - def test_delete_image(self): - r = requests.delete(_url("/images/alpine?force=true")) + def test_delete_image_compat(self): + r = requests.delete(PODMAN_URL + "/v1.40/images/alpine?force=true") self.assertEqual(r.status_code, 200, r.text) - json.loads(r.text) + obj = json.loads(r.content) + self.assertIn(type(obj), (list,)) def test_pull(self): r = requests.post(_url("/images/pull?reference=alpine"), timeout=15) @@ -295,12 +344,13 @@ class TestApi(unittest.TestCase): self.assertTrue(keys["images"], "Expected to find images stanza") self.assertTrue(keys["stream"], "Expected to find stream progress stanza's") - def test_search(self): + def test_search_compat(self): # Had issues with this test hanging when repositories not happy def do_search(): - r = requests.get(_url("/images/search?term=alpine"), timeout=5) + r = requests.get(PODMAN_URL + "/v1.40/images/search?term=alpine", timeout=5) self.assertEqual(r.status_code, 200, r.text) - json.loads(r.text) + objs = json.loads(r.text) + self.assertIn(type(objs), (list,)) search = Process(target=do_search) search.start() @@ -320,6 +370,20 @@ class TestApi(unittest.TestCase): r = requests.get(_url("/_ping")) self.assertEqual(r.status_code, 200, r.text) + def test_history_compat(self): + r = requests.get(PODMAN_URL + "/v1.40/images/alpine/history") + self.assertEqual(r.status_code, 200, r.text) + + # See https://docs.docker.com/engine/api/v1.40/#operation/ImageHistory + required_keys = ("Id", "Created", "CreatedBy", "Tags", "Size", "Comment") + + objs = json.loads(r.content) + self.assertIn(type(objs), (list,)) + for o in objs: + self.assertIsInstance(o, dict) + for k in required_keys: + self.assertIn(k, o) + if __name__ == "__main__": unittest.main() |