Merge pull request #8587 from jwhonce/jira/RUN-1106-images

Jira RUN-1106 Image handlers updates
This commit is contained in:
OpenShift Merge Robot
2020-12-04 06:23:16 -05:00
committed by GitHub
5 changed files with 101 additions and 38 deletions

View File

@ -81,5 +81,4 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
} }
utils.WriteResponse(w, http.StatusOK, "") utils.WriteResponse(w, http.StatusOK, "")
} }

View File

@ -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

View File

@ -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"`
} }

View File

@ -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,

View File

@ -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()