From b7f651a631881e782e39d4a3b62a3af0def1ff5f Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Wed, 8 Nov 2017 13:14:38 -0800 Subject: [PATCH] Add workspace module and tests This handles the recipe workspace, which is a temporary location to store recipes before committing them to git. It will be used by the /recipes/ API. --- src/pylorax/api/workspace.py | 99 +++++++++++++++++++++++++++++++++ tests/pylorax/test_workspace.py | 75 +++++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 tests/pylorax/test_workspace.py diff --git a/src/pylorax/api/workspace.py b/src/pylorax/api/workspace.py index e69de29b..6d9a9c8f 100644 --- a/src/pylorax/api/workspace.py +++ b/src/pylorax/api/workspace.py @@ -0,0 +1,99 @@ +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +import os + +from pylorax.api.recipes import recipe_filename, recipe_from_toml, RecipeFileError +from pylorax.sysutils import joinpaths + + +def workspace_dir(repo, branch): + """Create the workspace's path from a Repository and branch + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :returns: The path to the branch's workspace directory + :rtype: str + + """ + repo_path = repo.get_location().get_path() + return joinpaths(repo_path, "workspace", branch) + + +def workspace_read(repo, branch, recipe_name): + """Read a Recipe from the branch's workspace + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: The name of the recipe + :type recipe_name: str + :returns: The workspace copy of the recipe, or None if it doesn't exist + :rtype: Recipe or None + :raises: RecipeFileError + """ + ws_dir = workspace_dir(repo, branch) + if not os.path.isdir(ws_dir): + os.makedirs(ws_dir) + filename = joinpaths(ws_dir, recipe_filename(recipe_name)) + if not os.path.exists(filename): + return None + try: + f = open(filename, 'rb') + recipe = recipe_from_toml(f.read()) + except IOError: + raise RecipeFileError + return recipe + + +def workspace_write(repo, branch, recipe): + """Write a recipe to the workspace + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe: The recipe to write to the workspace + :type recipe: Recipe + :returns: None + :raises: IO related errors + """ + ws_dir = workspace_dir(repo, branch) + if not os.path.isdir(ws_dir): + os.makedirs(ws_dir) + filename = joinpaths(ws_dir, recipe.filename) + open(filename, 'wb').write(recipe.toml()) + + +def workspace_delete(repo, branch, recipe_name): + """Delete the recipe from the workspace + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: The name of the recipe + :type recipe_name: str + :returns: None + :raises: IO related errors + """ + ws_dir = workspace_dir(repo, branch) + filename = joinpaths(ws_dir, recipe_filename(recipe_name)) + if os.path.exists(filename): + os.unlink(filename) diff --git a/tests/pylorax/test_workspace.py b/tests/pylorax/test_workspace.py new file mode 100644 index 00000000..8fcab15f --- /dev/null +++ b/tests/pylorax/test_workspace.py @@ -0,0 +1,75 @@ +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +import os +import shutil +import tempfile +import unittest + +import pylorax.api.recipes as recipes +from pylorax.api.workspace import workspace_dir, workspace_read, workspace_write, workspace_delete +from pylorax.sysutils import joinpaths + +class WorkspaceTest(unittest.TestCase): + @classmethod + def setUpClass(self): + self.repo_dir = tempfile.mkdtemp(prefix="lorax.test.repo.") + self.repo = recipes.open_or_create_repo(self.repo_dir) + + self.results_path = "./tests/pylorax/results/" + self.examples_path = "./tests/pylorax/recipes/" + + recipe_path = joinpaths(self.examples_path, "http-server.toml") + f = open(recipe_path, 'rb') + self.example_recipe = recipes.recipe_from_toml(f.read()) + + @classmethod + def tearDownClass(self): + if self.repo is not None: + del self.repo + shutil.rmtree(self.repo_dir) + + def test_01_repo_creation(self): + """Test that creating the repository succeeded""" + self.assertNotEqual(self.repo, None) + + def test_02_workspace_dir(self): + """Test the workspace_dir function""" + ws_dir = workspace_dir(self.repo, "master") + self.assertEqual(ws_dir, joinpaths(self.repo_dir, "git", "workspace", "master")) + + def test_03_workspace_write(self): + """Test the workspace_write function""" + # Use an example recipe + workspace_write(self.repo, "master", self.example_recipe) + + # The file should have ended up here + ws_recipe_path = joinpaths(self.repo_dir, "git", "workspace", "master", "http-server.toml") + self.assertEqual(os.path.exists(ws_recipe_path), True) + + def test_04_workspace_read(self): + """Test the workspace_read function""" + # The recipe was written by the workspace_write test. Read it and compare with the source recipe. + recipe = workspace_read(self.repo, "master", "http-server") + self.assertEqual(self.example_recipe, recipe) + + def test_05_workspace_delete(self): + """Test the workspace_delete function""" + ws_recipe_path = joinpaths(self.repo_dir, "git", "workspace", "master", "http-server.toml") + + self.assertEqual(os.path.exists(ws_recipe_path), True) + workspace_delete(self.repo, "master", "http-server") + self.assertEqual(os.path.exists(ws_recipe_path), False)