From 176b12dd8c3e1af9cf9fd44e3829f772fd34011d Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Tue, 12 Dec 2017 11:38:56 +0100 Subject: [PATCH] Fix depsolving empty recipes - Fix `projects_depsolve()` to not consider a successful empty response (rc == 0) as an error. - Fix recipe_from_dict() to default modules and packages to empty lists instead of `None`, to avoid a Python-ism in the API for consumers and stay compatible to the bdcs API. Fixes #290 --- src/pylorax/api/projects.py | 2 +- src/pylorax/api/recipes.py | 4 ++-- tests/pylorax/results/minimal.dict | 2 +- tests/pylorax/results/modules-only.dict | 2 +- tests/pylorax/results/packages-only.dict | 2 +- tests/pylorax/test_server.py | 24 ++++++++++++++++++++++++ 6 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/pylorax/api/projects.py b/src/pylorax/api/projects.py index 0a08d63c..6f643340 100644 --- a/src/pylorax/api/projects.py +++ b/src/pylorax/api/projects.py @@ -198,7 +198,7 @@ def projects_depsolve(yb, project_names): for p in project_names: yb.install(pattern=p) (rc, msg) = yb.buildTransaction() - if rc not in [1,2]: + if rc not in [0, 1, 2]: raise ProjectsError("There was a problem depsolving %s: %s" % (project_names, msg)) yb.tsInfo.makelists() deps = sorted(map(tm_to_dep, yb.tsInfo.installed + yb.tsInfo.depinstalled), key=lambda p: p["name"].lower()) diff --git a/src/pylorax/api/recipes.py b/src/pylorax/api/recipes.py index 13dc74f2..68ea34b4 100644 --- a/src/pylorax/api/recipes.py +++ b/src/pylorax/api/recipes.py @@ -142,11 +142,11 @@ def recipe_from_dict(recipe_dict): if recipe_dict.get("modules"): modules = [RecipeModule(m.get("name"), m.get("version")) for m in recipe_dict["modules"]] else: - modules = None + modules = [] if recipe_dict.get("packages"): packages = [RecipePackage(p.get("name"), p.get("version")) for p in recipe_dict["packages"]] else: - packages = None + packages = [] name = recipe_dict["name"] description = recipe_dict["description"] version = recipe_dict.get("version", None) diff --git a/tests/pylorax/results/minimal.dict b/tests/pylorax/results/minimal.dict index 743b10a0..4af1c108 100644 --- a/tests/pylorax/results/minimal.dict +++ b/tests/pylorax/results/minimal.dict @@ -1 +1 @@ -{'description': u'An example http server with PHP and MySQL support.', 'packages': None, 'modules': None, 'version': u'0.0.1', 'name': u'http-server'} +{'description': u'An example http server with PHP and MySQL support.', 'packages': [], 'modules': [], 'version': u'0.0.1', 'name': u'http-server'} diff --git a/tests/pylorax/results/modules-only.dict b/tests/pylorax/results/modules-only.dict index e86f43c9..64b74b31 100644 --- a/tests/pylorax/results/modules-only.dict +++ b/tests/pylorax/results/modules-only.dict @@ -1 +1 @@ -{'description': u'An example http server with PHP and MySQL support.', 'packages': None, 'modules': [{'version': u'2.4.*', 'name': u'httpd'}, {'version': u'5.4', 'name': u'mod_auth_kerb'}, {'version': u'2.4.*', 'name': u'mod_ssl'}, {'version': u'5.4.*', 'name': u'php'}, {'version': u'5.4.*', 'name': u'php-mysql'}], 'version': u'0.0.1', 'name': u'http-server'} +{'description': u'An example http server with PHP and MySQL support.', 'packages': [], 'modules': [{'version': u'2.4.*', 'name': u'httpd'}, {'version': u'5.4', 'name': u'mod_auth_kerb'}, {'version': u'2.4.*', 'name': u'mod_ssl'}, {'version': u'5.4.*', 'name': u'php'}, {'version': u'5.4.*', 'name': u'php-mysql'}], 'version': u'0.0.1', 'name': u'http-server'} diff --git a/tests/pylorax/results/packages-only.dict b/tests/pylorax/results/packages-only.dict index 2f5b2773..8ad5412c 100644 --- a/tests/pylorax/results/packages-only.dict +++ b/tests/pylorax/results/packages-only.dict @@ -1 +1 @@ -{'description': u'An example http server with PHP and MySQL support.', 'packages': [{'version': u'6.6.*', 'name': u'openssh-server'}, {'version': u'3.0.*', 'name': u'rsync'}, {'version': u'2.2', 'name': u'tmux'}], 'modules': None, 'version': u'0.0.1', 'name': u'http-server'} +{'description': u'An example http server with PHP and MySQL support.', 'packages': [{'version': u'6.6.*', 'name': u'openssh-server'}, {'version': u'3.0.*', 'name': u'rsync'}, {'version': u'2.2', 'name': u'tmux'}], 'modules': [], 'version': u'0.0.1', 'name': u'http-server'} diff --git a/tests/pylorax/test_server.py b/tests/pylorax/test_server.py index 606b1cdb..35acd48a 100644 --- a/tests/pylorax/test_server.py +++ b/tests/pylorax/test_server.py @@ -369,6 +369,30 @@ class ServerTestCase(unittest.TestCase): self.assertEqual(len(recipes), 1) self.assertEqual(recipes[0]["recipe"]["name"], "glusterfs") self.assertEqual(len(recipes[0]["dependencies"]) > 10, True) + self.assertFalse(data.get("errors")) + + def test_14_recipes_depsolve_empty(self): + """Test /api/v0/recipes/depsolve/ on empty recipe""" + test_recipe = {"description": "An empty recipe", + "name":"void", + "version": "0.1.0"} + resp = self.server.post("/api/v0/recipes/new", + data=json.dumps(test_recipe), + content_type="application/json") + data = json.loads(resp.data) + self.assertEqual(data, {"status":True}) + + resp = self.server.get("/api/v0/recipes/depsolve/void") + data = json.loads(resp.data) + self.assertNotEqual(data, None) + recipes = data.get("recipes") + self.assertNotEqual(recipes, None) + self.assertEqual(len(recipes), 1) + self.assertEqual(recipes[0]["recipe"]["name"], "void") + self.assertEqual(recipes[0]["recipe"]["packages"], []) + self.assertEqual(recipes[0]["recipe"]["modules"], []) + self.assertEqual(recipes[0]["dependencies"], []) + self.assertFalse(data.get("errors")) def test_15_recipes_freeze(self): """Test /api/v0/recipes/freeze/"""