Fix DNF related issues with source selection
yum TumRepository.dump() function cannot be used as a .repo file Add a new function to write this in the correct format, and limited to the fields we use. Add a test for the new function. Fix /projects/source/info to return an error 400 if a nonexistant TOML source is requested. If JSON is used the error is part of the standard response. Update test_server.py to check for the correct error code.
This commit is contained in:
parent
3f7997d7ae
commit
2e95b56508
@ -320,6 +320,38 @@ def modules_info(yb, module_names):
|
|||||||
|
|
||||||
return modules
|
return modules
|
||||||
|
|
||||||
|
def yum_repo_to_file_repo(repo):
|
||||||
|
"""Return a string representation of a YumRepository object suitable for writing to a .repo file
|
||||||
|
|
||||||
|
:param repo: Yum Repository
|
||||||
|
:type repo: yum.yumRepo.YumRepository
|
||||||
|
:returns: A string
|
||||||
|
:rtype: str
|
||||||
|
|
||||||
|
The YumRepo.dump() function does not produce a string that can be used as a
|
||||||
|
yum .repo file. So do this manually with only the attributes we care about.
|
||||||
|
"""
|
||||||
|
repo_str = "[%s]\n" % repo.id
|
||||||
|
if repo.metalink:
|
||||||
|
repo_str += "metalink = %s\n" % repo.metalink
|
||||||
|
elif repo.mirrorlist:
|
||||||
|
repo_str += "mirrorlist = %s\n" % repo.mirrorlist
|
||||||
|
elif repo.baseurl:
|
||||||
|
repo_str += "baseurl = %s\n" % repo.baseurl[0]
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Repo has no baseurl, metalink, or mirrorlist")
|
||||||
|
|
||||||
|
# proxy is optional
|
||||||
|
if repo.proxy:
|
||||||
|
repo_str += "proxy = %s\n" % repo.proxy
|
||||||
|
|
||||||
|
repo_str += "sslverify = %s\n" % repo.sslverify
|
||||||
|
repo_str += "gpgcheck = %s\n" % repo.gpgcheck
|
||||||
|
if repo.gpgkey:
|
||||||
|
repo_str += "gpgkey = %s\n" % ",".join(repo.gpgkey)
|
||||||
|
|
||||||
|
return repo_str
|
||||||
|
|
||||||
def repo_to_source(repo, system_source):
|
def repo_to_source(repo, system_source):
|
||||||
"""Return a Weldr Source dict created from the YumRepository
|
"""Return a Weldr Source dict created from the YumRepository
|
||||||
|
|
||||||
@ -408,7 +440,7 @@ def source_to_repo(source):
|
|||||||
repo.skip_if_unavailable = False
|
repo.skip_if_unavailable = False
|
||||||
|
|
||||||
if source["type"] == "yum-baseurl":
|
if source["type"] == "yum-baseurl":
|
||||||
repo.baseurl = [source["url"]]
|
repo.baseurl = source["url"]
|
||||||
elif source["type"] == "yum-metalink":
|
elif source["type"] == "yum-metalink":
|
||||||
repo.metalink = source["url"]
|
repo.metalink = source["url"]
|
||||||
elif source["type"] == "yum-mirrorlist":
|
elif source["type"] == "yum-mirrorlist":
|
||||||
@ -428,7 +460,7 @@ def source_to_repo(source):
|
|||||||
repo.gpgcheck = False
|
repo.gpgcheck = False
|
||||||
|
|
||||||
if "gpgkey_urls" in source:
|
if "gpgkey_urls" in source:
|
||||||
repo.gpgkey = source["gpgkey_urls"]
|
repo.gpgkey = ",".join(source["gpgkey_urls"])
|
||||||
|
|
||||||
repo.enable()
|
repo.enable()
|
||||||
|
|
||||||
|
@ -973,7 +973,7 @@ from pylorax.api.compose import start_build, compose_types
|
|||||||
from pylorax.api.crossdomain import crossdomain
|
from pylorax.api.crossdomain import crossdomain
|
||||||
from pylorax.api.projects import projects_list, projects_info, projects_depsolve
|
from pylorax.api.projects import projects_list, projects_info, projects_depsolve
|
||||||
from pylorax.api.projects import modules_list, modules_info, ProjectsError, repo_to_source
|
from pylorax.api.projects import modules_list, modules_info, ProjectsError, repo_to_source
|
||||||
from pylorax.api.projects import get_repo_sources, delete_repo_source, source_to_repo
|
from pylorax.api.projects import get_repo_sources, delete_repo_source, source_to_repo, yum_repo_to_file_repo
|
||||||
from pylorax.api.queue import queue_status, build_status, uuid_delete, uuid_status, uuid_info
|
from pylorax.api.queue import queue_status, build_status, uuid_delete, uuid_status, uuid_info
|
||||||
from pylorax.api.queue import uuid_tar, uuid_image, uuid_cancel, uuid_log
|
from pylorax.api.queue import uuid_tar, uuid_image, uuid_cancel, uuid_log
|
||||||
from pylorax.api.recipes import list_branch_files, read_recipe_commit, recipe_filename, list_commits
|
from pylorax.api.recipes import list_branch_files, read_recipe_commit, recipe_filename, list_commits
|
||||||
@ -1423,9 +1423,12 @@ def v0_api(api):
|
|||||||
continue
|
continue
|
||||||
sources[repo.id] = repo_to_source(repo, repo.id in system_sources)
|
sources[repo.id] = repo_to_source(repo, repo.id in system_sources)
|
||||||
|
|
||||||
if out_fmt == "toml":
|
if out_fmt == "toml" and not errors:
|
||||||
# With TOML output we just want to dump the raw sources, skipping the errors
|
# With TOML output we just want to dump the raw sources, skipping the errors
|
||||||
return toml.dumps(sources)
|
return toml.dumps(sources)
|
||||||
|
elif out_fmt == "toml" and errors:
|
||||||
|
# TOML requested, but there was an error
|
||||||
|
return jsonify(status=False, errors=errors), 400
|
||||||
else:
|
else:
|
||||||
return jsonify(sources=sources, errors=errors)
|
return jsonify(sources=sources, errors=errors)
|
||||||
|
|
||||||
@ -1469,7 +1472,7 @@ def v0_api(api):
|
|||||||
# Make sure the source name can't contain a path traversal by taking the basename
|
# Make sure the source name can't contain a path traversal by taking the basename
|
||||||
source_path = joinpaths(repo_dir, os.path.basename("%s.repo" % source["name"]))
|
source_path = joinpaths(repo_dir, os.path.basename("%s.repo" % source["name"]))
|
||||||
with open(source_path, "w") as f:
|
with open(source_path, "w") as f:
|
||||||
f.write(str(repo))
|
f.write(yum_repo_to_file_repo(repo))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error("(v0_projects_source_add) adding %s failed: %s", source["name"], str(e))
|
log.error("(v0_projects_source_add) adding %s failed: %s", source["name"], str(e))
|
||||||
|
|
||||||
|
6
tests/pylorax/source/bad-repo.toml
Normal file
6
tests/pylorax/source/bad-repo.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
name = "bad-repo-1"
|
||||||
|
url = "file:///tmp/not-a-repo/"
|
||||||
|
type = "yum-baseurl"
|
||||||
|
check_ssl = true
|
||||||
|
check_gpg = true
|
||||||
|
gpgkey_urls = ["file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch"]
|
@ -29,8 +29,9 @@ from pylorax.api.config import configure, make_yum_dirs
|
|||||||
from pylorax.api.projects import api_time, api_changelog, yaps_to_project, yaps_to_project_info
|
from pylorax.api.projects import api_time, api_changelog, yaps_to_project, yaps_to_project_info
|
||||||
from pylorax.api.projects import tm_to_dep, yaps_to_module, projects_list, projects_info, projects_depsolve
|
from pylorax.api.projects import tm_to_dep, yaps_to_module, projects_list, projects_info, projects_depsolve
|
||||||
from pylorax.api.projects import modules_list, modules_info, ProjectsError, dep_evra, dep_nevra
|
from pylorax.api.projects import modules_list, modules_info, ProjectsError, dep_evra, dep_nevra
|
||||||
from pylorax.api.yumbase import get_base_object
|
|
||||||
from pylorax.api.projects import repo_to_source, get_repo_sources, delete_repo_source, source_to_repo
|
from pylorax.api.projects import repo_to_source, get_repo_sources, delete_repo_source, source_to_repo
|
||||||
|
from pylorax.api.projects import yum_repo_to_file_repo
|
||||||
|
from pylorax.api.yumbase import get_base_object
|
||||||
|
|
||||||
|
|
||||||
class Yaps(object):
|
class Yaps(object):
|
||||||
@ -271,6 +272,13 @@ def fakerepo_baseurl():
|
|||||||
"url": "https://fake-repo.base.url"
|
"url": "https://fake-repo.base.url"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def fakerepo_baseurl_str():
|
||||||
|
return """[fake-repo-baseurl]
|
||||||
|
baseurl = https://fake-repo.base.url
|
||||||
|
sslverify = True
|
||||||
|
gpgcheck = True
|
||||||
|
"""
|
||||||
|
|
||||||
class FakeSystemRepo(object):
|
class FakeSystemRepo(object):
|
||||||
id = "fake-system-repo"
|
id = "fake-system-repo"
|
||||||
baseurl = ["https://fake-repo.base.url"]
|
baseurl = ["https://fake-repo.base.url"]
|
||||||
@ -310,6 +318,13 @@ def fakerepo_metalink():
|
|||||||
"url": "https://fake-repo.metalink"
|
"url": "https://fake-repo.metalink"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def fakerepo_metalink_str():
|
||||||
|
return """[fake-repo-metalink]
|
||||||
|
metalink = https://fake-repo.metalink
|
||||||
|
sslverify = True
|
||||||
|
gpgcheck = True
|
||||||
|
"""
|
||||||
|
|
||||||
class FakeRepoMirrorlist(object):
|
class FakeRepoMirrorlist(object):
|
||||||
id = "fake-repo-mirrorlist"
|
id = "fake-repo-mirrorlist"
|
||||||
baseurl = []
|
baseurl = []
|
||||||
@ -330,6 +345,13 @@ def fakerepo_mirrorlist():
|
|||||||
"url": "https://fake-repo.mirrorlist"
|
"url": "https://fake-repo.mirrorlist"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def fakerepo_mirrorlist_str():
|
||||||
|
return """[fake-repo-mirrorlist]
|
||||||
|
mirrorlist = https://fake-repo.mirrorlist
|
||||||
|
sslverify = True
|
||||||
|
gpgcheck = True
|
||||||
|
"""
|
||||||
|
|
||||||
class FakeRepoProxy(object):
|
class FakeRepoProxy(object):
|
||||||
id = "fake-repo-proxy"
|
id = "fake-repo-proxy"
|
||||||
baseurl = ["https://fake-repo.base.url"]
|
baseurl = ["https://fake-repo.base.url"]
|
||||||
@ -351,6 +373,14 @@ def fakerepo_proxy():
|
|||||||
"url": "https://fake-repo.base.url"
|
"url": "https://fake-repo.base.url"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def fakerepo_proxy_str():
|
||||||
|
return """[fake-repo-proxy]
|
||||||
|
baseurl = https://fake-repo.base.url
|
||||||
|
proxy = https://fake-repo.proxy
|
||||||
|
sslverify = True
|
||||||
|
gpgcheck = True
|
||||||
|
"""
|
||||||
|
|
||||||
class FakeRepoGPGKey(object):
|
class FakeRepoGPGKey(object):
|
||||||
id = "fake-repo-gpgkey"
|
id = "fake-repo-gpgkey"
|
||||||
baseurl = ["https://fake-repo.base.url"]
|
baseurl = ["https://fake-repo.base.url"]
|
||||||
@ -374,6 +404,14 @@ def fakerepo_gpgkey():
|
|||||||
"url": "https://fake-repo.base.url"
|
"url": "https://fake-repo.base.url"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def fakerepo_gpgkey_str():
|
||||||
|
return """[fake-repo-gpgkey]
|
||||||
|
baseurl = https://fake-repo.base.url
|
||||||
|
sslverify = True
|
||||||
|
gpgcheck = True
|
||||||
|
gpgkey = https://fake-repo.gpgkey
|
||||||
|
"""
|
||||||
|
|
||||||
class SourceTest(unittest.TestCase):
|
class SourceTest(unittest.TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(self):
|
def setUpClass(self):
|
||||||
@ -395,19 +433,19 @@ class SourceTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_repo_to_source_metalink(self):
|
def test_repo_to_source_metalink(self):
|
||||||
"""Test a repo with a metalink"""
|
"""Test a repo with a metalink"""
|
||||||
self.assertEqual(repo_to_source(FakeRepoMetalink, False), fakerepo_metalink())
|
self.assertEqual(repo_to_source(FakeRepoMetalink(), False), fakerepo_metalink())
|
||||||
|
|
||||||
def test_repo_to_source_mirrorlist(self):
|
def test_repo_to_source_mirrorlist(self):
|
||||||
"""Test a repo with a mirrorlist"""
|
"""Test a repo with a mirrorlist"""
|
||||||
self.assertEqual(repo_to_source(FakeRepoMirrorlist, False), fakerepo_mirrorlist())
|
self.assertEqual(repo_to_source(FakeRepoMirrorlist(), False), fakerepo_mirrorlist())
|
||||||
|
|
||||||
def test_repo_to_source_proxy(self):
|
def test_repo_to_source_proxy(self):
|
||||||
"""Test a repo with a proxy"""
|
"""Test a repo with a proxy"""
|
||||||
self.assertEqual(repo_to_source(FakeRepoProxy, False), fakerepo_proxy())
|
self.assertEqual(repo_to_source(FakeRepoProxy(), False), fakerepo_proxy())
|
||||||
|
|
||||||
def test_repo_to_source_gpgkey(self):
|
def test_repo_to_source_gpgkey(self):
|
||||||
"""Test a repo with a GPG key"""
|
"""Test a repo with a GPG key"""
|
||||||
self.assertEqual(repo_to_source(FakeRepoGPGKey, False), fakerepo_gpgkey())
|
self.assertEqual(repo_to_source(FakeRepoGPGKey(), False), fakerepo_gpgkey())
|
||||||
|
|
||||||
def test_get_repo_sources(self):
|
def test_get_repo_sources(self):
|
||||||
"""Test getting a list of sources from a repo directory"""
|
"""Test getting a list of sources from a repo directory"""
|
||||||
@ -462,3 +500,23 @@ class SourceTest(unittest.TestCase):
|
|||||||
"""Test creating a yum.yumRepo.YumRepository with a proxy"""
|
"""Test creating a yum.yumRepo.YumRepository with a proxy"""
|
||||||
repo = source_to_repo(fakerepo_gpgkey())
|
repo = source_to_repo(fakerepo_gpgkey())
|
||||||
self.assertEqual(repo.gpgkey, fakerepo_gpgkey()["gpgkey_urls"])
|
self.assertEqual(repo.gpgkey, fakerepo_gpgkey()["gpgkey_urls"])
|
||||||
|
|
||||||
|
def test_drtfr_baseurl(self):
|
||||||
|
"""Test creating a yum .repo file from a baseurl Repo object"""
|
||||||
|
self.assertEqual(yum_repo_to_file_repo(FakeRepoBaseUrl()), fakerepo_baseurl_str())
|
||||||
|
|
||||||
|
def test_drtfr_metalink(self):
|
||||||
|
"""Test creating a yum .repo file from a metalink Repo object"""
|
||||||
|
self.assertEqual(yum_repo_to_file_repo(FakeRepoMetalink()), fakerepo_metalink_str())
|
||||||
|
|
||||||
|
def test_drtfr_mirrorlist(self):
|
||||||
|
"""Test creating a yum .repo file from a mirrorlist Repo object"""
|
||||||
|
self.assertEqual(yum_repo_to_file_repo(FakeRepoMirrorlist()), fakerepo_mirrorlist_str())
|
||||||
|
|
||||||
|
def test_drtfr_proxy(self):
|
||||||
|
"""Test creating a yum .repo file from a baseurl Repo object with proxy"""
|
||||||
|
self.assertEqual(yum_repo_to_file_repo(FakeRepoProxy()), fakerepo_proxy_str())
|
||||||
|
|
||||||
|
def test_drtfr_gpgkey(self):
|
||||||
|
"""Test creating a yum .repo file from a baseurl Repo object with gpgkey"""
|
||||||
|
self.assertEqual(yum_repo_to_file_repo(FakeRepoGPGKey()), fakerepo_gpgkey_str())
|
||||||
|
@ -549,12 +549,14 @@ class ServerTestCase(unittest.TestCase):
|
|||||||
resp = self.server.post("/api/v0/projects/source/new",
|
resp = self.server.post("/api/v0/projects/source/new",
|
||||||
data=toml_source,
|
data=toml_source,
|
||||||
content_type="text/x-toml")
|
content_type="text/x-toml")
|
||||||
|
self.assertEqual(resp.status_code, 400)
|
||||||
data = json.loads(resp.data)
|
data = json.loads(resp.data)
|
||||||
self.assertEqual(data["status"], False)
|
self.assertEqual(data["status"], False)
|
||||||
|
|
||||||
def test_projects_source_01_delete_system(self):
|
def test_projects_source_01_delete_system(self):
|
||||||
"""Test /api/v0/projects/source/delete a system source"""
|
"""Test /api/v0/projects/source/delete a system source"""
|
||||||
resp = self.server.delete("/api/v0/projects/source/delete/base")
|
resp = self.server.delete("/api/v0/projects/source/delete/base")
|
||||||
|
self.assertEqual(resp.status_code, 400)
|
||||||
data = json.loads(resp.data)
|
data = json.loads(resp.data)
|
||||||
self.assertNotEqual(data, None)
|
self.assertNotEqual(data, None)
|
||||||
self.assertEqual(data["status"], False)
|
self.assertEqual(data["status"], False)
|
||||||
@ -581,6 +583,7 @@ class ServerTestCase(unittest.TestCase):
|
|||||||
def test_projects_source_03_delete_unknown(self):
|
def test_projects_source_03_delete_unknown(self):
|
||||||
"""Test /api/v0/projects/source/delete an unknown source"""
|
"""Test /api/v0/projects/source/delete an unknown source"""
|
||||||
resp = self.server.delete("/api/v0/projects/source/delete/unknown-repo")
|
resp = self.server.delete("/api/v0/projects/source/delete/unknown-repo")
|
||||||
|
self.assertEqual(resp.status_code, 400)
|
||||||
data = json.loads(resp.data)
|
data = json.loads(resp.data)
|
||||||
self.assertNotEqual(data, None)
|
self.assertNotEqual(data, None)
|
||||||
self.assertEqual(data["status"], False)
|
self.assertEqual(data["status"], False)
|
||||||
|
Loading…
Reference in New Issue
Block a user