diff --git a/src/pylorax/api/server.py b/src/pylorax/api/server.py index 044e78c2..3eca9df3 100644 --- a/src/pylorax/api/server.py +++ b/src/pylorax/api/server.py @@ -14,15 +14,17 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # - +from collections import namedtuple from flask import Flask from pylorax.api.crossdomain import crossdomain from pylorax.api.v0 import v0_api +GitLock = namedtuple("GitLock", ["repo", "lock", "dir"]) + server = Flask(__name__) -__all__ = ["server"] +__all__ = ["server", "GitLock"] @server.route('/') @crossdomain(origin="*") diff --git a/src/pylorax/api/v0.py b/src/pylorax/api/v0.py index 2b4b3d5a..ff33a053 100644 --- a/src/pylorax/api/v0.py +++ b/src/pylorax/api/v0.py @@ -14,13 +14,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -from flask import jsonify +from flask import jsonify, request # Use pykickstart to calculate disk image size from pykickstart.parser import KickstartParser from pykickstart.version import makeVersion, RHEL7 from pylorax.api.crossdomain import crossdomain +from pylorax.api.recipes import list_branch_files 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 @@ -29,6 +30,8 @@ from pylorax.imgutils import Mount, PartitionMount, umount from pylorax.installer import InstallError from pylorax.sysutils import joinpaths +# The API functions don't actually get called by any code here +# pylint: disable=unused-variable # no-virt mode doesn't need libvirt, so make it optional try: @@ -42,3 +45,18 @@ def v0_api(api): @crossdomain(origin="*") def v0_status(): return jsonify(build="devel", api="0", db_version="0", schema_version="0", db_supported=False) + + @api.route("/api/v0/recipes/list") + @crossdomain(origin="*") + def v0_recipes_list(): + """List the available recipes on a branch.""" + try: + limit = int(request.args.get("limit", "20")) + offset = int(request.args.get("offset", "0")) + except ValueError: + # TODO return an error + pass + + with api.config["GITLOCK"].lock: + recipes = map(lambda f: f[:-5], list_branch_files(api.config["GITLOCK"].repo, "master")) + return jsonify(recipes=recipes, limit=limit, offset=offset, total=len(recipes)) diff --git a/src/sbin/lorax-composer b/src/sbin/lorax-composer index 222c76f7..27806cd8 100755 --- a/src/sbin/lorax-composer +++ b/src/sbin/lorax-composer @@ -25,10 +25,12 @@ pylorax_log = logging.getLogger("pylorax") import argparse import os import sys +from threading import Lock from gevent.wsgi import WSGIServer from pylorax import vernum -from pylorax.api.server import server +from pylorax.api.recipes import open_or_create_repo, commit_recipe_directory +from pylorax.api.server import server, GitLock VERSION = "{0}-{1}".format(os.path.basename(sys.argv[0]), vernum) @@ -105,6 +107,14 @@ if __name__ == '__main__': sys.exit(1) setup_logging(opts.logfile) + + server.config["REPO_DIR"] = opts.RECIPES + repo = open_or_create_repo(server.config["REPO_DIR"]) + server.config["GITLOCK"] = GitLock(repo=repo, lock=Lock(), dir=opts.RECIPES) + + # Import example recipes + commit_recipe_directory(server.config["GITLOCK"].repo, "master", opts.RECIPES) + http_server = WSGIServer((opts.host, opts.port), server) # The server writes directly to a file object, so point to our log directory server_logfile = os.path.abspath(os.path.dirname(opts.logfile))+"/server.log" diff --git a/tests/pylorax/test_server.py b/tests/pylorax/test_server.py index a6b5f539..cb9197dd 100644 --- a/tests/pylorax/test_server.py +++ b/tests/pylorax/test_server.py @@ -14,20 +14,30 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -import os +import tempfile +from threading import Lock import unittest from flask import json -from pylorax.api.server import server +from pylorax.api.recipes import open_or_create_repo, commit_recipe_directory +from pylorax.api.server import server, GitLock class ServerTestCase(unittest.TestCase): @classmethod def setUpClass(self): + repo_dir = tempfile.mkdtemp(prefix="lorax.test.repo.") + server.config["REPO_DIR"] = repo_dir + repo = open_or_create_repo(server.config["REPO_DIR"]) + server.config["GITLOCK"] = GitLock(repo=repo, lock=Lock(), dir=repo_dir) + server.config['TESTING'] = True self.server = server.test_client() + # Import the example recipes + commit_recipe_directory(server.config["GITLOCK"].repo, "master", "tests/pylorax/recipes/") + @classmethod def tearDownClass(self): pass @@ -38,3 +48,11 @@ class ServerTestCase(unittest.TestCase): resp = self.server.get("/api/v0/status") data = json.loads(resp.data) self.assertEqual(data, status_dict) + + def test_recipes_list(self): + """Test the /api/v0/recipes/list route""" + list_dict = {"recipes":["atlas", "development", "glusterfs", "http-server", "jboss", "kubernetes"], + "limit":20, "offset":0, "total":6} + resp = self.server.get("/api/v0/recipes/list") + data = json.loads(resp.data) + self.assertEqual(data, list_dict)