mirror of
https://github.com/containers/podman.git
synced 2025-06-21 01:19:15 +08:00
Merge pull request #8587 from jwhonce/jira/RUN-1106-images
Jira RUN-1106 Image handlers updates
This commit is contained in:
@ -81,5 +81,4 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils.WriteResponse(w, http.StatusOK, "")
|
utils.WriteResponse(w, http.StatusOK, "")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -145,13 +145,14 @@ type PodCreateConfig struct {
|
|||||||
Share string `json:"share"`
|
Share string `json:"share"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HistoryResponse provides details on image layers
|
||||||
type HistoryResponse struct {
|
type HistoryResponse struct {
|
||||||
ID string `json:"Id"`
|
ID string `json:"Id"`
|
||||||
Created int64 `json:"Created"`
|
Created int64
|
||||||
CreatedBy string `json:"CreatedBy"`
|
CreatedBy string
|
||||||
Tags []string `json:"Tags"`
|
Tags []string
|
||||||
Size int64 `json:"Size"`
|
Size int64
|
||||||
Comment string `json:"Comment"`
|
Comment string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImageLayer struct{}
|
type ImageLayer struct{}
|
||||||
@ -213,6 +214,7 @@ func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) {
|
|||||||
ID: l.ID(),
|
ID: l.ID(),
|
||||||
ParentId: l.Parent,
|
ParentId: l.Parent,
|
||||||
RepoTags: repoTags,
|
RepoTags: repoTags,
|
||||||
|
RepoDigests: digests,
|
||||||
Created: l.Created().Unix(),
|
Created: l.Created().Unix(),
|
||||||
Size: int64(*size),
|
Size: int64(*size),
|
||||||
SharedSize: 0,
|
SharedSize: 0,
|
||||||
@ -223,7 +225,6 @@ func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) {
|
|||||||
Dangling: l.Dangling(),
|
Dangling: l.Dangling(),
|
||||||
Names: l.Names(),
|
Names: l.Names(),
|
||||||
Digest: string(l.Digest()),
|
Digest: string(l.Digest()),
|
||||||
Digests: digests,
|
|
||||||
ConfigDigest: string(l.ConfigDigest),
|
ConfigDigest: string(l.ConfigDigest),
|
||||||
History: l.NamesHistory(),
|
History: l.NamesHistory(),
|
||||||
}
|
}
|
||||||
@ -329,7 +330,6 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
|
|||||||
dockerImageInspect.Parent = d.Parent.String()
|
dockerImageInspect.Parent = d.Parent.String()
|
||||||
}
|
}
|
||||||
return &ImageInspect{dockerImageInspect}, nil
|
return &ImageInspect{dockerImageInspect}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// portsToPortSet converts libpods exposed ports to dockers structs
|
// portsToPortSet converts libpods exposed ports to dockers structs
|
||||||
|
@ -51,22 +51,22 @@ func (i *Image) Id() string { // nolint
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ImageSummary struct {
|
type ImageSummary struct {
|
||||||
ID string `json:"Id"`
|
ID string `json:"Id"`
|
||||||
ParentId string // nolint
|
ParentId string // nolint
|
||||||
RepoTags []string `json:",omitempty"`
|
RepoTags []string
|
||||||
|
RepoDigests []string
|
||||||
Created int64
|
Created int64
|
||||||
Size int64 `json:",omitempty"`
|
Size int64
|
||||||
SharedSize int `json:",omitempty"`
|
SharedSize int
|
||||||
VirtualSize int64 `json:",omitempty"`
|
VirtualSize int64
|
||||||
Labels map[string]string `json:",omitempty"`
|
Labels map[string]string
|
||||||
Containers int `json:",omitempty"`
|
Containers int
|
||||||
ReadOnly bool `json:",omitempty"`
|
ReadOnly bool `json:",omitempty"`
|
||||||
Dangling bool `json:",omitempty"`
|
Dangling bool `json:",omitempty"`
|
||||||
|
|
||||||
// Podman extensions
|
// Podman extensions
|
||||||
Names []string `json:",omitempty"`
|
Names []string `json:",omitempty"`
|
||||||
Digest string `json:",omitempty"`
|
Digest string `json:",omitempty"`
|
||||||
Digests []string `json:",omitempty"`
|
|
||||||
ConfigDigest string `json:",omitempty"`
|
ConfigDigest string `json:",omitempty"`
|
||||||
History []string `json:",omitempty"`
|
History []string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
|
|||||||
Created: img.Created().Unix(),
|
Created: img.Created().Unix(),
|
||||||
Dangling: img.Dangling(),
|
Dangling: img.Dangling(),
|
||||||
Digest: string(img.Digest()),
|
Digest: string(img.Digest()),
|
||||||
Digests: digests,
|
RepoDigests: digests,
|
||||||
History: img.NamesHistory(),
|
History: img.NamesHistory(),
|
||||||
Names: img.Names(),
|
Names: img.Names(),
|
||||||
ParentId: img.Parent,
|
ParentId: img.Parent,
|
||||||
|
@ -179,15 +179,19 @@ class TestApi(unittest.TestCase):
|
|||||||
"NetworkDisabled": False,
|
"NetworkDisabled": False,
|
||||||
# FIXME adding these 2 lines cause: (This is sampled from docker-py)
|
# FIXME adding these 2 lines cause: (This is sampled from docker-py)
|
||||||
# "network already exists","message":"container
|
# "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"},
|
# "HostConfig": {"NetworkMode": "TestDefaultNetwork"},
|
||||||
# "NetworkingConfig": {"EndpointsConfig": {"TestDefaultNetwork": None}},
|
# "NetworkingConfig": {"EndpointsConfig": {"TestDefaultNetwork": None}},
|
||||||
# FIXME These two lines cause:
|
# 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"},
|
# "HostConfig": {"NetworkMode": "TestNetwork"},
|
||||||
# "NetworkingConfig": {"EndpointsConfig": {"TestNetwork": None}},
|
# "NetworkingConfig": {"EndpointsConfig": {"TestNetwork": None}},
|
||||||
# FIXME no networking defined cause: (note this error is from the container inspect below)
|
# 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)
|
self.assertEqual(create.status_code, 201, create.text)
|
||||||
@ -255,23 +259,68 @@ class TestApi(unittest.TestCase):
|
|||||||
def test_commit(self):
|
def test_commit(self):
|
||||||
r = requests.post(_url(ctnr("/commit?container={}")))
|
r = requests.post(_url(ctnr("/commit?container={}")))
|
||||||
self.assertEqual(r.status_code, 200, r.text)
|
self.assertEqual(r.status_code, 200, r.text)
|
||||||
validateObjectFields(r.text)
|
|
||||||
|
|
||||||
def test_images(self):
|
obj = json.loads(r.content)
|
||||||
r = requests.get(_url("/images/json"))
|
self.assertIsInstance(obj, dict)
|
||||||
self.assertEqual(r.status_code, 200, r.text)
|
self.assertIn("Id", obj)
|
||||||
validateObjectFields(r.content)
|
|
||||||
|
|
||||||
def test_inspect_image(self):
|
def test_images_compat(self):
|
||||||
r = requests.get(_url("/images/alpine/json"))
|
r = requests.get(PODMAN_URL + "/v1.40/images/json")
|
||||||
self.assertEqual(r.status_code, 200, r.text)
|
self.assertEqual(r.status_code, 200, r.text)
|
||||||
obj = validateObjectFields(r.content)
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# 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"])
|
_ = parse(obj["Created"])
|
||||||
|
|
||||||
def test_delete_image(self):
|
def test_delete_image_compat(self):
|
||||||
r = requests.delete(_url("/images/alpine?force=true"))
|
r = requests.delete(PODMAN_URL + "/v1.40/images/alpine?force=true")
|
||||||
self.assertEqual(r.status_code, 200, r.text)
|
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):
|
def test_pull(self):
|
||||||
r = requests.post(_url("/images/pull?reference=alpine"), timeout=15)
|
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["images"], "Expected to find images stanza")
|
||||||
self.assertTrue(keys["stream"], "Expected to find stream progress stanza's")
|
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
|
# Had issues with this test hanging when repositories not happy
|
||||||
def do_search():
|
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)
|
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 = Process(target=do_search)
|
||||||
search.start()
|
search.start()
|
||||||
@ -320,6 +370,20 @@ class TestApi(unittest.TestCase):
|
|||||||
r = requests.get(_url("/_ping"))
|
r = requests.get(_url("/_ping"))
|
||||||
self.assertEqual(r.status_code, 200, r.text)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Reference in New Issue
Block a user