diff --git a/src/pylorax/api/v0.py b/src/pylorax/api/v0.py index 1090845c..82290032 100644 --- a/src/pylorax/api/v0.py +++ b/src/pylorax/api/v0.py @@ -22,7 +22,8 @@ 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.workspace import workspace_read +from pylorax.api.recipes import recipe_from_dict, recipe_from_toml, commit_recipe +from pylorax.api.workspace import workspace_read, workspace_write from pylorax.creator import DRACUT_DEFAULT, mount_boot_part_over_root from pylorax.creator import make_appliance, make_image, make_livecd, make_live_images from pylorax.creator import make_runtime, make_squashfs @@ -141,3 +142,25 @@ def v0_api(api): errors = sorted(errors, key=lambda e: e["recipe"].lower()) return jsonify(recipes=recipes, errors=errors, offset=offset, limit=limit) + + @api.route("/api/v0/recipes/new", methods=["POST"]) + @crossdomain(origin="*") + def v0_recipes_new(): + """Commit a new recipe""" + errors = [] + try: + if request.headers['Content-Type'] == "text/x-toml": + recipe = recipe_from_toml(request.data) + else: + recipe = recipe_from_dict(request.get_json(cache=False)) + + with api.config["GITLOCK"].lock: + commit_recipe(api.config["GITLOCK"].repo, "master", recipe) + + # Read the recipe with new version and write it to the workspace + recipe = read_recipe_commit(api.config["GITLOCK"].repo, "master", recipe.filename) + 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 246f9eea..3c7cdbd1 100644 --- a/tests/pylorax/test_server.py +++ b/tests/pylorax/test_server.py @@ -19,9 +19,10 @@ from threading import Lock import unittest from flask import json +import pytoml as toml from pylorax.api.recipes import open_or_create_repo, commit_recipe_directory from pylorax.api.server import server, GitLock - +from pylorax.sysutils import joinpaths class ServerTestCase(unittest.TestCase): @@ -35,8 +36,10 @@ class ServerTestCase(unittest.TestCase): server.config['TESTING'] = True self.server = server.test_client() + self.examples_path = "./tests/pylorax/recipes/" + # Import the example recipes - commit_recipe_directory(server.config["GITLOCK"].repo, "master", "tests/pylorax/recipes/") + commit_recipe_directory(server.config["GITLOCK"].repo, "master", self.examples_path) @classmethod def tearDownClass(self): @@ -122,3 +125,47 @@ class ServerTestCase(unittest.TestCase): self.assertEqual(len(data["recipes"]), 1) self.assertEqual(data["recipes"][0]["name"], "http-server") self.assertEqual(len(data["recipes"][0]["changes"]), 1) + + def test_recipes_new_json(self): + """Test the /api/v0/recipes/new route with json recipe""" + test_recipe = {"description": "An example GlusterFS server with samba", + "name":"glusterfs", + "version": "0.2.0", + "modules":[{"name":"glusterfs", "version":"3.7.*"}, + {"name":"glusterfs-cli", "version":"3.7.*"}], + "packages":[{"name":"samba", "version":"4.2.*"}, + {"name":"tmux", "version":"2.2"}]} + + 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/info/glusterfs") + data = json.loads(resp.data) + self.assertNotEqual(data, None) + recipes = data.get("recipes") + self.assertEqual(len(recipes), 1) + self.assertEqual(recipes[0], test_recipe) + + def test_recipes_new_toml(self): + """Test the /api/v0/recipes/new route with toml recipe""" + test_recipe = open(joinpaths(self.examples_path, "glusterfs.toml"), "rb").read() + resp = self.server.post("/api/v0/recipes/new", + data=test_recipe, + content_type="text/x-toml") + data = json.loads(resp.data) + self.assertEqual(data, {"status":True}) + + resp = self.server.get("/api/v0/recipes/info/glusterfs") + data = json.loads(resp.data) + self.assertNotEqual(data, None) + recipes = data.get("recipes") + self.assertEqual(len(recipes), 1) + + # Returned recipe has had its version bumped to 0.2.1 + test_recipe = toml.loads(test_recipe) + test_recipe["version"] = "0.2.1" + + self.assertEqual(recipes[0], test_recipe)