Date: Mon, 13 May 2024 15:26:30 +0530
Subject: [PATCH 08/12] fix ios_service issues (#1068)
* fix ios_service issues
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* clean debug
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* fix tests
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Update
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Confirm changes
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
---
changelogs/fragments/ios_service_fix.yml | 4 +
docs/cisco.ios.ios_service_module.rst | 61 +++++-
.../network/ios/argspec/service/service.py | 6 +-
.../network/ios/config/service/service.py | 6 +-
.../network/ios/facts/service/service.py | 8 +-
.../network/ios/rm_templates/service.py | 178 ++++++++++++------
plugins/modules/ios_service.py | 25 ++-
.../modules/network/ios/test_ios_service.py | 45 ++---
8 files changed, 234 insertions(+), 99 deletions(-)
create mode 100644 changelogs/fragments/ios_service_fix.yml
diff --git a/changelogs/fragments/ios_service_fix.yml b/changelogs/fragments/ios_service_fix.yml
new file mode 100644
index 000000000..3ec24d6a9
--- /dev/null
+++ b/changelogs/fragments/ios_service_fix.yml
@@ -0,0 +1,4 @@
+---
+bugfixes:
+ - ios_service - Fix timestamps attribute, to generate right configuration.
+ - ios_service - Add tcp_small_servers and udp_small_servers attributes, to generate configuration.
diff --git a/docs/cisco.ios.ios_service_module.rst b/docs/cisco.ios.ios_service_module.rst
index ed859129d..a2d5eef38 100644
--- a/docs/cisco.ios.ios_service_module.rst
+++ b/docs/cisco.ios.ios_service_module.rst
@@ -45,7 +45,7 @@ Parameters
|
- A dictionnary of service configuration
+ A dictionary of service configuration
|
@@ -658,7 +658,7 @@ Parameters
|
- TCP and UDP small servers are servers (daemons, in Unix parlance) that run in the router which are useful for diagnostics.
+ TCP small servers are servers (daemons, in Unix parlance) that run in the router which are useful for diagnostics.
|
@@ -690,14 +690,35 @@ Parameters
max_servers
- string
+ integer
|
Set number of allowable TCP small servers
- 1 to 2147483647 or no-limit
+ 1 to 2147483647
+ |
+
+
+ |
+ |
+
+
+ no_limit
+
+
+ boolean
+
+ |
+
+
+ |
+
+ No limit on number of allowable TCP small servers
|
@@ -921,7 +942,7 @@ Parameters
|
- TCP and UDP small servers are servers (daemons, in Unix parlance) that run in the router which are useful for diagnostics.
+ UDP small servers are servers (daemons, in Unix parlance) that run in the router which are useful for diagnostics.
|
@@ -953,14 +974,35 @@ Parameters
max_servers
- string
+ integer
|
- Set number of allowable TCP small servers
- 1 to 2147483647 or no-limit
+ Set number of allowable UDP small servers
+ 1 to 2147483647
+ |
+
+
+ |
+ |
+
+
+ no_limit
+
+
+ boolean
+
+ |
+
+
+ |
+
+ No limit on number of allowable UDP small servers
|
@@ -1036,7 +1078,7 @@ Notes
-----
.. note::
- - Tested against Cisco IOSXE Version 16.9
+ - Tested against Cisco IOSXE Version 17.9.1a on CML.
- This module works with connection ``network_cli``. See https://docs.ansible.com/ansible/latest/network/user_guide/platform_ios.html
@@ -1556,3 +1598,4 @@ Authors
~~~~~~~
- Ambroise Rosset (@earendilfr)
+- Sagar Paul (@KB-perByte)
diff --git a/plugins/module_utils/network/ios/argspec/service/service.py b/plugins/module_utils/network/ios/argspec/service/service.py
index 238fc64a2..647eeb3d2 100644
--- a/plugins/module_utils/network/ios/argspec/service/service.py
+++ b/plugins/module_utils/network/ios/argspec/service/service.py
@@ -68,7 +68,8 @@ class ServiceArgs(object): # pylint: disable=R0903
"tcp_small_servers": {
"options": {
"enable": {"type": "bool"},
- "max_servers": {"type": "str"},
+ "max_servers": {"type": "int"},
+ "no_limit": {"type": "bool"},
},
"type": "dict",
},
@@ -97,7 +98,8 @@ class ServiceArgs(object): # pylint: disable=R0903
"udp_small_servers": {
"options": {
"enable": {"type": "bool"},
- "max_servers": {"type": "str"},
+ "max_servers": {"type": "int"},
+ "no_limit": {"type": "bool"},
},
"type": "dict",
},
diff --git a/plugins/module_utils/network/ios/config/service/service.py b/plugins/module_utils/network/ios/config/service/service.py
index 6a4c8a1ff..603e1060b 100644
--- a/plugins/module_utils/network/ios/config/service/service.py
+++ b/plugins/module_utils/network/ios/config/service/service.py
@@ -75,7 +75,9 @@ def __init__(self, module):
"slave_log",
"tcp_keepalives_in",
"tcp_keepalives_out",
+ "tcp_small_servers",
"telnet_zeroidle",
+ "udp_small_servers",
"unsupported_transceiver",
]
@@ -138,9 +140,9 @@ def _compare_lists_attrs(self, want, have):
for key, wanting in iteritems(i_want):
haveing = i_have.pop(key, {})
if wanting != haveing:
- self.addcmd(wanting, "timestamps")
+ self.addcmd(wanting, key + "_timestamps", False)
for key, haveing in iteritems(i_have):
- self.addcmd(haveing, "timestamps", negate=True)
+ self.addcmd(haveing, key + "_timestamps", negate=True)
def _service_list_to_dict(self, data):
"""Convert all list of dicts to dicts of dicts"""
diff --git a/plugins/module_utils/network/ios/facts/service/service.py b/plugins/module_utils/network/ios/facts/service/service.py
index df2dcf993..6ada10748 100644
--- a/plugins/module_utils/network/ios/facts/service/service.py
+++ b/plugins/module_utils/network/ios/facts/service/service.py
@@ -33,7 +33,7 @@ def __init__(self, module, subspec="config", options="options"):
self.argument_spec = ServiceArgs.argument_spec
def get_service_data(self, connection):
- return connection.get("show running-config all | section ^service ")
+ return connection.get("show running-config all | section ^service")
def populate_facts(self, connection, ansible_facts, data=None):
"""Populate the facts for Service network resource
@@ -59,7 +59,11 @@ def populate_facts(self, connection, ansible_facts, data=None):
ansible_facts["ansible_network_resources"].pop("service", None)
params = utils.remove_empties(
- service_parser.validate_config(self.argument_spec, {"config": objs}, redact=True),
+ service_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
)
facts["service"] = params.get("config", {})
diff --git a/plugins/module_utils/network/ios/rm_templates/service.py b/plugins/module_utils/network/ios/rm_templates/service.py
index 992892db8..c81593226 100644
--- a/plugins/module_utils/network/ios/rm_templates/service.py
+++ b/plugins/module_utils/network/ios/rm_templates/service.py
@@ -22,6 +22,21 @@
)
+def handleTimestamp(config_data):
+ command = "service timestamps"
+ command += " " + config_data.get("msg") if config_data.get("msg") else ""
+ command += " " + config_data.get("timestamp") if config_data.get("timestamp") else ""
+
+ if config_data.get("datetime_options"):
+ datetime_op = config_data.get("datetime_options")
+ command += " mesc" if datetime_op.get("msec") else ""
+ command += " localtime" if datetime_op.get("localtime") else ""
+ command += " show-timezone" if datetime_op.get("show_timezone") else ""
+ command += " year" if datetime_op.get("year") else ""
+
+ return command
+
+
class ServiceTemplate(NetworkTemplate):
def __init__(self, lines=None, module=None):
super(ServiceTemplate, self).__init__(lines=lines, tmplt=self, module=module)
@@ -32,36 +47,36 @@ def __init__(self, lines=None, module=None):
"name": "call_home",
"getval": re.compile(
r"""
- ^service\s(?Pcall-home)
+ ^service\scall-home
""", re.VERBOSE,
),
"setval": "service call-home",
"result": {
- "call_home": "{{ not not call_home }}",
+ "call_home": True,
},
},
{
"name": "compress_config",
"getval": re.compile(
r"""
- ^service\s(?Pcompress-config)
+ ^service\scompress-config
""", re.VERBOSE,
),
"setval": "service compress-config",
"result": {
- "compress_config": "{{ not not compress_config }}",
+ "compress_config": True,
},
},
{
"name": "config",
"getval": re.compile(
r"""
- ^service\s(?Pconfig)
+ ^service\sconfig
""", re.VERBOSE,
),
"setval": "service config",
"result": {
- "config": "{{ not not config }}",
+ "config": True,
},
},
{
@@ -92,120 +107,120 @@ def __init__(self, lines=None, module=None):
"name": "disable_ip_fast_frag",
"getval": re.compile(
r"""
- ^service\s(?Pdisable-ip-fast-frag)
+ ^service\sdisable-ip-fast-frag
""", re.VERBOSE,
),
"setval": "service disable-ip-fast-frag",
"result": {
- "disable_ip_fast_frag": "{{ not not disable_ip_fast_frag }}",
+ "disable_ip_fast_frag": True,
},
},
{
"name": "exec_callback",
"getval": re.compile(
r"""
- ^service\s(?Pexec-callback)
+ ^service\sexec-callback
""", re.VERBOSE,
),
"setval": "service exec-callback",
"result": {
- "exec_callback": "{{ not not exec_callback }}",
+ "exec_callback": True,
},
},
{
"name": "exec_wait",
"getval": re.compile(
r"""
- ^service\s(?Pexec-wait)
+ ^service\sexec-wait
""", re.VERBOSE,
),
"setval": "service exec-wait",
"return": {
- "exec_wait": "{{ not not exec_wait }}",
+ "exec_wait": True,
},
},
{
"name": "hide_telnet_addresses",
"getval": re.compile(
r"""
- ^service\s(?Phide-telnet-addresses)
+ ^service\shide-telnet-addresses
""", re.VERBOSE,
),
"setval": "service hide-telnet-addresses",
"result": {
- "hide_telnet_addresses": "{{ not not hide_telnet_addresses }}",
+ "hide_telnet_addresses": True,
},
},
{
"name": "internal",
"getval": re.compile(
r"""
- ^service\s(?Pinternal)
+ ^service\sinternal
""", re.VERBOSE,
),
"setval": "service internal",
"result": {
- "internal": "{{ not not internal }}",
+ "internal": True,
},
},
{
"name": "linenumber",
"getval": re.compile(
r"""
- ^service\s(?Plinenumber)
+ ^service\slinenumber
""", re.VERBOSE,
),
"setval": "service linenumber",
"result": {
- "linenumber": "{{ not not linenumber }}",
+ "linenumber": True,
},
},
{
"name": "log",
"getval": re.compile(
r"""
- ^service\slog(\s(?Pbacktrace))?
+ ^service\slog\sbacktrace?
""", re.VERBOSE,
),
"setval": "service log backtrace",
"result": {
- "log": "{{ not not backtrace }}",
+ "log": True,
},
},
{
"name": "log_hidden",
"getval": re.compile(
r"""
- ^service\s(?Plog-hidden)
+ ^service\slog-hidden
""", re.VERBOSE,
),
"setval": "service log-hidden",
"result": {
- "log_hidden": "{{ not not log_hidden }}",
+ "log_hidden": True,
},
},
{
"name": "nagle",
"getval": re.compile(
r"""
- ^service\s(?Pnagle)
+ ^service\snagle
""", re.VERBOSE,
),
"setval": "service nagle",
"result": {
- "nagle": "{{ not not nagle }}",
+ "nagle": True,
},
},
{
"name": "old_slip_prompts",
"getval": re.compile(
r"""
- ^service\s(?Pold-slip-prompts)
+ ^service\sold-slip-prompts
""", re.VERBOSE,
),
"setval": "service old-slip-prompts",
"result": {
- "old_slip_prompts": "{{ not not old_slip_prompts }}",
+ "old_slip_prompts": True,
},
},
{
@@ -260,12 +275,12 @@ def __init__(self, lines=None, module=None):
"name": "password_encryption",
"getval": re.compile(
r"""
- ^service\s(?Ppassword-encryption)
+ ^service\spassword-encryption
""", re.VERBOSE,
),
"setval": "service password-encryption",
"result": {
- "password_encryption": "{{ not not password_encryption }}",
+ "password_encryption": True,
},
},
{
@@ -309,48 +324,48 @@ def __init__(self, lines=None, module=None):
"name": "pt_vty_logging",
"getval": re.compile(
r"""
- ^service\s(?Ppt-vty-logging)
+ ^service\spt-vty-logging
""", re.VERBOSE,
),
"setval": "service pt-vty-logging",
"result": {
- "pt_vty_logging": "{{ not not pt_vty_logging }}",
+ "pt_vty_logging": True,
},
},
{
"name": "scripting",
"getval": re.compile(
r"""
- ^service\s(?Pscripting)
+ ^service\sscripting
""", re.VERBOSE,
),
"setval": "service scripting",
"result": {
- "scripting": "{{ not not scripting }}",
+ "scripting": True,
},
},
{
"name": "sequence_numbers",
"getval": re.compile(
r"""
- ^service\s(?Psequence-numbers)
+ ^service\ssequence-numbers
""", re.VERBOSE,
),
"setval": "service sequence-numbers",
"result": {
- "sequence_numbers": "{{ not not sequence_numbers }}",
+ "sequence_numbers": True,
},
},
{
"name": "slave_coredump",
"getval": re.compile(
r"""
- ^service\s(?Pslave-coredump)
+ ^service\sslave-coredump
""", re.VERBOSE,
),
"setval": "service slave-coredump",
"result": {
- "slave_coredump": "{{ not not slave_coredump }}",
+ "slave_coredump": True,
},
},
{
@@ -389,6 +404,46 @@ def __init__(self, lines=None, module=None):
"tcp_keepalives_out": True,
},
},
+ {
+ "name": "tcp_small_servers",
+ "getval": re.compile(
+ r"""
+ ^service\stcp-small-servers
+ (\s(?P\d+))?
+ (\s(?Pno-limit))?
+ """, re.VERBOSE,
+ ),
+ "setval": "service tcp-small-servers"
+ "{{ (' ' + tcp_small_servers.max_servers|string) if tcp_small_servers.max_servers is defined else '' }}"
+ "{{ (' no-limit') if tcp_small_servers.no_limit|d(False) else '' }}",
+ "result": {
+ "tcp_small_servers": {
+ "enable": True,
+ "max_servers": "{{ max_servers }}",
+ "no_limit": "{{ not not no_limit }}",
+ },
+ },
+ },
+ {
+ "name": "udp_small_servers",
+ "getval": re.compile(
+ r"""
+ ^service\sudp-small-servers
+ (\s(?P\d+))?
+ (\s(?Pno-limit))?
+ """, re.VERBOSE,
+ ),
+ "setval": "{{ ('service udp-small-servers') if udp_small_servers.enable|d(False) else '' }}"
+ "{{ (' ' + udp_small_servers.max_servers|string) if udp_small_servers.max_servers is defined else '' }}"
+ "{{ (' no-limit') if udp_small_servers.no_limit|d(False) else '' }}",
+ "result": {
+ "udp_small_servers": {
+ "enable": True,
+ "max_servers": "{{ max_servers }}",
+ "no_limit": "{{ not not no_limit }}",
+ },
+ },
+ },
{
"name": "telnet_zeroidle",
"getval": re.compile(
@@ -402,11 +457,39 @@ def __init__(self, lines=None, module=None):
},
},
{
- "name": "timestamps",
+ "name": "log_timestamps",
+ "getval": re.compile(
+ r"""
+ ^service\stimestamps\slog
+ (\s(?P\S+))?
+ (\s(?Pmsec))?
+ (\s(?Plocaltime))?
+ (\s(?Pshow-timezone))?
+ (\s(?Pyear))?
+ """, re.VERBOSE,
+ ),
+ "remval": "service timestamps log",
+ "setval": handleTimestamp,
+ "result": {
+ "timestamps": [
+ {
+ "msg": "log",
+ "timestamp": "{{ timestamp if timestamp is defined else 'uptime' }}",
+ "datetime_options": {
+ "msec": "{{ True if msec else False}}",
+ "localtime": "{{ True if localtime else False }}",
+ "show_timezone": "{{ True if show_timezone else False }}",
+ "year": "{{ True if year else False }}",
+ },
+ },
+ ],
+ },
+ },
+ {
+ "name": "debug_timestamps",
"getval": re.compile(
r"""
- ^service\stimestamps
- (\s(?P\S+))?
+ ^service\stimestamps\sdebug
(\s(?P\S+))?
(\s(?Pmsec))?
(\s(?Plocaltime))?
@@ -414,23 +497,12 @@ def __init__(self, lines=None, module=None):
(\s(?Pyear))?
""", re.VERBOSE,
),
- "remval": "service timestamps{{ (' ' + msg) if msg is defined else '' }}",
- "setval": "service timestamps"
- "{{ (' ' + msg) if msg is defined else '' }}"
- "{% if msg is defined %}"
- "{{ (' ' + timestamp) if timestamp is defined else '' }}"
- "{% if timestamp == 'datetime' and datetime_options is defined %}"
- "{{ ' msec' if datetime_options.msec else '' }}"
- "{{ ' localtime' if datetime_options.localtime else '' }}"
- "{{ ' show-timezone' if datetime_options.show_timezone else '' }}"
- "{{ ' year' if datetime_options.year else '' }}"
- "{% endif %}"
- "{% endif %}"
- "",
+ "remval": "service timestamps debug",
+ "setval": handleTimestamp,
"result": {
"timestamps": [
{
- "msg": "{{ msg if msg is defined else 'debug' }}",
+ "msg": "debug",
"timestamp": "{{ timestamp if timestamp is defined else 'uptime' }}",
"datetime_options": {
"msec": "{{ True if msec else False}}",
diff --git a/plugins/modules/ios_service.py b/plugins/modules/ios_service.py
index 46c456569..ebe0e7881 100644
--- a/plugins/modules/ios_service.py
+++ b/plugins/modules/ios_service.py
@@ -22,13 +22,14 @@
version_added: 4.6.0
author:
- Ambroise Rosset (@earendilfr)
+ - Sagar Paul (@KB-perByte)
notes:
- - Tested against Cisco IOSXE Version 16.9
+ - Tested against Cisco IOSXE Version 17.9.1a on CML.
- This module works with connection C(network_cli).
See U(https://docs.ansible.com/ansible/latest/network/user_guide/platform_ios.html)
options:
config:
- description: A dictionnary of service configuration
+ description: A dictionary of service configuration
suboptions:
call_home:
description: Cisco call-home service
@@ -128,7 +129,7 @@
type: bool
tcp_small_servers:
description:
- - TCP and UDP small servers are servers (daemons, in Unix parlance) that run in the
+ - TCP small servers are servers (daemons, in Unix parlance) that run in the
router which are useful for diagnostics.
suboptions:
enable:
@@ -137,8 +138,11 @@
max_servers:
description:
- Set number of allowable TCP small servers
- - 1 to 2147483647 or no-limit
- type: str
+ - 1 to 2147483647
+ type: int
+ no_limit:
+ description: No limit on number of allowable TCP small servers
+ type: bool
type: dict
telnet_zeroidle:
description: Set TCP window 0 when connection is idle
@@ -181,7 +185,7 @@
type: list
udp_small_servers:
description:
- - TCP and UDP small servers are servers (daemons, in Unix parlance) that run in the
+ - UDP small servers are servers (daemons, in Unix parlance) that run in the
router which are useful for diagnostics.
suboptions:
enable:
@@ -189,9 +193,12 @@
type: bool
max_servers:
description:
- - Set number of allowable TCP small servers
- - 1 to 2147483647 or no-limit
- type: str
+ - Set number of allowable UDP small servers
+ - 1 to 2147483647
+ type: int
+ no_limit:
+ description: No limit on number of allowable UDP small servers
+ type: bool
type: dict
unsupported_transceiver:
description: enable support for third-party transceivers
diff --git a/tests/unit/modules/network/ios/test_ios_service.py b/tests/unit/modules/network/ios/test_ios_service.py
index fa92efcdc..69af87eda 100644
--- a/tests/unit/modules/network/ios/test_ios_service.py
+++ b/tests/unit/modules/network/ios/test_ios_service.py
@@ -128,14 +128,13 @@ def test_ios_service_merged(self):
},
}
merged = [
- "service timestamps debug uptime",
- "service timestamps log datetime msec localtime show-timezone year",
"service password-encryption",
+ "service timestamps debug uptime mesc",
+ "service timestamps log datetime mesc localtime show-timezone year",
]
playbook["state"] = "merged"
set_module_args(playbook)
result = self.execute_module(changed=True)
-
self.assertEqual(sorted(result["commands"]), sorted(merged))
def test_ios_snm_server_deleted(self):
@@ -213,18 +212,17 @@ def test_ios_service_overridden(self):
overridden = [
"no service call-home",
"no service config",
- "no service pad",
"service counters max age 5",
+ "no service pad",
"service password-encryption",
"service tcp-keepalives-in",
"service tcp-keepalives-out",
+ "service timestamps log datetime mesc localtime show-timezone year",
"service timestamps debug datetime",
- "service timestamps log datetime msec localtime show-timezone year",
]
playbook["state"] = "overridden"
set_module_args(playbook)
result = self.execute_module(changed=True)
-
self.assertEqual(sorted(result["commands"]), sorted(overridden))
def test_ios_service_replaced(self):
@@ -258,6 +256,10 @@ def test_ios_service_replaced(self):
{
"msg": "debug",
"timestamp": "datetime",
+ "datetime_options": {
+ "localtime": True,
+ "msec": True,
+ },
},
],
"tcp_keepalives_in": True,
@@ -269,18 +271,17 @@ def test_ios_service_replaced(self):
replaced = [
"no service call-home",
"no service config",
- "no service pad",
"service counters max age 5",
+ "no service pad",
"service password-encryption",
"service tcp-keepalives-in",
"service tcp-keepalives-out",
- "service timestamps debug datetime",
- "service timestamps log datetime msec localtime show-timezone year",
+ "service timestamps log datetime mesc localtime show-timezone year",
+ "service timestamps debug datetime mesc localtime",
]
playbook["state"] = "replaced"
set_module_args(playbook)
result = self.execute_module(changed=True)
-
self.assertEqual(sorted(result["commands"]), sorted(replaced))
def test_ios_service_replaced_idempotent(self):
@@ -368,8 +369,6 @@ def test_ios_service_replaced_idempotent_old(self):
self.assertEqual(sorted(result["commands"]), sorted(replaced))
- ####################
-
def test_ios_service_parsed(self):
set_module_args(
dict(
@@ -426,36 +425,36 @@ def test_ios_service_gathered(self):
service timestamps log datetime msec localtime show-timezone year
service timestamps debug uptime
service call-home
+ service udp-small-servers
+ service tcp-small-servers no-limit
""",
)
set_module_args(dict(state="gathered"))
gathered = {
"timestamps": [
- {
- "msg": "debug",
- "timestamp": "uptime",
- },
{
"msg": "log",
"timestamp": "datetime",
"datetime_options": {
- "localtime": True,
"msec": True,
+ "localtime": True,
"show_timezone": True,
"year": True,
},
},
+ {"msg": "debug", "timestamp": "uptime"},
],
"call_home": True,
- "dhcp": True,
+ "udp_small_servers": {"enable": True},
+ "tcp_small_servers": {"enable": True, "no_limit": True},
"counters": 0,
+ "dhcp": True,
"password_recovery": True,
"prompt": True,
"slave_log": True,
}
result = self.execute_module(changed=False)
self.maxDiff = None
-
self.assertEqual(sorted(result["gathered"]), sorted(gathered))
def test_ios_service_rendered(self):
@@ -472,6 +471,9 @@ def test_ios_service_rendered(self):
{
"msg": "debug",
"timestamp": "uptime",
+ "datetime_options": {
+ "localtime": True,
+ },
},
{
"msg": "log",
@@ -497,10 +499,9 @@ def test_ios_service_rendered(self):
"service slave-log",
"service tcp-keepalives-in",
"service tcp-keepalives-out",
- "service timestamps debug uptime",
- "service timestamps log datetime msec localtime show-timezone year",
+ "service timestamps debug uptime localtime",
+ "service timestamps log datetime mesc localtime show-timezone year",
]
result = self.execute_module(changed=False)
self.maxDiff = None
-
self.assertEqual(sorted(result["rendered"]), sorted(rendered))
From 46108d05362c6696df52dddfb1edbe77647af9b8 Mon Sep 17 00:00:00 2001
From: Vinay M <63404819+roverflow@users.noreply.github.com>
Date: Tue, 14 May 2024 15:08:31 +0530
Subject: [PATCH 09/12] Fix snmp host syntax (#1073)
---
changelogs/fragments/snmp_server_host.yml | 3 +++
plugins/module_utils/network/ios/rm_templates/snmp_server.py | 4 ++--
tests/unit/modules/network/ios/test_ios_snmp_server.py | 2 +-
3 files changed, 6 insertions(+), 3 deletions(-)
create mode 100644 changelogs/fragments/snmp_server_host.yml
diff --git a/changelogs/fragments/snmp_server_host.yml b/changelogs/fragments/snmp_server_host.yml
new file mode 100644
index 000000000..b8bbe1ee0
--- /dev/null
+++ b/changelogs/fragments/snmp_server_host.yml
@@ -0,0 +1,3 @@
+---
+bugfixes:
+ - snmp_server - Fix wrong syntax of snmp-server host command generation.
diff --git a/plugins/module_utils/network/ios/rm_templates/snmp_server.py b/plugins/module_utils/network/ios/rm_templates/snmp_server.py
index 45cabaae9..6f0c04c69 100644
--- a/plugins/module_utils/network/ios/rm_templates/snmp_server.py
+++ b/plugins/module_utils/network/ios/rm_templates/snmp_server.py
@@ -63,12 +63,12 @@ def cmd_option_hosts(config_data): # contain sub list attr
cmd += " {host}".format(host=config_data.get("host"))
if config_data.get("informs"):
cmd += " informs"
+ if config_data.get("vrf"):
+ cmd += " vrf {vrf}".format(vrf=config_data.get("vrf"))
if config_data.get("version"):
cmd += " version {version}".format(version=config_data.get("version"))
if config_data.get("version_option"):
cmd += " {version}".format(version=config_data.get("version_option"))
- if config_data.get("vrf"):
- cmd += " vrf {vrf}".format(vrf=config_data.get("vrf"))
if config_data.get("community_string"):
cmd += " {community_string}".format(
community_string=config_data.get("community_string"),
diff --git a/tests/unit/modules/network/ios/test_ios_snmp_server.py b/tests/unit/modules/network/ios/test_ios_snmp_server.py
index 0b8f797a1..9674c894d 100644
--- a/tests/unit/modules/network/ios/test_ios_snmp_server.py
+++ b/tests/unit/modules/network/ios/test_ios_snmp_server.py
@@ -1928,7 +1928,7 @@ def test_ios_snmp_server_rendered(self):
"snmp-server enable traps ospf state-change",
"snmp-server enable traps ethernet cfm cc mep-up mep-down cross-connect loop config",
"snmp-server enable traps ethernet cfm crosscheck mep-missing mep-unknown service-up",
- "snmp-server host 172.16.1.1 version 3 auth vrf mgmt group0 tty",
+ "snmp-server host 172.16.1.1 vrf mgmt version 3 auth group0 tty",
"snmp-server host 172.16.2.1 version 3 priv newtera rsrb",
"snmp-server host 172.16.2.1 version 3 noauth replaceUser slb",
"snmp-server host 172.16.2.1 version 2c trapsac tty",
From 746df9662a67605ba181ef9f8ddecef1300c1e9c Mon Sep 17 00:00:00 2001
From: Vinay M <63404819+roverflow@users.noreply.github.com>
Date: Mon, 20 May 2024 18:29:04 +0530
Subject: [PATCH 10/12] Fix snmp-server host commad parsing (#1077)
* Fix snmp-server host commad parsing
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* remove extra spaces
* removed extra spaces
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
---
changelogs/fragments/snmp_parse_fix.yml | 3 +++
.../network/ios/rm_templates/snmp_server.py | 2 +-
.../modules/network/ios/test_ios_snmp_server.py | 15 ++++++++++++---
3 files changed, 16 insertions(+), 4 deletions(-)
create mode 100644 changelogs/fragments/snmp_parse_fix.yml
diff --git a/changelogs/fragments/snmp_parse_fix.yml b/changelogs/fragments/snmp_parse_fix.yml
new file mode 100644
index 000000000..fb2672474
--- /dev/null
+++ b/changelogs/fragments/snmp_parse_fix.yml
@@ -0,0 +1,3 @@
+---
+bugfixes:
+ - snmp_server - Fix configuration command for snmp-server host.
diff --git a/plugins/module_utils/network/ios/rm_templates/snmp_server.py b/plugins/module_utils/network/ios/rm_templates/snmp_server.py
index 6f0c04c69..777d4fbd9 100644
--- a/plugins/module_utils/network/ios/rm_templates/snmp_server.py
+++ b/plugins/module_utils/network/ios/rm_templates/snmp_server.py
@@ -322,9 +322,9 @@ def __init__(self, lines=None, module=None):
^snmp-server\shost
(\s(?P\S+))?
(\s(?Pinforms))?
+ (\svrf\s(?P\S+))?
(\sversion\s(?P1|3|2c))?
(\s(?Pauth|noauth|priv))?
- (\svrf\s(?P\S+))?
(\s(?P\S+))?
(\s+(?P.+$))?
""", re.VERBOSE,
diff --git a/tests/unit/modules/network/ios/test_ios_snmp_server.py b/tests/unit/modules/network/ios/test_ios_snmp_server.py
index 9674c894d..1c60a6628 100644
--- a/tests/unit/modules/network/ios/test_ios_snmp_server.py
+++ b/tests/unit/modules/network/ios/test_ios_snmp_server.py
@@ -1681,9 +1681,10 @@ def test_ios_snmp_server_parsed(self):
def test_ios_snmp_server_gathered(self):
self.execute_show_command.return_value = dedent(
"""\
- snmp-server host 172.16.2.99 checktrap isis hsrp
- snmp-server host 172.16.2.1 version 3 priv newtera rsrb pim rsvp slb pki
- snmp-server host 172.16.2.1 version 3 noauth replace-User! slb pki
+ snmp-server host 172.16.2.99 checktrap isis hsrp
+ snmp-server host 172.16.2.1 version 3 priv newtera rsrb pim rsvp slb pki
+ snmp-server host 172.16.2.1 version 3 noauth replace-User! slb pki
+ snmp-server host 172.16.2.1 vrf vrf1 version 3 priv newtera1 rsrb pim
""",
)
self.execute_show_command_user.return_value = dedent(
@@ -1753,6 +1754,14 @@ def test_ios_snmp_server_gathered(self):
"community_string": "checktrap",
"traps": ["isis", "hsrp"],
},
+ {
+ "host": "172.16.2.99",
+ "vrf": "vrf1",
+ "version": "3",
+ "version_option": "priv",
+ "community_string": "newtera1",
+ "traps": ["rsrb", "pim"],
+ },
],
"users": [
{
From 410718f4f56f3b4e832dab758cb5859c270c0b08 Mon Sep 17 00:00:00 2001
From: Vito <4026137+eleksis@users.noreply.github.com>
Date: Wed, 22 May 2024 11:55:28 +0200
Subject: [PATCH 11/12] FIX: Include netmask into static_routes parser as part
of result key (#1076)
* Include netmask into static_routes parser
Netmask is part of route destination and should be
included as 'primary' key for distinguishing routes.
For ipv6 it is already part of dest parameter.
* Add changelog & extend unit test for parsing facts
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---------
Co-authored-by: Vito
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Vinay M <63404819+roverflow@users.noreply.github.com>
---
.../fragments/static_routes_facts_fix.yml | 3 +
.../network/ios/rm_templates/static_routes.py | 2 +-
.../network/ios/test_ios_static_routes.py | 55 ++++++++++++++++++-
3 files changed, 57 insertions(+), 3 deletions(-)
create mode 100644 changelogs/fragments/static_routes_facts_fix.yml
diff --git a/changelogs/fragments/static_routes_facts_fix.yml b/changelogs/fragments/static_routes_facts_fix.yml
new file mode 100644
index 000000000..82bc47710
--- /dev/null
+++ b/changelogs/fragments/static_routes_facts_fix.yml
@@ -0,0 +1,3 @@
+---
+bugfixes:
+ - ios_static_routes - Fix gathering facts by properly distinguising routes.
diff --git a/plugins/module_utils/network/ios/rm_templates/static_routes.py b/plugins/module_utils/network/ios/rm_templates/static_routes.py
index a43d59cf7..bee1aed63 100644
--- a/plugins/module_utils/network/ios/rm_templates/static_routes.py
+++ b/plugins/module_utils/network/ios/rm_templates/static_routes.py
@@ -64,7 +64,7 @@ def __init__(self, lines=None, module=None):
"{{ (' dhcp' ) if ipv4.dhcp|d(False) else '' }}"
"{{ (' global' ) if ipv4.global|d(False) else '' }}",
"result": {
- "{{ dest }}_{{ vrf|d() }}_{{ topology|d() }}_ipv4": [
+ "{{ dest }}_{{ netmask }}_{{ vrf|d() }}_{{ topology|d() }}_ipv4": [
{
"_vrf": "{{ vrf }}",
"_topology": "{{ topology }}",
diff --git a/tests/unit/modules/network/ios/test_ios_static_routes.py b/tests/unit/modules/network/ios/test_ios_static_routes.py
index 57a416433..4bb89cc79 100644
--- a/tests/unit/modules/network/ios/test_ios_static_routes.py
+++ b/tests/unit/modules/network/ios/test_ios_static_routes.py
@@ -2138,6 +2138,11 @@ def test_ios_static_route_gathered(self):
self.execute_show_command.return_value = dedent(
"""\
ip route 10.0.0.0 255.0.0.0 Null0 permanent
+ ip route 192.168.1.0 255.255.255.0 GigabitEthernet0/1.22 10.0.0.1 tag 30
+ ip route 192.168.1.0 255.255.255.0 10.0.0.2
+ ip route 192.168.1.0 255.255.255.248 GigabitEthernet0/1.23 10.0.0.3 tag 30
+ ipv6 route 2001:DB8:0:3::/128 2001:DB8:0:3::33
+ ipv6 route 2001:DB8:0:3::/64 2001:DB8:0:3::3
""",
)
set_module_args(dict(state="gathered"))
@@ -2150,7 +2155,54 @@ def test_ios_static_route_gathered(self):
{
"dest": "10.0.0.0/8",
"next_hops": [
- {"interface": "Null0", "permanent": True},
+ {
+ "interface": "Null0",
+ "permanent": True,
+ },
+ ],
+ },
+ {
+ "dest": "192.168.1.0/24",
+ "next_hops": [
+ {
+ "forward_router_address": "10.0.0.1",
+ "interface": "GigabitEthernet0/1.22",
+ "tag": 30,
+ },
+ {
+ "forward_router_address": "10.0.0.2",
+ },
+ ],
+ },
+ {
+ "dest": "192.168.1.0/29",
+ "next_hops": [
+ {
+ "forward_router_address": "10.0.0.3",
+ "interface": "GigabitEthernet0/1.23",
+ "tag": 30,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "afi": "ipv6",
+ "routes": [
+ {
+ "dest": "2001:DB8:0:3::/128",
+ "next_hops": [
+ {
+ "forward_router_address": "2001:DB8:0:3::33",
+ },
+ ],
+ },
+ {
+ "dest": "2001:DB8:0:3::/64",
+ "next_hops": [
+ {
+ "forward_router_address": "2001:DB8:0:3::3",
+ },
],
},
],
@@ -2162,4 +2214,3 @@ def test_ios_static_route_gathered(self):
self.maxDiff = None
print(result["gathered"])
self.assertEqual(sorted(result["gathered"]), sorted(gathered))
- # self.assertEqual(result["gathered"], gathered)
From 37d99e153e3190612aa380fdc8582e9f6f091931 Mon Sep 17 00:00:00 2001
From: Vinay M <63404819+roverflow@users.noreply.github.com>
Date: Thu, 23 May 2024 22:57:21 +0530
Subject: [PATCH 12/12] Acls - fix incorrectly mapping of port 135/udp to msrpc
(#1078)
* acls - add option to ace udp port to 135
* added changelog
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* fix changelog
* remove print commands
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
---
changelogs/fragments/ios_acls_udp.yml | 3 ++
.../network/ios/config/acls/acls.py | 6 ++--
.../unit/modules/network/ios/test_ios_acls.py | 33 +++++++++++++++++++
3 files changed, 40 insertions(+), 2 deletions(-)
create mode 100644 changelogs/fragments/ios_acls_udp.yml
diff --git a/changelogs/fragments/ios_acls_udp.yml b/changelogs/fragments/ios_acls_udp.yml
new file mode 100644
index 000000000..71df169e5
--- /dev/null
+++ b/changelogs/fragments/ios_acls_udp.yml
@@ -0,0 +1,3 @@
+---
+bugfixes:
+ - ios_acls - fix incorrect mapping of port 135/udp to msrpc.
diff --git a/plugins/module_utils/network/ios/config/acls/acls.py b/plugins/module_utils/network/ios/config/acls/acls.py
index f604e4360..86feba1b0 100644
--- a/plugins/module_utils/network/ios/config/acls/acls.py
+++ b/plugins/module_utils/network/ios/config/acls/acls.py
@@ -323,7 +323,7 @@ def list_to_dict(self, param):
ace.get("destination", {}).get("port_protocol", {}).items()
):
ace["destination"]["port_protocol"][k] = (
- self.port_protocl_no_to_protocol(v)
+ self.port_protocl_no_to_protocol(v, ace.get("protocol"))
)
if acl.get("acl_type") == "standard":
for ks in list(ace.keys()):
@@ -376,7 +376,7 @@ def list_to_dict(self, param):
temp.update({each["afi"]: {"acls": temp_acls}})
return temp
- def port_protocl_no_to_protocol(self, num):
+ def port_protocl_no_to_protocol(self, num, protocol):
map_protocol = {
"179": "bgp",
"19": "chargen",
@@ -414,4 +414,6 @@ def port_protocl_no_to_protocol(self, num):
"43": "whois",
"80": "www",
} # NOTE - "514": "syslog" duplicate value device renders "cmd"
+ if protocol == "udp" and num in ["135"]:
+ return num
return map_protocol.get(num, num)
diff --git a/tests/unit/modules/network/ios/test_ios_acls.py b/tests/unit/modules/network/ios/test_ios_acls.py
index 36d96365a..b06978c3b 100644
--- a/tests/unit/modules/network/ios/test_ios_acls.py
+++ b/tests/unit/modules/network/ios/test_ios_acls.py
@@ -362,6 +362,36 @@ def test_ios_acls_merged_remarks_positional(self):
"acl_type": "extended",
"name": "mytest",
},
+ {
+ "aces": [
+ {
+ "destination": {
+ "any": True,
+ "port_protocol": {
+ "eq": "135",
+ },
+ },
+ "grant": "permit",
+ "protocol": "tcp",
+ "sequence": 10,
+ "source": {"any": True},
+ },
+ {
+ "destination": {
+ "any": True,
+ "port_protocol": {
+ "eq": "135",
+ },
+ },
+ "grant": "permit",
+ "protocol": "udp",
+ "sequence": 20,
+ "source": {"any": True},
+ },
+ ],
+ "name": "example",
+ "acl_type": "extended",
+ },
],
"afi": "ipv4",
},
@@ -467,6 +497,9 @@ def test_ios_acls_merged_remarks_positional(self):
"110 permit ip host 10.40.150.0 any",
"remark I am the peace ace",
"remark Peace out",
+ "ip access-list extended example",
+ "10 permit tcp any any eq msrpc",
+ "20 permit udp any any eq 135",
"ip access-list extended TEST",
"10 remark FIRST REMARK BEFORE LINE 10",
"10 remark ============",