def _add_or_update_vars(self): """ Creates host and/or group vars and returns None. :returns: None """ for target in ['host_vars', 'group_vars']: if target == 'host_vars': vars_target = copy.deepcopy(self.host_vars) for instance_name, _ in self.host_vars.items(): if instance_name == 'localhost': instance_key = instance_name else: instance_key = instance_name vars_target[instance_key] = vars_target.pop(instance_name) elif target == 'group_vars': vars_target = self.group_vars if vars_target: ephemeral_directory = self._config.scenario.ephemeral_directory target_vars_directory = os.path.join(ephemeral_directory, target) if not os.path.isdir(util.abs_path(target_vars_directory)): os.mkdir(util.abs_path(target_vars_directory)) for target in vars_target.keys(): target_var_content = vars_target[target] path = os.path.join( util.abs_path(target_vars_directory), target) util.write_file(path, util.safe_dump(target_var_content))
def _add_or_update_vars(self, target): """ Creates or updates to host/group variables if needed. :param target: :returns: .. todo:: Document this method. """ if target in self.config.config['ansible']: vars_target = self.config.config['ansible'][target] else: return molecule_dir = self.config.config['molecule']['molecule_dir'] target_vars_path = os.path.join(molecule_dir, target) if not os.path.exists(os.path.abspath(target_vars_path)): os.mkdir(os.path.abspath(target_vars_path)) for target in vars_target.keys(): target_var_content = vars_target[target][0] util.write_file( os.path.join(os.path.abspath(target_vars_path), target), "---\n" + yaml.dump( target_var_content, default_flow_style=False))
def _write_state_file(self): util.write_file( self._state_file, yaml.safe_dump( self._data, default_flow_style=False, explicit_start=True, encoding='utf-8'))
def test_write_file(temp_dir): dest_file = os.path.join(temp_dir, 'test_util_write_file.tmp') contents = binascii.b2a_hex(os.urandom(15)) util.write_file(dest_file, contents) with open(dest_file, 'r') as f: data = f.read() assert data == contents
def test_write_file(temp_dir): dest_file = os.path.join(temp_dir.strpath, "test_util_write_file.tmp") contents = binascii.b2a_hex(os.urandom(15)).decode("utf-8") util.write_file(dest_file, contents) with util.open_file(dest_file) as stream: data = stream.read() x = f"# Molecule managed\n\n{contents}" assert x == data
def write_config(self): """ Write the provisioner's config file to disk and returns None. :return: None """ template = util.render_template(self._get_config_template(), config_options=self.config_options) util.write_file(self.config_file, template)
def test_write_file(temp_dir): dest_file = os.path.join(temp_dir.strpath, 'test_util_write_file.tmp') contents = binascii.b2a_hex(os.urandom(15)).decode() util.write_file(dest_file, contents) with util.open_file(dest_file) as stream: data = stream.read() x = '# Molecule managed\n\n{}'.format(contents) assert x == data
def test_get_configs(config_instance): molecule_file = config_instance.molecule_file data = config_instance.config util.write_file(molecule_file, util.safe_dump(data)) result = base.get_configs({}, {}) assert 1 == len(result) assert isinstance(result, list) assert isinstance(result[0], config.Config)
def test_write_file(): tmp_file = '/tmp/test_util_write_file.tmp' contents = binascii.b2a_hex(os.urandom(15)) util.write_file(tmp_file, contents) with open(tmp_file, 'r') as f: data = f.read() os.remove(tmp_file) assert data == contents
def _write_inventory(self): """ Write the provisioner's inventory file to disk and returns None. :return: None """ self._verify_inventory() util.write_file(self.inventory_file, util.safe_dump(self.inventory))
def _write_inventory(self): """ Writes the provisioner's inventory file to disk and returns None. :return: None """ self._verify_inventory() util.write_file(self.inventory_file, util.safe_dump(self.inventory))
def test_write_file(temp_dir): dest_file = os.path.join(temp_dir.strpath, 'test_util_write_file.tmp') contents = binascii.b2a_hex(os.urandom(15)).decode('utf-8') util.write_file(dest_file, contents) with util.open_file(dest_file) as stream: data = stream.read() x = '# Molecule managed\n\n{}'.format(contents) assert x == data
def test_get_config_with_multiple_base_configs(config_instance): config_instance.args = {"base_config": ["./foo.yml", "./foo2.yml"]} contents = {"foo": "bar", "foo2": "bar"} util.write_file(config_instance.args["base_config"][0], util.safe_dump(contents)) contents = {"foo2": "bar2"} util.write_file(config_instance.args["base_config"][1], util.safe_dump(contents)) result = config_instance._get_config() assert result["foo"] == "bar" assert result["foo2"] == "bar2"
def test_set_env(config_instance): config_instance.args = {'env_file': '.env'} contents = { 'foo': 'bar', 'BAZ': 'zzyzx', } util.write_file(config_instance.args['env_file'], util.safe_dump(contents)) env = config_instance._set_env({}) assert contents == env
def test_open_file(temp_dir): path = os.path.join(temp_dir.strpath, 'foo') util.write_file(path, 'foo: bar') with util.open_file(path) as stream: try: file_types = (file, io.IOBase) except NameError: file_types = io.IOBase assert isinstance(stream, file_types)
def test_os_walk(temp_dir): scenarios = ['scenario1', 'scenario2', 'scenario3'] molecule_directory = pytest.helpers.molecule_directory() for scenario in scenarios: scenario_directory = os.path.join(molecule_directory, scenario) molecule_file = pytest.helpers.get_molecule_file(scenario_directory) os.makedirs(scenario_directory) util.write_file(molecule_file, '') result = [f for f in util.os_walk(molecule_directory, 'molecule.yml')] assert 3 == len(result)
def test_set_env_from_file(config_instance): config_instance.args = {'env_file': '.env'} contents = { 'foo': 'bar', 'BAZ': 'zzyzx', } env_file = config_instance.args.get('env_file') util.write_file(env_file, util.safe_dump(contents)) env = config.set_env_from_file({}, env_file) assert contents == env
def write_config(self): """ Writes the provisioner's config file to disk and returns None. :return: None """ # self._verify_config() template = util.render_template( self._get_config_template(), config_options=self.config_options) util.write_file(self.config_file, template)
def test_os_walk(temp_dir): scenarios = ["scenario1", "scenario2", "scenario3"] molecule_directory = pytest.helpers.molecule_directory() for scenario in scenarios: scenario_directory = os.path.join(molecule_directory, scenario) molecule_file = pytest.helpers.get_molecule_file(scenario_directory) os.makedirs(scenario_directory) util.write_file(molecule_file, "") result = [f for f in util.os_walk(molecule_directory, "molecule.yml")] assert 3 == len(result)
def test_open_file(temp_dir): path = os.path.join(temp_dir.strpath, "foo") util.write_file(path, "foo: bar") with util.open_file(path) as stream: try: file_types = (file, io.IOBase) except NameError: file_types = io.IOBase assert isinstance(stream, file_types)
def test_prune(_instance): e_dir = _instance.ephemeral_directory # prune data also includes files in the scenario inventory dir, # which is "<e_dir>/inventory" by default. # items are created in listed order, directories first, safe before pruned prune_data = { # these files should not be pruned 'safe_files': [ 'state.yml', 'ansible.cfg', 'inventory/ansible_inventory.yml', ], # these directories should not be pruned 'safe_dirs': ['inventory'], # these files should be pruned 'pruned_files': [ 'foo', 'bar', 'inventory/foo', 'inventory/bar', ], # these directories should be pruned, including empty subdirectories 'pruned_dirs': [ 'baz', 'roles', 'inventory/baz', 'roles/foo', ], } for directory in prune_data['safe_dirs'] + prune_data['pruned_dirs']: # inventory dir should already exist, and its existence is # required by the assertions below. if directory == 'inventory': continue os.mkdir(os.path.join(e_dir, directory)) for file in prune_data['safe_files'] + prune_data['pruned_files']: util.write_file(os.path.join(e_dir, file), '') _instance.prune() for safe_file in prune_data['safe_files']: assert os.path.isfile(os.path.join(e_dir, safe_file)) for safe_dir in prune_data['safe_dirs']: assert os.path.isdir(os.path.join(e_dir, safe_dir)) for pruned_file in prune_data['pruned_files']: assert not os.path.isfile(os.path.join(e_dir, pruned_file)) for pruned_dir in prune_data['pruned_dirs']: assert not os.path.isdir(os.path.join(e_dir, pruned_dir))
def test_execute_when_instances_already_prepared_but_force_provided( mocker, patched_logger_warn, _patched_ansible_prepare, config_instance): pb = os.path.join(config_instance.scenario.directory, 'prepare.yml') util.write_file(pb, '') config_instance.state.change_state('prepared', True) config_instance.command_args = {'force': True} p = prepare.Prepare(config_instance) p.execute() _patched_ansible_prepare.assert_called_once_with()
def test_execute(mocker, _patched_ansible_side_effect, patched_logger_info, patched_config_validate, config_instance): pb = os.path.join(config_instance.scenario.directory, 'side_effect.yml') util.write_file(pb, '') se = side_effect.SideEffect(config_instance) se.execute() x = [ mocker.call("Scenario: 'default'"), mocker.call("Action: 'side_effect'"), ] assert x == patched_logger_info.mock_calls _patched_ansible_side_effect.assert_called_once_with()
def test_execute(mocker, _patched_ansible_cleanup, patched_logger_info, patched_config_validate, config_instance): pb = os.path.join(config_instance.scenario.directory, 'cleanup.yml') util.write_file(pb, '') cu = cleanup.Cleanup(config_instance) cu.execute() x = [ mocker.call("Scenario: 'default'"), mocker.call("Action: 'cleanup'"), ] assert x == patched_logger_info.mock_calls _patched_ansible_cleanup.assert_called_once_with()
def test_additional_files_or_dirs_property(_instance): tests_directory = _instance._config.verifier.directory file1_file = os.path.join(tests_directory, "file1.py") file2_file = os.path.join(tests_directory, "file2.py") match1_file = os.path.join(tests_directory, "match1.py") match2_file = os.path.join(tests_directory, "match2.py") test_subdir = os.path.join(tests_directory, "dir") test_subdir_file = os.path.join(test_subdir, "test_subdir_file.py") os.mkdir(tests_directory) os.mkdir(test_subdir) for f in [file1_file, file2_file, match1_file, match2_file, test_subdir_file]: util.write_file(f, "") x = [file1_file, file2_file, match1_file, match2_file, test_subdir_file] assert sorted(x) == sorted(_instance.additional_files_or_dirs)
def test_combine_raises_on_failed_interpolation(patched_logger_critical, config_instance): contents = {'foo': '$6$8I5Cfmpr$kGZB'} util.write_file(config_instance.molecule_file, util.safe_dump(contents)) with pytest.raises(SystemExit) as e: config_instance._combine() assert 1 == e.value.code msg = ("parsing config file '{}'.\n\n" 'Invalid placeholder in string: line 4, col 6\n' '# Molecule managed\n\n' '---\n' 'foo: $6$8I5Cfmpr$kGZB\n').format(config_instance.molecule_file) patched_logger_critical.assert_called_once_with(msg)
def test_get_data_loads_existing_state_file(_instance, molecule_data, config_instance): data = { "converged": False, "created": True, "driver": None, "prepared": None } util.write_file(_instance._state_file, util.safe_dump(data)) s = state.State(config_instance) assert not s.converged assert s.created assert not s.driver assert not s.prepared
def create_inventory_file(self): """ Creates the inventory file used by molecule and returns None. :return: None """ inventory = '' for instance in self.driver.instances: inventory += self.driver.inventory_entry(instance) groups = {} for instance in self.driver.instances: ansible_groups = instance.get('ansible_groups') if ansible_groups: for group in ansible_groups: if isinstance(group, str): if group not in groups: groups[group] = [] groups[group].append(instance['name']) elif isinstance(group, dict): for group_name, group_list in group.iteritems(): for g in group_list: if group_name not in groups: groups[group_name] = [] groups[group_name].append(g) if self.args.get('platform') == 'all': self.driver.platform = 'all' for group, subgroups in groups.iteritems(): inventory += '\n[{}]\n'.format(group) for subgroup in subgroups: instance_name = util.format_instance_name( subgroup, self.driver.platform, self.driver.instances) if instance_name: inventory += '{}\n'.format(instance_name) else: inventory += '{}\n'.format(subgroup) inventory_file = self.config.config['ansible']['inventory_file'] try: util.write_file(inventory_file, inventory) except IOError: msg = 'WARNING: could not write inventory file {}.'.format( inventory_file) util.print_warn(msg)
def test_execute(mocker, patched_logger_info, _patched_ansible_prepare, patched_config_validate, config_instance): pb = os.path.join(config_instance.scenario.directory, 'prepare.yml') util.write_file(pb, '') p = prepare.Prepare(config_instance) p.execute() x = [ mocker.call("Scenario: 'default'"), mocker.call("Action: 'prepare'"), ] assert x == patched_logger_info.mock_calls _patched_ansible_prepare.assert_called_once_with() assert config_instance.state.prepared
def test_execute( mocker, _patched_ansible_cleanup, patched_logger_info, patched_config_validate, config_instance, ): pb = os.path.join(config_instance.scenario.directory, "cleanup.yml") util.write_file(pb, "") cu = cleanup.Cleanup(config_instance) cu.execute() assert len(patched_logger_info.mock_calls) == 1 name, args, kwargs = patched_logger_info.mock_calls[0] assert "cleanup" in args _patched_ansible_cleanup.assert_called_once_with()
def test_get_data_loads_existing_state_file(temp_dir, molecule_data): molecule_directory = pytest.helpers.molecule_directory() scenario_directory = os.path.join(molecule_directory, 'default') molecule_file = pytest.helpers.get_molecule_file(scenario_directory) ephemeral_directory = pytest.helpers.molecule_ephemeral_directory() state_file = os.path.join(ephemeral_directory, 'state.yml') os.makedirs(ephemeral_directory) data = {'converged': False, 'created': True, 'driver': None} util.write_file(state_file, util.safe_dump(data)) pytest.helpers.write_molecule_file(molecule_file, molecule_data) c = config.Config(molecule_file) s = state.State(c) assert not s.converged assert s.created assert not s.driver
def test_execute( mocker, _patched_ansible_side_effect, patched_logger_info, patched_config_validate, config_instance, ): pb = os.path.join(config_instance.scenario.directory, "side_effect.yml") util.write_file(pb, "") se = side_effect.SideEffect(config_instance) se.execute() assert len(patched_logger_info.mock_calls) == 1 name, args, kwargs = patched_logger_info.mock_calls[0] assert "default" in args assert "side_effect" in args _patched_ansible_side_effect.assert_called_once_with()
def _add_or_update_vars(self, target): """Creates or updates to host/group variables if needed.""" if target in self.config.config['ansible']: vars_target = self.config.config['ansible'][target] else: return molecule_dir = self.config.config['molecule']['molecule_dir'] target_vars_path = os.path.join(molecule_dir, target) if not os.path.exists(os.path.abspath(target_vars_path)): os.mkdir(os.path.abspath(target_vars_path)) for target in vars_target.keys(): target_var_content = vars_target[target][0] util.write_file( os.path.join(os.path.abspath(target_vars_path), target), "---\n" + yaml.dump(target_var_content, default_flow_style=False))
def test_bake(patched_testinfra_get_tests, inventory_file, testinfra_instance): tests_directory = testinfra_instance._config.verifier.directory file1_file = os.path.join(tests_directory, 'file1.py') os.mkdir(tests_directory) util.write_file(file1_file, '') testinfra_instance.bake() x = [ str(sh.Command('py.test')), '--ansible-inventory={}'.format(inventory_file), '--connection=ansible', '-vvv', '--foo=bar', 'foo.py', 'bar.py', file1_file, ] result = str(testinfra_instance._testinfra_command).split() assert sorted(x) == sorted(result)
def test_execute( mocker, patched_logger_info, _patched_ansible_prepare, patched_config_validate, config_instance, ): pb = os.path.join(config_instance.scenario.directory, "prepare.yml") util.write_file(pb, "") p = prepare.Prepare(config_instance) p.execute() assert len(patched_logger_info.mock_calls) == 1 name, args, kwargs = patched_logger_info.mock_calls[0] assert "default" in args assert "prepare" in args _patched_ansible_prepare.assert_called_once_with() assert config_instance.state.prepared
def test_prune(_instance): e_dir = _instance.ephemeral_directory # prune data also includes files in the scenario inventory dir, # which is "<e_dir>/inventory" by default. # items are created in listed order, directories first, safe before pruned prune_data = { # these files should not be pruned "safe_files": ["state.yml", "ansible.cfg", "inventory/ansible_inventory.yml"], # these directories should not be pruned "safe_dirs": ["inventory"], # these files should be pruned "pruned_files": ["foo", "bar", "inventory/foo", "inventory/bar"], # these directories should be pruned, including empty subdirectories "pruned_dirs": ["baz", "roles", "inventory/baz", "roles/foo"], } for directory in prune_data["safe_dirs"] + prune_data["pruned_dirs"]: # inventory dir should already exist, and its existence is # required by the assertions below. if directory == "inventory": continue os.mkdir(os.path.join(e_dir, directory)) for file in prune_data["safe_files"] + prune_data["pruned_files"]: util.write_file(os.path.join(e_dir, file), "") _instance.prune() for safe_file in prune_data["safe_files"]: assert os.path.isfile(os.path.join(e_dir, safe_file)) for safe_dir in prune_data["safe_dirs"]: assert os.path.isdir(os.path.join(e_dir, safe_dir)) for pruned_file in prune_data["pruned_files"]: assert not os.path.isfile(os.path.join(e_dir, pruned_file)) for pruned_dir in prune_data["pruned_dirs"]: assert not os.path.isdir(os.path.join(e_dir, pruned_dir))
def test_prune(base_instance): ephemeral_directory = base_instance._config.scenario.ephemeral_directory foo_file = os.path.join(ephemeral_directory, 'foo') bar_file = os.path.join(ephemeral_directory, 'bar') baz_directory = os.path.join(ephemeral_directory, 'baz') state_file = os.path.join(ephemeral_directory, 'state.yml') inventory_file = os.path.join(ephemeral_directory, 'ansible_inventory.yml') config_file = os.path.join(ephemeral_directory, 'ansible.cfg') os.mkdir(baz_directory) for f in [foo_file, bar_file, state_file]: util.write_file(f, '') base_instance.prune() assert not os.path.isfile(foo_file) assert not os.path.isfile(bar_file) assert os.path.isfile(state_file) assert os.path.isfile(config_file) assert os.path.isfile(inventory_file) assert not os.path.isdir(baz_directory)
def test_bake(_patched_testinfra_get_tests, inventory_file, _instance): tests_directory = _instance._config.verifier.directory file1_file = os.path.join(tests_directory, "file1.py") os.mkdir(tests_directory) util.write_file(file1_file, "") _instance.bake() x = [ str(sh.Command("pytest")), "--ansible-inventory={}".format(inventory_file), "--connection=ansible", "-v", "--foo=bar", "foo.py", "bar.py", "-p", "no:cacheprovider", file1_file, ] result = str(_instance._testinfra_command).split() assert sorted(x) == sorted(result)
def _create_inventory_file(self): """ Creates the inventory file used by molecule and later passed to ansible-playbook. :return: None """ inventory = '' for instance in self._driver.instances: inventory += self._driver.inventory_entry(instance) # get a list of all groups and hosts in those groups groups = {} for instance in self._driver.instances: if 'ansible_groups' in instance: for group in instance['ansible_groups']: if group not in groups: groups[group] = [] groups[group].append(instance['name']) if self._args.get('--platform') == 'all': self._driver.platform = 'all' for group, instances in groups.iteritems(): inventory += '\n[{}]\n'.format(group) for instance in instances: inventory += '{}\n'.format( util.format_instance_name(instance, self._driver.platform, self._driver.instances)) inventory_file = self.config.config['ansible']['inventory_file'] try: util.write_file(inventory_file, inventory) except IOError: LOG.warning('WARNING: could not write inventory file {}'.format( inventory_file))
def test_safe_load_file(temp_dir): path = os.path.join(temp_dir.strpath, 'foo') util.write_file(path, 'foo: bar') assert {'foo': 'bar'} == util.safe_load_file(path)
def write_ssh_config(self): ssh_config = self._get_ssh_config() if ssh_config is None: return out = self.driver.conf(ssh_config=True) util.write_file(ssh_config, out)
def write_molecule_file(filename, data): util.write_file(filename, util.safe_dump(data))