Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider parent also when comparing IncludedFile #37083

Merged
merged 2 commits into from
Apr 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/ansible/playbook/included_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def add_host(self, host):
self._hosts.append(host)

def __eq__(self, other):
return other._filename == self._filename and other._args == self._args
return other._filename == self._filename and other._args == self._args and other._task._parent._uuid == self._task._parent._uuid
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think (but haven't tested) that if self._task is a TaskInclude, then if used in conjunction with #37304, this could be:

def __eq__(self, other):
    return other._filename == self._filename and other._args == self._args and other._task._parent == self._task._parent

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly even

def __eq__(self, other):
    return other._filename == self._filename and other._args == self._args and other._task == self._task

But, untested...


def __repr__(self):
return "%s (%s): %s" % (self._filename, self._args, self._hosts)
Expand Down
151 changes: 102 additions & 49 deletions test/units/playbook/test_included_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@

import os

from ansible.compat.tests import unittest
import pytest

from ansible.compat.tests.mock import MagicMock
from units.mock.loader import DictDataLoader

Expand All @@ -32,70 +33,122 @@
from ansible.playbook.included_file import IncludedFile


class TestIncludedFile(unittest.TestCase):
def test(self):
filename = 'somefile.yml'
@pytest.fixture
def mock_iterator():
mock_iterator = MagicMock(name='MockIterator')
mock_iterator._play = MagicMock(name='MockPlay')
return mock_iterator


@pytest.fixture
def mock_variable_manager():
# TODO: can we use a real VariableManager?
mock_variable_manager = MagicMock(name='MockVariableManager')
mock_variable_manager.get_vars.return_value = dict()
return mock_variable_manager


def test_included_file_instantiation():
filename = 'somefile.yml'

inc_file = IncludedFile(filename=filename, args=[], task=None)

assert isinstance(inc_file, IncludedFile)
assert inc_file._filename == filename
assert inc_file._args == []
assert inc_file._task is None


def test_process_include_results(mock_iterator, mock_variable_manager):
hostname = "testhost1"
hostname2 = "testhost2"

parent_task_ds = {'debug': 'msg=foo'}
parent_task = Task.load(parent_task_ds)

task_ds = {'include': 'include_test.yml'}
loaded_task = TaskInclude.load(task_ds, task_include=parent_task)

return_data = {'include': 'include_test.yml'}
# The task in the TaskResult has to be a TaskInclude so it has a .static attr
result1 = task_result.TaskResult(host=hostname, task=loaded_task, return_data=return_data)
result2 = task_result.TaskResult(host=hostname2, task=loaded_task, return_data=return_data)
results = [result1, result2]

fake_loader = DictDataLoader({'include_test.yml': ""})

res = IncludedFile.process_include_results(results, mock_iterator, fake_loader, mock_variable_manager)
assert isinstance(res, list)
assert len(res) == 1
assert res[0]._filename == os.path.join(os.getcwd(), 'include_test.yml')
assert res[0]._hosts == ['testhost1', 'testhost2']
assert res[0]._args == {}


inc_file = IncludedFile(filename=filename, args=[], task=None)
def test_process_include_diff_files(mock_iterator, mock_variable_manager):
hostname = "testhost1"
hostname2 = "testhost2"

self.assertIsInstance(inc_file, IncludedFile)
self.assertEquals(inc_file._filename, filename)
self.assertEquals(inc_file._args, [])
self.assertEquals(inc_file._task, None)
parent_task_ds = {'debug': 'msg=foo'}
parent_task = Task.load(parent_task_ds)

def test_process_include_results(self):
hostname = "testhost1"
hostname2 = "testhost2"
task_ds = {'include': 'include_test.yml'}
loaded_task = TaskInclude.load(task_ds, task_include=parent_task)

parent_task_ds = {'debug': 'msg=foo'}
parent_task = Task()
parent_task.load(parent_task_ds)
child_task_ds = {'include': 'other_include_test.yml'}
loaded_child_task = TaskInclude.load(child_task_ds, task_include=loaded_task)

task_ds = {'include': 'include_test.yml'}
task_include = TaskInclude()
loaded_task = task_include.load(task_ds, task_include=parent_task)
return_data = {'include': 'include_test.yml'}
# The task in the TaskResult has to be a TaskInclude so it has a .static attr
result1 = task_result.TaskResult(host=hostname, task=loaded_task, return_data=return_data)

child_task_ds = {'include': 'other_include_test.yml'}
child_task_include = TaskInclude()
loaded_child_task = child_task_include.load(child_task_ds, task_include=loaded_task)
return_data = {'include': 'other_include_test.yml'}
result2 = task_result.TaskResult(host=hostname2, task=loaded_child_task, return_data=return_data)
results = [result1, result2]

return_data = {'include': 'include_test.yml'}
# The task in the TaskResult has to be a TaskInclude so it has a .static attr
result1 = task_result.TaskResult(host=hostname, task=loaded_task, return_data=return_data)
fake_loader = DictDataLoader({'include_test.yml': "",
'other_include_test.yml': ""})

return_data = {'include': 'other_include_test.yml'}
result2 = task_result.TaskResult(host=hostname2, task=loaded_child_task, return_data=return_data)
results = [result1, result2]
res = IncludedFile.process_include_results(results, mock_iterator, fake_loader, mock_variable_manager)
assert isinstance(res, list)
assert res[0]._filename == os.path.join(os.getcwd(), 'include_test.yml')
assert res[1]._filename == os.path.join(os.getcwd(), 'other_include_test.yml')

fake_loader = DictDataLoader({'include_test.yml': "",
'other_include_test.yml': ""})
assert res[0]._hosts == ['testhost1']
assert res[1]._hosts == ['testhost2']

mock_tqm = MagicMock(name='MockTaskQueueManager')
assert res[0]._args == {}
assert res[1]._args == {}

mock_play = MagicMock(name='MockPlay')

mock_iterator = MagicMock(name='MockIterator')
mock_iterator._play = mock_play
def test_process_include_simulate_free(mock_iterator, mock_variable_manager):
hostname = "testhost1"
hostname2 = "testhost2"

mock_inventory = MagicMock(name='MockInventory')
mock_inventory._hosts_cache = dict()
parent_task_ds = {'debug': 'msg=foo'}
parent_task1 = Task.load(parent_task_ds)
parent_task2 = Task.load(parent_task_ds)

def _get_host(host_name):
return None
task_ds = {'include': 'include_test.yml'}
loaded_task1 = TaskInclude.load(task_ds, task_include=parent_task1)
loaded_task2 = TaskInclude.load(task_ds, task_include=parent_task2)

mock_inventory.get_host.side_effect = _get_host
return_data = {'include': 'include_test.yml'}
# The task in the TaskResult has to be a TaskInclude so it has a .static attr
result1 = task_result.TaskResult(host=hostname, task=loaded_task1, return_data=return_data)
result2 = task_result.TaskResult(host=hostname2, task=loaded_task2, return_data=return_data)
results = [result1, result2]

# TODO: can we use a real VariableManager?
mock_variable_manager = MagicMock(name='MockVariableManager')
mock_variable_manager.get_vars.return_value = dict()
fake_loader = DictDataLoader({'include_test.yml': ""})

res = IncludedFile.process_include_results(results, mock_iterator, fake_loader, mock_variable_manager)
self.assertIsInstance(res, list)
self.assertEquals(res[0]._filename, os.path.join(os.getcwd(), 'include_test.yml'))
self.assertEquals(res[1]._filename, os.path.join(os.getcwd(), 'other_include_test.yml'))
res = IncludedFile.process_include_results(results, mock_iterator, fake_loader, mock_variable_manager)
assert isinstance(res, list)
assert len(res) == 2
assert res[0]._filename == os.path.join(os.getcwd(), 'include_test.yml')
assert res[1]._filename == os.path.join(os.getcwd(), 'include_test.yml')

self.assertEquals(res[0]._hosts, ['testhost1'])
self.assertEquals(res[1]._hosts, ['testhost2'])
assert res[0]._hosts == ['testhost1']
assert res[1]._hosts == ['testhost2']

self.assertEquals(res[0]._args, {})
self.assertEquals(res[1]._args, {})
assert res[0]._args == {}
assert res[1]._args == {}