Fix registry tests to not terminate prematurely when looking for errors
Also reorders a check in the V1 protocol to have better error messaging for the users
This commit is contained in:
parent
1f04b3ea03
commit
701eac5466
4 changed files with 42 additions and 20 deletions
|
@ -437,6 +437,13 @@ def put_image_json(namespace, repository, image_id):
|
|||
abort(404, 'Repository does not exist: %(namespace)s/%(repository)s', issue='no-repo',
|
||||
namespace=namespace, repository=repository)
|
||||
|
||||
parent_id = data.get('parent', None)
|
||||
if parent_id:
|
||||
logger.debug('Looking up parent image')
|
||||
if model.docker_v1_metadata(namespace, repository, parent_id) is None:
|
||||
abort(400, 'Image %(image_id)s depends on non existing parent image %(parent_id)s',
|
||||
issue='invalid-request', image_id=image_id, parent_id=parent_id)
|
||||
|
||||
v1_metadata = model.docker_v1_metadata(namespace, repository, image_id)
|
||||
if v1_metadata is None:
|
||||
username = get_authenticated_user() and get_authenticated_user().username
|
||||
|
@ -451,13 +458,6 @@ def put_image_json(namespace, repository, image_id):
|
|||
model.create_temp_hidden_tag(namespace, repository, image_id,
|
||||
app.config['PUSH_TEMP_TAG_EXPIRATION_SEC'])
|
||||
|
||||
parent_id = data.get('parent', None)
|
||||
if parent_id:
|
||||
logger.debug('Looking up parent image')
|
||||
if model.docker_v1_metadata(namespace, repository, parent_id) is None:
|
||||
abort(400, 'Image %(image_id)s depends on non existing parent image %(parent_id)s',
|
||||
issue='invalid-request', image_id=image_id, parent_id=parent_id)
|
||||
|
||||
logger.debug('Checking if image already exists')
|
||||
if v1_metadata and not model.is_image_uploading(namespace, repository, image_id):
|
||||
exact_abort(409, 'Image already exists')
|
||||
|
|
|
@ -13,6 +13,7 @@ class V1ProtocolSteps(Enum):
|
|||
PUT_IMAGES = 'put-images'
|
||||
GET_IMAGES = 'get-images'
|
||||
PUT_TAG = 'put-tag'
|
||||
PUT_IMAGE_JSON = 'put-image-json'
|
||||
|
||||
|
||||
class V1Protocol(RegistryProtocol):
|
||||
|
@ -34,6 +35,9 @@ class V1Protocol(RegistryProtocol):
|
|||
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
|
||||
Failures.NAMESPACE_DISABLED: 400,
|
||||
},
|
||||
V1ProtocolSteps.PUT_IMAGE_JSON: {
|
||||
Failures.INVALID_IMAGES: 400,
|
||||
},
|
||||
V1ProtocolSteps.PUT_TAG: {
|
||||
Failures.MISSING_TAG: 404,
|
||||
Failures.INVALID_TAG: 400,
|
||||
|
@ -77,7 +81,7 @@ class V1Protocol(RegistryProtocol):
|
|||
headers = {'X-Docker-Token': 'true'}
|
||||
result = self.conduct(session, 'GET', prefix + 'images', auth=auth, headers=headers,
|
||||
expected_status=(200, expected_failure, V1ProtocolSteps.GET_IMAGES))
|
||||
if expected_failure is not None:
|
||||
if result.status_code != 200:
|
||||
return
|
||||
|
||||
headers = {}
|
||||
|
@ -91,6 +95,10 @@ class V1Protocol(RegistryProtocol):
|
|||
assert len(image_ids.values()) == len(tag_names)
|
||||
|
||||
for tag_name in tag_names:
|
||||
if tag_name not in image_ids:
|
||||
assert expected_failure == Failures.UNKNOWN_TAG
|
||||
return None
|
||||
|
||||
tag_image_id = image_ids[tag_name]
|
||||
if not options.munge_shas:
|
||||
# Ensure we have a matching image ID.
|
||||
|
@ -133,8 +141,7 @@ class V1Protocol(RegistryProtocol):
|
|||
expected_status=(201, expected_failure, V1ProtocolSteps.PUT_IMAGES),
|
||||
json_data={},
|
||||
auth=auth)
|
||||
|
||||
if expected_failure is not None:
|
||||
if result.status_code != 201:
|
||||
return
|
||||
|
||||
headers = {}
|
||||
|
@ -152,8 +159,12 @@ class V1Protocol(RegistryProtocol):
|
|||
if image.config is not None:
|
||||
image_json_data['config'] = image.config
|
||||
|
||||
self.conduct(session, 'PUT', '/v1/images/%s/json' % image.id,
|
||||
json_data=image_json_data, headers=headers)
|
||||
response = self.conduct(session, 'PUT', '/v1/images/%s/json' % image.id,
|
||||
json_data=image_json_data, headers=headers,
|
||||
expected_status=(200, expected_failure,
|
||||
V1ProtocolSteps.PUT_IMAGE_JSON))
|
||||
if response.status_code != 200:
|
||||
break
|
||||
|
||||
# PUT /v1/images/{imageID}/layer
|
||||
self.conduct(session, 'PUT', '/v1/images/%s/layer' % image.id,
|
||||
|
|
|
@ -18,6 +18,7 @@ class V2ProtocolSteps(Enum):
|
|||
MOUNT_BLOB = 'mount-blob'
|
||||
CATALOG = 'catalog'
|
||||
LIST_TAGS = 'list-tags'
|
||||
START_UPLOAD = 'start-upload'
|
||||
|
||||
|
||||
class V2Protocol(RegistryProtocol):
|
||||
|
@ -36,15 +37,21 @@ class V2Protocol(RegistryProtocol):
|
|||
},
|
||||
V2ProtocolSteps.GET_MANIFEST: {
|
||||
Failures.UNKNOWN_TAG: 404,
|
||||
Failures.UNAUTHORIZED: 403,
|
||||
Failures.UNAUTHORIZED: 401,
|
||||
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
|
||||
},
|
||||
V2ProtocolSteps.BLOB_HEAD_CHECK: {
|
||||
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
|
||||
},
|
||||
V2ProtocolSteps.START_UPLOAD: {
|
||||
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
|
||||
},
|
||||
V2ProtocolSteps.PUT_MANIFEST: {
|
||||
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
|
||||
Failures.MISSING_TAG: 404,
|
||||
Failures.INVALID_TAG: 400,
|
||||
Failures.INVALID_TAG: 404,
|
||||
Failures.INVALID_IMAGES: 400,
|
||||
Failures.INVALID_BLOB: 400,
|
||||
Failures.INVALID_BLOB: 404,
|
||||
Failures.UNSUPPORTED_CONTENT_TYPE: 415,
|
||||
},
|
||||
}
|
||||
|
@ -103,8 +110,9 @@ class V2Protocol(RegistryProtocol):
|
|||
|
||||
response = self.conduct(session, 'GET', '/v2/auth', params=params, auth=auth,
|
||||
expected_status=(200, expected_failure, V2ProtocolSteps.AUTH))
|
||||
|
||||
if expected_failure is None:
|
||||
expect_token = (expected_failure is None or
|
||||
not V2Protocol.FAILURE_CODES[V2ProtocolSteps.AUTH].get(expected_failure))
|
||||
if expect_token:
|
||||
assert response.json().get('token') is not None
|
||||
return response.json().get('token'), response
|
||||
|
||||
|
@ -123,6 +131,7 @@ class V2Protocol(RegistryProtocol):
|
|||
token, _ = self.auth(session, credentials, namespace, repo_name, scopes=scopes,
|
||||
expected_failure=expected_failure)
|
||||
if token is None:
|
||||
assert V2Protocol.FAILURE_CODES[V2ProtocolSteps.AUTH].get(expected_failure)
|
||||
return
|
||||
|
||||
headers = {
|
||||
|
@ -182,8 +191,11 @@ class V2Protocol(RegistryProtocol):
|
|||
# Start a new upload of the layer data.
|
||||
response = self.conduct(session, 'POST',
|
||||
'/v2/%s/blobs/uploads/' % self.repo_name(namespace, repo_name),
|
||||
expected_status=202,
|
||||
expected_status=(202, expected_failure,
|
||||
V2ProtocolSteps.START_UPLOAD),
|
||||
headers=headers)
|
||||
if response.status_code != 202:
|
||||
continue
|
||||
|
||||
upload_uuid = response.headers['Docker-Upload-UUID']
|
||||
new_upload_location = response.headers['Location']
|
||||
|
|
|
@ -341,7 +341,7 @@ def test_push_library_with_support_disabled(pusher, basic_images, liveserver_ses
|
|||
should fail.
|
||||
"""
|
||||
credentials = ('devtable', 'password')
|
||||
|
||||
|
||||
with FeatureFlagValue('LIBRARY_SUPPORT', False, registry_server_executor.on(liveserver)):
|
||||
# Attempt to push a new repository.
|
||||
pusher.push(liveserver_session, '', 'newrepo', 'latest', basic_images,
|
||||
|
@ -527,7 +527,6 @@ def test_expiration_label(label_value, expected_expiration, manifest_protocol, l
|
|||
@pytest.mark.parametrize('content_type', [
|
||||
'application/vnd.oci.image.manifest.v1+json',
|
||||
'application/vnd.docker.distribution.manifest.v2+json',
|
||||
'application/vnd.foo.bar',
|
||||
])
|
||||
def test_unsupported_manifest_content_type(content_type, manifest_protocol, basic_images,
|
||||
liveserver_session, app_reloader):
|
||||
|
|
Reference in a new issue