Example #1
0
 def setUp(self):
     self.settings = Settings()
     self.settings.environmentdefs = {
         'any': ['localhost'],
     }
     self.settings.roledefs = {
         'role': ['localhost'],
     }
Example #2
0
class TestJinjaFilters(TestCase):
    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            'any': ['localhost'],
        }
        self.settings.roledefs = {
            'role': ['localhost'],
        }

    def test_built_in_filters(self):
        """
        Generated templates that use built-in filters have the correct values.
        """
        conffiles = ConfFiles(
            self.settings.for_env('any').all().next(),
            PackageEnvironmentLoader('confab.tests',
                                     'templates/jinjafilters/builtin'),
            lambda _: {
                'bar': [1, 2, 3],
                'pivot': 2,
                'foo': {
                    'key1': 'foo1',
                    'key2': 'foo2',
                },
                'key': 'key2',
            })

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            eq_('foo2', tmp_dir.read('generated/localhost/foo.txt'))

            eq_("['+2+', '+3+', '+1+']",
                tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_user_filters(self):
        """
        Generated templates that use user-defined filters have the correct values.
        """
        def multiply(value, mult):
            return value * mult

        with JinjaFilters(multiply):
            conffiles = ConfFiles(
                self.settings.for_env('any').all().next(),
                PackageEnvironmentLoader('confab.tests',
                                         'templates/jinjafilters/user'),
                lambda _: {'foo': 'foo'})

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            eq_('foofoofoo', tmp_dir.read('generated/localhost/foo.txt'))
Example #3
0
 def setUp(self):
     self.settings = Settings()
     self.settings.environmentdefs = {
         "test1": ["host1", "host2", "host3"],
         "test2": ["host2", "host3"],
         "test3": []
     }
     self.settings.roledefs = {
         "role1": ["host1", "host2", "host3"],
         "role2": ["host2", "host3"],
         "role3": [],
     }
class TestJinjaFilters(TestCase):

    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            'any': ['localhost'],
        }
        self.settings.roledefs = {
            'role': ['localhost'],
        }

    def test_built_in_filters(self):
        """
        Generated templates that use built-in filters have the correct values.
        """
        conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                              PackageEnvironmentLoader('confab.tests',
                                                       'templates/jinjafilters/builtin'),
                              lambda _: {
                                  'bar': [1, 2, 3],
                                  'pivot': 2,
                                  'foo': {
                                      'key1': 'foo1',
                                      'key2': 'foo2',
                                  },
                                  'key': 'key2',
                              })

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            eq_('foo2', tmp_dir.read('generated/localhost/foo.txt'))

            eq_("['+2+', '+3+', '+1+']", tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_user_filters(self):
        """
        Generated templates that use user-defined filters have the correct values.
        """
        def multiply(value, mult):
            return value * mult

        with JinjaFilters(multiply):
            conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                                  PackageEnvironmentLoader('confab.tests',
                                                           'templates/jinjafilters/user'),
                                  lambda _: {'foo': 'foo'})

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            eq_('foofoofoo', tmp_dir.read('generated/localhost/foo.txt'))
Example #5
0
 def setUp(self):
     self.settings = Settings()
     self.settings.environmentdefs = {
         "environment": ["host"],
     }
     self.settings.roledefs = {
         "role": ["host"],
     }
     self.settings.componentdefs = {
         "role": ["component"],
     }
     self.component = self.settings.for_env(
         "environment").components().next()
Example #6
0
 def test_load_from_empty_module(self):
     """
     Loading empty state results in empty dictionaries.
     """
     self.settings = Settings.load_from_module(join(self.dir_name, "empty.py"))
     for key in Settings.KEYS:
         eq_({}, getattr(self.settings, key, {}))
Example #7
0
def generate_tasks(settings_path=None):
    """
    Autogenerate `env` tasks for all defined environments.
    """
    def create_task(settings, environment):
        def select_environment(*roles):
            if hasattr(env, "environmentdef"
                       ) and env.environmentdef.name != environment:
                abort("Environment already defined as '{}'".format(
                    env.environmentdef.name))

            # Do not select hosts here.
            #
            # If `fab` is run with multiple hosts, this task will be run multiple
            # times, overwriting the value of "env.environmentdef". By not selecting hosts
            # here, we ensure that the same environmentdef will be loaded each
            # time. See also confab.iter:iter_conffiles
            env.environmentdef = settings.for_env(environment).with_roles(
                *roles)

        return select_environment

    settings = Settings.load_from_module(settings_path)

    for environment in settings.environmentdefs.iterkeys():
        _add_task(
            environment, create_task(settings, environment),
            "Set environment to '{environment}'".format(
                environment=environment))
    return settings
Example #8
0
 def setUp(self):
     self.settings = Settings()
     self.settings.environmentdefs = {
         "test1": ["host1", "host2", "host3"],
         "test2": ["host2", "host3"],
         "test3": []
     }
     self.settings.roledefs = {
         "role1": ["host1", "host2", "host3"],
         "role2": ["host2", "host3"],
         "role3": [],
     }
     self.settings.componentdefs = {
         "role1": ["comp1", "compgroup"],
         "compgroup": ["comp2", "comp3"],
     }
Example #9
0
def generate_tasks(settings_path=None):
    """
    Autogenerate `env` tasks for all defined environments.
    """
    def create_task(settings, environment):
        def select_environment(*roles):
            if hasattr(env, "environmentdef") and env.environmentdef.name != environment:
                abort("Environment already defined as '{}'".format(env.environmentdef.name))

            # Do not select hosts here.
            #
            # If `fab` is run with multiple hosts, this task will be run multiple
            # times, overwriting the value of "env.environmentdef". By not selecting hosts
            # here, we ensure that the same environmentdef will be loaded each
            # time. See also confab.iter:iter_conffiles
            env.environmentdef = settings.for_env(environment).with_roles(*roles)
        return select_environment

    settings = Settings.load_from_module(settings_path)

    for environment in settings.environmentdefs.iterkeys():
        _add_task(environment,
                  create_task(settings, environment),
                  "Set environment to '{environment}'".format(environment=environment))
    return settings
Example #10
0
    def test_extension_paths(self):
        """
        Test loading of templates and data from extension entry points.
        """
        settings_ = Settings.load_from_dict(
            dict(environmentdefs={'any': ['host1']},
                 roledefs={'role1': ['host1']}))

        # use an empty dir as the user's templates dir to make sure
        # only the test templates and data are loaded
        with TempDir() as tmp_dir:
            makedirs(join(tmp_dir.path, 'templates'))
            makedirs(join(tmp_dir.path, 'data'))

            # mock entry point loading to return one entry point with the test templates
            mock_entry_point = Mock()
            mock_entry_point.load.return_value = lambda: join(
                dirname(__file__), 'extension')

            with patch('confab.iter.iter_entry_points',
                       Mock(return_value=[mock_entry_point])):
                with settings(environmentdef=settings_.for_env('any')):

                    for conffiles in iter_conffiles(tmp_dir.path):
                        conffiles.generate(tmp_dir.path)

                    self.assertEquals('foo',
                                      tmp_dir.read('generated/host1/foo.txt'))
Example #11
0
 def test_load_from_empty_dict(self):
     """
     Loading empty state results in empty dictionaries.
     """
     self.settings = Settings.load_from_dict({})
     for key in Settings.KEYS:
         eq_({}, getattr(self.settings, key, {}))
Example #12
0
    def test_multiple_directories(self):
        """
        Generate templates for roles with components
        where templates and data are in multiple directories.
        """
        settings = Settings.load_from_dict(
            dict(environmentdefs={'any': ['host1']},
                 roledefs={
                     'role1': ['host1'],
                     'role2': ['host1']
                 },
                 componentdefs={'role1': ['comp1', 'comp2']}))

        subdirs = ['roles', 'components']
        template_dirs = map(
            lambda d: join(dirname(__file__), 'templates/multidir', d),
            subdirs)
        data_dirs = map(lambda d: join(dirname(__file__), 'data/multidir', d),
                        subdirs)

        with TempDir() as tmp_dir:
            for host_and_role in settings.for_env('any').all():
                conffiles = ConfFiles(
                    host_and_role, FileSystemEnvironmentLoader(*template_dirs),
                    DataLoader(data_dirs))
                conffiles.generate(tmp_dir.path)

            self.assertEquals('foo', tmp_dir.read('generated/host1/foo.txt'))
            self.assertEquals('bar', tmp_dir.read('generated/host1/bar.txt'))
            self.assertEquals('baz', tmp_dir.read('generated/host1/baz.conf'))
Example #13
0
 def setUp(self):
     self.settings = Settings()
     self.settings.environmentdefs = {
         'any': ['localhost'],
     }
     self.settings.roledefs = {
         'role': ['localhost'],
     }
Example #14
0
 def test_load_from_example_module(self):
     """
     Loading non-empty module results in expected dictionaries.
     """
     self.settings = Settings.load_from_module(join(self.dir_name, "example.py"))
     eq_(["host1", "host2"], self.settings.environmentdefs["environment1"])
     eq_(["host1"], self.settings.roledefs["role1"])
     eq_(["component1"], self.settings.componentdefs["role1"])
Example #15
0
 def setUp(self):
     self.settings = Settings()
     self.settings.environmentdefs = {
         "environment": ["host"],
     }
     self.settings.roledefs = {
         "role": ["host"],
     }
     self.settings.componentdefs = {
         "role": ["component"],
     }
     self.component = self.settings.for_env("environment").components().next()
Example #16
0
class TestHostDefinition(TestCase):
    """
    Test host iteration.
    """
    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            "test1": ["host1", "host2", "host3"],
            "test2": ["host2", "host3"],
            "test3": []
        }
        self.settings.roledefs = {
            "role1": ["host1", "host2", "host3"],
            "role2": ["host2", "host3"],
            "role3": [],
        }
        self.settings.componentdefs = {
            "role1": ["comp1", "compgroup"],
            "compgroup": ["comp2", "comp3"],
        }

    def test_iter_hosts_roles(self):
        """
        Test iteration over an environment's hosts to get roles.
        """
        def get_hosts_roles(envdef):
            return {hostdef.host: [host_and_role.role for host_and_role in hostdef.roles()]
                    for hostdef in envdef.hosts()}

        eq_({"host1": ["role1"],
             "host2": ["role1", "role2"],
             "host3": ["role1", "role2"]},
            get_hosts_roles(self.settings.for_env("test1")))

        eq_({"host2": ["role1", "role2"],
             "host3": ["role1", "role2"]},
            get_hosts_roles(self.settings.for_env("test2")))

        eq_({},
            get_hosts_roles(self.settings.for_env("test3")))

    def test_iter_hosts_components(self):
        """
        Test iteration over an environment's hosts to get components.
        """
        def get_hosts_components(envdef):
            return {hostdef.host: [compdef.name for compdef in hostdef.components()]
                    for hostdef in envdef.hosts()}

        eq_({"host1": ["comp1", "comp2", "comp3"],
             "host2": ["comp1", "comp2", "comp3", "role2"],
             "host3": ["comp1", "comp2", "comp3", "role2"]},
            get_hosts_components(self.settings.for_env("test1")))

        eq_({"host2": ["comp1", "comp2", "comp3", "role2"],
             "host3": ["comp1", "comp2", "comp3", "role2"]},
            get_hosts_components(self.settings.for_env("test2")))

        eq_({},
            get_hosts_components(self.settings.for_env("test3")))
Example #17
0
def main():
    """
    Diagnostics command line entry point.
    """
    try:
        # Parse and validate arguments
        parser, options, arguments = parse_options()

        settings = Settings.load_from_module(options.directory)

    except Exception as e:
        parser.error(e)

    descriptions = make_conffile_descriptions(settings,
                                              options.environment,
                                              options.hosts.split(",") if options.hosts else [],
                                              options.roles.split(",") if options.roles else [])
    print_conffiles(descriptions)
Example #18
0
 def test_load_from_dict(self):
     """
     Loading empty state results in empty dictionaries.
     """
     dct = {
         "environmentdefs": {
             "environment1": ["host1", "host2"],
         },
         "roledefs": {
             "role1": ["host1"],
         },
         "componentdefs": {
             "role1": ["component1"],
         }
     }
     self.settings = Settings.load_from_dict(dct)
     eq_(["host1", "host2"], self.settings.environmentdefs["environment1"])
     eq_(["host1"], self.settings.roledefs["role1"])
     eq_(["component1"], self.settings.componentdefs["role1"])
Example #19
0
def main():
    """
    Diagnostics command line entry point.
    """
    try:
        # Parse and validate arguments
        parser, options, arguments = parse_options()

        configure_output(verbosity=options.verbosity, quiet=options.quiet)

        settings = Settings.load_from_module(options.directory)

    except Exception as e:
        parser.error(e)

    table = make_table(settings,
                       options.environment,
                       options.hosts.split(",") if options.hosts else [],
                       options.roles.split(",") if options.roles else [])
    print(table)
Example #20
0
    def test_extension_paths(self):
        """
        Test loading of templates and data from extension entry points.
        """
        settings_ = Settings.load_from_dict(dict(environmentdefs={'any': ['host1']},
                                                 roledefs={'role1': ['host1']}))

        # use an empty dir as the user's templates dir to make sure
        # only the test templates and data are loaded
        with TempDir() as tmp_dir:
            makedirs(join(tmp_dir.path, 'templates'))
            makedirs(join(tmp_dir.path, 'data'))

            # mock entry point loading to return one entry point with the test templates
            mock_entry_point = Mock()
            mock_entry_point.load.return_value = lambda: join(dirname(__file__), 'extension')

            with patch('confab.iter.iter_entry_points', Mock(return_value=[mock_entry_point])):
                with settings(environmentdef=settings_.for_env('any')):

                    for conffiles in iter_conffiles(tmp_dir.path):
                        conffiles.generate(tmp_dir.path)

                    self.assertEquals('foo', tmp_dir.read('generated/host1/foo.txt'))
Example #21
0
def load_environmentdef(environment,
                        settings_path=None,
                        hosts=None,
                        roles=None):
    """
    Load settings, construct an environment definition, and save in Fabric env
    as ``confab`` for use by subsequent confab tasks.

    :param environment: environment name
    :param settings_path: path to settings module
    :param hosts: comma delimited host list
    :param roles: comma delimited role list
    """

    settings_ = Settings.load_from_module(settings_path)

    # Normalize and resolve hosts to roles mapping
    selected_hosts = hosts.split(",") if hosts else []
    selected_roles = roles.split(",") if roles else []

    env.environmentdef = settings_.for_env(environment)
    env.environmentdef = env.environmentdef.with_hosts(*selected_hosts)
    env.environmentdef = env.environmentdef.with_roles(*selected_roles)
    return env.environmentdef
Example #22
0
def load_environmentdef(environment,
                        settings_path=None,
                        hosts=None,
                        roles=None):
    """
    Load settings, construct an environment definition, and save in Fabric env
    as "confab" for use by subsequent confab tasks.

    :param environment: environment name
    :param settings_path: path to settings module
    :param hosts: comma delimited host list
    :param roles: comma delimited role list
    """

    settings_ = Settings.load_from_module(settings_path)

    # Normalize and resolve hosts to roles mapping
    selected_hosts = hosts.split(",") if hosts else []
    selected_roles = roles.split(",") if roles else []

    env.environmentdef = settings_.for_env(environment)
    env.environmentdef = env.environmentdef.with_hosts(*selected_hosts)
    env.environmentdef = env.environmentdef.with_roles(*selected_roles)
    return env.environmentdef
Example #23
0
    def test_multiple_directories(self):
        """
        Generate templates for roles with components
        where templates and data are in multiple directories.
        """
        settings = Settings.load_from_dict(dict(environmentdefs={'any': ['host1']},
                                                roledefs={'role1': ['host1'],
                                                          'role2': ['host1']},
                                                componentdefs={'role1': ['comp1', 'comp2']}))

        subdirs = ['roles', 'components']
        template_dirs = map(lambda d: join(dirname(__file__), 'templates/multidir', d), subdirs)
        data_dirs = map(lambda d: join(dirname(__file__), 'data/multidir', d), subdirs)

        with TempDir() as tmp_dir:
            for host_and_role in settings.for_env('any').all():
                conffiles = ConfFiles(host_and_role,
                                      FileSystemEnvironmentLoader(*template_dirs),
                                      DataLoader(data_dirs))
                conffiles.generate(tmp_dir.path)

            self.assertEquals('foo', tmp_dir.read('generated/host1/foo.txt'))
            self.assertEquals('bar', tmp_dir.read('generated/host1/bar.txt'))
            self.assertEquals('baz', tmp_dir.read('generated/host1/baz.conf'))
Example #24
0
class TestComponents(TestCase):
    """
    Tests for component selection.
    """
    def setUp(self):
        self.settings = Settings()

    def test_components_for_role(self):
        """
        Test key matching within componentdefs.
        """
        self.settings.environmentdefs = {
            "env": ["host1", "host2"],
        }
        self.settings.roledefs = {
            "role1": ["host1"],
            "role2": ["host2"],
            "role3": ["host2"],
        }

        # if there are no components, roles are treated like components
        eq_(["role3", "role2", "role1"],
            map(lambda c: c.name, self.settings.for_env("env").components()))

        self.settings.componentdefs = {
            "role1": ["comp1", "compgroup"],
            "role2": ["comp2", "comp3"],
            "compgroup": ["comp3", "comp4"]
        }

        eq_(["comp1", "comp3", "comp4"],
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components()))
        eq_(["comp2", "comp3"],
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role2").components()))
        eq_(["role3"],
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role3").components()))

    def test_componentdefs_cycle(self):
        """
        Fail if componentdefs has cycles.
        """
        self.settings.environmentdefs = {
            "env": ["host1"],
        }
        self.settings.roledefs = {
            "role1": ["host1"],
        }
        self.settings.componentdefs = {
            "role1": ["compgroup"],
            "compgroup": ["role1"],
        }
        with self.assertRaises(Exception):
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components())

    def test_componentdefs_cycle2(self):
        """
        Fail if componentdefs has cycles.
        """
        self.settings.environmentdefs = {
            "env": ["host1"],
        }
        self.settings.roledefs = {
            "role1": ["host1"],
        }
        self.settings.componentdefs = {
            "role1": ["compgroup1"],
            "compgroup1": ["compgroup2"],
            "compgroup2": ["compgroup1"],
        }
        with self.assertRaises(Exception):
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components())

    def test_multiple_paths(self):
        """
        Fail if componentdefs has multiple paths to a leaf component.
        """
        self.settings.environmentdefs = {
            "env": ["host1"],
        }
        self.settings.roledefs = {
            "role1": ["host1"],
        }
        self.settings.componentdefs = {
            "role1": ["comp1", "compgroup"],
            "compgroup": ["comp1"],
        }
        with self.assertRaises(Exception):
            map(lambda c: c.name, self.settings.for_env("env").with_roles("role1").components())
Example #25
0
class TestListing(TestCase):
    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            'any': ['host'],
        }
        self.settings.roledefs = {
            'role': ['host'],
        }

    def test_get_conf_files(self):
        """
        Generating conf files finds all templates in the package
        and generates their names properly.
        """

        conffiles = ConfFiles(
            self.settings.for_env('any').all().next(),
            PackageEnvironmentLoader('confab.tests', 'templates/default'),
            lambda _: {'bar': 'bar'})

        eq_(2, len(conffiles.conffiles))

        names = map(lambda x: x.name, conffiles.conffiles)

        self.assertTrue('foo.txt' in names)
        self.assertTrue('bar/bar.txt' in names)

    def test_undefined(self):
        """
        Raise an error if a template value is undefined.
        """

        with self.assertRaises(UndefinedError):
            ConfFiles(
                self.settings.for_env('any').all().next(),
                PackageEnvironmentLoader('confab.tests', 'templates/default'),
                lambda _: {})

    def test_filter_func(self):
        """
        Passing a filter_func limits which templates are generated.
        """

        with Options(filter_func=lambda file_name: file_name != 'foo.txt'):
            conffiles = ConfFiles(
                self.settings.for_env('any').all().next(),
                PackageEnvironmentLoader('confab.tests', 'templates/default'),
                lambda _: {'bar': 'bar'})

            eq_(1, len(conffiles.conffiles))

            names = map(lambda x: x.name, conffiles.conffiles)

            self.assertTrue('bar/bar.txt' in names)

    def test_same_component_for_different_roles(self):
        """
        Two roles using the same component on the same host.
        """
        self.settings.roledefs = {
            'role1': ['host'],
            'role2': ['host'],
        }
        self.settings.componentdefs = {
            'role1': ['comp'],
            'role2': ['comp'],
        }
        environment_loader = PackageEnvironmentLoader('confab.tests',
                                                      'templates/validate')

        # use data that will create different conffiles for the same
        # component in the two roles.

        conffiles = ConfFiles(
            self.settings.for_env('any').with_roles('role1').all().next(),
            environment_loader, lambda comp: {'foo': 'role1'})

        eq_(1, len(conffiles.conffiles))
        ok_('role1.txt' == conffiles.conffiles[0].name)

        conffiles = ConfFiles(
            self.settings.for_env('any').with_roles('role2').all().next(),
            environment_loader, lambda comp: {'foo': 'role2'})

        eq_(1, len(conffiles.conffiles))
        ok_('role2.txt' == conffiles.conffiles[0].name)

    def test_warn_no_conffiles(self):
        """
        Warn when a role doesn't have any configuration files.
        """
        with Options(filter_func=lambda _: False):
            with catch_warnings(record=True) as captured_warnings:
                conffiles = ConfFiles(
                    self.settings.for_env('any').all().next(),
                    PackageEnvironmentLoader('confab.tests',
                                             'templates/default'),
                    lambda _: {})

                eq_(0, len(conffiles.conffiles))
                eq_(1, len(captured_warnings))
Example #26
0
class TestHooks(TestCase):
    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            "environment": ["host"],
        }
        self.settings.roledefs = {
            "role": ["host"],
        }
        self.settings.componentdefs = {
            "role": ["component"],
        }
        self.component = self.settings.for_env("environment").components().next()

    def test_add_remove_hook(self):
        """
        Load additional configuration data via hook.

        * Test adding new hook
        * Test removing hook
        """
        def test_hook(host):
            return {'data': {'num_cores': 4}}

        testhook = Hook(test_hook)
        local_hooks = HookRegistry()

        local_hooks.add_hook('host', testhook)
        ok_(testhook in local_hooks._hooks['host'])

        local_hooks.remove_hook('host', testhook)
        ok_(testhook not in local_hooks._hooks['host'])

    def test_hook_override_data(self):
        """
        Test that data loaded via hook overwrites data loaded via config.
        """
        def test_hook(role):
            return {'data': {'role': 'role2'}}

        with ScopeAndHooks(('host', Hook(test_hook))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(loader(self.component)['data'],
                {'default': 'default',
                 'component': 'component',
                 'role': 'role2',
                 'environment': 'environment',
                 'host': 'host'})

    def test_data_override_hook(self):
        """
        Test that data loaded via hook will be overwritten by data loaded later via config.
        """
        def test_hook(role):
            return {'data': {'environment': 'environment2'}}

        with ScopeAndHooks(('role', Hook(test_hook))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(loader(self.component)['data'],
                {'default': 'default',
                 'component': 'component',
                 'role': 'role',
                 'environment': 'environment',
                 'host': 'host'})

    def test_hook_load_order(self):
        """
        Test that hooks overwrite each other based on order they are defined.
        """
        def test_hook1(host):
            return {'data': {'host': 'host1'}}

        def test_hook2(host):
            return {'data': {'host': 'host2'}}

        with ScopeAndHooks(('host', Hook(test_hook1)), ('host', Hook(test_hook2))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(loader(self.component)['data'],
                {'default': 'default',
                 'component': 'component',
                 'role': 'role',
                 'environment': 'environment',
                 'host': 'host2'})

    def test_filter_func(self):
        """
        Test that hooks only run if the filter_func returns true
        """
        def test_hook1(host):
            return {'data': {'host': 'host1'}}

        def test_hook2(host):
            return {'data': {'host': 'host2'}}

        with ScopeAndHooks(('host', Hook(test_hook1)),
                           ('host', Hook(test_hook2, lambda componentdef: False))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(loader(self.component)['data'],
                {'default': 'default',
                 'component': 'component',
                 'role': 'role',
                 'environment': 'environment',
                 'host': 'host1'})
Example #27
0
class TestGenerate(TestCase):

    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            'any': ['localhost'],
        }
        self.settings.roledefs = {
            'role': ['localhost'],
        }

    def test_generate(self):
        """
        Generated templates have the correct values.
        """
        conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                              PackageEnvironmentLoader('confab.tests', 'templates/default'),
                              lambda _: {'bar': 'bar', 'foo': 'foo'})

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            # foo.txt is populated with 'foo'
            eq_('foo', tmp_dir.read('generated/localhost/foo.txt'))

            # bar.txt is populated with 'bar' and path is substituted
            eq_('bar', tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_unicode(self):
        """
        Generated templates with unicode data.
        """
        conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                              PackageEnvironmentLoader('confab.tests', 'templates/default'),
                              lambda _: {'bar': 'bar', 'foo': u'\xc5\xae'})
        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            # foo.txt is populated with u'\xc5\xae'
            eq_(u'\xc5\xae', tmp_dir.read('generated/localhost/foo.txt'))

            # bar.txt is populated with 'bar' and path is substituted
            eq_('bar', tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_undefined(self):
        """
        An exception is raised if a template value is undefined.
        """
        conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                              PackageEnvironmentLoader('confab.tests', 'templates/default'),
                              lambda _: {'bar': 'bar'})

        with TempDir() as tmp_dir:
            with self.assertRaises(UndefinedError):
                conffiles.generate(tmp_dir.path)

    def test_should_render(self):
        """
        Passing a mime_type_func controls whether templates are rendered.
        """
        with Options(should_render=lambda mime_type: False):
            conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                                  PackageEnvironmentLoader('confab.tests', 'templates/default'),
                                  lambda _: {'bar': 'bar', 'foo': 'foo'})

            with TempDir() as tmp_dir:
                conffiles.generate(tmp_dir.path)

                # templates not rendered (though paths are)
                eq_('{{foo}}', tmp_dir.read('generated/localhost/foo.txt'))
                eq_('{{bar}}', tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_binary_template(self):
        """
        Confab copies binary config files verbatim to generated folder.
        """
        templates_dir = join(dirname(__file__), 'templates/binary')
        conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                              FileSystemEnvironmentLoader(templates_dir), lambda _: {})

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            ok_(filecmp.cmp(join(tmp_dir.path, 'generated/localhost/test.png'),
                            join(templates_dir, 'role/test.png')))

    def test_components(self):
        """
        Generate templates for roles with components.
        """
        self.settings.environmentdefs = {
            'any': ['host1'],
        }
        self.settings.roledefs = {
            'role1': ['host1'],
            'role2': ['host1'],
            'role3': ['host1'],
        }
        self.settings.componentdefs = {
            'role1': ['comp1'],
            'role2': ['compgroup'],
            'compgroup': ['comp2', 'comp3'],
        }
        with TempDir() as tmp_dir:
            for host_and_role in self.settings.for_env('any').all():
                conffiles = ConfFiles(host_and_role,
                                      PackageEnvironmentLoader('confab.tests',
                                                               'templates/components'),
                                      DataLoader(join(dirname(__file__), 'data/components')))
                conffiles.generate(tmp_dir.path)

            self.assertEquals('foo', tmp_dir.read('generated/host1/foo.txt'))
            self.assertEquals('bar', tmp_dir.read('generated/host1/bar/bar.txt'))
            self.assertEquals('baz', tmp_dir.read('generated/host1/baz.conf'))

    def test_multiple_directories(self):
        """
        Generate templates for roles with components
        where templates and data are in multiple directories.
        """
        settings = Settings.load_from_dict(dict(environmentdefs={'any': ['host1']},
                                                roledefs={'role1': ['host1'],
                                                          'role2': ['host1']},
                                                componentdefs={'role1': ['comp1', 'comp2']}))

        subdirs = ['roles', 'components']
        template_dirs = map(lambda d: join(dirname(__file__), 'templates/multidir', d), subdirs)
        data_dirs = map(lambda d: join(dirname(__file__), 'data/multidir', d), subdirs)

        with TempDir() as tmp_dir:
            for host_and_role in settings.for_env('any').all():
                conffiles = ConfFiles(host_and_role,
                                      FileSystemEnvironmentLoader(*template_dirs),
                                      DataLoader(data_dirs))
                conffiles.generate(tmp_dir.path)

            self.assertEquals('foo', tmp_dir.read('generated/host1/foo.txt'))
            self.assertEquals('bar', tmp_dir.read('generated/host1/bar.txt'))
            self.assertEquals('baz', tmp_dir.read('generated/host1/baz.conf'))
Example #28
0
class TestListing(TestCase):

    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            'any': ['host'],
        }
        self.settings.roledefs = {
            'role': ['host'],
        }

    def test_get_conf_files(self):
        """
        Generating conf files finds all templates in the package
        and generates their names properly.
        """

        conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                              PackageEnvironmentLoader('confab.tests', 'templates/default'),
                              lambda _: {'bar': 'bar'})

        eq_(2, len(conffiles.conffiles))

        names = map(lambda x: x.name, conffiles.conffiles)

        self.assertTrue('foo.txt' in names)
        self.assertTrue('bar/bar.txt' in names)

    def test_undefined(self):
        """
        Raise an error if a template value is undefined.
        """

        with self.assertRaises(UndefinedError):
            ConfFiles(self.settings.for_env('any').all().next(),
                      PackageEnvironmentLoader('confab.tests', 'templates/default'),
                      lambda _: {})

    def test_filter_func(self):
        """
        Passing a filter_func limits which templates are generated.
        """

        with Options(filter_func=lambda file_name: file_name != 'foo.txt'):
            conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                                  PackageEnvironmentLoader('confab.tests', 'templates/default'),
                                  lambda _: {'bar': 'bar'})

            eq_(1, len(conffiles.conffiles))

            names = map(lambda x: x.name, conffiles.conffiles)

            self.assertTrue('bar/bar.txt' in names)

    def test_same_component_for_different_roles(self):
        """
        Two roles using the same component on the same host.
        """
        self.settings.roledefs = {
            'role1': ['host'],
            'role2': ['host'],
        }
        self.settings.componentdefs = {
            'role1': ['comp'],
            'role2': ['comp'],
        }
        environment_loader = PackageEnvironmentLoader('confab.tests', 'templates/validate')

        # use data that will create different conffiles for the same
        # component in the two roles.

        conffiles = ConfFiles(self.settings.for_env('any').with_roles('role1').all().next(),
                              environment_loader,
                              lambda comp: {'foo': 'role1'})

        eq_(1, len(conffiles.conffiles))
        ok_('role1.txt' == conffiles.conffiles[0].name)

        conffiles = ConfFiles(self.settings.for_env('any').with_roles('role2').all().next(),
                              environment_loader,
                              lambda comp: {'foo': 'role2'})

        eq_(1, len(conffiles.conffiles))
        ok_('role2.txt' == conffiles.conffiles[0].name)

    def test_warn_no_conffiles(self):
        """
        Warn when a role doesn't have any configuration files.
        """
        with Options(filter_func=lambda _: False):
            with catch_warnings(record=True) as captured_warnings:
                conffiles = ConfFiles(self.settings.for_env('any').all().next(),
                                      PackageEnvironmentLoader('confab.tests',
                                                               'templates/default'),
                                      lambda _: {})

                eq_(0, len(conffiles.conffiles))
                eq_(1, len(captured_warnings))
Example #29
0
class TestHostAndRole(TestCase):
    """
    Test host and role resolution.
    """
    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            "test1": ["host1", "host2", "host3"],
            "test2": ["host2", "host3"],
            "test3": []
        }
        self.settings.roledefs = {
            "role1": ["host1", "host2", "host3"],
            "role2": ["host2", "host3"],
            "role3": [],
        }

    def test_resolve_only_environment(self):
        """
        Specifying only an environment, returns all of its hosts and roles.
        """
        eq_({"host1": ["role1"],
             "host2": ["role1", "role2"],
             "host3": ["role1", "role2"]},
            self.settings.for_env("test1").host_roles)

    def test_resolve_only_empty_environment(self):
        """
        Specifying an empty environment generates a warning.
        """
        with catch_warnings(record=True) as caught_warnings:
            eq_({},
                self.settings.for_env("test3").host_roles)
        eq_(1, len(caught_warnings))

    def test_resolve_host_without_roles(self):
        """
        Explicit hosts return all of their roles.
        """
        eq_({"host1": ["role1"]},
            self.settings.for_env("test1").with_hosts("host1").host_roles)
        eq_({"host2": ["role1", "role2"]},
            self.settings.for_env("test1").with_hosts("host2").host_roles)

    def test_resolve_hosts_without_roles(self):
        """
        Explicit host list returns all hosts and all of their roles.
        """
        eq_({"host1": ["role1"],
             "host2": ["role1", "role2"]},
            self.settings.for_env("test1").with_hosts("host1", "host2").host_roles)

    def test_resolve_role_without_hosts(self):
        """
        Explicit role returns all hosts in environment with that role.
        """
        eq_({"host1": ["role1"],
             "host2": ["role1"],
             "host3": ["role1"]},
            self.settings.for_env("test1").with_roles("role1").host_roles)

    def test_resolve_roles_without_hosts(self):
        """
        Explicit role list returns all hosts in environment with any of those roles.
        """
        eq_({"host1": ["role1"],
             "host2": ["role1", "role2"],
             "host3": ["role1", "role2"]},
            self.settings.for_env("test1").with_roles("role1", "role2").host_roles)

        eq_({"host2": ["role1", "role2"],
             "host3": ["role1", "role2"]},
            self.settings.for_env("test2").with_roles("role1", "role2").host_roles)

    def test_resolve_unknown_role_without_hosts(self):
        """
        Explicit role matching no hosts returns empty mapping.
        """
        eq_({},
            self.settings.for_env("test1").with_roles("role3").host_roles)

    def test_resolve_host_with_role(self):
        """
        Explicit host and role mappings return host and role.
        """
        eq_({"host1": ["role1"]},
            self.settings.for_env("test1").with_hosts("host1").with_roles("role1").host_roles)

    def test_resolve_hosts_with_role(self):
        """
        Explicit hosts and role mappings return role for all hosts.
        """
        eq_({"host1": ["role1"],
             "host2": ["role1"]},
            self.settings.for_env("test1").with_hosts("host1", "host2").with_roles("role1").host_roles)

    def test_resolve_host_with_roles(self):
        """
        Explicit host and roles mappings return all roles applicable for host.
        """
        eq_({"host1": ["role1"]},
            self.settings.for_env("test1").with_hosts("host1").with_roles("role1", "role2").host_roles)
        eq_({"host2": ["role1", "role2"]},
            self.settings.for_env("test1").with_hosts("host2").with_roles("role1", "role2").host_roles)

    def test_resolve_hosts_with_roles(self):
        """
        Explicit hosts and roles mappings return all roles applicable for hosts.
        """
        eq_({"host1": ["role1"],
             "host2": ["role1", "role2"]},
            self.settings.for_env("test1").with_hosts("host1", "host2").with_roles("role1", "role2").host_roles)
Example #30
0
class TestHooks(TestCase):
    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            "environment": ["host"],
        }
        self.settings.roledefs = {
            "role": ["host"],
        }
        self.settings.componentdefs = {
            "role": ["component"],
        }
        self.component = self.settings.for_env(
            "environment").components().next()

    def test_add_remove_hook(self):
        """
        Load additional configuration data via hook.

        * Test adding new hook
        * Test removing hook
        """
        def test_hook(host):
            return {'data': {'num_cores': 4}}

        testhook = Hook(test_hook)
        local_hooks = HookRegistry()

        local_hooks.add_hook('host', testhook)
        ok_(testhook in local_hooks._hooks['host'])

        local_hooks.remove_hook('host', testhook)
        ok_(testhook not in local_hooks._hooks['host'])

    def test_hook_override_data(self):
        """
        Test that data loaded via hook overwrites data loaded via config.
        """
        def test_hook(role):
            return {'data': {'role': 'role2'}}

        with ScopeAndHooks(('host', Hook(test_hook))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(
                loader(self.component)['data'], {
                    'default': 'default',
                    'component': 'component',
                    'role': 'role2',
                    'environment': 'environment',
                    'host': 'host'
                })

    def test_data_override_hook(self):
        """
        Test that data loaded via hook will be overwritten by data loaded later via config.
        """
        def test_hook(role):
            return {'data': {'environment': 'environment2'}}

        with ScopeAndHooks(('role', Hook(test_hook))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(
                loader(self.component)['data'], {
                    'default': 'default',
                    'component': 'component',
                    'role': 'role',
                    'environment': 'environment',
                    'host': 'host'
                })

    def test_hook_load_order(self):
        """
        Test that hooks overwrite each other based on order they are defined.
        """
        def test_hook1(host):
            return {'data': {'host': 'host1'}}

        def test_hook2(host):
            return {'data': {'host': 'host2'}}

        with ScopeAndHooks(('host', Hook(test_hook1)),
                           ('host', Hook(test_hook2))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(
                loader(self.component)['data'], {
                    'default': 'default',
                    'component': 'component',
                    'role': 'role',
                    'environment': 'environment',
                    'host': 'host2'
                })

    def test_filter_func(self):
        """
        Test that hooks only run if the filter_func returns true
        """
        def test_hook1(host):
            return {'data': {'host': 'host1'}}

        def test_hook2(host):
            return {'data': {'host': 'host2'}}

        with ScopeAndHooks(
            ('host', Hook(test_hook1)),
            ('host', Hook(test_hook2, lambda componentdef: False))):
            loader = DataLoader(join(dirname(__file__), 'data/order'))
            eq_(
                loader(self.component)['data'], {
                    'default': 'default',
                    'component': 'component',
                    'role': 'role',
                    'environment': 'environment',
                    'host': 'host1'
                })
Example #31
0
class TestData(TestCase):

    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            "environment": ["host"],
        }
        self.settings.roledefs = {
            "role": ["host"],
        }
        self.settings.componentdefs = {
            "role": ["component"],
        }
        self.component = self.settings.for_env("environment").components().next()

    def test_data_templates(self):
        """
        Data modules can be templates.

        This test loads the "bar.py_tmpl" file as a Jinja template and converts it
        into a Python module. In the process of resolving this template, the foo.py
        module is included (defining "foo") and the "baz.py" macro is evaluated
        (defining "baz").
        """

        data = import_configuration('bar', join(dirname(__file__), 'data/templates'))
        eq_(data,
            {'foo': 'foo',
             'bar': 'bar',
             'baz': {'n': 42}})

    def test_load_order(self):
        """
        Data modules are always loaded in the same order: default,
        component, role, environment, then host.
        """
        loader = DataLoader(join(dirname(__file__), 'data/order'))

        eq_(loader(self.component)['data'],
            {'default': 'default',
             'component': 'component',
             'role': 'role',
             'environment': 'environment',
             'host': 'host'})

    def test_custom_data_modules_load_order(self):
        """
        Defining custom data modules does not affect load order.
        """

        loader = DataLoader(join(dirname(__file__), 'data/order'),
                            data_modules=reversed(DataLoader.ALL))

        eq_(loader(self.component)['data'],
            {'default': 'default',
             'component': 'component',
             'role': 'role',
             'environment': 'environment',
             'host': 'host'})

    def test_custom_data_modules_selection(self):
        """
        Defining custom data modules may select specific modules to load.
        """

        loader = DataLoader(join(dirname(__file__), 'data/order'),
                            data_modules=['component',
                                          'host'])

        eq_(loader(self.component)['data'],
            {'role': 'component',
             'component': 'component',
             'environment': 'component',
             'host': 'host'})

    def test_nested_configuration_files(self):
        '''
        Load configuration data from nested folder structure.
        '''
        loader = DataLoader(join(dirname(__file__), 'data/nested'))

        eq_(loader(self.component)['data'],
            {'default': 'default',
             'component': 'component',
             'role': 'role',
             'environment': 'environment',
             'host': 'host'})

    def test_missing_data_module(self):
        """
        If a data module does not exist, it is ignored.
        """
        loader = DataLoader(join(dirname(__file__), 'data/missing'),
                            data_modules=['component'])

        # no module named component
        eq_(None, loader(self.component).get('data'))

    def test_broken_data_module(self):
        """
        If a data module has a broken import, an import error is raised.
        """
        loader = DataLoader(join(dirname(__file__), 'data/broken'),
                            data_modules=['component'])

        with self.assertRaises(ImportError):
            loader(self.component).get('data')

    def test_broken_data_template(self):
        """
        If a data template has a broken import, an import error is raised.
        """
        loader = DataLoader(join(dirname(__file__), 'data/broken'),
                            data_modules=['host'])

        with self.assertRaises(ImportError):
            loader(self.component).get('data')

    def test_data_callables(self):
        """
        Data callables are applied when merging.
        """
        loader = DataLoader(join(dirname(__file__), 'data/callables'))
        data = loader(self.component)

        eq_(data['appended'], ['default', 'environment'])
        eq_(data['prepended'], ['environment', 'default'])
        eq_(data['unique'], ['default'])
        eq_(data['rotated'], ['pivot', 'itemB', 'itemA'])
Example #32
0
class TestGenerate(TestCase):
    def setUp(self):
        self.settings = Settings()
        self.settings.environmentdefs = {
            'any': ['localhost'],
        }
        self.settings.roledefs = {
            'role': ['localhost'],
        }

    def test_generate(self):
        """
        Generated templates have the correct values.
        """
        conffiles = ConfFiles(
            self.settings.for_env('any').all().next(),
            PackageEnvironmentLoader('confab.tests', 'templates/default'),
            lambda _: {
                'bar': 'bar',
                'foo': 'foo'
            })

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            # foo.txt is populated with 'foo'
            eq_('foo', tmp_dir.read('generated/localhost/foo.txt'))

            # bar.txt is populated with 'bar' and path is substituted
            eq_('bar', tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_unicode(self):
        """
        Generated templates with unicode data.
        """
        conffiles = ConfFiles(
            self.settings.for_env('any').all().next(),
            PackageEnvironmentLoader('confab.tests', 'templates/default'),
            lambda _: {
                'bar': 'bar',
                'foo': u'\xc5\xae'
            })
        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            # foo.txt is populated with u'\xc5\xae'
            eq_(u'\xc5\xae', tmp_dir.read('generated/localhost/foo.txt'))

            # bar.txt is populated with 'bar' and path is substituted
            eq_('bar', tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_undefined(self):
        """
        An exception is raised if a template value is undefined.
        """
        conffiles = ConfFiles(
            self.settings.for_env('any').all().next(),
            PackageEnvironmentLoader('confab.tests', 'templates/default'),
            lambda _: {'bar': 'bar'})

        with TempDir() as tmp_dir:
            with self.assertRaises(UndefinedError):
                conffiles.generate(tmp_dir.path)

    def test_should_render(self):
        """
        Passing a mime_type_func controls whether templates are rendered.
        """
        with Options(should_render=lambda mime_type: False):
            conffiles = ConfFiles(
                self.settings.for_env('any').all().next(),
                PackageEnvironmentLoader('confab.tests', 'templates/default'),
                lambda _: {
                    'bar': 'bar',
                    'foo': 'foo'
                })

            with TempDir() as tmp_dir:
                conffiles.generate(tmp_dir.path)

                # templates not rendered (though paths are)
                eq_('{{foo}}', tmp_dir.read('generated/localhost/foo.txt'))
                eq_('{{bar}}', tmp_dir.read('generated/localhost/bar/bar.txt'))

    def test_binary_template(self):
        """
        Confab copies binary config files verbatim to generated folder.
        """
        templates_dir = join(dirname(__file__), 'templates/binary')
        conffiles = ConfFiles(
            self.settings.for_env('any').all().next(),
            FileSystemEnvironmentLoader(templates_dir), lambda _: {})

        with TempDir() as tmp_dir:
            conffiles.generate(tmp_dir.path)

            ok_(
                filecmp.cmp(join(tmp_dir.path, 'generated/localhost/test.png'),
                            join(templates_dir, 'role/test.png')))

    def test_components(self):
        """
        Generate templates for roles with components.
        """
        self.settings.environmentdefs = {
            'any': ['host1'],
        }
        self.settings.roledefs = {
            'role1': ['host1'],
            'role2': ['host1'],
            'role3': ['host1'],
        }
        self.settings.componentdefs = {
            'role1': ['comp1'],
            'role2': ['compgroup'],
            'compgroup': ['comp2', 'comp3'],
        }
        with TempDir() as tmp_dir:
            for host_and_role in self.settings.for_env('any').all():
                conffiles = ConfFiles(
                    host_and_role,
                    PackageEnvironmentLoader('confab.tests',
                                             'templates/components'),
                    DataLoader(join(dirname(__file__), 'data/components')))
                conffiles.generate(tmp_dir.path)

            self.assertEquals('foo', tmp_dir.read('generated/host1/foo.txt'))
            self.assertEquals('bar',
                              tmp_dir.read('generated/host1/bar/bar.txt'))
            self.assertEquals('baz', tmp_dir.read('generated/host1/baz.conf'))

    def test_multiple_directories(self):
        """
        Generate templates for roles with components
        where templates and data are in multiple directories.
        """
        settings = Settings.load_from_dict(
            dict(environmentdefs={'any': ['host1']},
                 roledefs={
                     'role1': ['host1'],
                     'role2': ['host1']
                 },
                 componentdefs={'role1': ['comp1', 'comp2']}))

        subdirs = ['roles', 'components']
        template_dirs = map(
            lambda d: join(dirname(__file__), 'templates/multidir', d),
            subdirs)
        data_dirs = map(lambda d: join(dirname(__file__), 'data/multidir', d),
                        subdirs)

        with TempDir() as tmp_dir:
            for host_and_role in settings.for_env('any').all():
                conffiles = ConfFiles(
                    host_and_role, FileSystemEnvironmentLoader(*template_dirs),
                    DataLoader(data_dirs))
                conffiles.generate(tmp_dir.path)

            self.assertEquals('foo', tmp_dir.read('generated/host1/foo.txt'))
            self.assertEquals('bar', tmp_dir.read('generated/host1/bar.txt'))
            self.assertEquals('baz', tmp_dir.read('generated/host1/baz.conf'))
Example #33
0
 def setUp(self):
     self.dir_name = join(dirname(__file__), "data/default")
     self.settings = Settings()
Example #34
0
class TestEnvironment(TestCase):
    """
    Tests for environment selection.
    """
    def setUp(self):
        self.dir_name = join(dirname(__file__), "data/default")
        self.settings = Settings()

    def test_no_environments(self):
        """
        Fail if there is no environments defined.
        """
        with self.assertRaises(Exception):
            self.settings.for_env("local")

    def test_unknown_environments(self):
        """
        Fail if an environment is unknown.
        """
        self.settings.environmentdefs = {
            "foo": ["bar"],
        }
        self.settings.roledefs = {
            "baz": ["bar"],
        }
        with self.assertRaises(Exception):
            self.settings.for_env("local")

    def test_environment(self):
        """
        Lookup by environments works.
        """
        self.settings.environmentdefs = {
            "foo": ["bar", "baz"],
            "bar": ["foo"],
        }
        self.settings.roledefs = {
            "role": ["foo", "bar", "baz"],
        }

        eq_({"bar": ["role"],
             "baz": ["role"]},
            self.settings.for_env("foo").host_roles)
        eq_({"foo": ["role"]},
            self.settings.for_env("bar").host_roles)

    def test_host_without_roles(self):
        """
        Fail if an environment host has no roles
        """
        self.settings.environmentdefs = {
            "foo": ["bar"],
        }
        self.settings.roledefs = {
        }

        with self.assertRaises(Exception):
            self.self.settings.for_env("foo")

    def test_select_hosts(self):
        """
        Selecting specific hosts works.
        """
        self.settings.environmentdefs = {
            "foo": ["bar", "baz"],
        }
        self.settings.roledefs = {
            "role": ["bar", "baz"],
        }

        eq_({"bar": ["role"]},
            self.settings.for_env("foo").with_hosts("bar").host_roles)
        eq_({"bar": ["role"],
             "baz": ["role"]},
            self.settings.for_env("foo").with_hosts("bar", "baz").host_roles)

    def test_select_unknown_hosts(self):
        """
        Fail if a selected host is not known.
        """
        self.settings.environmentdefs = {
            "foo": ["bar", "baz"],
            "other": ["blah"]
        }
        self.settings.roledefs = {
            "role": ["bar", "baz", "blah"],
        }
        with self.assertRaises(Exception):
            self.self.settings.for_env("foo").with_hosts("bad")
        with self.assertRaises(Exception):
            self.self.settings.for_env("foo").with_hosts("blah")

    def test_select_role(self):
        """
        Selecting specific roles works.
        """
        self.settings.environmentdefs = {
            "foo": ["bar", "baz"],
        }
        self.settings.roledefs = {
            "role1": ["bar", "baz"],
            "role2": ["bar"],
        }
        eq_({"bar": ["role1"],
             "baz": ["role1"]},
            self.settings.for_env("foo").with_roles("role1").host_roles)
        eq_({"bar": ["role2"]},
            self.settings.for_env("foo").with_roles("role2").host_roles)

    def test_select_unknown_role(self):
        """
        Fail if a selected role is not known.
        """
        self.settings.environmentdefs = {
            "foo": ["bar", "baz"],
        }
        self.settings.roledefs = {
            "role1": ["bar"],
            "role2": ["baz"],
        }
        with self.assertRaises(Exception):
            self.self.settings.for_env("foo").with_roles("bad")

    def test_select_roles_and_hosts(self):
        """
        Test key matching within roledefs.
        """
        self.settings.environmentdefs = {
            "foo": ["bar", "baz"],
        }
        self.settings.roledefs = {
            "role1": ["bar"],
            "role2": ["baz"],
        }
        eq_({"baz": ["role2"]},
            self.settings.for_env("foo").with_hosts("bar", "baz").with_roles("role2").host_roles)
Example #35
0
 def setUp(self):
     self.settings = Settings()