diff --git a/src/pylorax/api/v0.py b/src/pylorax/api/v0.py index a22b23e8..a80238da 100644 --- a/src/pylorax/api/v0.py +++ b/src/pylorax/api/v0.py @@ -22,7 +22,7 @@ from pykickstart.version import makeVersion, RHEL7 from pylorax.api.crossdomain import crossdomain from pylorax.api.recipes import list_branch_files, read_recipe_commit, recipe_filename, list_commits -from pylorax.api.recipes import recipe_from_dict, recipe_from_toml, commit_recipe, delete_recipe +from pylorax.api.recipes import recipe_from_dict, recipe_from_toml, commit_recipe, delete_recipe, revert_recipe from pylorax.api.workspace import workspace_read, workspace_write, workspace_delete from pylorax.creator import DRACUT_DEFAULT, mount_boot_part_over_root from pylorax.creator import make_appliance, make_image, make_livecd, make_live_images @@ -203,3 +203,19 @@ def v0_api(api): return jsonify(status=False, error={"msg":str(e)}), 400 else: return jsonify(status=True) + + @api.route("/api/v0/recipes/undo//", methods=["POST"]) + @crossdomain(origin="*") + def v0_recipes_undo(recipe_name, commit): + """Undo changes to a recipe by reverting to a previous commit.""" + try: + with api.config["GITLOCK"].lock: + revert_recipe(api.config["GITLOCK"].repo, "master", recipe_name, commit) + + # Read the new recipe and write it to the workspace + recipe = read_recipe_commit(api.config["GITLOCK"].repo, "master", recipe_name) + workspace_write(api.config["GITLOCK"].repo, "master", recipe) + except Exception as e: + return jsonify(status=False, error={"msg":str(e)}), 400 + else: + return jsonify(status=True) diff --git a/tests/pylorax/test_server.py b/tests/pylorax/test_server.py index fc7a387a..92e57ad8 100644 --- a/tests/pylorax/test_server.py +++ b/tests/pylorax/test_server.py @@ -256,3 +256,33 @@ class ServerTestCase(unittest.TestCase): self.assertNotEqual(data, None) recipes = data.get("recipes") self.assertEqual("glusterfs" in recipes, False) + + def test_11_recipes_undo(self): + """Test POST /api/v0/recipes/undo/""" + resp = self.server.get("/api/v0/recipes/changes/glusterfs") + data = json.loads(resp.data) + self.assertNotEqual(data, None) + + # Revert it to the first commit + recipes = data.get("recipes") + self.assertNotEqual(recipes, None) + changes = recipes[0].get("changes") + self.assertEqual(len(changes) > 1, True) + + # Revert it to the first commit + commit = changes[-1]["commit"] + resp = self.server.post("/api/v0/recipes/undo/glusterfs/%s" % commit) + data = json.loads(resp.data) + self.assertEqual(data, {"status":True}) + + resp = self.server.get("/api/v0/recipes/changes/glusterfs") + data = json.loads(resp.data) + self.assertNotEqual(data, None) + + recipes = data.get("recipes") + self.assertNotEqual(recipes, None) + changes = recipes[0].get("changes") + self.assertEqual(len(changes) > 1, True) + + expected_msg = "Recipe glusterfs.toml reverted to commit %s" % commit + self.assertEqual(changes[0]["message"], expected_msg)