feat(lookup/merge_variables): Add all hosts mode to collect configuration across multiple hosts (#7999)

* Add Feature to collect variables accross different hosts

* fix merging lists

* adjust unit tests

* lint fixes

* adjusting integration tests

* remove white spaces

* Update plugins/lookup/merge_variables.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/lookup/merge_variables.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/lookup/merge_variables.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* apply suggested changes to correctly handling the initial_value parameter, incl. additional test

* whitespace

---------

Co-authored-by: Alexander Petrenz <alexander.petrenz@posteo.de>
Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Alexander Petrenz 2024-03-08 07:25:39 +01:00 committed by GitHub
parent fa30b02294
commit 0ded1109fe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 302 additions and 12 deletions

View file

@ -24,7 +24,7 @@ class TestMergeVariablesLookup(unittest.TestCase):
self.merge_vars_lookup = merge_variables.LookupModule(loader=self.loader, templar=self.templar)
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix'])
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix', None])
@patch.object(Templar, 'template', side_effect=[['item1'], ['item3']])
def test_merge_list(self, mock_set_options, mock_get_option, mock_template):
results = self.merge_vars_lookup.run(['__merge_list'], {
@ -36,7 +36,7 @@ class TestMergeVariablesLookup(unittest.TestCase):
self.assertEqual(results, [['item1', 'item3']])
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[['initial_item'], 'ignore', 'suffix'])
@patch.object(AnsiblePlugin, 'get_option', side_effect=[['initial_item'], 'ignore', 'suffix', None])
@patch.object(Templar, 'template', side_effect=[['item1'], ['item3']])
def test_merge_list_with_initial_value(self, mock_set_options, mock_get_option, mock_template):
results = self.merge_vars_lookup.run(['__merge_list'], {
@ -48,7 +48,7 @@ class TestMergeVariablesLookup(unittest.TestCase):
self.assertEqual(results, [['initial_item', 'item1', 'item3']])
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix'])
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix', None])
@patch.object(Templar, 'template', side_effect=[{'item1': 'test', 'list_item': ['test1']},
{'item2': 'test', 'list_item': ['test2']}])
def test_merge_dict(self, mock_set_options, mock_get_option, mock_template):
@ -73,7 +73,7 @@ class TestMergeVariablesLookup(unittest.TestCase):
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[{'initial_item': 'random value', 'list_item': ['test0']},
'ignore', 'suffix'])
'ignore', 'suffix', None])
@patch.object(Templar, 'template', side_effect=[{'item1': 'test', 'list_item': ['test1']},
{'item2': 'test', 'list_item': ['test2']}])
def test_merge_dict_with_initial_value(self, mock_set_options, mock_get_option, mock_template):
@ -98,7 +98,7 @@ class TestMergeVariablesLookup(unittest.TestCase):
])
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'warn', 'suffix'])
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'warn', 'suffix', None])
@patch.object(Templar, 'template', side_effect=[{'item': 'value1'}, {'item': 'value2'}])
@patch.object(Display, 'warning')
def test_merge_dict_non_unique_warning(self, mock_set_options, mock_get_option, mock_template, mock_display):
@ -111,7 +111,7 @@ class TestMergeVariablesLookup(unittest.TestCase):
self.assertEqual(results, [{'item': 'value2'}])
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'error', 'suffix'])
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'error', 'suffix', None])
@patch.object(Templar, 'template', side_effect=[{'item': 'value1'}, {'item': 'value2'}])
def test_merge_dict_non_unique_error(self, mock_set_options, mock_get_option, mock_template):
with self.assertRaises(AnsibleError):
@ -121,7 +121,7 @@ class TestMergeVariablesLookup(unittest.TestCase):
})
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix'])
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix', None])
@patch.object(Templar, 'template', side_effect=[{'item1': 'test', 'list_item': ['test1']},
['item2', 'item3']])
def test_merge_list_and_dict(self, mock_set_options, mock_get_option, mock_template):
@ -133,3 +133,150 @@ class TestMergeVariablesLookup(unittest.TestCase):
},
'testdict__merge_var': ['item2', 'item3']
})
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix', ['all']])
@patch.object(Templar, 'template', side_effect=[
{'var': [{'item1': 'value1', 'item2': 'value2'}]},
{'var': [{'item5': 'value5', 'item6': 'value6'}]},
])
def test_merge_dict_group_all(self, mock_set_options, mock_get_option, mock_template):
results = self.merge_vars_lookup.run(['__merge_var'], {
'inventory_hostname': 'host1',
'hostvars': {
'host1': {
'group_names': ['dummy1'],
'inventory_hostname': 'host1',
'1testlist__merge_var': {
'var': [{'item1': 'value1', 'item2': 'value2'}]
}
},
'host2': {
'group_names': ['dummy1'],
'inventory_hostname': 'host2',
'2otherlist__merge_var': {
'var': [{'item5': 'value5', 'item6': 'value6'}]
}
}
}
})
self.assertEqual(results, [
{'var': [
{'item1': 'value1', 'item2': 'value2'},
{'item5': 'value5', 'item6': 'value6'}
]}
])
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix', ['dummy1']])
@patch.object(Templar, 'template', side_effect=[
{'var': [{'item1': 'value1', 'item2': 'value2'}]},
{'var': [{'item5': 'value5', 'item6': 'value6'}]},
])
def test_merge_dict_group_single(self, mock_set_options, mock_get_option, mock_template):
results = self.merge_vars_lookup.run(['__merge_var'], {
'inventory_hostname': 'host1',
'hostvars': {
'host1': {
'group_names': ['dummy1'],
'inventory_hostname': 'host1',
'1testlist__merge_var': {
'var': [{'item1': 'value1', 'item2': 'value2'}]
}
},
'host2': {
'group_names': ['dummy1'],
'inventory_hostname': 'host2',
'2otherlist__merge_var': {
'var': [{'item5': 'value5', 'item6': 'value6'}]
}
},
'host3': {
'group_names': ['dummy2'],
'inventory_hostname': 'host3',
'3otherlist__merge_var': {
'var': [{'item3': 'value3', 'item4': 'value4'}]
}
}
}
})
self.assertEqual(results, [
{'var': [
{'item1': 'value1', 'item2': 'value2'},
{'item5': 'value5', 'item6': 'value6'}
]}
])
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix', ['dummy1', 'dummy2']])
@patch.object(Templar, 'template', side_effect=[
{'var': [{'item1': 'value1', 'item2': 'value2'}]},
{'var': [{'item5': 'value5', 'item6': 'value6'}]},
])
def test_merge_dict_group_multiple(self, mock_set_options, mock_get_option, mock_template):
results = self.merge_vars_lookup.run(['__merge_var'], {
'inventory_hostname': 'host1',
'hostvars': {
'host1': {
'group_names': ['dummy1'],
'inventory_hostname': 'host1',
'1testlist__merge_var': {
'var': [{'item1': 'value1', 'item2': 'value2'}]
}
},
'host2': {
'group_names': ['dummy2'],
'inventory_hostname': 'host2',
'2otherlist__merge_var': {
'var': [{'item5': 'value5', 'item6': 'value6'}]
}
},
'host3': {
'group_names': ['dummy3'],
'inventory_hostname': 'host3',
'3otherlist__merge_var': {
'var': [{'item3': 'value3', 'item4': 'value4'}]
}
}
}
})
self.assertEqual(results, [
{'var': [
{'item1': 'value1', 'item2': 'value2'},
{'item5': 'value5', 'item6': 'value6'}
]}
])
@patch.object(AnsiblePlugin, 'set_options')
@patch.object(AnsiblePlugin, 'get_option', side_effect=[None, 'ignore', 'suffix', ['dummy1', 'dummy2']])
@patch.object(Templar, 'template', side_effect=[
['item1'],
['item5'],
])
def test_merge_list_group_multiple(self, mock_set_options, mock_get_option, mock_template):
print()
results = self.merge_vars_lookup.run(['__merge_var'], {
'inventory_hostname': 'host1',
'hostvars': {
'host1': {
'group_names': ['dummy1'],
'inventory_hostname': 'host1',
'1testlist__merge_var': ['item1']
},
'host2': {
'group_names': ['dummy2'],
'inventory_hostname': 'host2',
'2otherlist__merge_var': ['item5']
},
'host3': {
'group_names': ['dummy3'],
'inventory_hostname': 'host3',
'3otherlist__merge_var': ['item3']
}
}
})
self.assertEqual(results, [['item1', 'item5']])