Merge pull request #3199 from quay/fix-registry-tests

Fix registry tests to not terminate prematurely when looking for errors
This commit is contained in:
Joseph Schorr 2018-08-10 18:06:22 -04:00 committed by GitHub
commit 805e928dff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 20 deletions

View file

@ -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', abort(404, 'Repository does not exist: %(namespace)s/%(repository)s', issue='no-repo',
namespace=namespace, repository=repository) 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) v1_metadata = model.docker_v1_metadata(namespace, repository, image_id)
if v1_metadata is None: if v1_metadata is None:
username = get_authenticated_user() and get_authenticated_user().username 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, model.create_temp_hidden_tag(namespace, repository, image_id,
app.config['PUSH_TEMP_TAG_EXPIRATION_SEC']) 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') logger.debug('Checking if image already exists')
if v1_metadata and not model.is_image_uploading(namespace, repository, image_id): if v1_metadata and not model.is_image_uploading(namespace, repository, image_id):
exact_abort(409, 'Image already exists') exact_abort(409, 'Image already exists')

View file

@ -13,6 +13,7 @@ class V1ProtocolSteps(Enum):
PUT_IMAGES = 'put-images' PUT_IMAGES = 'put-images'
GET_IMAGES = 'get-images' GET_IMAGES = 'get-images'
PUT_TAG = 'put-tag' PUT_TAG = 'put-tag'
PUT_IMAGE_JSON = 'put-image-json'
class V1Protocol(RegistryProtocol): class V1Protocol(RegistryProtocol):
@ -34,6 +35,9 @@ class V1Protocol(RegistryProtocol):
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400, Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
Failures.NAMESPACE_DISABLED: 400, Failures.NAMESPACE_DISABLED: 400,
}, },
V1ProtocolSteps.PUT_IMAGE_JSON: {
Failures.INVALID_IMAGES: 400,
},
V1ProtocolSteps.PUT_TAG: { V1ProtocolSteps.PUT_TAG: {
Failures.MISSING_TAG: 404, Failures.MISSING_TAG: 404,
Failures.INVALID_TAG: 400, Failures.INVALID_TAG: 400,
@ -77,7 +81,7 @@ class V1Protocol(RegistryProtocol):
headers = {'X-Docker-Token': 'true'} headers = {'X-Docker-Token': 'true'}
result = self.conduct(session, 'GET', prefix + 'images', auth=auth, headers=headers, result = self.conduct(session, 'GET', prefix + 'images', auth=auth, headers=headers,
expected_status=(200, expected_failure, V1ProtocolSteps.GET_IMAGES)) expected_status=(200, expected_failure, V1ProtocolSteps.GET_IMAGES))
if expected_failure is not None: if result.status_code != 200:
return return
headers = {} headers = {}
@ -91,6 +95,10 @@ class V1Protocol(RegistryProtocol):
assert len(image_ids.values()) == len(tag_names) assert len(image_ids.values()) == len(tag_names)
for tag_name in 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] tag_image_id = image_ids[tag_name]
if not options.munge_shas: if not options.munge_shas:
# Ensure we have a matching image ID. # Ensure we have a matching image ID.
@ -133,8 +141,7 @@ class V1Protocol(RegistryProtocol):
expected_status=(201, expected_failure, V1ProtocolSteps.PUT_IMAGES), expected_status=(201, expected_failure, V1ProtocolSteps.PUT_IMAGES),
json_data={}, json_data={},
auth=auth) auth=auth)
if result.status_code != 201:
if expected_failure is not None:
return return
headers = {} headers = {}
@ -152,8 +159,12 @@ class V1Protocol(RegistryProtocol):
if image.config is not None: if image.config is not None:
image_json_data['config'] = image.config image_json_data['config'] = image.config
self.conduct(session, 'PUT', '/v1/images/%s/json' % image.id, response = self.conduct(session, 'PUT', '/v1/images/%s/json' % image.id,
json_data=image_json_data, headers=headers) 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 # PUT /v1/images/{imageID}/layer
self.conduct(session, 'PUT', '/v1/images/%s/layer' % image.id, self.conduct(session, 'PUT', '/v1/images/%s/layer' % image.id,

View file

@ -18,6 +18,7 @@ class V2ProtocolSteps(Enum):
MOUNT_BLOB = 'mount-blob' MOUNT_BLOB = 'mount-blob'
CATALOG = 'catalog' CATALOG = 'catalog'
LIST_TAGS = 'list-tags' LIST_TAGS = 'list-tags'
START_UPLOAD = 'start-upload'
class V2Protocol(RegistryProtocol): class V2Protocol(RegistryProtocol):
@ -36,15 +37,21 @@ class V2Protocol(RegistryProtocol):
}, },
V2ProtocolSteps.GET_MANIFEST: { V2ProtocolSteps.GET_MANIFEST: {
Failures.UNKNOWN_TAG: 404, 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, Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
}, },
V2ProtocolSteps.PUT_MANIFEST: { V2ProtocolSteps.PUT_MANIFEST: {
Failures.DISALLOWED_LIBRARY_NAMESPACE: 400, Failures.DISALLOWED_LIBRARY_NAMESPACE: 400,
Failures.MISSING_TAG: 404, Failures.MISSING_TAG: 404,
Failures.INVALID_TAG: 400, Failures.INVALID_TAG: 404,
Failures.INVALID_IMAGES: 400, Failures.INVALID_IMAGES: 400,
Failures.INVALID_BLOB: 400, Failures.INVALID_BLOB: 404,
Failures.UNSUPPORTED_CONTENT_TYPE: 415, Failures.UNSUPPORTED_CONTENT_TYPE: 415,
}, },
} }
@ -103,8 +110,9 @@ class V2Protocol(RegistryProtocol):
response = self.conduct(session, 'GET', '/v2/auth', params=params, auth=auth, response = self.conduct(session, 'GET', '/v2/auth', params=params, auth=auth,
expected_status=(200, expected_failure, V2ProtocolSteps.AUTH)) expected_status=(200, expected_failure, V2ProtocolSteps.AUTH))
expect_token = (expected_failure is None or
if expected_failure is None: not V2Protocol.FAILURE_CODES[V2ProtocolSteps.AUTH].get(expected_failure))
if expect_token:
assert response.json().get('token') is not None assert response.json().get('token') is not None
return response.json().get('token'), response return response.json().get('token'), response
@ -123,6 +131,7 @@ class V2Protocol(RegistryProtocol):
token, _ = self.auth(session, credentials, namespace, repo_name, scopes=scopes, token, _ = self.auth(session, credentials, namespace, repo_name, scopes=scopes,
expected_failure=expected_failure) expected_failure=expected_failure)
if token is None: if token is None:
assert V2Protocol.FAILURE_CODES[V2ProtocolSteps.AUTH].get(expected_failure)
return return
headers = { headers = {
@ -182,8 +191,11 @@ class V2Protocol(RegistryProtocol):
# Start a new upload of the layer data. # Start a new upload of the layer data.
response = self.conduct(session, 'POST', response = self.conduct(session, 'POST',
'/v2/%s/blobs/uploads/' % self.repo_name(namespace, repo_name), '/v2/%s/blobs/uploads/' % self.repo_name(namespace, repo_name),
expected_status=202, expected_status=(202, expected_failure,
V2ProtocolSteps.START_UPLOAD),
headers=headers) headers=headers)
if response.status_code != 202:
continue
upload_uuid = response.headers['Docker-Upload-UUID'] upload_uuid = response.headers['Docker-Upload-UUID']
new_upload_location = response.headers['Location'] new_upload_location = response.headers['Location']

View file

@ -341,7 +341,7 @@ def test_push_library_with_support_disabled(pusher, basic_images, liveserver_ses
should fail. should fail.
""" """
credentials = ('devtable', 'password') credentials = ('devtable', 'password')
with FeatureFlagValue('LIBRARY_SUPPORT', False, registry_server_executor.on(liveserver)): with FeatureFlagValue('LIBRARY_SUPPORT', False, registry_server_executor.on(liveserver)):
# Attempt to push a new repository. # Attempt to push a new repository.
pusher.push(liveserver_session, '', 'newrepo', 'latest', basic_images, 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', [ @pytest.mark.parametrize('content_type', [
'application/vnd.oci.image.manifest.v1+json', 'application/vnd.oci.image.manifest.v1+json',
'application/vnd.docker.distribution.manifest.v2+json', 'application/vnd.docker.distribution.manifest.v2+json',
'application/vnd.foo.bar',
]) ])
def test_unsupported_manifest_content_type(content_type, manifest_protocol, basic_images, def test_unsupported_manifest_content_type(content_type, manifest_protocol, basic_images,
liveserver_session, app_reloader): liveserver_session, app_reloader):