Example #1
0
    def _load_config(self, skip_molecule_file=False):
        config = self._get_config()
        molecule_file = None

        if not skip_molecule_file:
            molecule_file = self._load_molecule_file(config)

            # if molecule file has a molecule section, merge that into our config as
            # an override with the highest precedence
            if 'molecule' in molecule_file:
                config = utilities.merge_dicts(config, molecule_file['molecule'])

            # merge virtualbox provider options from molecule file with our defaults
            for provider in molecule_file['vagrant']['providers']:
                if provider['type'] in config['providers']:
                    if 'options' in provider:
                        config['providers'][provider['type']]['options'] = utilities.merge_dicts(
                            config['providers'][provider['type']]['options'], provider['options'])

        # append molecule_dir to filenames so they're easier to use later
        config['state_file'] = '/'.join([config['molecule_dir'], config['state_file']])
        config['vagrantfile_file'] = '/'.join([config['molecule_dir'], config['vagrantfile_file']])
        config['rakefile_file'] = '/'.join([config['molecule_dir'], config['rakefile_file']])
        config['ansible']['config_file'] = '/'.join([config['molecule_dir'], config['ansible']['config_file']])
        config['ansible']['inventory_file'] = '/'.join([config['molecule_dir'], config['ansible']['inventory_file']])

        return config, molecule_file
Example #2
0
 def test_merge_deep_deep_01(self):
     expected = {
         "users": {"remy": {"age": 21, "email": "*****@*****.**", "office": "Austin", "position": "python master"}}
     }
     with testtools.ExpectedException(LookupError):
         actual = utilities.merge_dicts(self.deep_dict_a, self.deep_dict_b, raise_conflicts=True)
         self.assertEqual(expected, actual)
Example #3
0
    def merge_molecule_file(self, molecule_file=None):
        """
        Looks for a molecule file in the local path and merges it into our config

        :param molecule_file: path and name of molecule file to look for
        :return: None
        """
        if molecule_file is None:
            molecule_file = self.config['molecule']['molecule_file']

        if not os.path.isfile(molecule_file):
            error = '\n{}Unable to find {}. Exiting.{}'
            utilities.logger.error(error.format(colorama.Fore.RED, self.config[
                'molecule']['molecule_file'], colorama.Fore.RESET))
            sys.exit(1)

        with open(molecule_file, 'r') as env:

            try:
                molecule_yml = yaml.load(env)
            except Exception as e:
                error = "\n{}{} isn't properly formatted: {}{}"
                utilities.logger.error(error.format(
                    colorama.Fore.RED, molecule_file, e, colorama.Fore.RESET))
                sys.exit(1)

            interim = utilities.merge_dicts(self.config, molecule_yml)
            self.config = interim
Example #4
0
    def merge_molecule_file(self, molecule_file=None):
        """
        Looks for a molecule file in the local path and merges it into our config

        :param molecule_file: path and name of molecule file to look for
        :return: None
        """
        if molecule_file is None:
            molecule_file = self.config['molecule']['molecule_file']

        if not os.path.isfile(molecule_file):
            error = '\n{}Unable to find {}. Exiting.{}'
            print(
                error.format(Fore.RED,
                             self.config['molecule']['molecule_file'],
                             Fore.RESET))
            sys.exit(1)

        with open(molecule_file, 'r') as env:
            try:
                molecule_yml = yaml.safe_load(env)
            except Exception as e:
                error = "\n{}{} isn't properly formatted: {}{}"
                print(error.format(Fore.RED, molecule_file, e, Fore.RESET))
                sys.exit(1)

            interim = utilities.merge_dicts(self.config, molecule_yml)
            self.config = interim
Example #5
0
 def test_merge_deep_deep_02(self):
     expected = {
         "users": {"remy": {"age": 21,
                            "email": "*****@*****.**",
                            "office": "San Jose",
                            "position": "python master"}}
     }
     actual = utilities.merge_dicts(self.deep_dict_b, self.deep_dict_a)
     self.assertEqual(expected, actual)
Example #6
0
 def test_merge_simple_deep_01(self):
     expected = {
         "name": "remy",
         "city": "Berkeley",
         "age": 21,
         "users": {"remy": {"email": "*****@*****.**", "office": "San Jose", "age": 21}},
     }
     actual = utilities.merge_dicts(self.deep_dict_a, self.simple_dict_a)
     self.assertEqual(expected, actual)
Example #7
0
 def test_merge_deep_deep_00(self):
     expected = {
         "users": {"remy": {"age": 21,
                            "email": "*****@*****.**",
                            "office": "Austin",
                            "position": "python master"}}
     }
     actual = utilities.merge_dicts(self.deep_dict_a, self.deep_dict_b)
     self.assertEqual(expected, actual)
Example #8
0
def test_merge_deep_deep_00(deep_dict_a, deep_dict_b):
    expected = {
        "users": {"remy": {"age": 21,
                           "email": "*****@*****.**",
                           "office": "Austin",
                           "position": "python master"}}
    }
    actual = utilities.merge_dicts(deep_dict_a, deep_dict_b)

    assert expected == actual
Example #9
0
 def test_merge_simple_deep_01(self):
     expected = {
         "name": "remy",
         "city": "Berkeley",
         "age": 21,
         "users": {"remy": {"email": "*****@*****.**",
                            "office": "San Jose",
                            "age": 21}}
     }
     actual = utilities.merge_dicts(self.deep_dict_a, self.simple_dict_a)
     self.assertEqual(expected, actual)
Example #10
0
def test_merge_dicts():
    # Example taken from python-anyconfig/anyconfig/__init__.py
    a = {'b': [{'c': 0}, {'c': 2}], 'd': {'e': 'aaa', 'f': 3}}
    b = {'a': 1, 'b': [{'c': 3}], 'd': {'e': 'bbb'}}
    expected = {'a': 1,
                'b': [{'c': 0}, {'c': 2}, {'c': 3}],
                'd': {'e': "bbb",
                      'f': 3}}
    result = utilities.merge_dicts(a, b)

    assert expected == result
Example #11
0
    def _get_config(self):
        merged_config = Molecule.CONFIG_DEFAULTS.copy()

        # merge defaults with a config file if found
        for path in Molecule.CONFIG_PATHS:
            if path and os.path.isfile(path):
                with open(path, 'r') as stream:
                    merged_config = utilities.merge_dicts(merged_config, yaml.load(stream))
                    return merged_config

        return Molecule.CONFIG_DEFAULTS
Example #12
0
 def test_merge_deep_deep_01(self):
     expected = {
         "users": {"remy": {"age": 21,
                            "email": "*****@*****.**",
                            "office": "Austin",
                            "position": "python master"}}
     }
     with testtools.ExpectedException(LookupError):
         actual = utilities.merge_dicts(self.deep_dict_a,
                                        self.deep_dict_b,
                                        raise_conflicts=True)
         self.assertEqual(expected, actual)
Example #13
0
def test_merge_simple_deep_01(deep_dict_a, simple_dict_a):
    expected = {
        "name": "remy",
        "city": "Berkeley",
        "age": 21,
        "users": {"remy": {"email": "*****@*****.**",
                           "office": "San Jose",
                           "age": 21}}
    }
    actual = utilities.merge_dicts(deep_dict_a, simple_dict_a)

    assert expected == actual
Example #14
0
def test_merge_deep_deep_01(deep_dict_a, deep_dict_b):
    expected = {
        "users": {"remy": {"age": 21,
                           "email": "*****@*****.**",
                           "office": "Austin",
                           "position": "python master"}}
    }
    with pytest.raises(LookupError):
        actual = utilities.merge_dicts(deep_dict_a,
                                       deep_dict_b,
                                       raise_conflicts=True)
        assert expected == actual
Example #15
0
    def merge_molecule_config_files(self, paths=CONFIG_PATHS):
        """
        Looks for a molecule config file in paths and merges it with current config if found

        Only the first file that's found will be merged in.
        :param paths: list of places to look for config files
        :return: Path of file that was merged into config, if found, otherwise None
        """
        # merge defaults with a config file if found
        for path in paths:
            if path and os.path.isfile(path):
                with open(path, 'r') as stream:
                    self.config = utilities.merge_dicts(self.config, yaml.safe_load(stream))
                    return path
        return
Example #16
0
    def merge_molecule_config_files(self, paths=CONFIG_PATHS):
        """
        Looks for a molecule config file in paths and merges it with current config if found

        Only the first file that's found will be merged in.
        :param paths: list of places to look for config files
        :return: Path of file that was merged into config, if found, otherwise None
        """
        # merge defaults with a config file if found
        for path in paths:
            if path and os.path.isfile(path):
                with open(path, 'r') as stream:
                    self.config = utilities.merge_dicts(
                        self.config, yaml.safe_load(stream))
                    return path
        return
Example #17
0
    def _create_playbook_args(self):
        merged_args = self._config['ansible'].copy()

        # don't pass these to molecule-playbook CLI
        env_args = ['raw_ssh_args', 'host_key_checking', 'config_file', 'raw_env_vars']

        # args that molecule-playbook doesn't accept as --arg=value
        special_args = ['playbook', 'verbose']

        # merge defaults with molecule.yml values
        if 'ansible' in self._molecule_file:
            merged_args = utilities.merge_dicts(merged_args, self._molecule_file['ansible'])

            # set raw environment variables if any are found
            if 'raw_env_vars' in self._molecule_file['ansible']:
                for key, value in self._molecule_file['ansible']['raw_env_vars'].iteritems():
                    self._env[key] = value

        self._env['PYTHONUNBUFFERED'] = '1'
        self._env['ANSIBLE_FORCE_COLOR'] = 'true'
        self._env['ANSIBLE_HOST_KEY_CHECKING'] = str(merged_args['host_key_checking']).lower()
        self._env['ANSIBLE_SSH_ARGS'] = ' '.join(merged_args['raw_ssh_args'])
        self._env['ANSIBLE_CONFIG'] = merged_args['config_file']

        kwargs = {}
        args = []

        # pull in values passed to molecule CLI
        if '--tags' in self._args:
            merged_args['tags'] = self._args['--tags']

        # pass supported --arg=value args
        for arg, value in merged_args.iteritems():
            # don't pass False arguments to ansible-playbook
            if value and arg not in (env_args + special_args):
                kwargs[arg] = value

        # verbose is weird -vvvv
        if merged_args['verbose']:
            args.append('-' + merged_args['verbose'])

        kwargs['_env'] = self._env
        kwargs['_out'] = self._print_line
        kwargs['_err'] = self._print_line

        return merged_args['playbook'], args, kwargs
Example #18
0
 def test_merge_simple_simple_01(self):
     expected = {"name": "remy", "city": "Berkeley", "age": 21}
     actual = utilities.merge_dicts(self.simple_dict_b, self.simple_dict_a)
     self.assertEqual(expected, actual)
Example #19
0
 def test_merge_simple_simple_00(self):
     expected = {"name": "remy", "city": "Austin", "age": 21}
     actual = utilities.merge_dicts(self.simple_dict_a, self.simple_dict_b)
     self.assertEqual(expected, actual)
Example #20
0
def test_merge_simple_simple_01(simple_dict_b, simple_dict_a):
    expected = {"name": "remy", "city": "Berkeley", "age": 21}
    actual = utilities.merge_dicts(simple_dict_b, simple_dict_a)

    assert expected == actual
Example #21
0
def molecule_docker_config(molecule_section_data, docker_section_data,
                           ansible_section_data):
    return reduce(
        lambda x, y: utilities.merge_dicts(x, y),
        [molecule_section_data, docker_section_data, ansible_section_data])
Example #22
0
def molecule_openstack_config(molecule_section_data, openstack_section_data,
                              ansible_section_data):
    return reduce(
        lambda x, y: utilities.merge_dicts(x, y),
        [molecule_section_data, openstack_section_data, ansible_section_data])
Example #23
0
 def test_merge_simple_simple_01(self):
     expected = {"name": "remy", "city": "Berkeley", "age": 21}
     actual = utilities.merge_dicts(self.simple_dict_b, self.simple_dict_a)
     self.assertEqual(expected, actual)
Example #24
0
 def test_merge_simple_simple_00(self):
     expected = {"name": "remy", "city": "Austin", "age": 21}
     actual = utilities.merge_dicts(self.simple_dict_a, self.simple_dict_b)
     self.assertEqual(expected, actual)
Example #25
0
    def execute(self, exit=True):
        if self.static:
            self.disabled('verify')

        serverspec_dir = self.molecule._config.config['molecule'][
            'serverspec_dir']
        testinfra_dir = self.molecule._config.config['molecule'][
            'testinfra_dir']
        rakefile = self.molecule._config.config['molecule']['rakefile_file']
        ignore_paths = self.molecule._config.config['molecule']['ignore_paths']

        # whitespace & trailing newline check
        validators.check_trailing_cruft(ignore_paths=ignore_paths, exit=exit)

        self.molecule._write_ssh_config()

        # testinfra's Ansible calls get same env vars as ansible-playbook
        ansible = ansible_playbook.AnsiblePlaybook(
            self.molecule._config.config['ansible'],
            _env=self.molecule._env)

        debug = self.molecule._args.get('--debug', False)

        testinfra_kwargs = utilities.merge_dicts(
            self.molecule._provisioner.testinfra_args,
            self.molecule._config.config['testinfra'])
        testinfra_kwargs['env'] = ansible.env
        testinfra_kwargs['env']['PYTHONDONTWRITEBYTECODE'] = '1'
        testinfra_kwargs['debug'] = debug
        testinfra_kwargs['sudo'] = self.molecule._args.get('--sudo', False)

        serverspec_kwargs = self.molecule._provisioner.serverspec_args
        serverspec_kwargs['debug'] = debug

        try:
            # testinfra
            tests = '{}/test_*.py'.format(testinfra_dir)
            tests_glob = glob.glob(tests)
            if len(tests_glob) > 0:
                msg = 'Executing testinfra tests found in {}/.'
                utilities.print_info(msg.format(testinfra_dir))
                validators.testinfra(tests_glob, **testinfra_kwargs)
            else:
                msg = 'No testinfra tests found in {}/.\n'
                utilities.logger.warning(msg.format(testinfra_dir))

            # serverspec / rubocop
            if os.path.isdir(serverspec_dir):
                msg = 'Executing rubocop on *.rb files found in {}/.'
                utilities.print_info(msg.format(serverspec_dir))
                validators.rubocop(serverspec_dir, **serverspec_kwargs)

                msg = 'Executing serverspec tests found in {}/.'
                utilities.print_info(msg.format(serverspec_dir))
                validators.rake(rakefile, **serverspec_kwargs)
            else:
                msg = 'No serverspec tests found in {}/.\n'
                utilities.logger.warning(msg.format(serverspec_dir))
        except sh.ErrorReturnCode as e:
            utilities.logger.error('ERROR: {}'.format(e))
            if exit:
                utilities.sysexit(e.exit_code)
            return e.exit_code, e.stdout

        return None, None
Example #26
0
def molecule_invalid_provisioner_config(
        molecule_section_data, invalid_section_data, ansible_section_data):
    return reduce(
        lambda x, y: utilities.merge_dicts(x, y),
        [molecule_section_data, invalid_section_data, ansible_section_data])
Example #27
0
    def execute(self, exit=True):
        if self.static:
            self.disabled('verify')

        serverspec_dir = self.molecule._config.config['molecule'][
            'serverspec_dir']
        testinfra_dir = self.molecule._config.config['molecule'][
            'testinfra_dir']
        rakefile = self.molecule._config.config['molecule']['rakefile_file']
        ignore_paths = self.molecule._config.config['molecule']['ignore_paths']

        # whitespace & trailing newline check
        validators.check_trailing_cruft(ignore_paths=ignore_paths, exit=exit)

        # no serverspec or testinfra
        if not os.path.isdir(serverspec_dir) and not os.path.isdir(
                testinfra_dir):
            msg = '{}Skipping tests, could not find {}/ or {}/.{}'
            utilities.logger.warning(msg.format(colorama.Fore.YELLOW,
                                                serverspec_dir, testinfra_dir,
                                                colorama.Fore.RESET))
            return None, None

        self.molecule._write_ssh_config()

        # testinfra's Ansible calls get same env vars as ansible-playbook
        ansible = AnsiblePlaybook(self.molecule._config.config['ansible'],
                                  _env=self.molecule._env)

        testinfra_kwargs = utilities.merge_dicts(
            self.molecule._provisioner.testinfra_args,
            self.molecule._config.config['testinfra'])
        serverspec_kwargs = self.molecule._provisioner.serverspec_args
        testinfra_kwargs['env'] = ansible.env
        testinfra_kwargs['env']['PYTHONDONTWRITEBYTECODE'] = '1'
        testinfra_kwargs['debug'] = True if self.molecule._args.get(
            '--debug') else False
        testinfra_kwargs['sudo'] = True if self.molecule._args.get(
            '--sudo') else False
        serverspec_kwargs['env'] = testinfra_kwargs['env']
        serverspec_kwargs['debug'] = testinfra_kwargs['debug']

        try:
            # testinfra
            if len(glob.glob1(testinfra_dir, "test_*.py")) > 0:
                msg = '\n{}Executing testinfra tests found in {}/.{}'
                print(msg.format(colorama.Fore.MAGENTA, testinfra_dir,
                                 colorama.Fore.RESET))
                validators.testinfra(testinfra_dir, **testinfra_kwargs)
                print()
            else:
                msg = '{}No testinfra tests found in {}/.\n{}'
                utilities.logger.warning(msg.format(
                    colorama.Fore.YELLOW, testinfra_dir, colorama.Fore.RESET))

            # serverspec / rubocop
            if os.path.isdir(serverspec_dir):
                msg = '{}Executing rubocop on *.rb files found in {}/.{}'
                print(msg.format(colorama.Fore.MAGENTA, serverspec_dir,
                                 colorama.Fore.RESET))
                validators.rubocop(serverspec_dir, **serverspec_kwargs)
                print()

                msg = '{}Executing serverspec tests found in {}/.{}'
                print(msg.format(colorama.Fore.MAGENTA, serverspec_dir,
                                 colorama.Fore.RESET))
                validators.rake(rakefile, **serverspec_kwargs)
                print()
            else:
                msg = '{}No serverspec tests found in {}/.\n{}'
                utilities.logger.warning(msg.format(
                    colorama.Fore.YELLOW, serverspec_dir, colorama.Fore.RESET))
        except sh.ErrorReturnCode as e:
            utilities.logger.error('ERROR: {}'.format(e))
            if exit:
                sys.exit(e.exit_code)
            return e.exit_code, e.stdout

        return None, None
Example #28
0
def test_merge_simple_simple_00(simple_dict_a, simple_dict_b):
    expected = {"name": "remy", "city": "Austin", "age": 21}
    actual = utilities.merge_dicts(simple_dict_a, simple_dict_b)

    expected == actual