From 4d407d17817a229faa349fd3791d68c737085932 Mon Sep 17 00:00:00 2001 From: hexdump0x0200 <43333029+hexdump0x0200@users.noreply.github.com> Date: Thu, 7 Mar 2019 19:10:03 +0700 Subject: [PATCH] ios_logging: fix idempotence errors (#53109) * ios_logging: fix the error checking the existence of "host" destinations (IOS 12) In the "have" list, records of type "host" do not contain the key "size", although in the list "want" it is always there. Because of this, the module assumes that the "host" type destinations is not configured and does it again. This does not change the configuration on the device, but is redundant and the status of the task will always be "changed". This patch fixes it. * ios_logging: fixes #53227 * ios_logging: minor changes in string matching --- .../modules/network/ios/ios_logging.py | 4 +- .../ios/fixtures/ios_logging_config.cfg | 1 + .../ios/fixtures/ios_logging_config_ios12.cfg | 6 ++ .../modules/network/ios/test_ios_logging.py | 74 +++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 test/units/modules/network/ios/fixtures/ios_logging_config_ios12.cfg diff --git a/lib/ansible/modules/network/ios/ios_logging.py b/lib/ansible/modules/network/ios/ios_logging.py index 16211dcc116..8c1d59a4d4d 100644 --- a/lib/ansible/modules/network/ios/ios_logging.py +++ b/lib/ansible/modules/network/ios/ios_logging.py @@ -274,7 +274,7 @@ def map_config_to_obj(module): data = get_config(module, flags=['| include logging']) for line in data.split('\n'): - match = re.search(r'logging (\S+)', line, re.M) + match = re.search(r'^logging (\S+)', line, re.M) if match: if match.group(1) in dest_group: dest = match.group(1) @@ -291,6 +291,7 @@ def map_config_to_obj(module): obj.append({ 'dest': dest, 'name': match.group(1), + 'size': parse_size(line, dest), 'facility': parse_facility(line, dest), 'level': parse_level(line, dest) }) @@ -301,6 +302,7 @@ def map_config_to_obj(module): obj.append({ 'dest': dest, 'name': match.group(1), + 'size': parse_size(line, dest), 'facility': parse_facility(line, dest), 'level': parse_level(line, dest) }) diff --git a/test/units/modules/network/ios/fixtures/ios_logging_config.cfg b/test/units/modules/network/ios/fixtures/ios_logging_config.cfg index 88ea9103523..8a51afa7e5c 100644 --- a/test/units/modules/network/ios/fixtures/ios_logging_config.cfg +++ b/test/units/modules/network/ios/fixtures/ios_logging_config.cfg @@ -2,6 +2,7 @@ logging buffered 5000 logging console informational logging facility local0 +no logging monitor logging host 1.2.3.4 transport tcp logging host 1.2.3.4 logging host 2.3.4.5 diff --git a/test/units/modules/network/ios/fixtures/ios_logging_config_ios12.cfg b/test/units/modules/network/ios/fixtures/ios_logging_config_ios12.cfg new file mode 100644 index 00000000000..58be36dff5b --- /dev/null +++ b/test/units/modules/network/ios/fixtures/ios_logging_config_ios12.cfg @@ -0,0 +1,6 @@ +! +logging buffered 5000 +logging console informational +logging facility local0 +logging 2.3.4.5 +! diff --git a/test/units/modules/network/ios/test_ios_logging.py b/test/units/modules/network/ios/test_ios_logging.py index 2031302b88d..503adc9426e 100644 --- a/test/units/modules/network/ios/test_ios_logging.py +++ b/test/units/modules/network/ios/test_ios_logging.py @@ -66,3 +66,77 @@ class TestIosLoggingModule(TestIosModule): set_module_args(dict(dest='buffered', size=6000)) commands = ['logging buffered 6000'] self.execute_module(changed=True, commands=commands) + + def test_ios_logging_add_host(self): + set_module_args(dict(dest='host', name='192.168.1.1')) + commands = ['logging host 192.168.1.1'] + self.execute_module(changed=True, commands=commands) + + def test_ios_logging_host_idempotent(self): + set_module_args(dict(dest='host', name='2.3.4.5')) + commands = [] + self.execute_module(changed=False, commands=commands) + + def test_ios_logging_delete_non_exist_host(self): + set_module_args(dict(dest='host', name='192.168.1.1', state='absent')) + commands = [] + self.execute_module(changed=False, commands=commands) + + def test_ios_logging_delete_host(self): + set_module_args(dict(dest='host', name='2.3.4.5', state='absent')) + commands = ['no logging host 2.3.4.5'] + self.execute_module(changed=True, commands=commands) + + def test_ios_logging_configure_disabled_monitor_destination(self): + set_module_args(dict(dest='monitor', level='debugging')) + commands = ['logging monitor debugging'] + self.execute_module(changed=True, commands=commands) + + +class TestIosLoggingModuleIOS12(TestIosModule): + + module = ios_logging + + def setUp(self): + super(TestIosLoggingModuleIOS12, self).setUp() + + self.mock_get_config = patch('ansible.modules.network.ios.ios_logging.get_config') + self.get_config = self.mock_get_config.start() + + self.mock_load_config = patch('ansible.modules.network.ios.ios_logging.load_config') + self.load_config = self.mock_load_config.start() + + self.mock_get_capabilities = patch('ansible.modules.network.ios.ios_logging.get_capabilities') + self.get_capabilities = self.mock_get_capabilities.start() + self.get_capabilities.return_value = {'device_info': {'network_os_version': '12.1(2)T'}} + + def tearDown(self): + super(TestIosLoggingModuleIOS12, self).tearDown() + + self.mock_get_config.stop() + self.mock_load_config.stop() + self.mock_get_capabilities.stop() + + def load_fixtures(self, commands=None): + self.get_config.return_value = load_fixture('ios_logging_config_ios12.cfg') + self.load_config.return_value = None + + def test_ios_logging_add_host(self): + set_module_args(dict(dest='host', name='192.168.1.1')) + commands = ['logging 192.168.1.1'] + self.execute_module(changed=True, commands=commands) + + def test_ios_logging_host_idempotent(self): + set_module_args(dict(dest='host', name='2.3.4.5')) + commands = [] + self.execute_module(changed=False, commands=commands) + + def test_ios_logging_delete_non_exist_host(self): + set_module_args(dict(dest='host', name='192.168.1.1', state='absent')) + commands = [] + self.execute_module(changed=False, commands=commands) + + def test_ios_logging_delete_host(self): + set_module_args(dict(dest='host', name='2.3.4.5', state='absent')) + commands = ['no logging 2.3.4.5'] + self.execute_module(changed=True, commands=commands)