diff --git a/src/pylorax/api/v0.py b/src/pylorax/api/v0.py index 73ba2f3e..ee961461 100644 --- a/src/pylorax/api/v0.py +++ b/src/pylorax/api/v0.py @@ -282,6 +282,60 @@ def v0_api(api): diff = recipe_diff(old_recipe, new_recipe) return jsonify(diff=diff) + @api.route("/api/v0/recipes/depsolve/") + @crossdomain(origin="*") + def v0_recipes_depsolve(recipe_names): + """Return the dependencies for a recipe""" + recipes = [] + errors = [] + for recipe_name in [n.strip() for n in sorted(recipe_names.split(","), key=lambda n: n.lower())]: + # get the recipe + # Get the workspace version (if it exists) + recipe = None + try: + with api.config["GITLOCK"].lock: + recipe = workspace_read(api.config["GITLOCK"].repo, "master", recipe_name) + except Exception: + pass + + if not recipe: + # No workspace version, get the git version (if it exists) + try: + with api.config["GITLOCK"].lock: + recipe = read_recipe_commit(api.config["GITLOCK"].repo, "master", recipe_name) + except Exception as e: + errors.append({"recipe":recipe_name, "msg":str(e)}) + log.error("(v0_recipes_depsolve) %s", str(e)) + + # No recipe found, skip it. + if not recipe: + errors.append({"recipe":recipe_name, "msg":"Recipe not found"}) + continue + + # Combine modules and packages and depsolve the list + # TODO include the version/glob in the depsolving + module_names = map(lambda m: m["name"], recipe["modules"] or []) + package_names = map(lambda p: p["name"], recipe["packages"] or []) + projects = sorted(set(module_names+package_names), key=lambda n: n.lower()) + deps = [] + try: + with api.config["YUMLOCK"].lock: + deps = projects_depsolve(api.config["YUMLOCK"].yb, projects) + except ProjectsError as e: + errors.append({"recipe":recipe_name, "msg":str(e)}) + log.error("(v0_recipes_depsolve) %s", str(e)) + + # Get the NEVRA's of the modules and projects, add as "modules" + modules = [] + for dep in deps: + if dep["name"] in projects: + modules.append(dep) + modules = sorted(modules, key=lambda m: m["name"].lower()) + + recipes.append({"recipe":recipe, "dependencies":deps, "modules":modules}) + + return jsonify(recipes=recipes, errors=errors) + @api.route("/api/v0/projects/list") @crossdomain(origin="*") def v0_projects_list(): diff --git a/tests/pylorax/test_server.py b/tests/pylorax/test_server.py index 9f60e7d6..e5a43405 100644 --- a/tests/pylorax/test_server.py +++ b/tests/pylorax/test_server.py @@ -359,6 +359,17 @@ class ServerTestCase(unittest.TestCase): "old": None}]} self.assertEqual(data, result) + def test_14_recipes_depsolve(self): + """Test /api/v0/recipes/depsolve/""" + resp = self.server.get("/api/v0/recipes/depsolve/glusterfs") + 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"], "glusterfs") + self.assertEqual(len(recipes[0]["dependencies"]) > 10, True) + def test_projects_list(self): """Test /api/v0/projects/list""" resp = self.server.get("/api/v0/projects/list") @@ -405,4 +416,3 @@ class ServerTestCase(unittest.TestCase): self.assertEqual(len(modules), 1) self.assertEqual(modules[0]["name"], "bash") self.assertEqual(modules[0]["dependencies"][0]["name"], "basesystem") -