def test_boundary_conditions(self): """Ensure that no exception happens in boundary cases""" components = app_util.validate_and_transform_repo_name('tags') self.assertEqual(components, ('', 'tags', 'tags')) components = app_util.validate_and_transform_repo_name('tags/') self.assertEqual(components, ('', 'tags/', 'tags')) components = app_util.validate_and_transform_repo_name('/tags') self.assertEqual(components, ('', 'tags', 'tags'))
def name_redirect(name, file_path): """ Redirects the client to the path from where the file can be accessed. :param name: name of the repository. The combination of username and repo specifies a repo id :type name: basestring :param file_path: the relative path :type file_path: basestring :return: 302 redirect response :rtype: flask.Response """ # name, repo_name, path = app_util.validate_and_transform_repo_name(username, repo, file_path) full_path = '/'.join([name, file_path]) name_component, path_component = app_util.validate_and_transform_repo_name( full_path) base_url = repository.get_path_for_repo(name_component) if not base_url.endswith('/'): base_url += '/' url = base_url + path_component return redirect(url)
def name_redirect(relative_path): """ Redirects the client to the path from where the file can be accessed. :param relative_path: the relative path after /v2/. :type relative_path: basestring :return: 302 redirect response :rtype: flask.Response """ name_component, path_component = app_util.validate_and_transform_repo_name(relative_path) base_url = repository.get_path_for_repo(name_component) if not base_url.endswith('/'): base_url += '/' schema2_data = repository.get_schema2_data_for_repo(name_component) if 'manifests' in path_component and schema2_data is not None: manifest_list_data = repository.get_manifest_list_data_for_repo(name_component) manifest_list_amd64_tags = repository.get_manifest_list_amd64_for_repo(name_component) if schema2_data: schema2_data = json.loads(schema2_data) if manifest_list_data: manifest_list_data = json.loads(manifest_list_data) if manifest_list_amd64_tags: manifest_list_amd64_tags = json.loads(manifest_list_amd64_tags) manifest, identifier = path_component.split('/') if schema2_data or manifest_list_data: # if it is a newer docker client it sets accept headers to manifest schema 1, 2 and list # if it is an older docker client, he doesnot set any of accept headers accept_headers = request.headers.get('Accept') schema2_mediatype = 'application/vnd.docker.distribution.manifest.v2+json' manifest_list_mediatype = 'application/vnd.docker.distribution.manifest.list.v2+json' # check first manifest list type if manifest_list_mediatype in accept_headers and identifier in manifest_list_data: path_component = os.path.join(manifest, 'list', identifier) # this is needed for older clients which do not understand manifest list elif identifier in manifest_list_amd64_tags.keys(): if schema2_mediatype in accept_headers: path_component = os.path.join( manifest, str(manifest_list_amd64_tags[identifier][1]), manifest_list_amd64_tags[identifier][0]) elif manifest_list_amd64_tags[identifier][1] == 1: path_component = os.path.join( manifest, '1', manifest_list_amd64_tags[identifier][0]) # this is needed in case when there is no amd64 image manifest, but there are within # one repo manifest list and image manifest with the same tag else: path_component = os.path.join(manifest, '1', identifier) elif schema2_mediatype in accept_headers and identifier in schema2_data: path_component = os.path.join(manifest, '2', identifier) else: path_component = os.path.join(manifest, '1', identifier) # this is needed for V3Repo which do not have schema2 manifests else: path_component = os.path.join(manifest, '1', identifier) url = base_url + path_component return redirect(url)
def test_funny_image_names(self): for image_name in ['tags', 'manifests', 'blobs']: for component_type in ['tags', 'manifests', 'blobs']: full_path = 'redhat/%s/%s/latest' % (image_name, component_type) name, path, component = app_util.validate_and_transform_repo_name(full_path) msg = 'Full path: ' + full_path self.assertEqual(name, 'redhat/' + image_name, msg=msg) self.assertEqual(path, component_type + '/latest', msg=msg) self.assertEqual(component, component_type, msg=msg)
def test_funny_image_names(self): for image_name in ['tags', 'manifests', 'blobs']: for component_type in ['tags', 'manifests', 'blobs']: full_path = 'redhat/%s/%s/latest' % (image_name, component_type) name, path, component = app_util.validate_and_transform_repo_name( full_path) msg = 'Full path: ' + full_path self.assertEqual(name, 'redhat/' + image_name, msg=msg) self.assertEqual(path, component_type + '/latest', msg=msg) self.assertEqual(component, component_type, msg=msg)
def name_redirect(relative_path): """ Redirects the client to the path from where the file can be accessed. :param relative_path: the relative path after /v2/. :type relative_path: basestring :return: 302 redirect response :rtype: flask.Response """ name_component, path_component = app_util.validate_and_transform_repo_name(relative_path) base_url = repository.get_path_for_repo(name_component) if not base_url.endswith('/'): base_url += '/' url = base_url + path_component return redirect(url)
def name_redirect(name, file_path): """ Redirects the client to the path from where the file can be accessed. :param name: name of the repository. The combination of username and repo specifies a repo id :type name: basestring :param file_path: the relative path :type file_path: basestring :return: 302 redirect response :rtype: flask.Response """ # name, repo_name, path = app_util.validate_and_transform_repo_name(username, repo, file_path) full_path = '/'.join([name, file_path]) name_component, path_component = app_util.validate_and_transform_repo_name(full_path) base_url = repository.get_path_for_repo(name_component) if not base_url.endswith('/'): base_url += '/' url = base_url + path_component return redirect(url)
def test_path_without_tags_or_manifest_or_blobs(self): with self.assertRaises(exceptions.HTTPError) as assertion: app_util.validate_and_transform_repo_name('redhat/rhel7.0/unknown/latest') self.assertEquals(assertion.exception.status_code, httplib.NOT_FOUND)
def test_normal(self): name, path, component = app_util.validate_and_transform_repo_name('redhat/rhel7.0/tags/latest') # noqa self.assertEqual(name, 'redhat/rhel7.0') self.assertEqual(path, 'tags/latest') self.assertEqual(component, 'tags')
def test_path_without_tags_or_manifest_or_blobs(self): with self.assertRaises(exceptions.HTTPError) as assertion: app_util.validate_and_transform_repo_name( 'redhat/rhel7.0/unknown/latest') self.assertEquals(assertion.exception.status_code, httplib.NOT_FOUND)
def test_normal(self): name, path = app_util.validate_and_transform_repo_name( 'redhat/rhel7.0/tags/latest') self.assertEqual(name, 'redhat/rhel7.0') self.assertEqual(path, 'tags/latest')
def name_serve_or_redirect(relative_path): """ Redirects the client to the path from where the file can be accessed. If 'serve_content' is set to true use send_file to provide the requested file directly, taking into account the 'content_dir_v2' parameter. :param relative_path: the relative path after /v2/. :type relative_path: basestring :return: 302 redirect response :rtype: flask.Response """ components = app_util.validate_and_transform_repo_name(relative_path) name_component, path_component, component_type = components base_url = repository.get_path_for_repo(name_component) if not base_url.endswith('/'): base_url += '/' schema2_data = repository.get_schema2_data_for_repo(name_component) used_mediatype = 'application/json' if component_type != 'blobs' else 'application/octet-stream' if component_type == 'manifests' and schema2_data is not None: manifest_list_data = repository.get_manifest_list_data_for_repo(name_component) manifest_list_amd64_tags = repository.get_manifest_list_amd64_for_repo(name_component) if schema2_data: schema2_data = json.loads(schema2_data) if manifest_list_data: manifest_list_data = json.loads(manifest_list_data) if manifest_list_amd64_tags: manifest_list_amd64_tags = json.loads(manifest_list_amd64_tags) manifest, identifier = path_component.split('/') if schema2_data or manifest_list_data: # if it is a newer docker client it sets accept headers to manifest schema 1, 2 and list # if it is an older docker client, he doesnot set any of accept headers accept_headers = get_accept_headers(request) schema2_mediatype = 'application/vnd.docker.distribution.manifest.v2+json' manifest_list_mediatype = 'application/vnd.docker.distribution.manifest.list.v2+json' # check first manifest list type if manifest_list_mediatype in accept_headers and identifier in manifest_list_data: path_component = os.path.join(manifest, 'list', identifier) used_mediatype = manifest_list_mediatype # this is needed for older clients which do not understand manifest list elif identifier in manifest_list_amd64_tags.keys(): if schema2_mediatype in accept_headers: schema_version = manifest_list_amd64_tags[identifier][1] if schema_version == 2: used_mediatype = schema2_mediatype path_component = os.path.join( manifest, str(schema_version), manifest_list_amd64_tags[identifier][0]) elif manifest_list_amd64_tags[identifier][1] == 1: path_component = os.path.join( manifest, '1', manifest_list_amd64_tags[identifier][0]) # this is needed in case when there is no amd64 image manifest, but there are within # one repo manifest list and image manifest with the same tag else: path_component = os.path.join(manifest, '1', identifier) elif schema2_mediatype in accept_headers and identifier in schema2_data: path_component = os.path.join(manifest, '2', identifier) used_mediatype = schema2_mediatype else: path_component = os.path.join(manifest, '1', identifier) # this is needed for V3Repo which do not have schema2 manifests else: path_component = os.path.join(manifest, '1', identifier) serve_content = current_app.config.get(config.KEY_SC_ENABLE) if serve_content: base_path = current_app.config.get(config.KEY_SC_CONTENT_DIR_V2) repo_name = repository.get_pulp_repository_name(name_component) result = os.path.join(base_path, repo_name, path_component) try: return send_file(result, mimetype=used_mediatype, add_etags=False) except OSError: raise exceptions.HTTPError(httplib.NOT_FOUND) else: url = base_url + path_component # perform CDN rewrites and auth url = cdn_rewrite_redirect_url(url) url = cdn_auth_token_url(url) return redirect(url)
def name_serve_or_redirect(relative_path): """ Redirects the client to the path from where the file can be accessed. If 'serve_content' is set to true use send_file to provide the requested file directly, taking into account the 'content_dir_v2' parameter. :param relative_path: the relative path after /v2/. :type relative_path: basestring :return: 302 redirect response :rtype: flask.Response """ components = app_util.validate_and_transform_repo_name(relative_path) name_component, path_component, component_type = components base_url = repository.get_path_for_repo(name_component) if not base_url.endswith('/'): base_url += '/' schema2_data = repository.get_schema2_data_for_repo(name_component) used_mediatype = 'application/json' if component_type != 'blobs' else 'application/octet-stream' if component_type == 'manifests' and schema2_data is not None: manifest_list_data = repository.get_manifest_list_data_for_repo( name_component) manifest_list_amd64_tags = repository.get_manifest_list_amd64_for_repo( name_component) if schema2_data: schema2_data = json.loads(schema2_data) if manifest_list_data: manifest_list_data = json.loads(manifest_list_data) if manifest_list_amd64_tags: manifest_list_amd64_tags = json.loads(manifest_list_amd64_tags) manifest, identifier = path_component.split('/') if schema2_data or manifest_list_data: # if it is a newer docker client it sets accept headers to manifest schema 1, 2 and list # if it is an older docker client, he doesnot set any of accept headers accept_headers = get_accept_headers(request) schema2_mediatype = 'application/vnd.docker.distribution.manifest.v2+json' manifest_list_mediatype = 'application/vnd.docker.distribution.manifest.list.v2+json' # check first manifest list type if manifest_list_mediatype in accept_headers and identifier in manifest_list_data: path_component = os.path.join(manifest, 'list', identifier) used_mediatype = manifest_list_mediatype # this is needed for older clients which do not understand manifest list elif identifier in manifest_list_amd64_tags.keys(): if schema2_mediatype in accept_headers: schema_version = manifest_list_amd64_tags[identifier][1] if schema_version == 2: used_mediatype = schema2_mediatype path_component = os.path.join( manifest, str(schema_version), manifest_list_amd64_tags[identifier][0]) elif manifest_list_amd64_tags[identifier][1] == 1: path_component = os.path.join( manifest, '1', manifest_list_amd64_tags[identifier][0]) # this is needed in case when there is no amd64 image manifest, but there are within # one repo manifest list and image manifest with the same tag else: path_component = os.path.join(manifest, '1', identifier) elif schema2_mediatype in accept_headers and identifier in schema2_data: path_component = os.path.join(manifest, '2', identifier) used_mediatype = schema2_mediatype else: path_component = os.path.join(manifest, '1', identifier) # this is needed for V3Repo which do not have schema2 manifests else: path_component = os.path.join(manifest, '1', identifier) serve_content = current_app.config.get(config.KEY_SC_ENABLE) if serve_content: base_path = current_app.config.get(config.KEY_SC_CONTENT_DIR_V2) repo_name = repository.get_pulp_repository_name(name_component) result = os.path.join(base_path, repo_name, path_component) try: return send_file(result, mimetype=used_mediatype, add_etags=False) except OSError: raise exceptions.HTTPError(httplib.NOT_FOUND) else: url = base_url + path_component # perform CDN rewrites and auth url = cdn_rewrite_redirect_url(url) url = cdn_auth_token_url(url) return redirect(url)