Example #1
0
 def setUp(self):
     self.nulecule_base = Nulecule_Base(dryrun=True)
     self.tmpdir = tempfile.mkdtemp(prefix="atomicapp-test", dir="/tmp")
     self.artifact_dir = os.path.dirname(
         __file__) + '/docker_artifact_test/'
     self.plugin = Plugin()
     self.plugin.load_plugins()
Example #2
0
class TestNuleculeBase(unittest.TestCase):
    def setUp(self):
        self.nulecule_base = Nulecule_Base(dryrun = True)
        self.tmpdir = tempfile.mkdtemp(prefix = "atomicapp-test", dir = "/tmp")
        self.plugin = Plugin()
        self.plugin.load_plugins()

    def tearDown(self):
        pass

    def create_temp_file(self):
        return tempfile.mktemp(prefix = "test-config", dir = self.tmpdir)

    def prepare_provider(self, data):
        self.nulecule_base.loadAnswers(data)
        provider_class = self.plugin.getProvider(self.nulecule_base.provider)
        config = self.nulecule_base.getValues(skip_asking=True)
        provider = provider_class(config, self.tmpdir, dryrun = False)

        return provider

    @mock.patch.object(KubernetesProvider, '_call', mock_provider_call)
    def test_provider_config_exist(self):
        provider_config_path = self.create_temp_file()
        mock_content = "%s_%s" % (MOCK_CONTENT, "_unchanged")
        with open(provider_config_path, "w") as fp:
            fp.write(mock_content)

        data = {'general': {'namespace': 'testing', 'provider': 'kubernetes', 'providerconfig': provider_config_path}}
        
        provider = self.prepare_provider(data)

        self.assertEqual(provider.config_file, provider_config_path)
        provider.checkConfigFile()
        with open(provider_config_path, "r") as fp:
            self.assertEqual(fp.read(), mock_content)

    @mock.patch("kubernetes.KubernetesProvider._call", mock_provider_call)
    def test_provider_check_config_generation(self):
        path = self.create_temp_file()
        data = {'general': {'namespace': 'testing', 'provider': 'kubernetes', 'providerconfig': path}}

        provider = self.prepare_provider(data)

        provider.checkConfigFile()
        with open(path, "r") as fp:
            self.assertEqual(fp.read(), MOCK_CONTENT)

    def test_provider_check_config_fail(self):
        path = self.create_temp_file()
        data = {'general': {'namespace': 'testing', 'provider': 'openshift'}}

        provider = self.prepare_provider(data)

        self.assertRaises(ProviderFailedException, provider.checkConfigFile)
Example #3
0
class TestDockerProviderBase(unittest.TestCase):

    # Create a temporary directory for our setup as well as load the required providers
    def setUp(self):
        self.nulecule_base = Nulecule_Base(dryrun=True)
        self.tmpdir = tempfile.mkdtemp(prefix="atomicapp-test", dir="/tmp")
        self.artifact_dir = os.path.dirname(
            __file__) + '/docker_artifact_test/'
        self.plugin = Plugin()
        self.plugin.load_plugins()

    def tearDown(self):
        pass

    # Lets prepare the docker provider with pre-loaded configuration
    def prepare_provider(self, data):
        self.nulecule_base.loadAnswers(data)
        provider_class = self.plugin.getProvider(self.nulecule_base.provider)
        config = self.nulecule_base.getValues(skip_asking=True)
        provider = provider_class(config, self.tmpdir, dryrun=True)
        return provider

    # Test deploying multiple artifacts within docker
    def test_multiple_artifact_load(self):
        data = {'general': {'namespace': 'test', 'provider': 'docker'}}
        provider = self.prepare_provider(data)
        provider.init()
        provider.artifacts = [
            self.artifact_dir + 'hello-world-one',
            self.artifact_dir + 'hello-world-two',
            self.artifact_dir + 'hello-world-three'
        ]
        # Mock the effects of 'docker ps -a'. As if each deployment adds the container to the host
        mock_container_list = mock.Mock(side_effect=[
            ["atomic_default_e9b9a7bfe8f9"],
            ["atomic_default_e9b9a7bfe8f9", "atomic_test_e9b9a7bfe8f9"],
            [
                "atomic_default_e9b9a7bfe8f9", "atomic_test_e9b9a7bfe8f9",
                "atomic_test_e9b9a7bfe8f9"
            ]
        ])
        with mock.patch("docker.DockerProvider._get_containers",
                        mock_container_list):
            provider.deploy()

    # Patch in a general container list and make sure it fails if there is already a container with the same name
    @mock.patch("docker.DockerProvider._get_containers", mock_name_get_call)
    def test_namespace_name_check(self):
        data = {'general': {'namespace': 'default', 'provider': 'docker'}}
        provider = self.prepare_provider(data)
        provider.init()
        provider.artifacts = [self.artifact_dir + 'hello-world-one']
        with pytest.raises(ProviderFailedException):
            provider.deploy()
Example #4
0
    def __init__(self, config, basepath, graph, provider, dryrun):
        self.plugin = Plugin()

        self.config = config
        self.basepath = basepath
        self.graph = graph
        self.dryrun = dryrun

        # We initialize the provider in order to gather provider-specific
        # information
        p = self.plugin.getProvider(provider)
        self.provider = p(config, basepath, dryrun)
        self.provider.init()
Example #5
0
class TestDockerProviderBase(unittest.TestCase):
    
    # Create a temporary directory for our setup as well as load the required providers
    def setUp(self):
        self.nulecule_base = Nulecule_Base(dryrun = True)
        self.tmpdir = tempfile.mkdtemp(prefix = "atomicapp-test", dir = "/tmp")
        self.artifact_dir = os.path.dirname(__file__) + '/docker_artifact_test/'
        self.plugin = Plugin()
        self.plugin.load_plugins()

    def tearDown(self):
        pass
    
    # Lets prepare the docker provider with pre-loaded configuration
    def prepare_provider(self, data):
        self.nulecule_base.loadAnswers(data)
        provider_class = self.plugin.getProvider(self.nulecule_base.provider)
        config = self.nulecule_base.getValues(skip_asking=True)
        provider = provider_class(config, self.tmpdir, dryrun = True)
        return provider

    # Test deploying multiple artifacts within docker
    def test_multiple_artifact_load(self):
        data = {'general': {'namespace': 'test', 'provider': 'docker'}}
        provider = self.prepare_provider(data)
        provider.init()
        provider.artifacts = [
                self.artifact_dir + 'hello-world-one',
                self.artifact_dir + 'hello-world-two',
                self.artifact_dir + 'hello-world-three'
                ]
        # Mock the effects of 'docker ps -a'. As if each deployment adds the container to the host
        mock_container_list = mock.Mock(side_effect = [
            ["atomic_default_e9b9a7bfe8f9"], 
            ["atomic_default_e9b9a7bfe8f9", "atomic_test_e9b9a7bfe8f9"],
            ["atomic_default_e9b9a7bfe8f9", "atomic_test_e9b9a7bfe8f9", "atomic_test_e9b9a7bfe8f9"]
            ])
        with mock.patch("docker.DockerProvider._get_containers", mock_container_list):
            provider.deploy()

   
    # Patch in a general container list and make sure it fails if there is already a container with the same name 
    @mock.patch("docker.DockerProvider._get_containers", mock_name_get_call)
    def test_namespace_name_check(self):
        data = {'general': {'namespace': 'default', 'provider': 'docker'}}
        provider = self.prepare_provider(data)
        provider.init()
        provider.artifacts = [self.artifact_dir + 'hello-world-one']
        with pytest.raises(ProviderFailedException):
            provider.deploy()
Example #6
0
 def test_getProvider(self):
     """
     Test if getProvider is returning appropriate classes to the
     corresponding keys.
     """
     p = Plugin()
    
     docker_mock = mock.Mock()
     kubernetes_mock = mock.Mock()
     # keep some mock objects in place of the actual corresponding
     # classes, getProvider reads from `plugins` dict.
     p.plugins = {
         'docker': docker_mock,
         'kubernetes': kubernetes_mock,
     }
     self.assertEqual(p.getProvider('docker'), docker_mock)
     self.assertEqual(p.getProvider('kubernetes'), kubernetes_mock)
     # if non-existent key provided
     self.assertEqual(p.getProvider('some_random'), None)
    def __init__(self, config, basepath, graph, provider, dryrun):
        self.plugin = Plugin()

        self.config = config
        self.basepath = basepath
        self.graph = graph
        self.dryrun = dryrun

        # We initialize the provider in order to gather provider-specific
        # information
        p = self.plugin.getProvider(provider)
        self.provider = p(config, basepath, dryrun)
        self.provider.init()
Example #8
0
    def test_getProvider(self):
        """
        Test if getProvider is returning appropriate classes to the
        corresponding keys.
        """
        p = Plugin()

        docker_mock = mock.Mock()
        kubernetes_mock = mock.Mock()
        # keep some mock objects in place of the actual corresponding
        # classes, getProvider reads from `plugins` dict.
        p.plugins = {
            'docker': docker_mock,
            'kubernetes': kubernetes_mock,
        }
        self.assertEqual(p.getProvider('docker'), docker_mock)
        self.assertEqual(p.getProvider('kubernetes'), kubernetes_mock)
        # if non-existent key provided
        self.assertEqual(p.getProvider('some_random'), None)
Example #9
0
class Requirements:
    """
    Requirements will search what is currently being used under
    the requirements section of Nulecule and deploy in accordance
    to the graph variables as well as whether or not said requirement
    exists within the provider.

    The REQUIREMENTS_FUNCTIONS dictionary maps all current requirement
    names to the function names for each provider.

    For example, the persistentVolume requirement in Nulecule is mapped as
    the persistent_storage function within each provider.

    Requirements tries to be as modular as possible.
    """
    def __init__(self, config, basepath, graph, provider, dryrun):
        self.plugin = Plugin()
        self.plugin.load_plugins()

        self.config = config
        self.basepath = basepath
        self.graph = graph
        self.dryrun = dryrun

        # We initialize the provider in order to gather provider-specific
        # information
        p = self.plugin.getProvider(provider)
        self.provider = p(config, basepath, dryrun)
        self.provider.init()

    def run(self):
        self._exec("run")

    def stop(self):
        self._exec("stop")

    # Find if the requirement does not exist within REQUIREMENT_FUNCTIONS
    def _find_requirement_function_name(self, key):
        logger.debug("Checking if %s matches any of %s" %
                     (key, REQUIREMENT_FUNCTIONS))
        if key in REQUIREMENT_FUNCTIONS.keys():
            return REQUIREMENT_FUNCTIONS[key]
        raise RequirementFailedException("Requirement %s does not exist." %
                                         key)

    # We loop through the given requirements graph and
    # execute each passed requirement
    def _exec(self, action):
        for req in self.graph:
            key_name = req.keys()[0]
            requirement_function = self._find_requirement_function_name(
                key_name)

            # Check to see if the function exists in the provider,
            # if it does not: warn the user
            try:
                requirement = getattr(self.provider, requirement_function)
            except AttributeError:
                logger.warning(
                    "Requirement %s does not exist within %s. Skipping." %
                    (requirement_function, self.provider))
                continue

            # Run the requirement function
            requirement(req[key_name], action)
Example #10
0
class NuleculeBase(object):

    """
    This is the base class for Nulecule and NuleculeComponent in
    atomicapp.nulecule.base.
    """

    def __init__(self, basepath, params, namespace):
        self.plugin = Plugin()
        self.basepath = basepath
        self.params = params or []
        self.namespace = namespace

    def load(self):
        pass

    def load_config(self, config, ask=False, skip_asking=False):
        """
        Load config data. Sets the loaded config data to self.config.

        Args:
            config (dict): Initial config data
            ask (bool): When True, ask for values for a param from user even
                        if the param has a default value
            skip_asking (bool): When True, skip asking for values for params
                                with missing values and set the value as
                                None

        Returns:
            None
        """
        self.config = config
        for param in self.params:
            value = config.get(param[NAME_KEY], scope=self.namespace, ignore_sources=["defaults"])
            if value is None:
                if ask or (not skip_asking and param.get(DEFAULTNAME_KEY) is None):
                    cockpit_logger.info("%s is missing in answers.conf." % param[NAME_KEY])
                    value = config.get(param[NAME_KEY], scope=self.namespace) or Utils.askFor(
                        param[NAME_KEY], param, self.namespace
                    )
                else:
                    value = param.get(DEFAULTNAME_KEY)
                config.set(param[NAME_KEY], value, source="runtime", scope=self.namespace)

    def get_provider(self, provider_key=None, dry=False):
        """
        Get provider key and provider instance.

        Args:
            provider_key (str or None): Name of provider
            dry (bool): Do not make change to the host system while True

        Returns:
            tuple: (provider key, provider instance)
        """
        # If provider_key isn't provided via CLI, let's grab it the configuration
        if provider_key is None:
            provider_key = self.config.get("provider", scope=GLOBAL_CONF)
        provider_class = self.plugin.getProvider(provider_key)
        if provider_class is None:
            raise NuleculeException(
                "Invalid Provider - '{}', provided in "
                "answers.conf (choose from {})".format(provider_key, ", ".join(PROVIDERS))
            )
        return provider_key, provider_class(self.config.context(), self.basepath, dry)

    def run(self, provider_key=None, dry=False):
        raise NotImplementedError

    def stop(self, provider):
        raise NotImplementedError

    def fetch(self):
        raise NotImplementedError

    def uninstall(self):
        raise NotImplementedError
Example #11
0
# -*- coding: utf-8 -*-
from atomicapp.constants import (GLOBAL_CONF, DEFAULT_PROVIDER,
                                 DEFAULT_ANSWERS)
from atomicapp.utils import Utils
from atomicapp.plugin import Plugin

plugin = Plugin()
plugin.load_plugins()


class NuleculeBase(object):
    """
    This is the base class for Nulecule and NuleculeComponent in
    atomicapp.nulecule.base.
    """
    def __init__(self, basepath, params, namespace):
        self.basepath = basepath
        self.params = params or []
        self.namespace = namespace

    def load(self):
        pass

    def load_config(self, config=None, ask=False, skip_asking=False):
        """
        Load config data. Sets the loaded config data to self.config.

        Args:
            config (dict): Initial config data
            ask (bool): When True, ask for values for a param from user even
                        if the param has a default value
Example #12
0
# -*- coding: utf-8 -*-
from atomicapp.constants import (GLOBAL_CONF, DEFAULT_PROVIDER,
                                 DEFAULT_ANSWERS)
from atomicapp.utils import Utils
from atomicapp.plugin import Plugin

plugin = Plugin()
plugin.load_plugins()


class NuleculeBase(object):
    """
    This is the base class for Nulecule and NuleculeComponent in
    atomicapp.nulecule.base.
    """
    def __init__(self, basepath, params, namespace):
        self.basepath = basepath
        self.params = params or []
        self.namespace = namespace

    def load(self):
        pass

    def load_config(self, config=None, ask=False, skip_asking=False):
        """
        Load config data. Sets the loaded config data to self.config.

        Args:
            config (dict): Initial config data
            ask (bool): When True, ask for values for a param from user even
                        if the param has a default value
class Requirements:

    """
    Requirements will search what is currently being used under
    the requirements section of Nulecule and deploy in accordance
    to the graph variables as well as whether or not said requirement
    exists within the provider.

    The REQUIREMENTS_FUNCTIONS dictionary maps all current requirement
    names to the function names for each provider.

    For example, the persistentVolume requirement in Nulecule is mapped as
    the persistent_storage function within each provider.

    Requirements tries to be as modular as possible.
    """

    def __init__(self, config, basepath, graph, provider, dryrun):
        self.plugin = Plugin()

        self.config = config
        self.basepath = basepath
        self.graph = graph
        self.dryrun = dryrun

        # We initialize the provider in order to gather provider-specific
        # information
        p = self.plugin.getProvider(provider)
        self.provider = p(config, basepath, dryrun)
        self.provider.init()

    def run(self):
        self._exec("run")

    def stop(self):
        self._exec("stop")

    # Find if the requirement does not exist within REQUIREMENT_FUNCTIONS
    def _find_requirement_function_name(self, key):
        logger.debug("Checking if %s matches any of %s" %
                     (key, REQUIREMENT_FUNCTIONS))
        if key in REQUIREMENT_FUNCTIONS.keys():
            return REQUIREMENT_FUNCTIONS[key]
        raise RequirementFailedException("Requirement %s does not exist." % key)

    # We loop through the given requirements graph and
    # execute each passed requirement
    def _exec(self, action):
        for req in self.graph:
            key_name = req.keys()[0]
            requirement_function = self._find_requirement_function_name(key_name)

            # Check to see if the function exists in the provider,
            # if it does not: warn the user
            try:
                requirement = getattr(self.provider, requirement_function)
            except AttributeError:
                logger.warning(
                    "Requirement %s does not exist within %s. Skipping." %
                    (requirement_function, self.provider))
                continue

            # Run the requirement function
            requirement(req[key_name], action)
Example #14
0
class NuleculeBase(object):

    """
    This is the base class for Nulecule and NuleculeComponent in
    atomicapp.nulecule.base.
    """

    def __init__(self, basepath, params, namespace):
        self.plugin = Plugin()
        self.basepath = basepath
        self.params = params or []
        self.namespace = namespace

    def load(self):
        pass

    def load_config(self, config, ask=False, skip_asking=False):
        """
        Load config data. Sets the loaded config data to self.config.

        Args:
            config (dict): Initial config data
            ask (bool): When True, ask for values for a param from user even
                        if the param has a default value
            skip_asking (bool): When True, skip asking for values for params
                                with missing values and set the value as
                                None

        Returns:
            None
        """
        for param in self.params:
            value = config.get(self.namespace, {}).get(param[NAME_KEY]) or config.get(GLOBAL_CONF, {}).get(
                param[NAME_KEY]
            )
            if value is None and (ask or (not skip_asking and param.get(DEFAULTNAME_KEY) is None)):
                cockpit_logger.info("%s is missing in answers.conf." % param[NAME_KEY])
                value = Utils.askFor(param[NAME_KEY], param, self.namespace)
            elif value is None:
                value = param.get(DEFAULTNAME_KEY)
            if config.get(self.namespace) is None:
                config[self.namespace] = {}
            config[self.namespace][param[NAME_KEY]] = value
        self.config = config

    def merge_config(self, to_config, from_config):
        """
        Merge values from from_config to to_config. If value for a key
        in a group in to_config is missing, then only set it's value from
        corresponding key in the same group in from_config.

        Args:
            to_config (dict): Dictionary to merge config into
            from_config (dict): Dictionary to merge config from

        Returns:
            None
        """
        for group, group_vars in from_config.items():
            to_config[group] = to_config.get(group) or {}
            for key, value in (group_vars or {}).items():
                if to_config[group].get(key) is None:
                    to_config[group][key] = value

    def get_context(self):
        """
        Get context data from config data for rendering an artifact.
        """
        context = {}
        context.update(self.config.get(GLOBAL_CONF) or {})
        context.update(self.config.get(self.namespace) or {})
        return context

    def get_provider(self, provider_key=None, dry=False):
        """
        Get provider key and provider instance.

        Args:
            provider_key (str or None): Name of provider
            dry (bool): Do not make change to the host system while True

        Returns:
            tuple: (provider key, provider instance)
        """
        # If provider_key isn't provided via CLI, let's grab it the configuration
        if provider_key is None:
            provider_key = self.config.get(GLOBAL_CONF)[PROVIDER_KEY]
        provider_class = self.plugin.getProvider(provider_key)
        if provider_class is None:
            raise NuleculeException(
                "Invalid Provider - '{}', provided in "
                "answers.conf (choose from {})".format(provider_key, ", ".join(PROVIDERS))
            )
        return provider_key, provider_class(self.get_context(), self.basepath, dry)

    def run(self, provider_key=None, dry=False):
        raise NotImplementedError

    def stop(self, provider):
        raise NotImplementedError

    def fetch(self):
        raise NotImplementedError

    def uninstall(self):
        raise NotImplementedError
Example #15
0
 def __init__(self, basepath, params, namespace):
     self.plugin = Plugin()
     self.basepath = basepath
     self.params = params or []
     self.namespace = namespace
Example #16
0
 def __init__(self, basepath, params, namespace):
     self.plugin = Plugin()
     self.plugin.load_plugins()
     self.basepath = basepath
     self.params = params or []
     self.namespace = namespace
Example #17
0
 def setUp(self):
     self.nulecule_base = Nulecule_Base(dryrun = True)
     self.tmpdir = tempfile.mkdtemp(prefix = "atomicapp-test", dir = "/tmp")
     self.artifact_dir = os.path.dirname(__file__) + '/docker_artifact_test/'
     self.plugin = Plugin()
     self.plugin.load_plugins()
class TestKubernetesProviderBase(unittest.TestCase):
    def setUp(self):
        self.nulecule_base = Nulecule_Base(dryrun=True)
        self.tmpdir = tempfile.mkdtemp(prefix="atomicapp-test", dir="/tmp")
        self.plugin = Plugin()
        self.plugin.load_plugins()

    def tearDown(self):
        pass

    def create_temp_file(self):
        return tempfile.mktemp(prefix="test-config", dir=self.tmpdir)

    def prepare_provider(self, data):
        self.nulecule_base.loadAnswers(data)
        provider_class = self.plugin.getProvider(self.nulecule_base.provider)
        config = self.nulecule_base.getValues(skip_asking=True)
        provider = provider_class(config, self.tmpdir, dryrun=False)

        return provider

    @mock.patch.object(KubernetesProvider, '_call', mock_provider_call)
    def test_provider_config_exist(self):
        provider_config_path = self.create_temp_file()
        mock_content = "%s_%s" % (MOCK_CONTENT, "_unchanged")
        with open(provider_config_path, "w") as fp:
            fp.write(mock_content)

        data = {
            'general': {
                'namespace': 'testing',
                'provider': 'kubernetes',
                'providerconfig': provider_config_path
            }
        }

        provider = self.prepare_provider(data)

        self.assertEqual(provider.config_file, provider_config_path)
        provider.checkConfigFile()
        with open(provider_config_path, "r") as fp:
            self.assertEqual(fp.read(), mock_content)

    @mock.patch("kubernetes.KubernetesProvider._call", mock_provider_call)
    def test_provider_check_config_generation(self):
        path = self.create_temp_file()
        data = {
            'general': {
                'namespace': 'testing',
                'provider': 'kubernetes',
                'providerconfig': path
            }
        }

        provider = self.prepare_provider(data)

        provider.checkConfigFile()
        with open(path, "r") as fp:
            self.assertEqual(fp.read(), MOCK_CONTENT)

    def test_provider_check_config_fail(self):
        path = self.create_temp_file()
        data = {'general': {'namespace': 'testing', 'provider': 'openshift'}}
        provider = self.prepare_provider(data)

        self.assertRaises(ProviderFailedException, provider.checkConfigFile)
Example #19
0
class NuleculeBase(object):

    """
    This is the base class for Nulecule and NuleculeComponent in
    atomicapp.nulecule.base.
    """

    def __init__(self, basepath, params, namespace):
        self.plugin = Plugin()
        self.basepath = basepath
        self.params = params or []
        self.namespace = namespace

    def load(self):
        pass

    def load_config(self, config, ask=False, skip_asking=False):
        """
        Load config data. Sets the loaded config data to self.config.

        Args:
            config (dict): Initial config data
            ask (bool): When True, ask for values for a param from user even
                        if the param has a default value
            skip_asking (bool): When True, skip asking for values for params
                                with missing values and set the value as
                                None

        Returns:
            None
        """
        self.config = config
        for param in self.params:
            value = config.get(param[NAME_KEY], scope=self.namespace, ignore_sources=['defaults'])
            if value is None:
                if ask or (not skip_asking and
                           param.get(DEFAULTNAME_KEY) is None):
                    cockpit_logger.info(
                        "%s is missing in answers.conf." % param[NAME_KEY])
                    value = config.get(param[NAME_KEY], scope=self.namespace) \
                        or Utils.askFor(param[NAME_KEY], param, self.namespace)
                else:
                    value = param.get(DEFAULTNAME_KEY)
                config.set(param[NAME_KEY], value, source='runtime',
                           scope=self.namespace)

    def get_provider(self, provider_key=None, dry=False):
        """
        Get provider key and provider instance.

        Args:
            provider_key (str or None): Name of provider
            dry (bool): Do not make change to the host system while True

        Returns:
            tuple: (provider key, provider instance)
        """
        # If provider_key isn't provided via CLI, let's grab it the configuration
        if provider_key is None:
            provider_key = self.config.get('provider', scope=GLOBAL_CONF)
        provider_class = self.plugin.getProvider(provider_key)
        if provider_class is None:
            raise NuleculeException("Invalid Provider - '{}', provided in "
                                    "answers.conf (choose from {})"
                                    .format(provider_key, ', '
                                                          .join(PROVIDERS)))
        return provider_key, provider_class(
            self.config.context(), self.basepath, dry)

    def run(self, provider_key=None, dry=False):
        raise NotImplementedError

    def stop(self, provider):
        raise NotImplementedError

    def fetch(self):
        raise NotImplementedError

    def uninstall(self):
        raise NotImplementedError
 def setUp(self):
     self.nulecule_base = Nulecule_Base(dryrun=True)
     self.tmpdir = tempfile.mkdtemp(prefix="atomicapp-test", dir="/tmp")
     self.plugin = Plugin()
     self.plugin.load_plugins()
 def setUp(self):
     self.nulecule_base = Nulecule_Base(dryrun = True)
     self.tmpdir = tempfile.mkdtemp(prefix = "atomicapp-test", dir = "/tmp")
     self.plugin = Plugin()
     self.plugin.load_plugins()
Example #22
0
class NuleculeBase(object):
    """
    This is the base class for Nulecule and NuleculeComponent in
    atomicapp.nulecule.base.
    """
    def __init__(self, basepath, params, namespace):
        self.plugin = Plugin()
        self.plugin.load_plugins()
        self.basepath = basepath
        self.params = params or []
        self.namespace = namespace

    def load(self):
        pass

    def load_config(self, config, ask=False, skip_asking=False):
        """
        Load config data. Sets the loaded config data to self.config.

        Args:
            config (dict): Initial config data
            ask (bool): When True, ask for values for a param from user even
                        if the param has a default value
            skip_asking (bool): When True, skip asking for values for params
                                with missing values and set the value as
                                None

        Returns:
            None
        """
        for param in self.params:
            value = config.get(self.namespace, {}).get(param[NAME_KEY]) or \
                config.get(GLOBAL_CONF, {}).get(param[NAME_KEY])
            if value is None and (ask or
                                  (not skip_asking
                                   and param.get(DEFAULTNAME_KEY) is None)):
                cockpit_logger.info("%s is missing in answers.conf." %
                                    param[NAME_KEY])
                value = Utils.askFor(param[NAME_KEY], param)
            elif value is None:
                value = param.get(DEFAULTNAME_KEY)
            if config.get(self.namespace) is None:
                config[self.namespace] = {}
            config[self.namespace][param[NAME_KEY]] = value
        self.config = config

    def merge_config(self, to_config, from_config):
        """
        Merge values from from_config to to_config. If value for a key
        in a group in to_config is missing, then only set it's value from
        corresponding key in the same group in from_config.

        Args:
            to_config (dict): Dictionary to merge config into
            from_config (dict): Dictionary to merge config from

        Returns:
            None
        """
        for group, group_vars in from_config.items():
            to_config[group] = to_config.get(group) or {}
            for key, value in (group_vars or {}).items():
                if to_config[group].get(key) is None:
                    to_config[group][key] = value

    def get_context(self):
        """
        Get context data from config data for rendering an artifact.
        """
        context = {}
        context.update(self.config.get(GLOBAL_CONF) or {})
        context.update(self.config.get(self.namespace) or {})
        return context

    def get_provider(self, provider_key=None, dry=False):
        """
        Get provider key and provider instance.

        Args:
            provider_key (str or None): Name of provider
            dry (bool): Do not make change to the host system while True

        Returns:
            tuple: (provider key, provider instance)
        """
        # If provider_key isn't provided via CLI, let's grab it the configuration
        if provider_key is None:
            provider_key = self.config.get(GLOBAL_CONF)[PROVIDER_KEY]
        provider_class = self.plugin.getProvider(provider_key)
        if provider_class is None:
            raise NuleculeException("Invalid Provider - '{}', provided in "
                                    "answers.conf (choose from {})".format(
                                        provider_key, ', '.join(PROVIDERS)))
        return provider_key, provider_class(self.get_context(), self.basepath,
                                            dry)

    def run(self, provider_key=None, dry=False):
        raise NotImplementedError

    def stop(self, provider):
        raise NotImplementedError

    def fetch(self):
        raise NotImplementedError

    def uninstall(self):
        raise NotImplementedError