mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-08-05 00:15:44 +00:00
fix: compat API image push err meg propagation
When returning error http code (e.g. 4xx, 5xx) the body needs to contain a JSON that has a key "message" in it, we must not use jsonmessage.JSONMessage. The JSON of shape jsonmessage.JSONMessage is used only when client already received 200. Signed-off-by: Matej Vašek <matejvasek@gmail.com>
This commit is contained in:
parent
d1f0833c5f
commit
db70e73056
3 changed files with 39 additions and 7 deletions
|
|
@ -189,15 +189,18 @@ loop: // break out of for/select infinite loop
|
|||
flush()
|
||||
case err := <-pushErrChan:
|
||||
if err != nil {
|
||||
var msg string
|
||||
code := http.StatusInternalServerError
|
||||
if errors.Is(err, storage.ErrImageUnknown) {
|
||||
// Image may have been removed in the meantime.
|
||||
writeStatusCode(http.StatusNotFound)
|
||||
msg = "An image does not exist locally with the tag: " + imageName
|
||||
} else {
|
||||
writeStatusCode(http.StatusInternalServerError)
|
||||
msg = err.Error()
|
||||
code = http.StatusNotFound
|
||||
err = errors.New("An image does not exist locally with the tag: " + imageName)
|
||||
}
|
||||
if !statusWritten {
|
||||
utils.Error(w, code, err)
|
||||
flush()
|
||||
break loop
|
||||
}
|
||||
var msg = err.Error()
|
||||
report.Error = &jsonstream.Error{
|
||||
Message: msg,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ t GET libpod/images/$IMAGE/json 200 \
|
|||
|
||||
# Push to local registry...
|
||||
t POST "/v1.40/images/localhost:$REGISTRY_PORT/myrepo/push?tag=mytag" 500 \
|
||||
.error~".*x509: certificate signed by unknown authority"
|
||||
.message~".*x509: certificate signed by unknown authority"
|
||||
t POST "images/localhost:$REGISTRY_PORT/myrepo/push?tlsVerify=false&tag=mytag" 200 \
|
||||
.error~null
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ import io
|
|||
import os
|
||||
import unittest
|
||||
import json
|
||||
from typing import Iterator
|
||||
|
||||
from docker import errors
|
||||
from docker.errors import APIError
|
||||
|
||||
# pylint: disable=no-name-in-module,import-error,wrong-import-order
|
||||
from test.python.docker.compat import common, constant
|
||||
|
|
@ -135,6 +137,33 @@ class TestImages(common.DockerTestCase):
|
|||
raise IOError(f"Line '{line}' was not JSON parsable")
|
||||
assert "errorDetail" not in parsed
|
||||
|
||||
def test_push_error(self):
|
||||
"""Validates that push error is correctly propagated"""
|
||||
alpine = self.docker.images.get(constant.ALPINE)
|
||||
if not alpine.tag("non-existent.lan:5000/alpine", "latest"):
|
||||
self.fail("not tagged")
|
||||
try:
|
||||
resp: str = self.docker.images.push("non-existent.lan:5000/alpine", "latest")
|
||||
for obj in json_stream(resp):
|
||||
if 'no such host' in obj.get('errorDetail', {}).get('message', ''):
|
||||
return
|
||||
self.fail('expected error not found in the response')
|
||||
except APIError as e:
|
||||
if 'no such host' not in e.explanation:
|
||||
self.fail('expected error not found in the response')
|
||||
|
||||
def json_stream(data: str) -> Iterator[dict]:
|
||||
decoder = json.JSONDecoder()
|
||||
pos = 0
|
||||
length = len(data)
|
||||
while pos < length:
|
||||
if data[pos].isspace():
|
||||
pos += 1
|
||||
continue
|
||||
obj, pos_end = decoder.raw_decode(data, pos)
|
||||
yield obj
|
||||
pos = pos_end
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Setup temporary space
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue