diff --git a/lib/cdist/core/object.py b/lib/cdist/core/object.py index 76634a65..b7890eeb 100644 --- a/lib/cdist/core/object.py +++ b/lib/cdist/core/object.py @@ -81,6 +81,7 @@ class Object(object): """define equality as 'attributes are the same'""" return self.__dict__ == other.__dict__ + # FIXME: still needed? @property def explorer_path(self): """Create and return the relative path to this objects explorers""" @@ -93,6 +94,7 @@ class Object(object): requirements = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'require')) parameters = fsproperty.DirectoryDictProperty(lambda obj: os.path.join(obj.absolute_path, 'parameter')) + explorers = fsproperty.DirectoryDictProperty(lambda obj: os.path.join(obj.base_path, obj.explorer_path)) changed = fsproperty.FileBooleanProperty(lambda obj: os.path.join(obj.absolute_path, "changed")) prepared = fsproperty.FileBooleanProperty(lambda obj: os.path.join(obj.absolute_path, "prepared")) ran = fsproperty.FileBooleanProperty(lambda obj: os.path.join(obj.absolute_path, "ran")) diff --git a/lib/cdist/exec.py b/lib/cdist/exec.py index 7ec9bc0a..13cec499 100644 --- a/lib/cdist/exec.py +++ b/lib/cdist/exec.py @@ -23,75 +23,75 @@ import logging import os import subprocess -log = logging.getLogger(__name__) - import cdist -class ExecWrapper(object): - def __init__(self, remote_exec, remote_copy, target_host): + +class Wrapper(object): + def __init__(self, target_host, remote_exec, remote_copy): + self.target_host = target_host self.remote_exec = remote_exec - -def shell_run_or_debug_fail(script, *args, remote_prefix=False, **kargs): - # Manually execute /bin/sh, because sh -e does what we want - # and sh -c -e does not exit if /bin/false called - args[0][:0] = [ "/bin/sh", "-e" ] - - if remote_prefix: - remote_prefix = os.environ['__remote_exec'].split() - remote_prefix.append(os.environ['__target_host']) - args[0][:0] = remote_prefix - - log.debug("Shell exec cmd: %s", args) - - if 'env' in kargs: - log.debug("Shell exec env: %s", kargs['env']) - - try: - subprocess.check_call(*args, **kargs) - except subprocess.CalledProcessError: - log.error("Code that raised the error:\n") - - if remote_prefix: - run_or_fail(["cat", script], remote_prefix=remote_prefix) - - else: - try: - script_fd = open(script) - print(script_fd.read()) - script_fd.close() - except IOError as error: - raise cdist.Error(str(error)) - - raise cdist.Error("Command failed (shell): " + " ".join(*args)) - except OSError as error: - raise cdist.Error(" ".join(*args) + ": " + error.args[1]) - -def run_or_fail(*args, remote_prefix=False, **kargs): - if remote_prefix: - remote_prefix = os.environ['__remote_exec'].split() - remote_prefix.append(os.environ['__target_host']) - args[0][:0] = remote_prefix - - log.debug("Exec: " + " ".join(*args)) - try: - subprocess.check_call(*args, **kargs) - except subprocess.CalledProcessError: - raise cdist.Error("Command failed: " + " ".join(*args)) - except OSError as error: - raise cdist.Error(" ".join(*args) + ": " + error.args[1]) - - + self.remote_copy = remote_copy + self.log = logging.getLogger(self.target_host) def remote_mkdir(self, directory): """Create directory on remote side""" - cdist.exec.run_or_fail(["mkdir", "-p", directory], remote_prefix=True) + self.run_or_fail(["mkdir", "-p", directory], remote=True) def remove_remote_path(self, destination): """Ensure path on remote side vanished""" - cdist.exec.run_or_fail(["rm", "-rf", destination], remote_prefix=True) + self.run_or_fail(["rm", "-rf", destination], remote=True) def transfer_path(self, source, destination): """Transfer directory and previously delete the remote destination""" self.remove_remote_path(destination) - cdist.exec.run_or_fail(os.environ['__remote_copy'].split() + + self.run_or_fail(os.environ['__remote_copy'].split() + ["-r", source, self.target_host + ":" + destination]) + + def shell_run_or_debug_fail(self, script, *args, remote=False, **kargs): + # Manually execute /bin/sh, because sh -e does what we want + # and sh -c -e does not exit if /bin/false called + args[0][:0] = [ "/bin/sh", "-e" ] + + if remote: + remote_prefix = self.remote_exec.split() + remote_prefix.append(self.target_host) + args[0][:0] = remote_prefix + + self.log.debug("Shell exec cmd: %s", args) + + if 'env' in kargs: + self.log.debug("Shell exec env: %s", kargs['env']) + + try: + subprocess.check_call(*args, **kargs) + except subprocess.CalledProcessError: + self.log.error("Code that raised the error:\n") + + if remote: + self.run_or_fail(["cat", script], remote=remote) + + else: + try: + script_fd = open(script) + print(script_fd.read()) + script_fd.close() + except IOError as error: + raise cdist.Error(str(error)) + + raise cdist.Error("Command failed (shell): " + " ".join(*args)) + except OSError as error: + raise cdist.Error(" ".join(*args) + ": " + error.args[1]) + + def run_or_fail(self, *args, remote=False, **kargs): + if remote: + remote_prefix = self.remote_exec.split() + remote_prefix.append(self.target_host) + args[0][:0] = remote_prefix + + self.log.debug("Exec: " + " ".join(*args)) + try: + subprocess.check_call(*args, **kargs) + except subprocess.CalledProcessError: + raise cdist.Error("Command failed: " + " ".join(*args)) + except OSError as error: + raise cdist.Error(" ".join(*args) + ": " + error.args[1]) diff --git a/lib/cdist/test/object/__init__.py b/lib/cdist/test/object/__init__.py index eee1563c..6f26fd19 100644 --- a/lib/cdist/test/object/__init__.py +++ b/lib/cdist/test/object/__init__.py @@ -62,7 +62,7 @@ class ObjectTestCase(unittest.TestCase): self.cdist_object.changed = False self.cdist_object.prepared = False self.cdist_object.ran = False - self.cdist_object.source = "" + self.cdist_object.source = [] def test_name(self): self.assertEqual(self.cdist_object.name, '__third/moon') @@ -92,6 +92,19 @@ class ObjectTestCase(unittest.TestCase): expected_parameters = {'planet': 'Saturn', 'name': 'Prometheus'} self.assertEqual(self.cdist_object.parameters, expected_parameters) + def test_explorers(self): + self.assertEqual(self.cdist_object.explorers, {}) + + def test_explorers_after_changing(self): + expected = {'first': 'foo', 'second': 'bar'} + # when set, written to file + self.cdist_object.explorers = expected + # when accessed, read from file + self.assertEqual(self.cdist_object.explorers, expected) + # remove dynamically created folder + self.cdist_object.explorers = {} + os.rmdir(os.path.join(self.cdist_object.base_path, self.cdist_object.explorer_path)) + def test_requirements(self): expected = [] self.assertEqual(list(self.cdist_object.requirements), expected) @@ -118,8 +131,8 @@ class ObjectTestCase(unittest.TestCase): self.assertTrue(self.cdist_object.ran) def test_source(self): - self.assertEqual(self.cdist_object.source, '') + self.assertEqual(list(self.cdist_object.source), []) def test_source_after_changing(self): - self.cdist_object.source = '/path/to/manifest' - self.assertEqual(self.cdist_object.source, '/path/to/manifest') + self.cdist_object.source = ['/path/to/manifest'] + self.assertEqual(list(self.cdist_object.source), ['/path/to/manifest']) diff --git a/lib/cdist/test/object/fixtures/object/__third/moon/.cdist/explorer/.keep b/lib/cdist/test/object/fixtures/object/__third/moon/.cdist/explorer/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/cdist/test/test_exec.py b/lib/cdist/test/test_exec.py index 901b5efd..c2bb52f6 100644 --- a/lib/cdist/test/test_exec.py +++ b/lib/cdist/test/test_exec.py @@ -22,18 +22,14 @@ import os -import sys import shutil -import subprocess import tempfile import unittest -sys.path.insert(0, os.path.abspath( - os.path.join(os.path.dirname(os.path.realpath(__file__)), '../lib'))) - import cdist.exec -class Exec(unittest.TestCase): + +class ExecTestCase(unittest.TestCase): def setUp(self): """Create shell code and co.""" @@ -49,32 +45,35 @@ class Exec(unittest.TestCase): false_fd.writelines(["#!/bin/sh\n", "/bin/false"]) false_fd.close() + target_host = "does.not.exist" + remote_exec = "ssh -o User=root -q" + remote_copy = "scp -o User=root -q" + self.wrapper = cdist.exec.Wrapper(target_host, remote_exec, remote_copy) + def tearDown(self): shutil.rmtree(self.temp_dir) def test_local_success_shell(self): try: - cdist.exec.shell_run_or_debug_fail(self.shell_true, [self.shell_true]) + self.wrapper.shell_run_or_debug_fail(self.shell_true, [self.shell_true]) except cdist.Error: failed = True else: failed = False - self.assertFalse(failed) def test_local_fail_shell(self): - self.assertRaises(cdist.Error, cdist.exec.shell_run_or_debug_fail, + self.assertRaises(cdist.Error, self.wrapper.shell_run_or_debug_fail, self.shell_false, [self.shell_false]) def test_local_success(self): try: - cdist.exec.run_or_fail(["/bin/true"]) + self.wrapper.run_or_fail(["/bin/true"]) except cdist.Error: failed = True else: failed = False - self.assertFalse(failed) def test_local_fail(self): - self.assertRaises(cdist.Error, cdist.exec.run_or_fail, ["/bin/false"]) + self.assertRaises(cdist.Error, self.wrapper.run_or_fail, ["/bin/false"]) diff --git a/lib/cdist/util/fsproperty.py b/lib/cdist/util/fsproperty.py index c18a1553..68d5edaa 100644 --- a/lib/cdist/util/fsproperty.py +++ b/lib/cdist/util/fsproperty.py @@ -134,7 +134,11 @@ class FileListProperty(FileList): def __set__(self, obj, value): self._set_path(obj) - os.unlink(self.path) + try: + os.unlink(self.path) + except EnvironmentError: + # ignored + pass for item in value: self.append(item)