summaryrefslogtreecommitdiffstats
path: root/ansible_collections/cisco/iosxr/tests/unit
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 16:03:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 16:03:42 +0000
commit66cec45960ce1d9c794e9399de15c138acb18aed (patch)
tree59cd19d69e9d56b7989b080da7c20ef1a3fe2a5a /ansible_collections/cisco/iosxr/tests/unit
parentInitial commit. (diff)
downloadansible-upstream.tar.xz
ansible-upstream.zip
Adding upstream version 7.3.0+dfsg.upstream/7.3.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/cisco/iosxr/tests/unit')
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/compat/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/compat/builtins.py35
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/compat/mock.py129
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/compat/unittest.py41
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/mock/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/mock/loader.py117
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/mock/path.py13
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/mock/procenv.py97
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/mock/vault_helper.py44
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/mock/yaml_helper.py177
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/conftest.py34
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_running-config_hostname1
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_2017
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname1
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_2015
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/dir_7all6
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acl_interfaces_config.cfg11
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acls_config.cfg8
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_banner_config.cfg2
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_config.cfg12
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_src.cfg11
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_interface_config.cfg9
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l2_interface_config.cfg9
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l3_interface_config.cfg6
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_config.cfg2
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_interfaces_config.cfg11
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lag_interface_config.cfg24
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_global_config.cfg10
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_interfaces_config.cfg16
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospf_interfaces.cfg8
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv2.cfg8
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv3.cfg8
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_static_routes_config.cfg18
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_system_config.cfg8
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_user_config.cfg8
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_interfaces41
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_ipv6_interface5
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp1
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp_neighbors_detail1
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_memory_summary5
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_running-config43
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version84
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version___utility_head_-n_2018
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version_brief18
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/iosxr_module.py108
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_hostname.py114
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr.py97
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acl_interfaces.py329
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acls.py496
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_banner.py117
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_address_family.py384
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_global.py493
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_neighbor_address_family.py826
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_command.py128
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_config.py313
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_facts.py120
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_interfaces.py288
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l2_interfaces.py246
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l3_interfaces.py255
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp.py93
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp_interfaces.py263
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lag_interfaces.py375
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_global.py206
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_interfaces.py206
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_logging_global.py1263
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_n540.py96
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_netconf.py115
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ntp_global.py902
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospf_interfaces.py359
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv2.py277
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv3.py271
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ping.py180
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_prefix_lists.py442
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_snmp_server.py3612
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_static_routes.py380
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_system.py123
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_user.py131
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_utils.py28
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/modules/utils.py55
-rw-r--r--ansible_collections/cisco/iosxr/tests/unit/requirements.txt42
85 files changed, 14865 insertions, 0 deletions
diff --git a/ansible_collections/cisco/iosxr/tests/unit/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/__init__.py
diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/compat/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/compat/__init__.py
diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/builtins.py b/ansible_collections/cisco/iosxr/tests/unit/compat/builtins.py
new file mode 100644
index 00000000..e898a081
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/compat/builtins.py
@@ -0,0 +1,35 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+#
+# Compat for python2.7
+#
+
+# One unittest needs to import builtins via __import__() so we need to have
+# the string that represents it
+try:
+ import __builtin__
+except ImportError:
+ BUILTINS = "builtins"
+else:
+ BUILTINS = "__builtin__"
diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/mock.py b/ansible_collections/cisco/iosxr/tests/unit/compat/mock.py
new file mode 100644
index 00000000..e4ce72b3
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/compat/mock.py
@@ -0,0 +1,129 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+"""
+Compat module for Python3.x's unittest.mock module
+"""
+import sys
+
+import _io
+
+
+# Python 2.7
+
+# Note: Could use the pypi mock library on python3.x as well as python2.x. It
+# is the same as the python3 stdlib mock library
+
+try:
+ # Allow wildcard import because we really do want to import all of mock's
+ # symbols into this compat shim
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ from unittest.mock import *
+except ImportError:
+ # Python 2
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ try:
+ from mock import *
+ except ImportError:
+ print("You need the mock library installed on python2.x to run tests")
+
+
+# Prior to 3.4.4, mock_open cannot handle binary read_data
+if sys.version_info >= (3,) and sys.version_info < (3, 4, 4):
+ file_spec = None
+
+ def _iterate_read_data(read_data):
+ # Helper for mock_open:
+ # Retrieve lines from read_data via a generator so that separate calls to
+ # readline, read, and readlines are properly interleaved
+ sep = b"\n" if isinstance(read_data, bytes) else "\n"
+ data_as_list = [l + sep for l in read_data.split(sep)]
+
+ if data_as_list[-1] == sep:
+ # If the last line ended in a newline, the list comprehension will have an
+ # extra entry that's just a newline. Remove this.
+ data_as_list = data_as_list[:-1]
+ else:
+ # If there wasn't an extra newline by itself, then the file being
+ # emulated doesn't have a newline to end the last line remove the
+ # newline that our naive format() added
+ data_as_list[-1] = data_as_list[-1][:-1]
+
+ for line in data_as_list:
+ yield line
+
+ def mock_open(mock=None, read_data=""):
+ """
+ A helper function to create a mock to replace the use of `open`. It works
+ for `open` called directly or used as a context manager.
+
+ The `mock` argument is the mock object to configure. If `None` (the
+ default) then a `MagicMock` will be created for you, with the API limited
+ to methods or attributes available on standard file handles.
+
+ `read_data` is a string for the `read` methoddline`, and `readlines` of the
+ file handle to return. This is an empty string by default.
+ """
+
+ def _readlines_side_effect(*args, **kwargs):
+ if handle.readlines.return_value is not None:
+ return handle.readlines.return_value
+ return list(_data)
+
+ def _read_side_effect(*args, **kwargs):
+ if handle.read.return_value is not None:
+ return handle.read.return_value
+ return type(read_data)().join(_data)
+
+ def _readline_side_effect():
+ if handle.readline.return_value is not None:
+ while True:
+ yield handle.readline.return_value
+ for line in _data:
+ yield line
+
+ global file_spec
+ if file_spec is None:
+ file_spec = list(
+ set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))),
+ )
+
+ if mock is None:
+ mock = MagicMock(name="open", spec=open)
+
+ handle = MagicMock(spec=file_spec)
+ handle.__enter__.return_value = handle
+
+ _data = _iterate_read_data(read_data)
+
+ handle.write.return_value = None
+ handle.read.return_value = None
+ handle.readline.return_value = None
+ handle.readlines.return_value = None
+
+ handle.read.side_effect = _read_side_effect
+ handle.readline.side_effect = _readline_side_effect()
+ handle.readlines.side_effect = _readlines_side_effect
+
+ mock.return_value = handle
+ return mock
diff --git a/ansible_collections/cisco/iosxr/tests/unit/compat/unittest.py b/ansible_collections/cisco/iosxr/tests/unit/compat/unittest.py
new file mode 100644
index 00000000..df4266ec
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/compat/unittest.py
@@ -0,0 +1,41 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+"""
+Compat module for Python2.7's unittest module
+"""
+
+import sys
+
+
+# Allow wildcard import because we really do want to import all of
+# unittests's symbols into this compat shim
+# pylint: disable=wildcard-import,unused-wildcard-import
+if sys.version_info < (2, 7):
+ try:
+ # Need unittest2 on python2.6
+ from unittest2 import *
+ except ImportError:
+ print("You need unittest2 installed on python2.6.x to run tests")
+else:
+ from unittest import *
diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/mock/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/mock/__init__.py
diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/loader.py b/ansible_collections/cisco/iosxr/tests/unit/mock/loader.py
new file mode 100644
index 00000000..2b5eb36a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/mock/loader.py
@@ -0,0 +1,117 @@
+# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import os
+
+from ansible.errors import AnsibleParserError
+from ansible.module_utils._text import to_bytes, to_text
+from ansible.parsing.dataloader import DataLoader
+
+
+class DictDataLoader(DataLoader):
+ def __init__(self, file_mapping=None):
+ file_mapping = {} if file_mapping is None else file_mapping
+ assert type(file_mapping) == dict
+
+ super(DictDataLoader, self).__init__()
+
+ self._file_mapping = file_mapping
+ self._build_known_directories()
+ self._vault_secrets = None
+
+ def load_from_file(self, path, cache=True, unsafe=False):
+ path = to_text(path)
+ if path in self._file_mapping:
+ return self.load(self._file_mapping[path], path)
+ return None
+
+ # TODO: the real _get_file_contents returns a bytestring, so we actually convert the
+ # unicode/text it's created with to utf-8
+ def _get_file_contents(self, path):
+ path = to_text(path)
+ if path in self._file_mapping:
+ return (to_bytes(self._file_mapping[path]), False)
+ else:
+ raise AnsibleParserError("file not found: %s" % path)
+
+ def path_exists(self, path):
+ path = to_text(path)
+ return path in self._file_mapping or path in self._known_directories
+
+ def is_file(self, path):
+ path = to_text(path)
+ return path in self._file_mapping
+
+ def is_directory(self, path):
+ path = to_text(path)
+ return path in self._known_directories
+
+ def list_directory(self, path):
+ ret = []
+ path = to_text(path)
+ for x in list(self._file_mapping.keys()) + self._known_directories:
+ if x.startswith(path):
+ if os.path.dirname(x) == path:
+ ret.append(os.path.basename(x))
+ return ret
+
+ def is_executable(self, path):
+ # FIXME: figure out a way to make paths return true for this
+ return False
+
+ def _add_known_directory(self, directory):
+ if directory not in self._known_directories:
+ self._known_directories.append(directory)
+
+ def _build_known_directories(self):
+ self._known_directories = []
+ for path in self._file_mapping:
+ dirname = os.path.dirname(path)
+ while dirname not in ("/", ""):
+ self._add_known_directory(dirname)
+ dirname = os.path.dirname(dirname)
+
+ def push(self, path, content):
+ rebuild_dirs = False
+ if path not in self._file_mapping:
+ rebuild_dirs = True
+
+ self._file_mapping[path] = content
+
+ if rebuild_dirs:
+ self._build_known_directories()
+
+ def pop(self, path):
+ if path in self._file_mapping:
+ del self._file_mapping[path]
+ self._build_known_directories()
+
+ def clear(self):
+ self._file_mapping = dict()
+ self._known_directories = []
+
+ def get_basedir(self):
+ return os.getcwd()
+
+ def set_vault_secrets(self, vault_secrets):
+ self._vault_secrets = vault_secrets
diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/path.py b/ansible_collections/cisco/iosxr/tests/unit/mock/path.py
new file mode 100644
index 00000000..0c87896d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/mock/path.py
@@ -0,0 +1,13 @@
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+from ansible.utils.path import unfrackpath
+
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import MagicMock
+
+
+mock_unfrackpath_noop = MagicMock(
+ spec_set=unfrackpath,
+ side_effect=lambda x, *args, **kwargs: x,
+)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/procenv.py b/ansible_collections/cisco/iosxr/tests/unit/mock/procenv.py
new file mode 100644
index 00000000..3a4231bd
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/mock/procenv.py
@@ -0,0 +1,97 @@
+# (c) 2016, Matt Davis <mdavis@ansible.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import json
+import sys
+
+from contextlib import contextmanager
+from io import BytesIO, StringIO
+
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils.six import PY3
+
+from ansible_collections.cisco.iosxr.tests.unit.compat import unittest
+
+
+@contextmanager
+def swap_stdin_and_argv(stdin_data="", argv_data=tuple()):
+ """
+ context manager that temporarily masks the test runner's values for stdin and argv
+ """
+ real_stdin = sys.stdin
+ real_argv = sys.argv
+
+ if PY3:
+ fake_stream = StringIO(stdin_data)
+ fake_stream.buffer = BytesIO(to_bytes(stdin_data))
+ else:
+ fake_stream = BytesIO(to_bytes(stdin_data))
+
+ try:
+ sys.stdin = fake_stream
+ sys.argv = argv_data
+
+ yield
+ finally:
+ sys.stdin = real_stdin
+ sys.argv = real_argv
+
+
+@contextmanager
+def swap_stdout():
+ """
+ context manager that temporarily replaces stdout for tests that need to verify output
+ """
+ old_stdout = sys.stdout
+
+ if PY3:
+ fake_stream = StringIO()
+ else:
+ fake_stream = BytesIO()
+
+ try:
+ sys.stdout = fake_stream
+
+ yield fake_stream
+ finally:
+ sys.stdout = old_stdout
+
+
+class ModuleTestCase(unittest.TestCase):
+ def setUp(self, module_args=None):
+ if module_args is None:
+ module_args = {
+ "_ansible_remote_tmp": "/tmp",
+ "_ansible_keep_remote_files": False,
+ }
+
+ args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args))
+
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap = swap_stdin_and_argv(stdin_data=args)
+ self.stdin_swap.__enter__()
+
+ def tearDown(self):
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap.__exit__(None, None, None)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/vault_helper.py b/ansible_collections/cisco/iosxr/tests/unit/mock/vault_helper.py
new file mode 100644
index 00000000..82d01f5c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/mock/vault_helper.py
@@ -0,0 +1,44 @@
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible.module_utils._text import to_bytes
+from ansible.parsing.vault import VaultSecret
+
+
+class TextVaultSecret(VaultSecret):
+ """A secret piece of text. ie, a password. Tracks text encoding.
+
+ The text encoding of the text may not be the default text encoding so
+ we keep track of the encoding so we encode it to the same bytes."""
+
+ def __init__(self, text, encoding=None, errors=None, _bytes=None):
+ super(TextVaultSecret, self).__init__()
+ self.text = text
+ self.encoding = encoding or "utf-8"
+ self._bytes = _bytes
+ self.errors = errors or "strict"
+
+ @property
+ def bytes(self):
+ """The text encoded with encoding, unless we specifically set _bytes."""
+ return self._bytes or to_bytes(
+ self.text,
+ encoding=self.encoding,
+ errors=self.errors,
+ )
diff --git a/ansible_collections/cisco/iosxr/tests/unit/mock/yaml_helper.py b/ansible_collections/cisco/iosxr/tests/unit/mock/yaml_helper.py
new file mode 100644
index 00000000..e46d3180
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/mock/yaml_helper.py
@@ -0,0 +1,177 @@
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+import io
+
+import yaml
+
+from ansible.module_utils.six import PY3
+from ansible.parsing.yaml.dumper import AnsibleDumper
+from ansible.parsing.yaml.loader import AnsibleLoader
+
+
+class YamlTestUtils(object):
+ """Mixin class to combine with a unittest.TestCase subclass."""
+
+ def _loader(self, stream):
+ """Vault related tests will want to override this.
+
+ Vault cases should setup a AnsibleLoader that has the vault password."""
+ return AnsibleLoader(stream)
+
+ def _dump_stream(self, obj, stream, dumper=None):
+ """Dump to a py2-unicode or py3-string stream."""
+ if PY3:
+ return yaml.dump(obj, stream, Dumper=dumper)
+ else:
+ return yaml.dump(obj, stream, Dumper=dumper, encoding=None)
+
+ def _dump_string(self, obj, dumper=None):
+ """Dump to a py2-unicode or py3-string"""
+ if PY3:
+ return yaml.dump(obj, Dumper=dumper)
+ else:
+ return yaml.dump(obj, Dumper=dumper, encoding=None)
+
+ def _dump_load_cycle(self, obj):
+ # Each pass though a dump or load revs the 'generation'
+ # obj to yaml string
+ string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper)
+
+ # wrap a stream/file like StringIO around that yaml
+ stream_from_object_dump = io.StringIO(string_from_object_dump)
+ loader = self._loader(stream_from_object_dump)
+ # load the yaml stream to create a new instance of the object (gen 2)
+ obj_2 = loader.get_data()
+
+ # dump the gen 2 objects directory to strings
+ string_from_object_dump_2 = self._dump_string(
+ obj_2,
+ dumper=AnsibleDumper,
+ )
+
+ # The gen 1 and gen 2 yaml strings
+ self.assertEqual(string_from_object_dump, string_from_object_dump_2)
+ # the gen 1 (orig) and gen 2 py object
+ self.assertEqual(obj, obj_2)
+
+ # again! gen 3... load strings into py objects
+ stream_3 = io.StringIO(string_from_object_dump_2)
+ loader_3 = self._loader(stream_3)
+ obj_3 = loader_3.get_data()
+
+ string_from_object_dump_3 = self._dump_string(
+ obj_3,
+ dumper=AnsibleDumper,
+ )
+
+ self.assertEqual(obj, obj_3)
+ # should be transitive, but...
+ self.assertEqual(obj_2, obj_3)
+ self.assertEqual(string_from_object_dump, string_from_object_dump_3)
+
+ def _old_dump_load_cycle(self, obj):
+ """Dump the passed in object to yaml, load it back up, dump again, compare."""
+ stream = io.StringIO()
+
+ yaml_string = self._dump_string(obj, dumper=AnsibleDumper)
+ self._dump_stream(obj, stream, dumper=AnsibleDumper)
+
+ yaml_string_from_stream = stream.getvalue()
+
+ # reset stream
+ stream.seek(0)
+
+ loader = self._loader(stream)
+ # loader = AnsibleLoader(stream, vault_password=self.vault_password)
+ obj_from_stream = loader.get_data()
+
+ stream_from_string = io.StringIO(yaml_string)
+ loader2 = self._loader(stream_from_string)
+ # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password)
+ obj_from_string = loader2.get_data()
+
+ stream_obj_from_stream = io.StringIO()
+ stream_obj_from_string = io.StringIO()
+
+ if PY3:
+ yaml.dump(
+ obj_from_stream,
+ stream_obj_from_stream,
+ Dumper=AnsibleDumper,
+ )
+ yaml.dump(
+ obj_from_stream,
+ stream_obj_from_string,
+ Dumper=AnsibleDumper,
+ )
+ else:
+ yaml.dump(
+ obj_from_stream,
+ stream_obj_from_stream,
+ Dumper=AnsibleDumper,
+ encoding=None,
+ )
+ yaml.dump(
+ obj_from_stream,
+ stream_obj_from_string,
+ Dumper=AnsibleDumper,
+ encoding=None,
+ )
+
+ yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue()
+ yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue()
+
+ stream_obj_from_stream.seek(0)
+ stream_obj_from_string.seek(0)
+
+ if PY3:
+ yaml_string_obj_from_stream = yaml.dump(
+ obj_from_stream,
+ Dumper=AnsibleDumper,
+ )
+ yaml_string_obj_from_string = yaml.dump(
+ obj_from_string,
+ Dumper=AnsibleDumper,
+ )
+ else:
+ yaml_string_obj_from_stream = yaml.dump(
+ obj_from_stream,
+ Dumper=AnsibleDumper,
+ encoding=None,
+ )
+ yaml_string_obj_from_string = yaml.dump(
+ obj_from_string,
+ Dumper=AnsibleDumper,
+ encoding=None,
+ )
+
+ assert yaml_string == yaml_string_obj_from_stream
+ assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+ assert (
+ yaml_string
+ == yaml_string_obj_from_stream
+ == yaml_string_obj_from_string
+ == yaml_string_stream_obj_from_stream
+ == yaml_string_stream_obj_from_string
+ )
+ assert obj == obj_from_stream
+ assert obj == obj_from_string
+ assert obj == yaml_string_obj_from_stream
+ assert obj == yaml_string_obj_from_string
+ assert (
+ obj
+ == obj_from_stream
+ == obj_from_string
+ == yaml_string_obj_from_stream
+ == yaml_string_obj_from_string
+ )
+ return {
+ "obj": obj,
+ "yaml_string": yaml_string,
+ "yaml_string_from_stream": yaml_string_from_stream,
+ "obj_from_stream": obj_from_stream,
+ "obj_from_string": obj_from_string,
+ "yaml_string_obj_from_string": yaml_string_obj_from_string,
+ }
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/__init__.py
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/conftest.py b/ansible_collections/cisco/iosxr/tests/unit/modules/conftest.py
new file mode 100644
index 00000000..349e71ad
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/conftest.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2017 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import json
+
+import pytest
+
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils.common._collections_compat import MutableMapping
+from ansible.module_utils.six import string_types
+
+
+@pytest.fixture
+def patch_ansible_module(request, mocker):
+ if isinstance(request.param, string_types):
+ args = request.param
+ elif isinstance(request.param, MutableMapping):
+ if "ANSIBLE_MODULE_ARGS" not in request.param:
+ request.param = {"ANSIBLE_MODULE_ARGS": request.param}
+ if "_ansible_remote_tmp" not in request.param["ANSIBLE_MODULE_ARGS"]:
+ request.param["ANSIBLE_MODULE_ARGS"]["_ansible_remote_tmp"] = "/tmp"
+ if "_ansible_keep_remote_files" not in request.param["ANSIBLE_MODULE_ARGS"]:
+ request.param["ANSIBLE_MODULE_ARGS"]["_ansible_keep_remote_files"] = False
+ args = json.dumps(request.param)
+ else:
+ raise Exception(
+ "Malformed data to the patch_ansible_module pytest fixture",
+ )
+
+ mocker.patch("ansible.module_utils.basic._ANSIBLE_ARGS", to_bytes(args))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/__init__.py
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/__init__.py
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/__init__.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/__init__.py
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_running-config_hostname b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_running-config_hostname
new file mode 100644
index 00000000..ebc5bf85
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_running-config_hostname
@@ -0,0 +1 @@
+hostname iosxr01
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_20 b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_20
new file mode 100644
index 00000000..6922cbbf
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf/iosxr/show_version__utility_head_-n_20
@@ -0,0 +1,17 @@
+Cisco IOS XR Software, Version 6.0.0[Default]
+Copyright (c) 2015 by Cisco Systems, Inc.
+
+ROM: GRUB, Version 1.99(0), DEV RELEASE
+
+iosxr01 uptime is 11 weeks, 2 days, 5 hours, 48 minutes
+System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm"
+
+cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes of memory.
+Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174
+IOS XRv Chassis
+
+1 Management Ethernet
+6 GigabitEthernet
+97070k bytes of non-volatile configuration memory.
+866M bytes of hard disk.
+2321392k bytes of disk0: (Sector size 512 bytes).
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname
new file mode 100644
index 00000000..ebc5bf85
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_running-config_hostname
@@ -0,0 +1 @@
+hostname iosxr01
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_20 b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_20
new file mode 100644
index 00000000..5aa174c4
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/cliconf_ncs540/iosxr/show_version__utility_head_-n_20
@@ -0,0 +1,15 @@
+Cisco IOS XR Software, Version 7.5.2 LNT
+Copyright (c) 2013-2022 by Cisco Systems, Inc.
+
+Build Information:
+ Built By : ingunawa
+ Built On : Tue Apr 26 23:47:22 UTC 2022
+ Build Host : iox-lnx-023
+ Workspace : /auto/srcarchive14/prod/7.5.2/ncs540l-aarch64/ws
+ Version : 7.5.2
+ Label : 7.5.2
+
+cisco NCS540L
+cisco N540X-6Z18G-SYS-A processor with 8GB of memory
+iosxr01 uptime is 5 days, 1 hour, 45 minutes
+Cisco NCS 540 Series Fixed Router 18x1G, 6x1/10G, AC
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/dir_7all b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/dir_7all
new file mode 100644
index 00000000..b992498c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/dir_7all
@@ -0,0 +1,6 @@
+Directory of disk0:
+file1
+file2
+
+Directory of flash0:
+file3
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acl_interfaces_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acl_interfaces_config.cfg
new file mode 100644
index 00000000..6a05274a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acl_interfaces_config.cfg
@@ -0,0 +1,11 @@
+interface GigabitEthernet0/0/0/0
+ shutdown
+ ipv4 access-group acl_1 ingress
+ ipv4 access-group acl_2 egress
+ ipv6 access-group acl6_1 ingress
+ ipv6 access-group acl6_2 egress
+!
+interface GigabitEthernet0/0/0/1
+ shutdown
+ ipv4 access-group acl_1 egress
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acls_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acls_config.cfg
new file mode 100644
index 00000000..f5d1708c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_acls_config.cfg
@@ -0,0 +1,8 @@
+ipv4 access-list acl_2
+ 10 deny ipv4 any any
+ 20 permit tcp host 192.168.1.100 any
+ipv4 access-list acl_1
+ 10 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1
+ 20 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1
+ipv6 access-list acl6_1
+ 10 deny icmpv6 any any
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_banner_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_banner_config.cfg
new file mode 100644
index 00000000..ed8e6d6d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_banner_config.cfg
@@ -0,0 +1,2 @@
+banner motd this is my motd banner
+banner login this is my login banner
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_config.cfg
new file mode 100644
index 00000000..afad9d08
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_config.cfg
@@ -0,0 +1,12 @@
+!
+hostname router
+!
+interface GigabitEthernet0/0
+ ip address 1.2.3.4 255.255.255.0
+ description test string
+!
+interface GigabitEthernet0/1
+ ip address 6.7.8.9 255.255.255.0
+ description test string
+ shutdown
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_src.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_src.cfg
new file mode 100644
index 00000000..b3d8961a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_config_src.cfg
@@ -0,0 +1,11 @@
+!
+hostname foo
+!
+interface GigabitEthernet0/0
+ no ip address
+!
+interface GigabitEthernet0/1
+ ip address 6.7.8.9 255.255.255.0
+ description test string
+ shutdown
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_interface_config.cfg
new file mode 100644
index 00000000..700dde0a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_interface_config.cfg
@@ -0,0 +1,9 @@
+interface GigabitEthernet0/0/0/0
+ description Configured and Merged by Ansible-Network
+ mtu 110
+ duplex half
+interface GigabitEthernet0/0/0/1
+ description Configured and Merged by Ansible-Network
+ no shutdown
+ mtu 2800
+ speed 100
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l2_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l2_interface_config.cfg
new file mode 100644
index 00000000..4192ee39
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l2_interface_config.cfg
@@ -0,0 +1,9 @@
+interface GigabitEthernet0/0/0/1
+ l2transport
+ l2protocol cpsv tunnel
+ propagate remote-status
+ !
+!
+interface GigabitEthernet0/0/0/3.900
+ encapsulation dot1q 20 second-dot1q 40
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l3_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l3_interface_config.cfg
new file mode 100644
index 00000000..d870f4e8
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_l3_interface_config.cfg
@@ -0,0 +1,6 @@
+interface GigabitEthernet0/0/0/0
+ipv4 address 198.51.100.1 255.255.255.0
+ipv6 address 2001:db8::/32
+interface GigabitEthernet0/0/0/1
+ipv4 address 192.0.2.1 255.255.255.0
+ipv4 address 192.0.2.2 255.255.255.0 secondary
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_config.cfg
new file mode 100644
index 00000000..01776dbe
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_config.cfg
@@ -0,0 +1,2 @@
+lacp system mac 00c1.4c00.bd15
+lacp system priority 12
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_interfaces_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_interfaces_config.cfg
new file mode 100644
index 00000000..b38bb39f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lacp_interfaces_config.cfg
@@ -0,0 +1,11 @@
+interface Bundle-Ether10
+ lacp churn logging actor
+ lacp switchover suppress-flaps 500
+ lacp collector-max-delay 100
+!
+interface Bundle-Ether11
+ lacp system mac 00c2.4c00.bd15
+!
+interface GigabitEthernet0/0/0/1
+ lacp period 200
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lag_interface_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lag_interface_config.cfg
new file mode 100644
index 00000000..256d3f23
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lag_interface_config.cfg
@@ -0,0 +1,24 @@
+interface Bundle-Ether10
+ lacp mode active
+ bundle maximum-active links 10
+ bundle minimum-active links 2
+!
+interface Bundle-Ether11
+lacp mode active
+!
+interface GigabitEthernet0/0/0/0
+ description "GigabitEthernet - 0"
+ bundle id 10 mode inherit
+!
+interface GigabitEthernet0/0/0/1
+ description "GigabitEthernet - 2"
+ bundle id 10 mode passive
+!
+interface GigabitEthernet0/0/0/8
+ description "GigabitEthernet - 8"
+ bundle id 11 mode passive
+!
+interface GigabitEthernet0/0/0/9
+ description "GigabitEthernet - 9"
+ bundle id 11 mode passive
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_global_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_global_config.cfg
new file mode 100644
index 00000000..4bd23847
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_global_config.cfg
@@ -0,0 +1,10 @@
+lldp
+ timer 3000
+ reinit 2
+ subinterfaces enable
+ holdtime 100
+ tlv-select
+ management-address disable
+ system-description disable
+ !
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_interfaces_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_interfaces_config.cfg
new file mode 100644
index 00000000..b50b42e5
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_lldp_interfaces_config.cfg
@@ -0,0 +1,16 @@
+interface TenGigE0/0/0/0
+ ipv4 address 192.0.2.11 255.255.255.192
+!
+interface preconfigure GigabitEthernet0/0/0/0
+ lldp
+ transmit disable
+ destination mac-address
+ ieee-nearest-bridge
+ !
+ !
+!
+interface preconfigure GigabitEthernet0/0/0/1
+ lldp
+ receive disable
+ destination mac-address
+ ieee-nearest-non-tmpr-bridge
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospf_interfaces.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospf_interfaces.cfg
new file mode 100644
index 00000000..9ddb8d66
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospf_interfaces.cfg
@@ -0,0 +1,8 @@
+router ospf LAB3
+ area 0.0.0.3
+ interface GigabitEthernet0/0/0/0
+ cost 20
+ authentication message-digest keychain cisco
+ !
+ !
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv2.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv2.cfg
new file mode 100644
index 00000000..8645482e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv2.cfg
@@ -0,0 +1,8 @@
+Sun Jun 14 12:10:47.455 UTC
+router ospf 30
+ cost 2
+ default-metric 10
+ area 11
+ default-cost 5
+ !
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv3.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv3.cfg
new file mode 100644
index 00000000..b52c0ee0
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_ospfv3.cfg
@@ -0,0 +1,8 @@
+Sun Jun 14 12:10:47.455 UTC
+router ospfv3 30
+ cost 2
+ default-metric 10
+ area 11
+ default-cost 5
+ !
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_static_routes_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_static_routes_config.cfg
new file mode 100644
index 00000000..35948336
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_static_routes_config.cfg
@@ -0,0 +1,18 @@
+Fri Nov 29 21:10:41.896 UTC
+router static
+ address-family ipv4 unicast
+ 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+ 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+ 192.0.2.32/28 192.0.2.11 100
+ !
+ address-family ipv6 unicast
+ 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+ 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+ !
+ vrf DEV_SITE
+ address-family ipv4 unicast
+ 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+ 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+ !
+ !
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_system_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_system_config.cfg
new file mode 100644
index 00000000..fc6fd2b7
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_system_config.cfg
@@ -0,0 +1,8 @@
+hostname iosxr01
+domain name eng.ansible.com
+domain lookup disable
+domain lookup source-interface MgmtEth0/0/CPU0/0
+domain list redhat.com
+domain list cisco.com
+domain name-server 8.8.8.8
+domain name-server 8.8.4.4
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_user_config.cfg b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_user_config.cfg
new file mode 100644
index 00000000..0f0ab168
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/iosxr_user_config.cfg
@@ -0,0 +1,8 @@
+username admin
+ secret 5 $1$mdQIUxjg$3t3lzBpfKfITKvFm1uEIY.
+ group sysadmin
+!
+username ansible
+ secret 5 $1$3yWSXiIi$VdzV59ChiurrNdGxlDeAW/
+ group sysadmin
+!
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_interfaces b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_interfaces
new file mode 100644
index 00000000..edb3c6a0
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_interfaces
@@ -0,0 +1,41 @@
+Loopback0 is up, line protocol is up
+ Interface state transitions: 1
+ Hardware is Loopback interface(s)
+ Description: Loopback
+ Internet address is 192.168.0.3/32
+ MTU 1500 bytes, BW 0 Kbit
+ reliability Unknown, txload Unknown, rxload Unknown
+ Encapsulation Loopback, loopback not set,
+ Last link flapped 12w1d
+ Last input Unknown, output Unknown
+ Last clearing of "show interface" counters Unknown
+ Input/output data rate is disabled.
+
+GigabitEthernet0/0/0/0 is up, line protocol is up
+ Interface state transitions: 1
+ Hardware is GigabitEthernet, address is fa16.3e6c.20bd (bia fa16.3e6c.20bd)
+ Description: to nxos01
+ Internet address is 10.0.0.5/30
+ MTU 1514 bytes, BW 1000000 Kbit (Max: 1000000 Kbit)
+ reliability 255/255, txload 0/255, rxload 0/255
+ Encapsulation ARPA,
+ Full-duplex, 1000Mb/s, unknown, link type is force-up
+ output flow control is off, input flow control is off
+ Carrier delay (up) is 10 msec
+ loopback not set,
+ Last link flapped 12w1d
+ ARP type ARPA, ARP timeout 04:00:00
+ Last input 00:00:44, output 00:12:45
+ Last clearing of "show interface" counters never
+ 5 minute input rate 0 bits/sec, 0 packets/sec
+ 5 minute output rate 0 bits/sec, 0 packets/sec
+ 150700 packets input, 36897055 bytes, 0 total input drops
+ 0 drops for unrecognized upper-level protocol
+ Received 1 broadcast packets, 150445 multicast packets
+ 0 runts, 0 giants, 0 throttles, 0 parity
+ 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
+ 11691 packets output, 2904632 bytes, 0 total output drops
+ Output 1 broadcast packets, 11436 multicast packets
+ 0 output errors, 0 underruns, 0 applique, 0 resets
+ 0 output buffer failures, 0 output buffers swapped out
+ 1 carrier transitions
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_ipv6_interface b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_ipv6_interface
new file mode 100644
index 00000000..971d1f65
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_ipv6_interface
@@ -0,0 +1,5 @@
+Loopback0 is Up, ipv6 protocol is Up, Vrfid is default (0x60000000)
+ IPv6 is disabled, link-local address unassigned
+ No global unicast address is configured
+GigabitEthernet0/0/0/0 is Up, ipv6 protocol is Up, Vrfid is default (0x60000000)
+ IPv6 is disabled, link-local address unassigned
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp
new file mode 100644
index 00000000..60ab287f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp
@@ -0,0 +1 @@
+% LLDP is not enabled
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp_neighbors_detail b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp_neighbors_detail
new file mode 100644
index 00000000..60ab287f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_lldp_neighbors_detail
@@ -0,0 +1 @@
+% LLDP is not enabled
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_memory_summary b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_memory_summary
new file mode 100644
index 00000000..b26abeae
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_memory_summary
@@ -0,0 +1,5 @@
+Physical Memory: 3095M total (1499M available)
+ Application Memory : 2893M (1499M available)
+ Image: 73M (bootram: 73M)
+ Reserved: 128M, IOMem: 0, flashfsys: 0
+ Total shared window: 23M
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_running-config b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_running-config
new file mode 100644
index 00000000..085baef4
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_running-config
@@ -0,0 +1,43 @@
+hostname iosxr01
+service timestamps log datetime msec
+service timestamps debug datetime msec
+telnet vrf default ipv4 server max-servers 10
+telnet vrf Mgmt-intf ipv4 server max-servers 10
+domain name eng.ansible.com
+domain lookup disable
+vrf Mgmt-intf
+ address-family ipv4 unicast
+ !
+ address-family ipv6 unicast
+ !
+!
+line template vty
+ timestamp
+ exec-timeout 720 0
+!
+line console
+ exec-timeout 0 0
+!
+line default
+ exec-timeout 720 0
+!
+vty-pool default 0 50
+control-plane
+ management-plane
+ inband
+ interface all
+ allow all
+ !
+ !
+ !
+!
+interface Loopback0
+ description Loopback
+ ipv4 address 192.168.0.1 255.255.255.255
+!
+interface GigabitEthernet0/0/0/0
+ description to nxos01
+ cdp
+ ipv4 address 10.0.0.1 255.255.255.252
+!
+end
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version
new file mode 100644
index 00000000..faecfffd
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version
@@ -0,0 +1,84 @@
+Cisco IOS XR Software, Version 6.0.0[Default]
+Copyright (c) 2015 by Cisco Systems, Inc.
+
+ROM: GRUB, Version 1.99(0), DEV RELEASE
+
+iosxr01 uptime is 11 weeks, 2 days, 5 hours, 48 minutes
+System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm"
+
+cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes of memory.
+Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174
+IOS XRv Chassis
+
+1 Management Ethernet
+6 GigabitEthernet
+97070k bytes of non-volatile configuration memory.
+866M bytes of hard disk.
+2321392k bytes of disk0: (Sector size 512 bytes).
+
+Configuration register on node 0/0/CPU0 is 0x2102
+Boot device on node 0/0/CPU0 is disk0:
+Package active on node 0/0/CPU0:
+iosxr-infra, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-infra-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-fwding, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-fwding-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-routing, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-routing-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-ce, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-ce-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+xrvr-os-mbi, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-os-mbi-6.0.0
+ Built on Thu Dec 24 08:54:41 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+xrvr-base, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-base-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+xrvr-fwding, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-fwding-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+xrvr-mgbl-x, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-mgbl-x-6.0.0
+ Built on Thu Dec 24 08:53:57 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-mpls, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-mpls-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-mgbl, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-mgbl-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-mcast, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-mcast-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+xrvr-mcast-supp, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-mcast-supp-6.0.0
+ Built on Thu Dec 24 08:53:49 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-bng, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-bng-6.0.0
+ Built on Thu Dec 24 08:53:47 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+xrvr-bng-supp, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-bng-supp-6.0.0
+ Built on Thu Dec 24 08:53:47 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+iosxr-security, V 6.0.0[Default], Cisco Systems, at disk0:iosxr-security-6.0.0
+ Built on Thu Dec 24 08:53:41 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
+
+xrvr-fullk9-x, V 6.0.0[Default], Cisco Systems, at disk0:xrvr-fullk9-x-6.0.0
+ Built on Thu Dec 24 08:55:12 UTC 2015
+ By iox-lnx-010 in /auto/srcarchive16/production/6.0.0/xrvr/workspace for pie
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version___utility_head_-n_20 b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version___utility_head_-n_20
new file mode 100644
index 00000000..7f82039f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version___utility_head_-n_20
@@ -0,0 +1,18 @@
+Cisco IOS XR Software, Version 6.0.0[Default]
+Copyright (c) 2015 by Cisco Systems, Inc.
+
+ROM: GRUB, Version 1.99(0), DEV RELEASE
+
+iosxr01 uptime is 11 weeks, 6 days, 2 hours, 2 minutes
+System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm"
+
+cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes
+of memory.
+Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174
+IOS XRv Chassis
+
+1 Management Ethernet
+6 GigabitEthernet
+97070k bytes of non-volatile configuration memory.
+866M bytes of hard disk.
+2321392k bytes of disk0: (Sector size 512 bytes).
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version_brief b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version_brief
new file mode 100644
index 00000000..7f82039f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/fixtures/show_version_brief
@@ -0,0 +1,18 @@
+Cisco IOS XR Software, Version 6.0.0[Default]
+Copyright (c) 2015 by Cisco Systems, Inc.
+
+ROM: GRUB, Version 1.99(0), DEV RELEASE
+
+iosxr01 uptime is 11 weeks, 6 days, 2 hours, 2 minutes
+System image file is "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm"
+
+cisco IOS XRv Series (Pentium Celeron Stepping 3) processor with 3169911K bytes
+of memory.
+Pentium Celeron Stepping 3 processor at 3836MHz, Revision 2.174
+IOS XRv Chassis
+
+1 Management Ethernet
+6 GigabitEthernet
+97070k bytes of non-volatile configuration memory.
+866M bytes of hard disk.
+2321392k bytes of disk0: (Sector size 512 bytes).
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/iosxr_module.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/iosxr_module.py
new file mode 100644
index 00000000..1915b07e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/iosxr_module.py
@@ -0,0 +1,108 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import json
+import os
+
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import (
+ AnsibleExitJson,
+ AnsibleFailJson,
+ ModuleTestCase,
+)
+
+
+fixture_path = os.path.join(os.path.dirname(__file__), "fixtures")
+fixture_data = {}
+
+
+def load_fixture(name):
+ path = os.path.join(fixture_path, name)
+
+ if path in fixture_data:
+ return fixture_data[path]
+
+ with open(path) as f:
+ data = f.read()
+
+ try:
+ data = json.loads(data)
+ except Exception:
+ pass
+
+ fixture_data[path] = data
+ return data
+
+
+class TestIosxrModule(ModuleTestCase):
+ def execute_module(
+ self,
+ failed=False,
+ changed=False,
+ commands=None,
+ sort=True,
+ defaults=False,
+ ):
+
+ self.load_fixtures(commands)
+
+ if failed:
+ result = self.failed()
+ self.assertTrue(result["failed"], result)
+ else:
+ result = self.changed(changed)
+ self.assertEqual(result["changed"], changed, result)
+
+ if commands is not None:
+ if sort:
+ self.assertEqual(
+ sorted(commands),
+ sorted(result["commands"]),
+ result["commands"],
+ )
+ else:
+ self.assertEqual(
+ commands,
+ result["commands"],
+ result["commands"],
+ )
+
+ return result
+
+ def failed(self):
+ with self.assertRaises(AnsibleFailJson) as exc:
+ self.module.main()
+
+ result = exc.exception.args[0]
+ self.assertTrue(result["failed"], result)
+ return result
+
+ def changed(self, changed=False):
+ with self.assertRaises(AnsibleExitJson) as exc:
+ self.module.main()
+
+ result = exc.exception.args[0]
+ self.assertEqual(result["changed"], changed, result)
+ return result
+
+ def load_fixtures(self, commands=None):
+ pass
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_hostname.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_hostname.py
new file mode 100644
index 00000000..7c676530
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_hostname.py
@@ -0,0 +1,114 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_hostname
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrHostnameModule(TestIosxrModule):
+ module = iosxr_hostname
+
+ def setUp(self):
+ super(TestIosxrHostnameModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.hostname.hostname."
+ "HostnameFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrHostnameModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_hostname_merged_idempotent(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ hostname iosxr1
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=dict(hostname="iosxr1"), state="merged"))
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_hostname_merged(self):
+ self.maxDiff = None
+ set_module_args(dict(config=dict(hostname="iosxr1"), state="merged"))
+ commands = ["hostname iosxr1"]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_hostname_deleted(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ hostname iosxr1
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(state="deleted"))
+ commands = ["no hostname iosxr1"]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_hostname_rendered(self):
+ self.maxDiff = None
+ set_module_args(dict(config=dict(hostname="iosxr1"), state="rendered"))
+ commands = ["hostname iosxr1"]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_hostname_gathered(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ hostname iosxr1
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ print(self.get_config.return_value)
+ set_module_args(dict(state="gathered"))
+ gathered = {"hostname": "iosxr1"}
+ result = self.execute_module(changed=False)
+ self.assertEqual(gathered, result["gathered"])
+
+ def test_iosxr_hostname_parsed(self):
+ self.maxDiff = None
+ set_module_args(dict(running_config="hostname iosxr1", state="parsed"))
+ result = self.execute_module(changed=False)
+ parsed_list = {"hostname": "iosxr1"}
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr.py
new file mode 100644
index 00000000..af2fd3a5
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr.py
@@ -0,0 +1,97 @@
+#
+# (c) 2020 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from os import path
+
+from ansible.module_utils._text import to_bytes, to_text
+from mock import MagicMock
+
+from ansible_collections.cisco.iosxr.plugins.cliconf import iosxr
+from ansible_collections.cisco.iosxr.tests.unit.compat import unittest
+
+
+class TestPluginCLIConfIOSXR(unittest.TestCase):
+ """Test class for IOSXR CLI Conf Methods"""
+
+ def setUp(self):
+ self._mock_connection = MagicMock()
+ self._prepare()
+ self._cliconf = iosxr.Cliconf(self._mock_connection)
+ self.maxDiff = None
+
+ def _prepare(self, platform="iosxr"):
+ b_FIXTURE_DIR = b"%s/fixtures/cliconf/%s" % (
+ to_bytes(
+ path.dirname(path.abspath(__file__)),
+ errors="surrogate_or_strict",
+ ),
+ to_bytes(platform),
+ )
+
+ def _connection_side_effect(*args, **kwargs):
+ try:
+ if args:
+ value = args[0]
+ else:
+ value = kwargs.get("command")
+ if b"|" in value:
+ value = value.replace(b"|", b"")
+ fixture_path = path.abspath(
+ b"%s/%s" % (b_FIXTURE_DIR, b"_".join(value.split(b" "))),
+ )
+ with open(fixture_path, "rb") as file_desc:
+ return to_text(file_desc.read())
+ except (OSError, IOError):
+ if args:
+ value = args[0]
+ return value
+ elif kwargs.get("command"):
+ value = kwargs.get("command")
+ return value
+ return "NO-OP"
+
+ self._mock_connection.send.side_effect = _connection_side_effect
+
+ def tearDown(self):
+ pass
+
+ def test_get_device_info_iosxr(self):
+ """Test get_device_info for nxos"""
+ device_info = self._cliconf.get_device_info()
+
+ mock_device_info = {
+ "network_os_image": "bootflash:disk0/xrvr-os-mbi-6.0.0/mbixrvr-rp.vm",
+ "network_os_version": "6.0.0[Default]",
+ "network_os": "iosxr",
+ "network_os_hostname": "iosxr01",
+ "network_os_model": "IOS XRv",
+ }
+
+ self.assertEqual(device_info, mock_device_info)
+
+ def test_get_command_output_iosxr(self):
+ """Test _get_command_with_output for iosxr"""
+ self._prepare()
+ cmd = self._cliconf.get_command_output("show running-config hostname")
+
+ self.assertEqual(cmd, "hostname iosxr01")
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acl_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acl_interfaces.py
new file mode 100644
index 00000000..8500c073
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acl_interfaces.py
@@ -0,0 +1,329 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_acl_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrAclInterfacesModule(TestIosxrModule):
+ module = iosxr_acl_interfaces
+
+ def setUp(self):
+ super(TestIosxrAclInterfacesModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acl_interfaces.acl_interfaces.Acl_interfacesFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrAclInterfacesModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_acl_interfaces_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_acl_interfaces_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ access_groups=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(name="acl_1", direction="in"),
+ dict(name="acl_2", direction="out"),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ acls=[
+ dict(name="acl6_1", direction="in"),
+ dict(name="acl6_2", direction="out"),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ access_groups=[
+ dict(
+ afi="ipv4",
+ acls=[dict(name="acl_1", direction="out")],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_acl_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ access_groups=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(name="acl_1", direction="in"),
+ dict(name="acl_2", direction="out"),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ acls=[
+ dict(name="acl6_1", direction="in"),
+ dict(name="acl6_2", direction="out"),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ access_groups=[
+ dict(
+ afi="ipv4",
+ acls=[dict(name="acl_1", direction="in")],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "ipv4 access-group acl_1 ingress",
+ "ipv4 access-group acl_2 egress",
+ "ipv6 access-group acl6_1 ingress",
+ "ipv6 access-group acl6_2 egress",
+ "interface GigabitEthernet0/0/0/1",
+ "ipv4 access-group acl_1 ingress",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_acl_interfaces_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ access_groups=[
+ dict(
+ afi="ipv6",
+ acls=[dict(name="acl6_3", direction="in")],
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no ipv4 access-group acl_1 ingress",
+ "no ipv4 access-group acl_2 egress",
+ "no ipv6 access-group acl6_2 egress",
+ "ipv6 access-group acl6_3 ingress",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_acl_interfaces_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no ipv4 access-group acl_1 ingress",
+ "no ipv4 access-group acl_2 egress",
+ "no ipv6 access-group acl6_1 ingress",
+ "no ipv6 access-group acl6_2 egress",
+ "interface GigabitEthernet0/0/0/1",
+ "no ipv4 access-group acl_1 egress",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_acl_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ access_groups=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(name="acl_1", direction="in"),
+ dict(name="acl_2", direction="out"),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ acls=[
+ dict(name="acl6_1", direction="in"),
+ dict(name="acl6_2", direction="out"),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ access_groups=[
+ dict(
+ afi="ipv4",
+ acls=[dict(name="acl_1", direction="in")],
+ ),
+ ],
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "ipv4 access-group acl_1 ingress",
+ "ipv4 access-group acl_2 egress",
+ "ipv6 access-group acl6_1 ingress",
+ "ipv6 access-group acl6_2 egress",
+ "interface GigabitEthernet0/0/0/1",
+ "ipv4 access-group acl_1 ingress",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_acl_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="interface GigabitEthernet0/0/0/0\r\n shutdown\r\n ipv4 access-group acl_1 ingress\r\n"
+ " ipv4 access-group acl_2 egress\r\n ipv6 access-group acl6_1 ingress\r\n ipv6 "
+ "access-group acl6_2 egress\r\n!\r\ninterface GigabitEthernet0/0/0/1\r\n "
+ "shutdown\r\n ipv4 access-group acl_1 egress\r\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ print(result["parsed"])
+ parsed_list = [
+ {
+ "name": "GigabitEthernet0/0/0/0",
+ "access_groups": [
+ {
+ "afi": "ipv4",
+ "acls": [
+ {"name": "acl_1", "direction": "in"},
+ {"name": "acl_2", "direction": "out"},
+ ],
+ },
+ {
+ "afi": "ipv6",
+ "acls": [
+ {"name": "acl6_1", "direction": "in"},
+ {"name": "acl6_2", "direction": "out"},
+ ],
+ },
+ ],
+ },
+ {
+ "name": "GigabitEthernet0/0/0/1",
+ "access_groups": [
+ {
+ "afi": "ipv4",
+ "acls": [{"name": "acl_1", "direction": "out"}],
+ },
+ ],
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_acl_interfaces_overridden(self):
+ self.maxDiff = None
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ access_groups=[
+ dict(
+ afi="ipv6",
+ acls=[dict(name="acl6_3", direction="in")],
+ ),
+ ],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ access_groups=[
+ dict(
+ afi="ipv4",
+ acls=[dict(name="acl_2", direction="in")],
+ ),
+ dict(
+ afi="ipv6",
+ acls=[dict(name="acl6_3", direction="out")],
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no ipv4 access-group acl_1 ingress",
+ "no ipv4 access-group acl_2 egress",
+ "no ipv6 access-group acl6_2 egress",
+ "ipv6 access-group acl6_3 ingress",
+ "interface GigabitEthernet0/0/0/1",
+ "no ipv4 access-group acl_1 egress",
+ "ipv4 access-group acl_2 ingress",
+ "ipv6 access-group acl6_3 egress",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acls.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acls.py
new file mode 100644
index 00000000..ed826b93
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_acls.py
@@ -0,0 +1,496 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_acls
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrAclsModule(TestIosxrModule):
+ module = iosxr_acls
+
+ def setUp(self):
+ super(TestIosxrAclsModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acls.acls.AclsFacts.get_device_data",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrAclsModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_acls_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_acls_merged(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_1",
+ aces=[
+ dict(
+ sequence="30",
+ grant="permit",
+ protocol="ospf",
+ source=dict(prefix="192.168.1.0/24"),
+ destination=dict(any="true"),
+ log="true",
+ ),
+ dict(
+ sequence="40",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ net_group="netgroup1",
+ ),
+ ),
+ dict(
+ sequence="50",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ port_group="portgroup1",
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "ipv4 access-list acl_1",
+ "30 permit ospf 192.168.1.0 0.0.0.255 any log",
+ "40 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1",
+ "50 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_acls_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_2",
+ aces=[
+ dict(
+ sequence="10",
+ grant="deny",
+ protocol="ipv4",
+ destination=dict(any="true"),
+ source=dict(any="true"),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_acls_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_2",
+ aces=[
+ dict(
+ sequence="30",
+ grant="permit",
+ protocol="ospf",
+ source=dict(prefix="10.0.0.0/8"),
+ destination=dict(any="true"),
+ log="true",
+ ),
+ dict(
+ sequence="40",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ net_group="netgroup1",
+ ),
+ ),
+ dict(
+ sequence="50",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ port_group="portgroup1",
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "ipv4 access-list acl_2",
+ "no 10",
+ "no 20",
+ "30 permit ospf 10.0.0.0 0.255.255.255 any log",
+ "40 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1",
+ "50 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_acls_replaced_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_2",
+ aces=[
+ dict(
+ sequence="10",
+ grant="deny",
+ protocol="ipv4",
+ destination=dict(any="true"),
+ source=dict(any="true"),
+ ),
+ dict(
+ sequence="20",
+ grant="permit",
+ protocol="tcp",
+ destination=dict(any="true"),
+ source=dict(host="192.168.1.100"),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_acls_overridden(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_2",
+ aces=[
+ dict(
+ sequence="40",
+ grant="permit",
+ protocol="ospf",
+ source=dict(any="true"),
+ destination=dict(any="true"),
+ log="true",
+ ),
+ dict(
+ sequence="50",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ net_group="netgroup1",
+ ),
+ ),
+ dict(
+ sequence="60",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ port_group="portgroup1",
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "no ipv6 access-list acl6_1",
+ "no ipv4 access-list acl_1",
+ "ipv4 access-list acl_2",
+ "no 10",
+ "no 20",
+ "40 permit ospf any any log",
+ "50 deny ipv4 10.233.0.0 0.0.255.255 net-group netgroup1",
+ "60 deny ipv4 10.233.0.0 0.0.255.255 port-group portgroup1",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_acls_overridden_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_1",
+ aces=[
+ dict(
+ sequence="10",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ net_group="netgroup1",
+ ),
+ ),
+ dict(
+ sequence="20",
+ grant="deny",
+ protocol="ipv4",
+ source=dict(
+ address="10.233.0.0",
+ wildcard_bits="0.0.255.255",
+ ),
+ destination=dict(
+ port_group="portgroup1",
+ ),
+ ),
+ ],
+ ),
+ dict(
+ name="acl_2",
+ aces=[
+ dict(
+ sequence="10",
+ grant="deny",
+ protocol="ipv4",
+ destination=dict(any="true"),
+ source=dict(any="true"),
+ ),
+ dict(
+ sequence="20",
+ grant="permit",
+ protocol="tcp",
+ destination=dict(any="true"),
+ source=dict(host="192.168.1.100"),
+ ),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv6",
+ acls=[
+ dict(
+ name="acl6_1",
+ aces=[
+ dict(
+ sequence="10",
+ grant="deny",
+ protocol="icmpv6",
+ destination=dict(any="true"),
+ source=dict(any="true"),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_acls_deletedacls(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[dict(afi="ipv6", acls=[dict(name="acl6_1")])],
+ state="deleted",
+ ),
+ )
+ commands = ["no ipv6 access-list acl6_1"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_acls_deletedafis(self):
+ self._prepare()
+ set_module_args(dict(config=[dict(afi="ipv4")], state="deleted"))
+ commands = ["no ipv4 access-list acl_2", "no ipv4 access-list acl_1"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_acls_rendered(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_2",
+ aces=[
+ dict(
+ grant="permit",
+ source=dict(any="true"),
+ destination=dict(any="true"),
+ protocol="igmp",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+ commands = ["ipv4 access-list acl_2", "permit igmp any any"]
+ result = self.execute_module(changed=False)
+ self.assertEqual(
+ sorted(result["rendered"]),
+ sorted(commands),
+ result["rendered"],
+ )
+
+ def test_iosxr_acls_overridden_on_empty_config(self):
+ self.execute_show_command.return_value = ""
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ acls=[
+ dict(
+ name="acl_1",
+ aces=[
+ dict(
+ sequence="10",
+ grant="deny",
+ source=dict(any=True),
+ destination=dict(any=True),
+ protocol="ip",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ cmds = ["ipv4 access-list acl_1", "10 deny ip any any"]
+ self.execute_module(changed=True, commands=cmds)
+
+ def test_iosxr_acls_parsed_matches(self):
+ set_module_args(
+ dict(
+ running_config="""ipv4 access-list ACL_NAME\n5 permit ipv4 host x.x.x.x any (409 matches)""",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = [
+ {
+ "acls": [
+ {
+ "name": "ACL_NAME",
+ "aces": [
+ {
+ "sequence": 5,
+ "grant": "permit",
+ "protocol": "ipv4",
+ "source": {"host": "x.x.x.x"},
+ "destination": {"any": True},
+ },
+ ],
+ },
+ ],
+ "afi": "ipv4",
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_banner.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_banner.py
new file mode 100644
index 00000000..8c426f83
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_banner.py
@@ -0,0 +1,117 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_banner
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrBannerModule(TestIosxrModule):
+
+ module = iosxr_banner
+
+ def setUp(self):
+ super(TestIosxrBannerModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_banner.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_banner.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_is_cliconf = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_banner.is_cliconf",
+ )
+ self.is_cliconf = self.mock_is_cliconf.start()
+
+ def tearDown(self):
+ super(TestIosxrBannerModule, self).tearDown()
+
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_is_cliconf.stop()
+
+ def load_fixtures(self, commands=None):
+ self.get_config.return_value = load_fixture("iosxr_banner_config.cfg")
+ self.load_config.return_value = dict(diff=None, session="session")
+ self.is_cliconf.return_value = True
+
+ def test_iosxr_banner_login_create(self):
+ set_module_args(dict(banner="login", text="test\nbanner\nstring"))
+ commands = ["banner login test\nbanner\nstring"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_banner_login_remove(self):
+ set_module_args(dict(banner="login", state="absent"))
+ commands = ["no banner login"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_banner_fail_create(self):
+ set_module_args(dict(banner="exec1", text="test\nbanner\nstring"))
+ result = self.execute_module(failed=True, changed=True)
+ self.assertEqual(
+ result["msg"],
+ "value of banner must be one of: login, motd, got: exec1",
+ )
+
+ def test_iosxr_banner_exec1_fail_remove(self):
+ set_module_args(dict(banner="exec1", state="absent"))
+ result = self.execute_module(failed=True, changed=True)
+ self.assertIn(
+ result["msg"],
+ "value of banner must be one of: login, motd, got: exec1",
+ )
+
+ def test_iosxr_banner_motd_create(self):
+ set_module_args(dict(banner="motd", text="test\nbanner\nstring"))
+ commands = ["banner motd test\nbanner\nstring"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_banner_motd_remove(self):
+ set_module_args(dict(banner="motd", state="absent"))
+ commands = ["no banner motd"]
+ self.execute_module(changed=True, commands=commands)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_address_family.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_address_family.py
new file mode 100644
index 00000000..57770b59
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_address_family.py
@@ -0,0 +1,384 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_bgp_address_family
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrBgpGlobalModule(TestIosxrModule):
+ module = iosxr_bgp_address_family
+
+ def setUp(self):
+ super(TestIosxrBgpGlobalModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base.get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_address_family.bgp_address_family.Bgp_address_familyFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrBgpGlobalModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_bgp_address_family_merged_idempotent(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ address-family ipv4 unicast
+ bgp attribute-download
+ advertise best-external
+ dynamic-med interval 10
+ bgp scan-time 20
+ redistribute connected metric 10
+ redistribute isis test3 metric 4
+ redistribute application test1 metric 10
+ allocate-label all
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ dynamic_med=10,
+ redistribute=[
+ dict(
+ protocol="application",
+ id="test1",
+ metric=10,
+ ),
+ dict(protocol="connected", metric=10),
+ dict(protocol="isis", id="test3", metric=4),
+ ],
+ bgp=dict(scan_time=20, attribute_download=True),
+ advertise_best_external=True,
+ allocate_label=dict(all=True),
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_bgp_address_family_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ dynamic_med=10,
+ redistribute=[
+ dict(
+ protocol="application",
+ id="test1",
+ metric=10,
+ ),
+ dict(protocol="connected", metric=10),
+ dict(protocol="isis", id="test3", metric=4),
+ ],
+ bgp=dict(scan_time=20, attribute_download=True),
+ advertise_best_external=True,
+ allocate_label=dict(all=True),
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "router bgp 65536",
+ "address-family ipv4 unicast",
+ "advertise best-external",
+ "allocate-label all",
+ "bgp attribute-download",
+ "bgp scan-time 20",
+ "dynamic-med interval 10",
+ "redistribute application test1 metric 10",
+ "redistribute connected metric 10",
+ "redistribute isis test3 metric 4",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_address_family_replaced(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ address-family ipv4 unicast
+ bgp attribute-download
+ advertise best-external
+ dynamic-med interval 10
+ bgp scan-time 20
+ redistribute connected metric 10
+ redistribute isis test3 metric 4
+ redistribute application test1 metric 10
+ allocate-label all
+ address-family ipv4 mvpn
+ """,
+ )
+ self.get_config.return_value = run_cfg
+
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ dynamic_med=4,
+ redistribute=[
+ dict(
+ protocol="application",
+ id="test1",
+ metric=10,
+ ),
+ dict(protocol="connected", metric=10),
+ dict(protocol="isis", id="test3", metric=4),
+ ],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "router bgp 65536",
+ "address-family ipv4 unicast",
+ "no advertise best-external",
+ "no allocate-label all",
+ "no bgp attribute-download",
+ "no bgp scan-time 20",
+ "dynamic-med interval 4",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_address_family_replaced_idempotent(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ address-family ipv4 unicast
+ dynamic-med interval 4
+ redistribute connected metric 10
+ redistribute isis test3 metric 4
+ redistribute application test1 metric 10
+ address-family ipv4 mvpn
+ """,
+ )
+ self.get_config.return_value = run_cfg
+
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ dynamic_med=4,
+ redistribute=[
+ dict(
+ protocol="application",
+ id="test1",
+ metric=10,
+ ),
+ dict(protocol="connected", metric=10),
+ dict(protocol="isis", id="test3", metric=4),
+ ],
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_bgp_address_family_deleted(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ address-family ipv4 unicast
+ bgp attribute-download
+ advertise best-external
+ dynamic-med interval 10
+ bgp scan-time 20
+ redistribute connected metric 10
+ redistribute isis test3 metric 4
+ redistribute application test1 metric 10
+ allocate-label all
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=dict(), state="deleted"))
+
+ commands = ["router bgp 65536", "no address-family ipv4 unicast"]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_address_family_deleted1(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ address-family ipv6 unicast
+ dynamic-med interval 4
+ address-family ipv4 unicast
+ bgp attribute-download
+ advertise best-external
+ dynamic-med interval 10
+ bgp scan-time 20
+ redistribute connected metric 10
+ redistribute isis test3 metric 4
+ redistribute application test1 metric 10
+ allocate-label all
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number=65536,
+ address_family=[
+ dict(afi="ipv6", safi="unicast", dynamic_med=4),
+ ],
+ ),
+ state="deleted",
+ ),
+ )
+ commands = ["router bgp 65536", "no address-family ipv6 unicast"]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_address_family_deleted_idempotent(self):
+ run_cfg = dedent(
+ """\
+ "router bgp 65536"
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=dict(as_number="65536"), state="deleted"))
+
+ result = self.execute_module(changed=False)
+ self.assertEqual(result["commands"], [])
+
+ def test_iosxr_bgp_address_family_rendered(self):
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ dynamic_med=10,
+ redistribute=[
+ dict(
+ protocol="application",
+ id="test1",
+ metric=10,
+ ),
+ dict(protocol="connected", metric=10),
+ dict(protocol="isis", id="test3", metric=4),
+ ],
+ bgp=dict(scan_time=20, attribute_download=True),
+ advertise_best_external=True,
+ allocate_label=dict(all=True),
+ ),
+ ],
+ ),
+ state="rendered",
+ ),
+ )
+ commands = [
+ "router bgp 65536",
+ "address-family ipv4 unicast",
+ "advertise best-external",
+ "allocate-label all",
+ "bgp attribute-download",
+ "bgp scan-time 20",
+ "dynamic-med interval 10",
+ "redistribute application test1 metric 10",
+ "redistribute connected metric 10",
+ "redistribute isis test3 metric 4",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_bgp_address_family_parsed(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ address-family ipv4 unicast
+ bgp attribute-download
+ advertise best-external
+ dynamic-med interval 10
+ bgp scan-time 20
+ redistribute application test1 metric 10
+ allocate-label all
+ """,
+ )
+ set_module_args(dict(running_config=run_cfg, state="parsed"))
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "address_family": [
+ {
+ "advertise_best_external": True,
+ "safi": "unicast",
+ "afi": "ipv4",
+ "allocate_label": {"all": True},
+ "bgp": {"attribute_download": True, "scan_time": 20},
+ "dynamic_med": 10,
+ "redistribute": [
+ {
+ "protocol": "application",
+ "metric": 10,
+ "id": "test1",
+ },
+ ],
+ },
+ ],
+ "as_number": "65536",
+ }
+
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_global.py
new file mode 100644
index 00000000..05480d09
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_global.py
@@ -0,0 +1,493 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_bgp_global
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrBgpGlobalModule(TestIosxrModule):
+ module = iosxr_bgp_global
+
+ def setUp(self):
+ super(TestIosxrBgpGlobalModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_global.bgp_global."
+ "Bgp_globalFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrBgpGlobalModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_bgp_global_merged_idempotent(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ bgp confederation identifier 4
+ bgp router-id 192.0.2.10
+ bgp cluster-id 5
+ default-metric 4
+ socket send-buffer-size 4098
+ bgp bestpath med confed
+ socket receive-buffer-size 514
+ neighbor 192.0.2.11
+ remote-as 65537
+ cluster-id 3
+ neighbor 192.0.2.14
+ remote-as 65538
+ bfd fast-detect strict-mode
+ bfd multiplier 6
+ bfd minimum-interval 20
+ vrf vrf1
+ default-metric 5
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ default_metric=4,
+ socket=dict(
+ receive_buffer_size=514,
+ send_buffer_size=4098,
+ ),
+ bgp=dict(
+ confederation=dict(identifier=4),
+ bestpath=dict(med=dict(confed=True)),
+ cluster_id=5,
+ router_id="192.0.2.10",
+ ),
+ neighbors=[
+ dict(
+ neighbor="192.0.2.11",
+ cluster_id=3,
+ remote_as="65537",
+ ),
+ dict(
+ neighbor="192.0.2.14",
+ remote_as="65538",
+ bfd=dict(
+ multiplier=6,
+ minimum_interval=20,
+ fast_detect=dict(strict_mode=True),
+ ),
+ ),
+ ],
+ vrfs=[dict(vrf="vrf1", default_metric=5)],
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_bgp_global_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ default_metric=4,
+ socket=dict(
+ receive_buffer_size=514,
+ send_buffer_size=4098,
+ ),
+ bgp=dict(
+ confederation=dict(identifier=4),
+ bestpath=dict(med=dict(confed=True)),
+ cluster_id=5,
+ router_id="192.0.2.10",
+ ),
+ neighbors=[
+ dict(
+ neighbor="192.0.2.11",
+ cluster_id=3,
+ remote_as="65537",
+ ),
+ dict(
+ neighbor="192.0.2.14",
+ remote_as="65538",
+ bfd=dict(
+ multiplier=6,
+ minimum_interval=20,
+ fast_detect=dict(strict_mode=True),
+ ),
+ ),
+ ],
+ vrfs=[dict(vrf="vrf1", default_metric=5)],
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "router bgp 65536",
+ "bgp cluster-id 5",
+ "bgp router-id 192.0.2.10",
+ "bgp bestpath med confed",
+ "bgp confederation identifier 4",
+ "default-metric 4",
+ "socket receive-buffer-size 514",
+ "socket send-buffer-size 4098",
+ "neighbor 192.0.2.11",
+ "cluster-id 3",
+ "remote-as 65537",
+ "neighbor 192.0.2.14",
+ "bfd fast-detect strict-mode",
+ "bfd minimum-interval 20",
+ "bfd multiplier 6",
+ "remote-as 65538",
+ "vrf vrf1",
+ "default-metric 5",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_global_replaced(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ bgp confederation identifier 4
+ bgp router-id 192.0.2.10
+ bgp cluster-id 5
+ default-metric 4
+ socket send-buffer-size 4098
+ bgp bestpath med confed
+ socket receive-buffer-size 514
+ neighbor 192.0.2.11
+ remote-as 65537
+ cluster-id 3
+ neighbor 192.0.2.14
+ remote-as 65538
+ bfd fast-detect strict-mode
+ bfd multiplier 6
+ bfd minimum-interval 20
+ vrf vrf1
+ default-metric 5
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ default_metric=5,
+ socket=dict(
+ receive_buffer_size=514,
+ send_buffer_size=4098,
+ ),
+ bgp=dict(
+ confederation=dict(identifier=4),
+ bestpath=dict(med=dict(confed=True)),
+ cluster_id=5,
+ router_id="192.0.2.10",
+ ),
+ neighbors=[
+ dict(
+ neighbor="192.0.2.13",
+ remote_as="65538",
+ bfd=dict(
+ multiplier=6,
+ minimum_interval=20,
+ fast_detect=dict(strict_mode=True),
+ ),
+ ),
+ ],
+ vrfs=[dict(vrf="vrf1", default_metric=5)],
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "router bgp 65536",
+ "no neighbor 192.0.2.11",
+ "no neighbor 192.0.2.14",
+ "default-metric 5",
+ "neighbor 192.0.2.13",
+ "bfd fast-detect strict-mode",
+ "bfd minimum-interval 20",
+ "bfd multiplier 6",
+ "remote-as 65538",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_global_replaced_idempotent(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ bgp confederation identifier 4
+ bgp router-id 192.0.2.10
+ bgp cluster-id 5
+ default-metric 4
+ socket send-buffer-size 4098
+ bgp bestpath med confed
+ socket receive-buffer-size 514
+ neighbor 192.0.2.11
+ remote-as 65537
+ cluster-id 3
+ neighbor 192.0.2.14
+ remote-as 65538
+ bfd fast-detect strict-mode
+ bfd multiplier 6
+ bfd minimum-interval 20
+ vrf vrf1
+ default-metric 5
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ default_metric=4,
+ socket=dict(
+ receive_buffer_size=514,
+ send_buffer_size=4098,
+ ),
+ bgp=dict(
+ confederation=dict(identifier=4),
+ bestpath=dict(med=dict(confed=True)),
+ cluster_id=5,
+ router_id="192.0.2.10",
+ ),
+ neighbors=[
+ dict(
+ neighbor="192.0.2.11",
+ cluster_id=3,
+ remote_as="65537",
+ ),
+ dict(
+ neighbor="192.0.2.14",
+ remote_as="65538",
+ bfd=dict(
+ multiplier=6,
+ minimum_interval=20,
+ fast_detect=dict(strict_mode=True),
+ ),
+ ),
+ ],
+ vrfs=[dict(vrf="vrf1", default_metric=5)],
+ ),
+ state="replaced",
+ ),
+ )
+
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_bgp_global_deleted(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ bgp confederation identifier 4
+ bgp router-id 192.0.2.10
+ bgp cluster-id 5
+ default-metric 4
+ socket send-buffer-size 4098
+ bgp bestpath med confed
+ socket receive-buffer-size 514
+ neighbor 192.0.2.11
+ remote-as 65537
+ cluster-id 3
+ neighbor 192.0.2.14
+ remote-as 65538
+ bfd fast-detect strict-mode
+ bfd multiplier 6
+ bfd minimum-interval 20
+ vrf vrf1
+ default-metric 5
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=dict(as_number="65536"), state="deleted"))
+
+ commands = [
+ "router bgp 65536",
+ "no bgp cluster-id 5",
+ "no bgp router-id 192.0.2.10",
+ "no bgp bestpath med confed",
+ "no bgp confederation identifier 4",
+ "no default-metric 4",
+ "no socket receive-buffer-size 514",
+ "no socket send-buffer-size 4098",
+ "no neighbor 192.0.2.11",
+ "no neighbor 192.0.2.14",
+ "no vrf vrf1",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_global_deleted_idempotent(self):
+ run_cfg = dedent(
+ """\
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=dict(as_number="65536"), state="deleted"))
+
+ result = self.execute_module(changed=False)
+ self.assertEqual(result["commands"], [])
+
+ def test_iosxr_bgp_global_rendered(self):
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="65536",
+ default_metric=4,
+ socket=dict(
+ receive_buffer_size=514,
+ send_buffer_size=4098,
+ ),
+ bgp=dict(
+ confederation=dict(identifier=4),
+ bestpath=dict(med=dict(confed=True)),
+ cluster_id=5,
+ router_id="192.0.2.10",
+ ),
+ neighbors=[
+ dict(
+ neighbor="192.0.2.11",
+ cluster_id=3,
+ remote_as="65537",
+ ),
+ dict(
+ neighbor="192.0.2.14",
+ remote_as="65538",
+ bfd=dict(
+ multiplier=6,
+ minimum_interval=20,
+ fast_detect=dict(set=True),
+ ),
+ ),
+ ],
+ vrfs=[dict(vrf="vrf1", default_metric=5)],
+ ),
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "router bgp 65536",
+ "bgp cluster-id 5",
+ "bgp router-id 192.0.2.10",
+ "bgp bestpath med confed",
+ "bgp confederation identifier 4",
+ "default-metric 4",
+ "socket receive-buffer-size 514",
+ "socket send-buffer-size 4098",
+ "neighbor 192.0.2.11",
+ "cluster-id 3",
+ "remote-as 65537",
+ "neighbor 192.0.2.14",
+ "bfd fast-detect",
+ "bfd minimum-interval 20",
+ "bfd multiplier 6",
+ "remote-as 65538",
+ "vrf vrf1",
+ "default-metric 5",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_bgp_global_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="router bgp 65536\n bgp confederation identifier 4\n "
+ "bgp router-id 192.0.2.10\n bgp cluster-id 5\n default-metric 4\n "
+ "socket send-buffer-size 4098\n bgp bestpath med confed\n "
+ "socket receive-buffer-size 514\n neighbor 192.0.2.11\n remote-as 65537\n "
+ "cluster-id 3\n !\n neighbor 192.0.2.14\n remote-as 65538\n description test nbr description\n"
+ " bfd fast-detect strict-mode\n "
+ " bfd multiplier 6\n bfd minimum-interval 20\n !\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "as_number": "65536",
+ "bgp": {
+ "confederation": {"identifier": 4},
+ "cluster_id": "5",
+ "router_id": "192.0.2.10",
+ "bestpath": {"med": {"confed": True}},
+ },
+ "default_metric": 4,
+ "socket": {"send_buffer_size": 4098, "receive_buffer_size": 514},
+ "neighbors": [
+ {"neighbor_address": "192.0.2.11", "remote_as": 65537, "cluster_id": "3"},
+ {
+ "neighbor_address": "192.0.2.14",
+ "remote_as": 65538,
+ "description": "test nbr description",
+ },
+ ],
+ "bfd": {"multiplier": 6, "minimum_interval": 20},
+ }
+
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_bgp_global_purged(self):
+ run_cfg = dedent(
+ """\
+ router bgp 65536
+ bgp confederation identifier 4
+ bgp router-id 192.0.2.10
+ bgp cluster-id 5
+ default-metric 4
+ socket send-buffer-size 4098
+ bgp bestpath med confed
+ socket receive-buffer-size 514
+ neighbor 192.0.2.11
+ remote-as 65537
+ cluster-id 3
+ neighbor 192.0.2.14
+ remote-as 65538
+ bfd fast-detect strict-mode
+ bfd multiplier 6
+ bfd minimum-interval 20
+ vrf vrf1
+ default-metric 5
+ """,
+ )
+
+ self.get_config.return_value = run_cfg
+
+ set_module_args(dict(state="purged"))
+ commands = ["no router bgp 65536"]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(set(result["commands"]), set(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_neighbor_address_family.py
new file mode 100644
index 00000000..d6fd0610
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_bgp_neighbor_address_family.py
@@ -0,0 +1,826 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_bgp_neighbor_address_family
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrBgpNeighborAddressFamilyModule(TestIosxrModule):
+ module = iosxr_bgp_neighbor_address_family
+
+ def setUp(self):
+ super(TestIosxrBgpNeighborAddressFamilyModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_neighbor_address_family.bgp_neighbor_address_family."
+ "Bgp_neighbor_address_familyFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrBgpNeighborAddressFamilyModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_bgp_nbr_af_merged_idempotent(self):
+ run_cfg = dedent(
+ """\
+ router bgp 1
+ bgp router-id 1.2.3.4
+ neighbor 1.1.1.1
+ remote-as 5
+ address-family ipv4 unicast
+ origin-as validation disable
+ bestpath origin-as allow invalid
+ aigp
+ aigp send med
+ send-community-ebgp
+ multipath
+ allowas-in 4
+ maximum-prefix 10 20 restart 10
+ as-override
+ capability orf prefix both
+ send-extended-community-ebgp
+ default-originate
+ next-hop-self
+ send-community-gshut-ebgp
+ soft-reconfiguration inbound
+ send-multicast-attributes
+ remove-private-AS inbound entire-aspath
+ route-policy test1 in
+ route-policy test1 out
+ next-hop-unchanged multipath
+ vrf vrf1
+ rd auto
+ address-family ipv4 unicast
+ neighbor 1.2.1.2
+ remote-as 5
+ address-family ipv4 unicast
+ multipath
+ capability orf prefix both
+ default-originate
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="1",
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ neighbors=[
+ dict(
+ neighbor_address="1.2.1.2",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="1.1.1.1",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ send_multicast_attributes=dict(set=True),
+ soft_reconfiguration=dict(inbound=dict(set=True)),
+ send_community_gshut_ebgp=dict(set=True),
+ send_extended_community_ebgp=dict(set=True),
+ send_community_ebgp=dict(set=True),
+ origin_as=dict(validation=dict(disable=True)),
+ remove_private_AS=dict(
+ set=True,
+ inbound=True,
+ entire_aspath=True,
+ ),
+ route_policy=dict(inbound="test1", outbound="test1"),
+ maximum_prefix=dict(
+ max_limit=10,
+ threshold_value=20,
+ restart=10,
+ ),
+ next_hop_self=dict(set=True),
+ next_hop_unchanged=dict(multipath=True),
+ aigp=dict(set=True, send_med=dict(set=True)),
+ as_override=dict(set=True),
+ allowas_in=dict(value=4),
+ bestpath_origin_as_allow_invalid=True,
+ long_lived_graceful_restart=dict(
+ stale_time=dict(send=20, accept=30),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_bgp_nbr_af_merged(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="1",
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ neighbors=[
+ dict(
+ neighbor_address="1.2.1.2",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="1.1.1.1",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ send_multicast_attributes=dict(set=True),
+ soft_reconfiguration=dict(inbound=dict(set=True)),
+ send_community_gshut_ebgp=dict(set=True),
+ send_extended_community_ebgp=dict(set=True),
+ send_community_ebgp=dict(set=True),
+ origin_as=dict(validation=dict(disable=True)),
+ remove_private_AS=dict(
+ set=True,
+ inbound=True,
+ entire_aspath=True,
+ ),
+ route_policy=dict(inbound="test1", outbound="test1"),
+ maximum_prefix=dict(
+ max_limit=10,
+ threshold_value=20,
+ restart=10,
+ ),
+ next_hop_self=dict(set=True),
+ next_hop_unchanged=dict(multipath=True),
+ aigp=dict(set=True, send_med=dict(set=True)),
+ as_override=dict(set=True),
+ bestpath_origin_as_allow_invalid=True,
+ long_lived_graceful_restart=dict(
+ stale_time=dict(send=20, accept=30),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "router bgp 1",
+ "neighbor 1.1.1.1",
+ "address-family ipv4 unicast",
+ "aigp",
+ "aigp send med",
+ "as-override",
+ "bestpath origin-as allow invalid",
+ "capability orf prefix both",
+ "default-originate",
+ "maximum-prefix 10 20 restart 10",
+ "multipath",
+ "next-hop-self",
+ "next-hop-unchanged multipath",
+ "origin-as validation disable",
+ "remove-private-AS inbound entire-aspath",
+ "route-policy test1 in",
+ "route-policy test1 out",
+ "send-community-ebgp",
+ "send-community-gshut-ebgp",
+ "send-extended-community-ebgp",
+ "send-multicast-attributes",
+ "soft-reconfiguration inbound",
+ "vrf vrf1",
+ "neighbor 1.2.1.2",
+ "address-family ipv4 unicast",
+ "capability orf prefix both",
+ "default-originate",
+ "multipath",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_nbr_af_replaced(self):
+ run_cfg = dedent(
+ """\
+ router bgp 1
+ bgp router-id 1.2.3.4
+ neighbor 1.1.1.1
+ remote-as 5
+ address-family ipv4 unicast
+ origin-as validation disable
+ bestpath origin-as allow invalid
+ aigp
+ aigp send med
+ send-community-ebgp
+ multipath
+ allowas-in 4
+ maximum-prefix 10 20 restart 10
+ as-override
+ capability orf prefix both
+ send-extended-community-ebgp
+ default-originate
+ next-hop-self
+ send-community-gshut-ebgp
+ soft-reconfiguration inbound
+ send-multicast-attributes
+ remove-private-AS inbound entire-aspath
+ next-hop-unchanged multipath
+ vrf vrf1
+ rd auto
+ address-family ipv4 unicast
+ neighbor 1.2.1.2
+ remote-as 5
+ address-family ipv4 unicast
+ multipath
+ capability orf prefix both
+ default-originate
+ route-policy test2 in
+ route-policy test2 out
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="1",
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ neighbors=[
+ dict(
+ neighbor_address="1.2.1.2",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ route_policy=dict(inbound="test1", outbound="test1"),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "router bgp 1",
+ "vrf vrf1",
+ "neighbor 1.2.1.2",
+ "address-family ipv4 unicast",
+ "no capability orf prefix both",
+ "route-policy test1 in",
+ "route-policy test1 out",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_nbr_af_replaced_idempotent(self):
+ run_cfg = dedent(
+ """\
+ router bgp 1
+ bgp router-id 1.2.3.4
+ neighbor 1.1.1.1
+ remote-as 5
+ address-family ipv4 unicast
+ origin-as validation disable
+ bestpath origin-as allow invalid
+ aigp
+ aigp send med
+ send-community-ebgp
+ multipath
+ allowas-in 4
+ maximum-prefix 10 20 restart 10
+ as-override
+ capability orf prefix both
+ send-extended-community-ebgp
+ default-originate
+ next-hop-self
+ send-community-gshut-ebgp
+ soft-reconfiguration inbound
+ send-multicast-attributes
+ remove-private-AS inbound entire-aspath
+ next-hop-unchanged multipath
+ vrf vrf1
+ rd auto
+ address-family ipv4 unicast
+ neighbor 1.2.1.2
+ remote-as 5
+ address-family ipv4 unicast
+ multipath
+ capability orf prefix both
+ default-originate
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="1",
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ neighbors=[
+ dict(
+ neighbor_address="1.2.1.2",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_bgp_nbr_af_deleted(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ router bgp 1
+ bgp router-id 1.2.3.4
+ neighbor 1.1.1.1
+ remote-as 5
+ address-family ipv4 unicast
+ origin-as validation disable
+ bestpath origin-as allow invalid
+ aigp
+ aigp send med
+ send-community-ebgp
+ multipath
+ allowas-in 4
+ maximum-prefix 10 20 restart 10
+ as-override
+ capability orf prefix both
+ send-extended-community-ebgp
+ default-originate
+ next-hop-self
+ send-community-gshut-ebgp
+ soft-reconfiguration inbound
+ send-multicast-attributes
+ remove-private-AS inbound entire-aspath
+ next-hop-unchanged multipath
+ vrf vrf1
+ rd auto
+ address-family ipv4 unicast
+ neighbor 1.2.1.2
+ remote-as 5
+ address-family ipv4 unicast
+ multipath
+ capability orf prefix both
+ default-originate
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=dict(), state="deleted"))
+ commands = [
+ "router bgp 1",
+ "neighbor 1.1.1.1",
+ "no address-family ipv4 unicast",
+ "vrf vrf1",
+ "neighbor 1.2.1.2",
+ "no address-family ipv4 unicast",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_nbr_af_deleted_idempotent(self):
+ run_cfg = dedent(
+ """\
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=dict(as_number="1"), state="deleted"))
+
+ result = self.execute_module(changed=False)
+ self.assertEqual(result["commands"], [])
+
+ def test_iosxr_bgp_nbr_af_rendered(self):
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="1",
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ neighbors=[
+ dict(
+ neighbor_address="1.2.1.2",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ as_override=dict(set=True),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ neighbors=[
+ dict(
+ neighbor_address="1.1.1.1",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ send_multicast_attributes=dict(set=True),
+ soft_reconfiguration=dict(inbound=dict(set=True)),
+ send_community_gshut_ebgp=dict(set=True),
+ send_extended_community_ebgp=dict(set=True),
+ send_community_ebgp=dict(set=True),
+ origin_as=dict(validation=dict(disable=True)),
+ remove_private_AS=dict(
+ set=True,
+ inbound=True,
+ entire_aspath=True,
+ ),
+ maximum_prefix=dict(
+ max_limit=10,
+ threshold_value=20,
+ restart=10,
+ ),
+ next_hop_self=dict(set=True),
+ next_hop_unchanged=dict(multipath=True),
+ aigp=dict(set=True, send_med=dict(set=True)),
+ as_override=dict(set=True),
+ allowas_in=dict(value=4),
+ bestpath_origin_as_allow_invalid=True,
+ long_lived_graceful_restart=dict(
+ stale_time=dict(send=20, accept=30),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ state="rendered",
+ ),
+ )
+ commands = [
+ "router bgp 1",
+ "neighbor 1.1.1.1",
+ "address-family ipv4 unicast",
+ "aigp",
+ "aigp send med",
+ "allowas-in 4",
+ "as-override",
+ "bestpath origin-as allow invalid",
+ "capability orf prefix both",
+ "default-originate",
+ "maximum-prefix 10 20 restart 10",
+ "multipath",
+ "next-hop-self",
+ "next-hop-unchanged multipath",
+ "origin-as validation disable",
+ "remove-private-AS inbound entire-aspath",
+ "send-community-ebgp",
+ "send-community-gshut-ebgp",
+ "send-extended-community-ebgp",
+ "send-multicast-attributes",
+ "soft-reconfiguration inbound",
+ "vrf vrf1",
+ "neighbor 1.2.1.2",
+ "address-family ipv4 unicast",
+ "as-override",
+ "capability orf prefix both",
+ "default-originate",
+ "multipath",
+ ]
+
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_bgp_global_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="router bgp 1\n bgp router-id 1.2.1.3\n neighbor 1.1.1.1\n "
+ "remote-as 6\n address-family ipv4 unicast\n origin-as validation disable\n "
+ "bestpath origin-as allow invalid\n weight 0\n send-community-ebgp\n "
+ " multipath\n allowas-in 3\n maximum-prefix 1 1 discard-extra-paths\n"
+ " capability orf prefix both\n "
+ "send-extended-community-ebgp\n long-lived-graceful-restart capable\n"
+ " next-hop-self\n "
+ "remove-private-AS\n send-community-gshut-ebgp inheritance-disable\n "
+ " send-multicast-attributes\n "
+ "remove-private-AS inbound entire-aspath\n "
+ "next-hop-unchanged multipath\n !\n "
+ "!\n !",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "as_number": "1",
+ "neighbors": [
+ {
+ "address_family": [
+ {
+ "afi": "ipv4",
+ "allowas_in": {"value": 3},
+ "bestpath_origin_as_allow_invalid": True,
+ "capability_orf_prefix": "both",
+ "long_lived_graceful_restart": {"capable": True},
+ "multipath": True,
+ "next_hop_self": {"set": True},
+ "next_hop_unchanged": {"multipath": True},
+ "origin_as": {"validation": {"disable": True}},
+ "remove_private_AS": {
+ "entire_aspath": True,
+ "inbound": True,
+ "set": True,
+ },
+ "safi": "unicast",
+ "send_community_ebgp": {"set": True},
+ "send_community_gshut_ebgp": {"inheritance_disable": True},
+ "send_extended_community_ebgp": {"set": True},
+ "send_multicast_attributes": {"set": True},
+ "weight": 0,
+ },
+ ],
+ "neighbor_address": "1.1.1.1",
+ },
+ ],
+ }
+
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_bgp_add_fam_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="router bgp 1\n bgp router-id 1.2.1.3\n neighbor 1.1.1.1\n "
+ "remote-as 6\n address-family vpnv4 unicast\n origin-as validation disable\n "
+ "bestpath origin-as allow invalid\n weight 0\n send-community-ebgp\n "
+ " multipath\n allowas-in 3\n maximum-prefix 1 1 discard-extra-paths\n"
+ " capability orf prefix both\n "
+ "next-hop-unchanged multipath\n !\n "
+ "!\n !",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "as_number": "1",
+ "neighbors": [
+ {
+ "neighbor_address": "1.1.1.1",
+ "address_family": [
+ {
+ "afi": "vpnv4",
+ "safi": "unicast",
+ "origin_as": {"validation": {"disable": True}},
+ "bestpath_origin_as_allow_invalid": True,
+ "weight": 0,
+ "send_community_ebgp": {"set": True},
+ "multipath": True,
+ "allowas_in": {"value": 3},
+ "capability_orf_prefix": "both",
+ "next_hop_unchanged": {"multipath": True},
+ },
+ ],
+ },
+ ],
+ }
+
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_bgp_nbr_af_afi_replaced(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="1",
+ neighbors=[
+ dict(
+ neighbor_address="1.1.1.1",
+ address_family=[
+ dict(
+ afi="vpnv4",
+ safi="flowspec",
+ multipath=True,
+ default_originate=dict(set=True),
+ capability_orf_prefix="both",
+ send_multicast_attributes=dict(set=True),
+ soft_reconfiguration=dict(inbound=dict(set=True)),
+ send_community_gshut_ebgp=dict(set=True),
+ send_extended_community_ebgp=dict(set=True),
+ send_community_ebgp=dict(set=True),
+ origin_as=dict(validation=dict(disable=True)),
+ remove_private_AS=dict(
+ set=True,
+ inbound=True,
+ entire_aspath=True,
+ ),
+ route_policy=dict(inbound="test1", outbound="test1"),
+ maximum_prefix=dict(
+ max_limit=10,
+ threshold_value=20,
+ restart=10,
+ ),
+ next_hop_self=dict(set=True),
+ next_hop_unchanged=dict(multipath=True),
+ aigp=dict(set=True, send_med=dict(set=True)),
+ as_override=dict(set=True),
+ bestpath_origin_as_allow_invalid=True,
+ long_lived_graceful_restart=dict(
+ stale_time=dict(send=20, accept=30),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "address-family vpnv4 flowspec",
+ "aigp",
+ "aigp send med",
+ "as-override",
+ "bestpath origin-as allow invalid",
+ "capability orf prefix both",
+ "default-originate",
+ "maximum-prefix 10 20 restart 10",
+ "multipath",
+ "neighbor 1.1.1.1",
+ "next-hop-self",
+ "next-hop-unchanged multipath",
+ "origin-as validation disable",
+ "remove-private-AS inbound entire-aspath",
+ "route-policy test1 in",
+ "route-policy test1 out",
+ "router bgp 1",
+ "send-community-ebgp",
+ "send-community-gshut-ebgp",
+ "send-extended-community-ebgp",
+ "send-multicast-attributes",
+ "soft-reconfiguration inbound",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_bgp_nbr_af_overridden(self):
+ run_cfg = dedent(
+ """\
+ router bgp 1
+ bgp router-id 1.2.3.4
+ neighbor 1.1.1.1
+ remote-as 5
+ address-family ipv4 unicast
+ origin-as validation disable
+ bestpath origin-as allow invalid
+ aigp
+ aigp send med
+ send-community-ebgp
+ multipath
+ allowas-in 4
+ maximum-prefix 10 20 restart 10
+ as-override
+ capability orf prefix both
+ send-extended-community-ebgp
+ default-originate
+ next-hop-self
+ send-community-gshut-ebgp
+ soft-reconfiguration inbound
+ send-multicast-attributes
+ remove-private-AS inbound entire-aspath
+ next-hop-unchanged multipath
+ vrf vrf1
+ rd auto
+ address-family ipv4 unicast
+ neighbor 1.2.1.2
+ remote-as 5
+ address-family ipv4 unicast
+ multipath
+ capability orf prefix both
+ default-originate
+ route-policy test2 in
+ route-policy test2 out
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ as_number="1",
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ neighbors=[
+ dict(
+ neighbor_address="1.2.1.2",
+ address_family=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ multipath=True,
+ default_originate=dict(set=True),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ state="overridden",
+ ),
+ )
+ commands = [
+ "router bgp 1",
+ "vrf vrf1",
+ "neighbor 1.2.1.2",
+ "address-family ipv4 unicast",
+ "no capability orf prefix both",
+ "no route-policy test2 in",
+ "no route-policy test2 out",
+ "neighbor 1.1.1.1",
+ "no address-family ipv4 unicast",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_command.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_command.py
new file mode 100644
index 00000000..feb70876
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_command.py
@@ -0,0 +1,128 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_command
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrCommandModule(TestIosxrModule):
+
+ module = iosxr_command
+
+ def setUp(self):
+ super(TestIosxrCommandModule, self).setUp()
+
+ self.mock_run_commands = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_command.run_commands",
+ )
+ self.run_commands = self.mock_run_commands.start()
+
+ def tearDown(self):
+ super(TestIosxrCommandModule, self).tearDown()
+
+ self.mock_run_commands.stop()
+
+ def load_fixtures(self, commands=None):
+ def load_from_file(*args, **kwargs):
+ module, commands = args
+ output = list()
+
+ for item in commands:
+ try:
+ command = item["command"]
+ except Exception:
+ command = item
+ filename = str(command).replace(" ", "_")
+ output.append(load_fixture(filename))
+ return output
+
+ self.run_commands.side_effect = load_from_file
+
+ def test_iosxr_command_simple(self):
+ set_module_args(dict(commands=["show version"]))
+ result = self.execute_module()
+ self.assertEqual(len(result["stdout"]), 1)
+ self.assertTrue(
+ result["stdout"][0].startswith("Cisco IOS XR Software"),
+ )
+
+ def test_iosxr_command_multiple(self):
+ set_module_args(dict(commands=["show version", "show version"]))
+ result = self.execute_module()
+ self.assertEqual(len(result["stdout"]), 2)
+ self.assertTrue(
+ result["stdout"][0].startswith("Cisco IOS XR Software"),
+ )
+
+ def test_iosxr_command_wait_for(self):
+ wait_for = 'result[0] contains "Cisco IOS"'
+ set_module_args(dict(commands=["show version"], wait_for=wait_for))
+ self.execute_module()
+
+ def test_iosxr_command_wait_for_fails(self):
+ wait_for = 'result[0] contains "test string"'
+ set_module_args(dict(commands=["show version"], wait_for=wait_for))
+ self.execute_module(failed=True)
+ self.assertEqual(self.run_commands.call_count, 10)
+
+ def test_iosxr_command_retries(self):
+ wait_for = 'result[0] contains "test string"'
+ set_module_args(
+ dict(commands=["show version"], wait_for=wait_for, retries=2),
+ )
+ self.execute_module(failed=True)
+ self.assertEqual(self.run_commands.call_count, 2)
+
+ def test_iosxr_command_match_any(self):
+ wait_for = [
+ 'result[0] contains "Cisco IOS"',
+ 'result[0] contains "test string"',
+ ]
+ set_module_args(
+ dict(commands=["show version"], wait_for=wait_for, match="any"),
+ )
+ self.execute_module()
+
+ def test_iosxr_command_match_all(self):
+ wait_for = [
+ 'result[0] contains "Cisco IOS"',
+ 'result[0] contains "XR Software"',
+ ]
+ set_module_args(
+ dict(commands=["show version"], wait_for=wait_for, match="all"),
+ )
+ self.execute_module()
+
+ def test_iosxr_command_match_all_failure(self):
+ wait_for = [
+ 'result[0] contains "Cisco IOS"',
+ 'result[0] contains "test string"',
+ ]
+ commands = ["show version", "show version"]
+ set_module_args(
+ dict(commands=commands, wait_for=wait_for, match="all"),
+ )
+ self.execute_module(failed=True)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_config.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_config.py
new file mode 100644
index 00000000..bbfdcb3e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_config.py
@@ -0,0 +1,313 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.cliconf.iosxr import Cliconf
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_config
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import MagicMock, patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrConfigModule(TestIosxrModule):
+
+ module = iosxr_config
+
+ def setUp(self):
+ super(TestIosxrConfigModule, self).setUp()
+
+ self.patcher_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_config.get_config",
+ )
+ self.mock_get_config = self.patcher_get_config.start()
+
+ self.patcher_exec_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_config.load_config",
+ )
+ self.mock_exec_command = self.patcher_exec_command.start()
+
+ self.mock_get_connection = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_config.get_connection",
+ )
+ self.get_connection = self.mock_get_connection.start()
+
+ self.conn = self.get_connection()
+ self.conn.edit_config = MagicMock()
+
+ self.cliconf_obj = Cliconf(MagicMock())
+ self.running_config = load_fixture("iosxr_config_config.cfg")
+
+ def tearDown(self):
+ super(TestIosxrConfigModule, self).tearDown()
+
+ self.patcher_get_config.stop()
+ self.patcher_exec_command.stop()
+ self.mock_get_connection.stop()
+
+ def load_fixtures(self, commands=None):
+ config_file = "iosxr_config_config.cfg"
+ self.mock_get_config.return_value = load_fixture(config_file)
+ self.mock_exec_command.return_value = "dummy diff"
+
+ def test_iosxr_config_unchanged(self):
+ src = load_fixture("iosxr_config_config.cfg")
+ set_module_args(dict(src=src))
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(src, src),
+ )
+ self.execute_module()
+
+ def test_iosxr_config_src(self):
+ src = load_fixture("iosxr_config_src.cfg")
+ set_module_args(dict(src=src))
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(src, self.running_config),
+ )
+ commands = [
+ "hostname foo",
+ "interface GigabitEthernet0/0",
+ "no ip address",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_config_backup(self):
+ set_module_args(dict(backup=True))
+ result = self.execute_module()
+ self.assertIn("__backup__", result)
+
+ def test_iosxr_config_lines_wo_parents(self):
+ lines = ["hostname foo"]
+ set_module_args(dict(lines=lines))
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ "\n".join(lines),
+ self.running_config,
+ ),
+ )
+ commands = ["hostname foo"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_config_lines_w_parents(self):
+ lines = ["shutdown"]
+ parents = ["interface GigabitEthernet0/0"]
+ set_module_args(dict(lines=lines, parents=parents))
+ module = MagicMock()
+ module.params = {"lines": lines, "parents": parents, "src": None}
+ candidate_config = iosxr_config.get_candidate(module)
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ candidate_config,
+ self.running_config,
+ ),
+ )
+ commands = ["interface GigabitEthernet0/0", "shutdown"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_config_before(self):
+ lines = ["hostname foo"]
+ set_module_args(dict(lines=lines, before=["test1", "test2"]))
+ commands = ["test1", "test2", "hostname foo"]
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ "\n".join(lines),
+ self.running_config,
+ ),
+ )
+ self.execute_module(changed=True, commands=commands, sort=False)
+
+ def test_iosxr_config_after(self):
+ lines = ["hostname foo"]
+ set_module_args(dict(lines=lines, after=["test1", "test2"]))
+ commands = ["hostname foo", "test1", "test2"]
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ "\n".join(lines),
+ self.running_config,
+ ),
+ )
+ self.execute_module(changed=True, commands=commands, sort=False)
+
+ def test_iosxr_config_before_after_no_change(self):
+ lines = ["hostname router"]
+ set_module_args(
+ dict(
+ lines=lines,
+ before=["test1", "test2"],
+ after=["test3", "test4"],
+ ),
+ )
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ "\n".join(lines),
+ self.running_config,
+ ),
+ )
+ self.execute_module()
+
+ def test_iosxr_config_config(self):
+ config = "hostname localhost"
+ lines = ["hostname router"]
+ set_module_args(dict(lines=["hostname router"], config=config))
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff("\n".join(lines), config),
+ )
+ commands = ["hostname router"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_config_replace_block(self):
+ lines = ["description test string", "test string"]
+ parents = ["interface GigabitEthernet0/0"]
+ set_module_args(dict(lines=lines, replace="block", parents=parents))
+ commands = parents + lines
+
+ module = MagicMock()
+ module.params = {"lines": lines, "parents": parents, "src": None}
+ candidate_config = iosxr_config.get_candidate(module)
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ candidate_config,
+ self.running_config,
+ diff_replace="block",
+ path=parents,
+ ),
+ )
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_config_force(self):
+ lines = ["hostname router"]
+ set_module_args(dict(lines=lines, force=True))
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ "\n".join(lines),
+ self.running_config,
+ diff_match="none",
+ ),
+ )
+ self.execute_module(changed=True, commands=lines)
+
+ def test_iosxr_config_admin(self):
+ lines = ["username admin", "group root-system", "secret P@ssw0rd"]
+ set_module_args(dict(lines=lines, admin=True))
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ "\n".join(lines),
+ self.running_config,
+ ),
+ )
+ self.execute_module(changed=True, commands=lines)
+
+ def test_iosxr_config_match_none(self):
+ lines = ["ip address 1.2.3.4 255.255.255.0", "description test string"]
+ parents = ["interface GigabitEthernet0/0"]
+ set_module_args(dict(lines=lines, parents=parents, match="none"))
+ commands = parents + lines
+ module = MagicMock()
+ module.params = {"lines": lines, "parents": parents, "src": None}
+ candidate_config = iosxr_config.get_candidate(module)
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ candidate_config,
+ self.running_config,
+ diff_match="none",
+ path=parents,
+ ),
+ )
+
+ self.execute_module(changed=True, commands=commands, sort=False)
+
+ def test_iosxr_config_match_strict(self):
+ lines = [
+ "ip address 1.2.3.4 255.255.255.0",
+ "description test string",
+ "shutdown",
+ ]
+ parents = ["interface GigabitEthernet0/0"]
+ set_module_args(dict(lines=lines, parents=parents, match="strict"))
+ commands = parents + ["shutdown"]
+ module = MagicMock()
+ module.params = {"lines": lines, "parents": parents, "src": None}
+ candidate_config = iosxr_config.get_candidate(module)
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ candidate_config,
+ self.running_config,
+ diff_match="strict",
+ path=parents,
+ ),
+ )
+
+ self.execute_module(changed=True, commands=commands, sort=False)
+
+ def test_iosxr_config_match_exact(self):
+ lines = [
+ "ip address 1.2.3.4 255.255.255.0",
+ "description test string",
+ "shutdown",
+ ]
+ parents = ["interface GigabitEthernet0/0"]
+ set_module_args(dict(lines=lines, parents=parents, match="exact"))
+ commands = parents + lines
+ module = MagicMock()
+ module.params = {"lines": lines, "parents": parents, "src": None}
+ candidate_config = iosxr_config.get_candidate(module)
+ self.conn.get_diff = MagicMock(
+ return_value=self.cliconf_obj.get_diff(
+ candidate_config,
+ self.running_config,
+ diff_match="exact",
+ path=parents,
+ ),
+ )
+
+ self.execute_module(changed=True, commands=commands, sort=False)
+
+ def test_iosxr_config_src_and_lines_fails(self):
+ args = dict(src="foo", lines="foo")
+ set_module_args(args)
+ self.execute_module(failed=True)
+
+ def test_iosxr_config_src_and_parents_fails(self):
+ args = dict(src="foo", parents="foo")
+ set_module_args(args)
+ self.execute_module(failed=True)
+
+ def test_iosxr_config_match_exact_requires_lines(self):
+ args = dict(match="exact")
+ set_module_args(args)
+ self.execute_module(failed=True)
+
+ def test_iosxr_config_match_strict_requires_lines(self):
+ args = dict(match="strict")
+ set_module_args(args)
+ self.execute_module(failed=True)
+
+ def test_iosxr_config_replace_block_requires_lines(self):
+ args = dict(replace="block")
+ set_module_args(args)
+ self.execute_module(failed=True)
+
+ def test_iosxr_config_replace_config_requires_src(self):
+ args = dict(replace="config")
+ set_module_args(args)
+ self.execute_module(failed=True)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_facts.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_facts.py
new file mode 100644
index 00000000..7848f798
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_facts.py
@@ -0,0 +1,120 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import json
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_facts
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrFacts(TestIosxrModule):
+
+ module = iosxr_facts
+
+ def setUp(self):
+ super(TestIosxrFacts, self).setUp()
+
+ self.mock_run_commands = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.legacy.base.run_commands",
+ )
+ self.run_commands = self.mock_run_commands.start()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_capabilities = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.legacy.base.get_capabilities",
+ )
+ self.get_capabilities = self.mock_get_capabilities.start()
+ self.get_capabilities.return_value = {
+ "device_info": {
+ "network_os": "iosxr",
+ "network_os_hostname": "iosxr01",
+ "network_os_image": "bootflash:disk0/xrvr-os-mbi-6.1.3/mbixrvr-rp.vm",
+ "network_os_version": "6.1.3[Default]",
+ },
+ "network_api": "cliconf",
+ }
+
+ def tearDown(self):
+ super(TestIosxrFacts, self).tearDown()
+
+ self.mock_run_commands.stop()
+ self.mock_get_capabilities.stop()
+ self.mock_get_resource_connection.stop()
+
+ def load_fixtures(self, commands=None):
+ def load_from_file(*args, **kwargs):
+ module, commands = args
+ output = list()
+
+ for item in commands:
+ try:
+ obj = json.loads(item)
+ command = obj["command"]
+ except ValueError:
+ command = item
+ filename = str(command).replace(" ", "_")
+ filename = filename.replace("/", "7")
+ filename = filename.replace("|", "_")
+ output.append(load_fixture(filename))
+ return output
+
+ self.run_commands.side_effect = load_from_file
+
+ def test_iosxr_facts_gather_subset_default(self):
+ set_module_args(dict())
+ result = self.execute_module()
+ ansible_facts = result["ansible_facts"]
+ self.assertIn("default", ansible_facts["ansible_net_gather_subset"][0])
+ self.assertEqual(
+ [],
+ ansible_facts["ansible_net_gather_network_resources"],
+ )
+ self.assertEqual("iosxr", ansible_facts["ansible_net_system"])
+ self.assertEqual(
+ True,
+ True if ansible_facts.get("ansible_net_version") else False,
+ )
+ self.assertEqual(
+ True,
+ True if ansible_facts.get("ansible_net_python_version") else False,
+ )
+ self.assertEqual(
+ True,
+ True if ansible_facts.get("ansible_net_api") else False,
+ )
+
+ def test_iosxr_facts_gather_subset_config(self):
+ set_module_args({"gather_subset": "config"})
+ result = self.execute_module()
+ ansible_facts = result["ansible_facts"]
+ self.assertIn("default", ansible_facts["ansible_net_gather_subset"])
+ self.assertIn("config", ansible_facts["ansible_net_gather_subset"])
+ self.assertEqual("iosxr01", ansible_facts["ansible_net_hostname"])
+ self.assertIn("ansible_net_config", ansible_facts)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_interfaces.py
new file mode 100644
index 00000000..4b7a0bcd
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_interfaces.py
@@ -0,0 +1,288 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrInterfacesModule(TestIosxrModule):
+ module = iosxr_interfaces
+
+ def setUp(self):
+ super(TestIosxrInterfacesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.interfaces.interfaces.InterfacesFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrInterfacesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_interface_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_interfaces_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ description="Configured and Merged by Ansible-Network",
+ mtu=110,
+ enabled=True,
+ duplex="half",
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ description="Configured and Merged by Ansible-Network",
+ mtu=2800,
+ speed=100,
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ description="Configured and Merged by Ansible-Network",
+ mtu=110,
+ enabled=True,
+ duplex="half",
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ description="Configured and Merged by Ansible-Network",
+ mtu=2800,
+ enabled=False,
+ duplex="full",
+ speed=100,
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "description Configured and Merged by Ansible-Network",
+ "mtu 110",
+ "duplex half",
+ "no shutdown",
+ "interface GigabitEthernet0/0/0/1",
+ "description Configured and Merged by Ansible-Network",
+ "mtu 2800",
+ "speed 100",
+ "duplex full",
+ "shutdown",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_interfaces_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ description="Configured and Replaced by Ansible-Network",
+ mtu=110,
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ description="Configured and Replaced by Ansible-Network",
+ speed=100,
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "description Configured and Replaced by Ansible-Network",
+ "no duplex",
+ "interface GigabitEthernet0/0/0/1",
+ "description Configured and Replaced by Ansible-Network",
+ "no mtu",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_interfaces_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no description",
+ "no mtu",
+ "no duplex",
+ "interface GigabitEthernet0/0/0/1",
+ "no description",
+ "no speed",
+ "no mtu",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ description="Configured and Merged by Ansible-Network",
+ mtu=110,
+ enabled=True,
+ duplex="half",
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ description="Configured and Merged by Ansible-Network",
+ mtu=2800,
+ enabled=False,
+ duplex="full",
+ speed=100,
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "description Configured and Merged by Ansible-Network",
+ "mtu 110",
+ "duplex half",
+ "no shutdown",
+ "interface GigabitEthernet0/0/0/1",
+ "description Configured and Merged by Ansible-Network",
+ "mtu 2800",
+ "speed 100",
+ "duplex full",
+ "shutdown",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="interface GigabitEthernet0/0/0/0\n description Configured and Merged by Ansible-Network\n "
+ "mtu 110\n duplex half\ninterface GigabitEthernet0/0/0/1\n "
+ "description Configured and Merged by Ansible-Network\n no shutdown\n mtu 2800\n speed 100",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = [
+ {
+ "description": "Configured and Merged by Ansible-Network",
+ "duplex": "half",
+ "enabled": True,
+ "mtu": 110,
+ "name": "GigabitEthernet0/0/0/0",
+ },
+ {
+ "description": "Configured and Merged by Ansible-Network",
+ "enabled": True,
+ "mtu": 2800,
+ "name": "GigabitEthernet0/0/0/1",
+ "speed": 100,
+ },
+ ]
+
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_interfaces_overridden(self):
+ self.maxDiff = None
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ description="Configured and Overridden by Ansible-Network",
+ mtu=2000,
+ enabled=False,
+ duplex="full",
+ speed=100,
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no description",
+ "no mtu",
+ "no duplex",
+ "interface GigabitEthernet0/0/0/1",
+ "description Configured and Overridden by Ansible-Network",
+ "mtu 2000",
+ "duplex full",
+ "shutdown",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l2_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l2_interfaces.py
new file mode 100644
index 00000000..10053878
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l2_interfaces.py
@@ -0,0 +1,246 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_l2_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrL2InterfacesModule(TestIosxrModule):
+ module = iosxr_l2_interfaces
+
+ def setUp(self):
+ super(TestIosxrL2InterfacesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+ self.mock_get_os_version = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.l2_interfaces.l2_interfaces.get_os_version",
+ )
+ self.get_os_version = self.mock_get_os_version.start()
+ self.get_os_version.return_value = "7.0.2"
+ self.mock_get_os_version1 = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l2_interfaces.l2_interfaces.get_os_version",
+ )
+ self.get_os_version1 = self.mock_get_os_version1.start()
+ self.get_os_version1.return_value = "7.0.2"
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l2_interfaces.l2_interfaces.L2_InterfacesFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrL2InterfacesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_get_os_version.stop()
+ self.get_os_version1.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_l2_interface_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_l2_interfaces_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ l2transport=True,
+ l2protocol=[dict(cpsv="tunnel")],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/3.900",
+ encapsulation=dict(dot1q=20, second_dot1q=40),
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_l2_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ l2transport=True,
+ l2protocol=[dict(cpsv="tunnel")],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/3.900",
+ encapsulation=dict(dot1q=20, second_dot1q=40),
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/1",
+ "l2transport l2protocol cpsv tunnel",
+ "interface GigabitEthernet0/0/0/3.900",
+ "encapsulation dot1q 20 second-dot1q 40",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_l2_interfaces_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ l2transport=True,
+ l2protocol=[dict(cpsv="drop")],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/1",
+ "l2transport l2protocol cpsv drop",
+ "no l2transport",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_l2_interfaces_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "interface GigabitEthernet0/0/0/1",
+ "no l2transport",
+ "interface GigabitEthernet0/0/0/3.900",
+ "no encapsulation dot1q",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_l2_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ l2transport=True,
+ l2protocol=[dict(cpsv="tunnel")],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/3.900",
+ encapsulation=dict(dot1q=20, second_dot1q=40),
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "interface GigabitEthernet0/0/0/1",
+ "l2transport l2protocol cpsv tunnel",
+ "interface GigabitEthernet0/0/0/3.900",
+ "encapsulation dot1q 20 second-dot1q 40",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_l2_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="interface GigabitEthernet0/0/0/1\n l2transport\n l2protocol cpsv tunnel\n "
+ "propagate remote-status\n !",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ print(result["parsed"])
+ parsed_list = [
+ {
+ "name": "GigabitEthernet0/0/0/1",
+ "l2transport": True,
+ "l2protocol": [{"cpsv": "tunnel"}],
+ "propagate": True,
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_l2_interfaces_overridden(self):
+ self.maxDiff = None
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/4",
+ l2transport=True,
+ l2protocol=[dict(cpsv="tunnel")],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/3.900",
+ encapsulation=dict(dot1q=40, second_dot1q=60),
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/4",
+ "l2transport l2protocol cpsv tunnel",
+ "interface GigabitEthernet0/0/0/3.900",
+ "encapsulation dot1q 40 second-dot1q 60",
+ "interface GigabitEthernet0/0/0/1",
+ "no l2transport",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l3_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l3_interfaces.py
new file mode 100644
index 00000000..5fab9f7e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_l3_interfaces.py
@@ -0,0 +1,255 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_l3_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrL3InterfacesModule(TestIosxrModule):
+ module = iosxr_l3_interfaces
+
+ def setUp(self):
+ super(TestIosxrL3InterfacesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l3_interfaces.l3_interfaces.L3_InterfacesFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrL3InterfacesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_l3_interface_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_l3_interfaces_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ ipv4=[dict(address="198.51.100.1/24")],
+ ipv6=[dict(address="2001:db8::/32")],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ ipv4=[
+ dict(address="192.0.2.1/24"),
+ dict(address="192.0.2.2/24", secondary=True),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_l3_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ ipv4=[dict(address="198.51.100.1/24")],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ ipv4=[
+ dict(address="192.0.2.1/24"),
+ dict(address="192.0.2.2/24", secondary=True),
+ ],
+ ipv6=[dict(address="2001:db8:0:3::/64")],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "ipv4 address 198.51.100.1 255.255.255.0",
+ "interface GigabitEthernet0/0/0/1",
+ "ipv4 address 192.0.2.2 255.255.255.0 secondary",
+ "ipv4 address 192.0.2.1 255.255.255.0",
+ "ipv6 address 2001:db8:0:3::/64",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_l3_interfaces_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ ipv4=[
+ dict(address="203.0.113.27/24"),
+ dict(address="203.0.114.1/24", secondary=True),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no ipv6 address",
+ "ipv4 address 203.0.113.27 255.255.255.0",
+ "ipv4 address 203.0.114.1 255.255.255.0 secondary",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_l3_interfaces_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no ipv4 address",
+ "no ipv6 address",
+ "interface GigabitEthernet0/0/0/1",
+ "no ipv4 address",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_l3_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ ipv4=[dict(address="198.51.100.1/24")],
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ ipv4=[
+ dict(address="192.0.2.1/24"),
+ dict(address="192.0.2.2/24", secondary=True),
+ ],
+ ipv6=[dict(address="2001:db8:0:3::/64")],
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "ipv4 address 198.51.100.1 255.255.255.0",
+ "interface GigabitEthernet0/0/0/1",
+ "ipv4 address 192.0.2.2 255.255.255.0 secondary",
+ "ipv4 address 192.0.2.1 255.255.255.0",
+ "ipv6 address 2001:db8:0:3::/64",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_l3_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="interface GigabitEthernet0/0/0/0\nipv4 address 198.51.100.1 255.255.255.0\n"
+ "ipv6 address 2001:db8::/32\ninterface GigabitEthernet0/0/0/1\nipv4 address"
+ " 192.0.2.1 255.255.255.0\nipv4 address 192.0.2.2 255.255.255.0 secondary\n",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ print(result["parsed"])
+ parsed_list = [
+ {
+ "name": "GigabitEthernet0/0/0/0",
+ "ipv4": [{"address": "198.51.100.1 255.255.255.0"}],
+ "ipv6": [{"address": "2001:db8::/32"}],
+ },
+ {
+ "name": "GigabitEthernet0/0/0/1",
+ "ipv4": [
+ {"address": "192.0.2.1 255.255.255.0"},
+ {"address": "192.0.2.2 255.255.255.0", "secondary": True},
+ ],
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_l3_interfaces_overridden(self):
+ self.maxDiff = None
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ ipv4=[dict(address="198.51.102.1/24")],
+ ipv6=[dict(address="2001:db8:1::/64")],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no ipv4 address",
+ "no ipv6 address",
+ "interface GigabitEthernet0/0/0/1",
+ "no ipv4 address",
+ "ipv4 address 198.51.102.1 255.255.255.0",
+ "ipv6 address 2001:db8:1::/64",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp.py
new file mode 100644
index 00000000..e4c9c467
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp.py
@@ -0,0 +1,93 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lacp
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrLacpModule(TestIosxrModule):
+ module = iosxr_lacp
+
+ def setUp(self):
+ super(TestIosxrLacpModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp.lacp.LacpFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrLacpModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_lacp_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_lacp_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ system=dict(
+ priority=12,
+ mac=dict(address="00c1.4c00.bd15"),
+ ),
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "lacp system mac 00c1.4c00.bd15",
+ "lacp system priority 12",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp_interfaces.py
new file mode 100644
index 00000000..55358a06
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lacp_interfaces.py
@@ -0,0 +1,263 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lacp_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrLacpInterfacesModule(TestIosxrModule):
+ module = iosxr_lacp_interfaces
+
+ def setUp(self):
+ super(TestIosxrLacpInterfacesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp_interfaces.lacp_interfaces.Lacp_interfacesFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrLacpInterfacesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_lacp_interfaces_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_lacp_interfaces_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether10",
+ churn_logging="actor",
+ collector_max_delay=100,
+ switchover_suppress_flaps=500,
+ ),
+ dict(
+ name="Bundle-Ether11",
+ system=dict(mac="00c2.4c00.bd15"),
+ ),
+ dict(name="GigabitEthernet0/0/0/1", period=200),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_lacp_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether10",
+ churn_logging="actor",
+ collector_max_delay=100,
+ switchover_suppress_flaps=500,
+ ),
+ dict(
+ name="Bundle-Ether11",
+ system=dict(mac="00c2.4c00.bd15"),
+ ),
+ dict(name="GigabitEthernet0/0/0/1", period=100),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "interface Bundle-Ether10",
+ "lacp churn logging actor",
+ "lacp switchover suppress-flaps 500",
+ "lacp collector-max-delay 100",
+ "interface Bundle-Ether11",
+ "lacp system mac 00c2.4c00.bd15",
+ "interface GigabitEthernet0/0/0/1",
+ "lacp period 100",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lacp_interfaces_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(name="Bundle-Ether10", churn_logging="partner"),
+ dict(name="GigabitEthernet0/0/0/1", period=300),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "interface Bundle-Ether10",
+ "no lacp switchover suppress-flaps 500",
+ "no lacp collector-max-delay 100",
+ "lacp churn logging partner",
+ "interface GigabitEthernet0/0/0/1",
+ "lacp period 300",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lacp_interfaces_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "interface Bundle-Ether10",
+ "no lacp switchover suppress-flaps 500",
+ "no lacp collector-max-delay 100",
+ "no lacp churn logging actor",
+ "interface Bundle-Ether11",
+ "no lacp system mac 00c2.4c00.bd15",
+ "interface GigabitEthernet0/0/0/1",
+ "no lacp period 200",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lag_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether10",
+ churn_logging="actor",
+ collector_max_delay=100,
+ switchover_suppress_flaps=500,
+ ),
+ dict(
+ name="Bundle-Ether11",
+ system=dict(mac="00c2.4c00.bd15"),
+ ),
+ dict(name="GigabitEthernet0/0/0/1", period=100),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "interface Bundle-Ether10",
+ "lacp churn logging actor",
+ "lacp switchover suppress-flaps 500",
+ "lacp collector-max-delay 100",
+ "interface Bundle-Ether11",
+ "lacp system mac 00c2.4c00.bd15",
+ "interface GigabitEthernet0/0/0/1",
+ "lacp period 100",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_lacp_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="interface Bundle-Ether10\r\n lacp churn logging actor\r\n lacp"
+ " switchover suppress-flaps 500\r\n "
+ "lacp collector-max-delay 100\r\n!\r\ninterface "
+ "Bundle-Ether11\r\n lacp system mac 00c2.4c00.bd15\r"
+ "\n!\r\ninterface MgmtEth0/RP0/CPU0/0\r\n ipv4 address"
+ " 192.0.2.11 255.255.255.0\r\n!\r\ninterface "
+ "GigabitEthernet0/0/0/1\r\n lacp period 200\r\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ print(result["parsed"])
+ parsed_list = [
+ {
+ "churn_logging": "actor",
+ "collector_max_delay": 100,
+ "name": "Bundle-Ether10",
+ "switchover_suppress_flaps": 500,
+ },
+ {"name": "Bundle-Ether11", "system": {"mac": "00c2.4c00.bd15"}},
+ {"name": "GigabitEthernet0/0/0/1", "period": 200},
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_lag_interfaces_overridden(self):
+ self.maxDiff = None
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether12",
+ churn_logging="both",
+ collector_max_delay=100,
+ switchover_suppress_flaps=500,
+ ),
+ dict(name="GigabitEthernet0/0/0/1", period=300),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "interface Bundle-Ether10",
+ "no lacp switchover suppress-flaps 500",
+ "no lacp collector-max-delay 100",
+ "no lacp churn logging actor",
+ "interface Bundle-Ether11",
+ "no lacp system mac 00c2.4c00.bd15",
+ "interface Bundle-Ether12",
+ "lacp churn logging both",
+ "lacp collector-max-delay 100",
+ "lacp switchover suppress-flaps 500",
+ "interface GigabitEthernet0/0/0/1",
+ "lacp period 300",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lag_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lag_interfaces.py
new file mode 100644
index 00000000..b0d68fc6
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lag_interfaces.py
@@ -0,0 +1,375 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lag_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrLagInterfacesModule(TestIosxrModule):
+ module = iosxr_lag_interfaces
+
+ def setUp(self):
+ super(TestIosxrLagInterfacesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lag_interfaces.lag_interfaces.Lag_interfacesFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrLagInterfacesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_lag_interface_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_lag_interfaces_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether10",
+ mode="active",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/0",
+ mode="inherit",
+ ),
+ dict(
+ member="GigabitEthernet0/0/0/1",
+ mode="passive",
+ ),
+ ],
+ links=dict(max_active=10, min_active=2),
+ ),
+ dict(
+ name="Bundle-Ether11",
+ mode="active",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/8",
+ mode="passive",
+ ),
+ dict(
+ member="GigabitEthernet0/0/0/9",
+ mode="passive",
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_lag_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether10",
+ mode="active",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/0",
+ mode="inherit",
+ ),
+ dict(
+ member="GigabitEthernet0/0/0/1",
+ mode="passive",
+ ),
+ ],
+ links=dict(max_active=10, min_active=2),
+ ),
+ dict(
+ name="Bundle-Ether11",
+ mode="active",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/8",
+ mode="passive",
+ ),
+ dict(
+ member="GigabitEthernet0/0/0/9",
+ mode="passive",
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "interface Bundle-Ether10",
+ "bundle minimum-active links 2",
+ "bundle maximum-active links 10",
+ "lacp mode active",
+ "interface GigabitEthernet0/0/0/1",
+ "bundle id 10 mode passive",
+ "interface GigabitEthernet0/0/0/0",
+ "bundle id 10 mode inherit",
+ "interface Bundle-Ether11",
+ "lacp mode active",
+ "interface GigabitEthernet0/0/0/8",
+ "bundle id 11 mode passive",
+ "interface GigabitEthernet0/0/0/9",
+ "bundle id 11 mode passive",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lag_interfaces_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether10",
+ mode="passive",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/0",
+ mode="passive",
+ ),
+ ],
+ ),
+ dict(name="Bundle-Ether12", mode="active"),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "interface Bundle-Ether10",
+ "no bundle maximum-active links 10",
+ "no bundle minimum-active links 2",
+ "lacp mode passive",
+ "interface GigabitEthernet0/0/0/1",
+ "no bundle id",
+ "interface GigabitEthernet0/0/0/0",
+ "bundle id 10 mode passive",
+ "interface Bundle-Ether12",
+ "lacp mode active",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lag_interfaces_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "interface Bundle-Ether10",
+ "no bundle maximum-active links 10",
+ "no bundle minimum-active links 2",
+ "no lacp mode active",
+ "interface GigabitEthernet0/0/0/0",
+ "no bundle id",
+ "interface GigabitEthernet0/0/0/1",
+ "no bundle id",
+ "interface Bundle-Ether11",
+ "no lacp mode active",
+ "interface GigabitEthernet0/0/0/8",
+ "no bundle id",
+ "interface GigabitEthernet0/0/0/9",
+ "no bundle id",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lag_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether10",
+ mode="active",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/0",
+ mode="passive",
+ ),
+ dict(
+ member="GigabitEthernet0/0/0/1",
+ mode="passive",
+ ),
+ ],
+ links=dict(max_active=10, min_active=2),
+ ),
+ dict(
+ name="Bundle-Ether11",
+ mode="active",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/8",
+ mode="passive",
+ ),
+ dict(
+ member="GigabitEthernet0/0/0/9",
+ mode="passive",
+ ),
+ ],
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "interface Bundle-Ether10",
+ "bundle minimum-active links 2",
+ "bundle maximum-active links 10",
+ "lacp mode active",
+ "interface GigabitEthernet0/0/0/1",
+ "bundle id 10 mode passive",
+ "interface GigabitEthernet0/0/0/0",
+ "bundle id 10 mode passive",
+ "interface Bundle-Ether11",
+ "lacp mode active",
+ "interface GigabitEthernet0/0/0/8",
+ "bundle id 11 mode passive",
+ "interface GigabitEthernet0/0/0/9",
+ "bundle id 11 mode passive",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_lag_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="interface Bundle-Ether10\r\n lacp mode active\r\n bundle maximum-active "
+ "links 10\r\n bundle minimum-active links 2\r\n!\r\ninterface Bundle-Ether11"
+ "\r\nlacp mode active\r\n!\r\ninterface GigabitEthernet0/0/0/0\r\n description "
+ '"GigabitEthernet - 0"\r\n bundle id 10 mode inherit\r\n!\r\ninterface '
+ "GigabitEthernet0/0/0/1"
+ '\r\n description "GigabitEthernet - 2"\r\n bundle id 10 mode passive\r\n!\r\n'
+ 'interface GigabitEthernet0/0/0/8\r\n description "GigabitEthernet - 8"'
+ "\r\n bundle id 11 mode passive"
+ "\r\n!\r\ninterface GigabitEthernet0/0/0/9\r\n description "
+ '"GigabitEthernet - 9"\r\n bundle id 11 mode passive\r\n!',
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ print(result["parsed"])
+ parsed_list = [
+ {
+ "links": {"max_active": 10, "min_active": 2},
+ "members": [
+ {"member": "GigabitEthernet0/0/0/0", "mode": "inherit"},
+ {"member": "GigabitEthernet0/0/0/1", "mode": "passive"},
+ ],
+ "mode": "active",
+ "name": "Bundle-Ether10",
+ },
+ {
+ "members": [
+ {"member": "GigabitEthernet0/0/0/8", "mode": "passive"},
+ {"member": "GigabitEthernet0/0/0/9", "mode": "passive"},
+ ],
+ "mode": "active",
+ "name": "Bundle-Ether11",
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_lag_interfaces_overridden(self):
+ self.maxDiff = None
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="Bundle-Ether11",
+ mode="active",
+ members=[
+ dict(
+ member="GigabitEthernet0/0/0/0",
+ mode="active",
+ ),
+ dict(
+ member="GigabitEthernet0/0/0/1",
+ mode="active",
+ ),
+ ],
+ links=dict(max_active=10, min_active=5),
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "interface Bundle-Ether10",
+ "no bundle maximum-active links 10",
+ "no bundle minimum-active links 2",
+ "no lacp mode active",
+ "interface GigabitEthernet0/0/0/0",
+ "no bundle id",
+ "interface GigabitEthernet0/0/0/1",
+ "no bundle id",
+ "interface Bundle-Ether11",
+ "bundle minimum-active links 5",
+ "bundle maximum-active links 10",
+ "interface GigabitEthernet0/0/0/8",
+ "no bundle id",
+ "interface GigabitEthernet0/0/0/9",
+ "no bundle id",
+ "interface GigabitEthernet0/0/0/0",
+ "bundle id 11 mode active",
+ "interface GigabitEthernet0/0/0/1",
+ "bundle id 11 mode active",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_global.py
new file mode 100644
index 00000000..65f749ec
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_global.py
@@ -0,0 +1,206 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lldp_global
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrLldpModule(TestIosxrModule):
+ module = iosxr_lldp_global
+
+ def setUp(self):
+ super(TestIosxrLldpModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_global.lldp_global.Lldp_globalFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrLldpModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_lldp_global_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_lldp_global_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=dict(
+ holdtime=100,
+ reinit=2,
+ timer=3000,
+ subinterfaces=True,
+ tlv_select=dict(
+ management_address=False,
+ system_description=False,
+ ),
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_lldp_global_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ holdtime=100,
+ reinit=2,
+ timer=3000,
+ subinterfaces=True,
+ tlv_select=dict(
+ management_address=False,
+ system_description=False,
+ ),
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "lldp reinit 2",
+ "lldp holdtime 100",
+ "lldp timer 3000",
+ "lldp subinterfaces enable",
+ "lldp tlv-select system-description disable",
+ "lldp tlv-select management-address disable",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lldp_global_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=dict(
+ holdtime=100,
+ tlv_select=dict(
+ management_address=False,
+ system_description=False,
+ port_description=False,
+ ),
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "no lldp reinit 2",
+ "no lldp subinterfaces enable",
+ "no lldp timer 3000",
+ "lldp tlv-select port-description disable",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lldp_global_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "no lldp holdtime 100",
+ "no lldp reinit 2",
+ "no lldp subinterfaces enable",
+ "no lldp timer 3000",
+ "no lldp tlv-select management-address disable",
+ "no lldp tlv-select system-description disable",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lldp_global_rendered(self):
+ set_module_args(
+ dict(
+ config=dict(
+ holdtime=100,
+ reinit=2,
+ timer=3000,
+ subinterfaces=True,
+ tlv_select=dict(
+ management_address=False,
+ system_description=False,
+ ),
+ ),
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "lldp reinit 2",
+ "lldp holdtime 100",
+ "lldp timer 3000",
+ "lldp subinterfaces enable",
+ "lldp tlv-select system-description disable",
+ "lldp tlv-select management-address disable",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_lag_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="lldp reinit 2\nlldp holdtime 100\nlldp timer 3000\nlldp subinterfaces\
+ enable\nlldp tlv-select system-description disable\nlldp tlv-select management-address\
+ disable\n",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "holdtime": 100,
+ "reinit": 2,
+ "timer": 3000,
+ "tlv_select": {"system_description": False},
+ }
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_interfaces.py
new file mode 100644
index 00000000..78b6d79f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_lldp_interfaces.py
@@ -0,0 +1,206 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_lldp_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrLldpInterfacesModule(TestIosxrModule):
+ module = iosxr_lldp_interfaces
+
+ def setUp(self):
+ super(TestIosxrLldpInterfacesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_interfaces.lldp_interfaces.Lldp_interfacesFacts.get_config",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrLldpInterfacesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def _prepare(self):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_lldp_interfaces_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_lldp_interfaces_merged_idempotent(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[
+ dict(name="GigabitEthernet0/0/0/0", transmit=False),
+ dict(name="GigabitEthernet0/0/0/1", receive=False),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_lldp_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(name="GigabitEthernet0/0/0/0", transmit=False),
+ dict(name="GigabitEthernet0/0/0/1", receive=False),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "lldp transmit disable",
+ "interface GigabitEthernet0/0/0/1",
+ "lldp receive disable",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lldp_interfaces_replaced(self):
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[dict(name="GigabitEthernet0/0/0/1", transmit=False)],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/1",
+ "no lldp receive disable",
+ "no lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+ "lldp transmit disable",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lldp_interfaces_deleted(self):
+ self._prepare()
+ set_module_args(dict(state="deleted"))
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "no lldp transmit disable",
+ "no lldp destination mac-address ieee-nearest-bridge",
+ "interface GigabitEthernet0/0/0/1",
+ "no lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+ "no lldp receive disable",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_lldp_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(name="GigabitEthernet0/0/0/0", transmit=False),
+ dict(name="GigabitEthernet0/0/0/1", receive=False),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "interface GigabitEthernet0/0/0/0",
+ "lldp transmit disable",
+ "interface GigabitEthernet0/0/0/1",
+ "lldp receive disable",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_lldp_interfaces_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="interface TenGigE0/0/0/0\r\n ipv4 address 192.0.2.11 255.255.255.192\r\n!\r\ninterface preconfigure "
+ "GigabitEthernet0/0/0/0\r\n lldp\r\n transmit disable\r\n destination mac-address\r\n "
+ "ieee-nearest-bridge\r\n !\r\n !\r\n!\r\ninterface preconfigure GigabitEthernet0/0/0/1\r\n lldp\r\n "
+ "receive disable\r\n destination mac-address\r\n ieee-nearest-non-tmpr-bridge\r\n",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ print(result["parsed"])
+ parsed_list = [
+ {"name": "TenGigE0/0/0/0"},
+ {
+ "destination": {"mac_address": "ieee-nearest-bridge"},
+ "name": "GigabitEthernet0/0/0/0",
+ "transmit": False,
+ },
+ {
+ "destination": {"mac_address": "ieee-nearest-non-tmpr-bridge"},
+ "name": "GigabitEthernet0/0/0/1",
+ "receive": False,
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_lldp_interfaces_overridden(self):
+ self.maxDiff = None
+ self._prepare()
+ set_module_args(
+ dict(
+ config=[dict(name="GigabitEthernet0/0/0/0", transmit=False)],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "interface GigabitEthernet0/0/0/1",
+ "no lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+ "no lldp receive disable",
+ "interface GigabitEthernet0/0/0/0",
+ "no lldp destination mac-address ieee-nearest-bridge",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_logging_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_logging_global.py
new file mode 100644
index 00000000..bffee2b1
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_logging_global.py
@@ -0,0 +1,1263 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_logging_global
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrLoggingGlobalModule(TestIosxrModule):
+ module = iosxr_logging_global
+
+ def setUp(self):
+ super(TestIosxrLoggingGlobalModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.logging_global.logging_global."
+ "Logging_globalFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrLoggingGlobalModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_logging_global_merged_idempotent(self):
+ run_cfg = dedent(
+ """\
+ logging tls-server test
+ vrf test
+ trustpoint test2
+ tls-hostname test2
+ !
+ logging file test path test maxfilesize 1024 severity info
+ logging file test2 path test1 maxfilesize 1024 severity debugging
+ logging ipv4 dscp af11
+ logging ipv6 precedence routine
+ logging trap informational
+ logging events filter
+ match test
+ match test1
+ !
+ logging events threshold 10
+ logging events buffer-size 1024
+ logging events display-location
+ logging events level warnings
+ logging format rfc5424
+ logging archive
+ device disk0
+ severity alerts
+ file-size 1
+ frequency daily
+ archive-size 1
+ archive-length 1
+ !
+ logging console warning
+ logging console discriminator
+ match1 test
+ nomatch1 test3
+ !
+ logging history size 10
+ logging monitor errors
+ logging monitor discriminator
+ match1 test1
+ !
+ logging buffered 2097152
+ logging buffered warnings
+ logging buffered discriminator
+ match2 test
+ !
+ logging 1.1.1.1 vrf default severity critical port default
+ logging correlator rule test type stateful
+ reissue-nonbistate
+ timeout 5
+ reparent
+ context-correlation
+ !
+ logging correlator rule test1 type nonstateful
+ timeout 6
+ context-correlation
+ !
+ logging correlator ruleset test
+ rulename test
+ rulename test1
+ !
+ logging correlator buffer-size 1024
+ logging localfilesize 1024
+ logging source-interface GigabitEthernet0/0/0/0 vrf test
+ logging hostnameprefix test
+ logging suppress duplicates
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ archive=dict(
+ archive_length=1,
+ archive_size=1,
+ device="disk0",
+ file_size=1,
+ frequency="daily",
+ severity="alerts",
+ ),
+ buffered=dict(
+ size=2097152,
+ severity="warnings",
+ discriminator=[
+ dict(match_params="match2", name="test"),
+ ],
+ ),
+ console=dict(
+ severity="warning",
+ discriminator=[
+ dict(match_params="match1", name="test"),
+ dict(match_params="nomatch1", name="test3"),
+ ],
+ ),
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[
+ dict(name="test", rulename=["test1", "test"]),
+ ],
+ rules=[
+ dict(
+ rule_name="test",
+ rule_type="stateful",
+ timeout=5,
+ context_correlation=True,
+ reissue_nonbistate=True,
+ reparent=True,
+ ),
+ dict(
+ rule_name="test1",
+ rule_type="nonstateful",
+ timeout=6,
+ context_correlation=True,
+ ),
+ ],
+ ),
+ events=dict(
+ severity="warnings",
+ display_location=True,
+ buffer_size=1024,
+ filter_match=["test1", "test"],
+ threshold=10,
+ ),
+ format=True,
+ files=[
+ dict(
+ maxfilesize=1024,
+ name="test",
+ path="test",
+ severity="info",
+ ),
+ dict(
+ maxfilesize=1024,
+ name="test2",
+ path="test1",
+ severity="debugging",
+ ),
+ ],
+ history=dict(size=10),
+ hostnameprefix="test",
+ hosts=[
+ dict(
+ host="1.1.1.1",
+ port="default",
+ severity="critical",
+ vrf="default",
+ ),
+ ],
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ localfilesize=1024,
+ monitor=dict(
+ severity="errors",
+ discriminator=[
+ dict(match_params="match1", name="test1"),
+ ],
+ ),
+ source_interfaces=[
+ dict(interface="GigabitEthernet0/0/0/0", vrf="test"),
+ ],
+ suppress=dict(duplicates=True),
+ tls_servers=[
+ dict(
+ name="test",
+ tls_hostname="test2",
+ trustpoint="test2",
+ vrf="test",
+ ),
+ ],
+ trap=dict(severity="informational"),
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_logging_global_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ archive=dict(
+ archive_length=1,
+ archive_size=1,
+ device="disk0",
+ file_size=1,
+ frequency="daily",
+ severity="alerts",
+ ),
+ buffered=dict(
+ size=2097152,
+ severity="warnings",
+ discriminator=[
+ dict(match_params="match2", name="test"),
+ ],
+ ),
+ console=dict(
+ severity="warning",
+ discriminator=[
+ dict(match_params="match1", name="test"),
+ dict(match_params="nomatch1", name="test3"),
+ ],
+ ),
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[
+ dict(name="test", rulename=["test1", "test"]),
+ ],
+ rules=[
+ dict(
+ rule_name="test",
+ rule_type="stateful",
+ timeout=5,
+ context_correlation=True,
+ reissue_nonbistate=True,
+ reparent=True,
+ ),
+ dict(
+ rule_name="test1",
+ rule_type="nonstateful",
+ timeout=6,
+ context_correlation=True,
+ ),
+ ],
+ ),
+ events=dict(
+ severity="warnings",
+ display_location=True,
+ buffer_size=1024,
+ filter_match=["test1", "test"],
+ threshold=10,
+ ),
+ format=True,
+ files=[
+ dict(
+ maxfilesize=1024,
+ name="test",
+ path="test",
+ severity="info",
+ ),
+ dict(
+ maxfilesize=1024,
+ name="test2",
+ path="test1",
+ severity="debugging",
+ ),
+ ],
+ history=dict(state="disabled", size=10),
+ hostnameprefix="test",
+ hosts=[
+ dict(
+ host="1.1.1.1",
+ port="default",
+ severity="critical",
+ vrf="default",
+ ),
+ ],
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ localfilesize=1024,
+ monitor=dict(
+ severity="errors",
+ discriminator=[
+ dict(match_params="match1", name="test1"),
+ ],
+ ),
+ source_interfaces=[
+ dict(interface="GigabitEthernet0/0/0/0", vrf="test"),
+ ],
+ suppress=dict(duplicates=True),
+ tls_servers=[
+ dict(
+ name="test",
+ tls_hostname="test2",
+ trustpoint="test2",
+ vrf="test",
+ ),
+ ],
+ trap=dict(severity="informational"),
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "logging archive device disk0",
+ "logging archive frequency daily",
+ "logging archive severity alerts",
+ "logging archive archive-size 1",
+ "logging archive archive-length 1",
+ "logging archive file-size 1",
+ "logging buffered 2097152",
+ "logging buffered warnings",
+ "logging console warning",
+ "logging correlator buffer-size 1024",
+ "logging events threshold 10",
+ "logging events buffer-size 1024",
+ "logging events display-location",
+ "logging events level warnings",
+ "logging hostnameprefix test",
+ "logging format rfc5424",
+ "logging ipv4 dscp af11",
+ "logging ipv6 precedence routine",
+ "logging localfilesize 1024",
+ "logging suppress duplicates",
+ "logging monitor errors",
+ "logging history size 10",
+ "logging history disable",
+ "logging trap informational",
+ "logging 1.1.1.1 vrf default severity critical port default",
+ "logging file test path test maxfilesize 1024 severity info",
+ "logging file test2 path test1 maxfilesize 1024 severity debugging",
+ "logging source-interface GigabitEthernet0/0/0/0 vrf test",
+ "logging tls-server test tls-hostname test2",
+ "logging tls-server test trustpoint test2",
+ "logging tls-server test vrf test",
+ "logging correlator ruleset test rulename test1",
+ "logging correlator ruleset test rulename test",
+ "logging correlator rule test type stateful timeout 5",
+ "logging correlator rule test type stateful reissue-nonbistate",
+ "logging correlator rule test type stateful reparent",
+ "logging correlator rule test type stateful context-correlation",
+ "logging correlator rule test1 type nonstateful timeout 6",
+ "logging correlator rule test1 type nonstateful context-correlation",
+ "logging events filter match test1",
+ "logging events filter match test",
+ "logging buffered discriminator match2 test",
+ "logging monitor discriminator match1 test1",
+ "logging console discriminator match1 test",
+ "logging console discriminator nomatch1 test3",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_logging_global_deleted(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ logging tls-server test
+ vrf test
+ trustpoint test2
+ tls-hostname test2
+ !
+ logging file test path test maxfilesize 1024 severity info
+ logging file test2 path test1 maxfilesize 1024 severity debugging
+ logging ipv4 dscp af11
+ logging ipv6 precedence routine
+ logging trap informational
+ logging events filter
+ match test
+ match test1
+ !
+ logging events threshold 10
+ logging events buffer-size 1024
+ logging events display-location
+ logging events level warnings
+ logging format rfc5424
+ logging archive
+ device disk0
+ severity alerts
+ file-size 1
+ frequency daily
+ archive-size 1
+ archive-length 1
+ !
+ logging console warning
+ logging console discriminator
+ match1 test
+ nomatch1 test3
+ !
+ logging history size 10
+ logging history disable
+ logging monitor errors
+ logging monitor discriminator
+ match1 test1
+ !
+ logging buffered 2097152
+ logging buffered warnings
+ logging buffered discriminator
+ match2 test
+ !
+ logging 1.1.1.1 vrf default severity critical port default
+ logging correlator rule test type stateful
+ reissue-nonbistate
+ timeout 5
+ reparent
+ context-correlation
+ !
+ logging correlator rule test1 type nonstateful
+ timeout 6
+ context-correlation
+ !
+ logging correlator ruleset test
+ rulename test
+ rulename test1
+ !
+ logging correlator buffer-size 1024
+ logging localfilesize 1024
+ logging source-interface GigabitEthernet0/0/0/0 vrf test
+ logging hostnameprefix test
+ logging suppress duplicates
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(state="deleted"))
+ commands = [
+ "no logging archive device disk0",
+ "no logging archive frequency daily",
+ "no logging archive severity alerts",
+ "no logging archive archive-size 1",
+ "no logging archive archive-length 1",
+ "no logging archive file-size 1",
+ "no logging buffered 2097152",
+ "no logging buffered warnings",
+ "no logging console warning",
+ "no logging correlator buffer-size 1024",
+ "no logging events threshold 10",
+ "no logging events buffer-size 1024",
+ "no logging events display-location",
+ "no logging events level warnings",
+ "no logging hostnameprefix test",
+ "no logging format rfc5424",
+ "no logging ipv4 dscp af11",
+ "no logging ipv6 precedence routine",
+ "no logging localfilesize 1024",
+ "no logging suppress duplicates",
+ "no logging monitor errors",
+ "no logging history size 10",
+ "no logging history disable",
+ "no logging trap informational",
+ "no logging 1.1.1.1 vrf default severity critical port default",
+ "no logging file test path test maxfilesize 1024 severity info",
+ "no logging file test2 path test1 maxfilesize 1024 severity debugging",
+ "no logging source-interface GigabitEthernet0/0/0/0 vrf test",
+ "no logging tls-server test",
+ "no logging correlator ruleset test rulename test",
+ "no logging correlator ruleset test rulename test1",
+ "no logging correlator rule test type stateful timeout 5",
+ "no logging correlator rule test type stateful reissue-nonbistate",
+ "no logging correlator rule test type stateful reparent",
+ "no logging correlator rule test type stateful context-correlation",
+ "no logging correlator rule test1 type nonstateful timeout 6",
+ "no logging correlator rule test1 type nonstateful context-correlation",
+ "no logging events filter match test",
+ "no logging events filter match test1",
+ "no logging buffered discriminator match2 test",
+ "no logging monitor discriminator match1 test1",
+ "no logging console discriminator match1 test",
+ "no logging console discriminator nomatch1 test3",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_logging_global_replaced(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ logging tls-server test
+ vrf test
+ trustpoint test2
+ tls-hostname test2
+ !
+ logging file test path test maxfilesize 1024 severity info
+ logging file test2 path test1 maxfilesize 1024 severity debugging
+ logging ipv4 dscp af11
+ logging ipv6 precedence routine
+ logging trap informational
+ logging events filter
+ match test
+ match test1
+ !
+ logging events threshold 10
+ logging events buffer-size 1024
+ logging events display-location
+ logging events level warnings
+ logging format rfc5424
+ logging archive
+ device disk0
+ severity alerts
+ file-size 1
+ frequency daily
+ archive-size 1
+ archive-length 1
+ !
+ logging console warning
+ logging console discriminator
+ match1 test
+ nomatch1 test3
+ !
+ logging history size 10
+ logging history disable
+ logging monitor errors
+ logging monitor discriminator
+ match1 test1
+ !
+ logging buffered 2097152
+ logging buffered warnings
+ logging buffered discriminator
+ match2 test
+ !
+ logging 1.1.1.1 vrf default severity critical port default
+ logging correlator rule test type stateful
+ reissue-nonbistate
+ timeout 5
+ reparent
+ context-correlation
+ !
+ logging correlator rule test1 type nonstateful
+ timeout 6
+ context-correlation
+ !
+ logging correlator ruleset test
+ rulename test
+ rulename test1
+ !
+ logging correlator buffer-size 1024
+ logging localfilesize 1024
+ logging source-interface GigabitEthernet0/0/0/0 vrf test
+ logging hostnameprefix test
+ logging suppress duplicates
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ archive=dict(
+ archive_length=1,
+ archive_size=1,
+ device="disk0",
+ file_size=1,
+ severity="alerts",
+ ),
+ buffered=dict(size=2097152, severity="warnings"),
+ console=dict(
+ severity="warning",
+ discriminator=[
+ dict(match_params="match1", name="test1"),
+ ],
+ ),
+ correlator=dict(
+ buffer_size=1024,
+ rules=[
+ dict(
+ rule_name="test",
+ rule_type="stateful",
+ timeout=6,
+ context_correlation=True,
+ reissue_nonbistate=True,
+ reparent=True,
+ ),
+ ],
+ ),
+ events=dict(
+ severity="warnings",
+ display_location=True,
+ buffer_size=1024,
+ filter_match=["test1"],
+ threshold=12,
+ ),
+ format=True,
+ files=[
+ dict(
+ maxfilesize=1024,
+ name="test",
+ path="test1",
+ severity="info",
+ ),
+ ],
+ history=dict(state="disabled", size=10),
+ hostnameprefix="test",
+ hosts=[
+ dict(
+ host="1.1.1.2",
+ port="default",
+ severity="critical",
+ vrf="default",
+ ),
+ ],
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ localfilesize=1024,
+ source_interfaces=[
+ dict(interface="GigabitEthernet0/0/0/0", vrf="test"),
+ ],
+ tls_servers=[
+ dict(
+ name="test",
+ tls_hostname="test2",
+ trustpoint="test3",
+ vrf="test",
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "logging console discriminator match1 test1",
+ "logging correlator rule test type stateful timeout 6",
+ "logging events threshold 12",
+ "logging 1.1.1.2 vrf default severity critical port default",
+ "logging file test path test1 maxfilesize 1024 severity info",
+ "logging tls-server test trustpoint test3",
+ "no logging 1.1.1.1 vrf default severity critical port default",
+ "no logging archive frequency daily",
+ "no logging buffered discriminator match2 test",
+ "no logging console discriminator match1 test",
+ "no logging console discriminator nomatch1 test3",
+ "no logging correlator rule test1 type nonstateful context-correlation",
+ "no logging correlator rule test1 type nonstateful timeout 6",
+ "no logging correlator ruleset test rulename test",
+ "no logging correlator ruleset test rulename test1",
+ "no logging events filter match test",
+ "no logging file test2 path test1 maxfilesize 1024 severity debugging",
+ "no logging monitor discriminator match1 test1",
+ "no logging monitor errors",
+ "no logging suppress duplicates",
+ "no logging trap informational",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_logging_global_rendered(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ config=dict(
+ archive=dict(
+ archive_length=1,
+ archive_size=1,
+ device="disk0",
+ file_size=1,
+ frequency="daily",
+ severity="alerts",
+ ),
+ buffered=dict(
+ size=2097152,
+ severity="warnings",
+ discriminator=[
+ dict(match_params="match2", name="test"),
+ ],
+ ),
+ console=dict(
+ severity="warning",
+ discriminator=[
+ dict(match_params="match1", name="test"),
+ dict(match_params="nomatch1", name="test3"),
+ ],
+ ),
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[
+ dict(name="test", rulename=["test1", "test"]),
+ ],
+ rules=[
+ dict(
+ rule_name="test",
+ rule_type="stateful",
+ timeout=5,
+ context_correlation=True,
+ reissue_nonbistate=True,
+ reparent=True,
+ ),
+ dict(
+ rule_name="test1",
+ rule_type="nonstateful",
+ timeout=6,
+ context_correlation=True,
+ ),
+ ],
+ ),
+ events=dict(
+ severity="warnings",
+ display_location=True,
+ buffer_size=1024,
+ filter_match=["test1", "test"],
+ threshold=10,
+ ),
+ format=True,
+ files=[
+ dict(
+ maxfilesize=1024,
+ name="test",
+ path="test",
+ severity="info",
+ ),
+ dict(
+ maxfilesize=1024,
+ name="test2",
+ path="test1",
+ severity="debugging",
+ ),
+ ],
+ history=dict(state="disabled", size=10),
+ hostnameprefix="test",
+ hosts=[
+ dict(
+ host="1.1.1.1",
+ port="default",
+ severity="critical",
+ vrf="default",
+ ),
+ ],
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ localfilesize=1024,
+ monitor=dict(
+ severity="errors",
+ discriminator=[
+ dict(match_params="match1", name="test1"),
+ ],
+ ),
+ source_interfaces=[
+ dict(interface="GigabitEthernet0/0/0/0", vrf="test"),
+ ],
+ suppress=dict(duplicates=True),
+ tls_servers=[
+ dict(
+ name="test",
+ tls_hostname="test2",
+ trustpoint="test2",
+ vrf="test",
+ ),
+ ],
+ trap=dict(severity="informational"),
+ ),
+ state="rendered",
+ ),
+ )
+ commands = [
+ "logging archive device disk0",
+ "logging archive frequency daily",
+ "logging archive severity alerts",
+ "logging archive archive-size 1",
+ "logging archive archive-length 1",
+ "logging archive file-size 1",
+ "logging buffered 2097152",
+ "logging buffered warnings",
+ "logging console warning",
+ "logging correlator buffer-size 1024",
+ "logging events threshold 10",
+ "logging events buffer-size 1024",
+ "logging events display-location",
+ "logging events level warnings",
+ "logging hostnameprefix test",
+ "logging format rfc5424",
+ "logging ipv4 dscp af11",
+ "logging ipv6 precedence routine",
+ "logging localfilesize 1024",
+ "logging suppress duplicates",
+ "logging monitor errors",
+ "logging history size 10",
+ "logging history disable",
+ "logging trap informational",
+ "logging 1.1.1.1 vrf default severity critical port default",
+ "logging file test path test maxfilesize 1024 severity info",
+ "logging file test2 path test1 maxfilesize 1024 severity debugging",
+ "logging source-interface GigabitEthernet0/0/0/0 vrf test",
+ "logging tls-server test tls-hostname test2",
+ "logging tls-server test trustpoint test2",
+ "logging tls-server test vrf test",
+ "logging correlator ruleset test rulename test1",
+ "logging correlator ruleset test rulename test",
+ "logging correlator rule test type stateful timeout 5",
+ "logging correlator rule test type stateful reissue-nonbistate",
+ "logging correlator rule test type stateful reparent",
+ "logging correlator rule test type stateful context-correlation",
+ "logging correlator rule test1 type nonstateful timeout 6",
+ "logging correlator rule test1 type nonstateful context-correlation",
+ "logging events filter match test1",
+ "logging events filter match test",
+ "logging buffered discriminator match2 test",
+ "logging monitor discriminator match1 test1",
+ "logging console discriminator match1 test",
+ "logging console discriminator nomatch1 test3",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_logging_global_overridden(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ logging tls-server test
+ vrf test
+ trustpoint test2
+ tls-hostname test2
+ !
+ logging file test path test maxfilesize 1024 severity info
+ logging file test2 path test1 maxfilesize 1024 severity debugging
+ logging ipv4 dscp af11
+ logging ipv6 precedence routine
+ logging trap informational
+ logging events filter
+ match test
+ match test1
+ !
+ logging events threshold 10
+ logging events buffer-size 1024
+ logging events display-location
+ logging events level warnings
+ logging format rfc5424
+ logging archive
+ device disk0
+ severity alerts
+ file-size 1
+ frequency daily
+ archive-size 1
+ archive-length 1
+ !
+ logging console warning
+ logging console discriminator
+ match1 test
+ nomatch1 test3
+ !
+ logging history size 10
+ logging history disable
+ logging monitor errors
+ logging monitor discriminator
+ match1 test1
+ !
+ logging buffered 2097152
+ logging buffered warnings
+ logging buffered discriminator
+ match2 test
+ !
+ logging 1.1.1.1 vrf default severity critical port default
+ logging correlator rule test type stateful
+ reissue-nonbistate
+ timeout 5
+ reparent
+ context-correlation
+ !
+ logging correlator rule test1 type nonstateful
+ timeout 6
+ context-correlation
+ !
+ logging correlator ruleset test
+ rulename test
+ rulename test1
+ !
+ logging correlator buffer-size 1024
+ logging localfilesize 1024
+ logging source-interface GigabitEthernet0/0/0/0 vrf test
+ logging hostnameprefix test
+ logging suppress duplicates
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ archive=dict(
+ archive_length=1,
+ archive_size=1,
+ device="disk0",
+ file_size=1,
+ severity="alerts",
+ ),
+ buffered=dict(size=2097152, severity="warnings"),
+ console=dict(
+ severity="warning",
+ discriminator=[
+ dict(match_params="match1", name="test1"),
+ ],
+ ),
+ correlator=dict(
+ buffer_size=1024,
+ rules=[
+ dict(
+ rule_name="test",
+ rule_type="stateful",
+ timeout=6,
+ context_correlation=True,
+ reissue_nonbistate=True,
+ reparent=True,
+ ),
+ ],
+ ),
+ events=dict(
+ severity="warnings",
+ display_location=True,
+ buffer_size=1024,
+ filter_match=["test1"],
+ threshold=12,
+ ),
+ format=True,
+ files=[
+ dict(
+ maxfilesize=1024,
+ name="test",
+ path="test1",
+ severity="info",
+ ),
+ ],
+ history=dict(state="disabled", size=10),
+ hostnameprefix="test",
+ hosts=[
+ dict(
+ host="1.1.1.2",
+ port="default",
+ severity="critical",
+ vrf="default",
+ ),
+ ],
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ localfilesize=1024,
+ source_interfaces=[
+ dict(interface="GigabitEthernet0/0/0/0", vrf="test"),
+ ],
+ tls_servers=[
+ dict(
+ name="test",
+ tls_hostname="test2",
+ trustpoint="test3",
+ vrf="test",
+ ),
+ ],
+ ),
+ state="overridden",
+ ),
+ )
+ commands = [
+ "logging console discriminator match1 test1",
+ "logging correlator rule test type stateful timeout 6",
+ "logging events threshold 12",
+ "logging 1.1.1.2 vrf default severity critical port default",
+ "logging file test path test1 maxfilesize 1024 severity info",
+ "logging tls-server test trustpoint test3",
+ "no logging 1.1.1.1 vrf default severity critical port default",
+ "no logging archive frequency daily",
+ "no logging buffered discriminator match2 test",
+ "no logging console discriminator match1 test",
+ "no logging console discriminator nomatch1 test3",
+ "no logging correlator rule test1 type nonstateful context-correlation",
+ "no logging correlator rule test1 type nonstateful timeout 6",
+ "no logging correlator ruleset test rulename test",
+ "no logging correlator ruleset test rulename test1",
+ "no logging events filter match test",
+ "no logging file test2 path test1 maxfilesize 1024 severity debugging",
+ "no logging monitor discriminator match1 test1",
+ "no logging monitor errors",
+ "no logging suppress duplicates",
+ "no logging trap informational",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_logging_global_gathered(self):
+ run_cfg = dedent(
+ """\
+ logging tls-server test
+ vrf test
+ trustpoint test2
+ tls-hostname test2
+ !
+ logging file test path test maxfilesize 1024 severity info
+ logging ipv4 dscp af11
+ logging ipv6 precedence routine
+ logging trap informational
+ logging events filter
+ match test
+ !
+ logging events threshold 10
+ logging events buffer-size 1024
+ logging events display-location
+ logging events level warnings
+ logging format rfc5424
+ logging archive
+ device disk0
+ severity alerts
+ file-size 1
+ frequency daily
+ archive-size 1
+ archive-length 1
+ !
+ logging console warning
+ logging console discriminator
+ match1 test
+ !
+ logging history size 10
+ logging history disable
+ logging monitor errors
+ logging monitor discriminator
+ match1 test1
+ !
+ logging buffered 2097152
+ logging buffered warnings
+ logging buffered discriminator
+ match2 test
+ !
+ logging 1.1.1.1 vrf default severity critical port default
+ logging correlator rule test type stateful
+ reissue-nonbistate
+ timeout 5
+ reparent
+ context-correlation
+ !
+ logging correlator ruleset test
+ rulename test
+ !
+ logging correlator buffer-size 1024
+ logging localfilesize 1024
+ logging source-interface GigabitEthernet0/0/0/0 vrf test
+ logging hostnameprefix test
+ logging suppress duplicates
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(state="gathered"))
+ gathered = {
+ "archive": {
+ "archive_length": 1,
+ "archive_size": 1,
+ "device": "disk0",
+ "file_size": 1,
+ "frequency": "daily",
+ "severity": "alerts",
+ },
+ "buffered": {
+ "discriminator": [{"match_params": "match2", "name": "test"}],
+ "severity": "warnings",
+ "size": 2097152,
+ },
+ "console": {
+ "discriminator": [{"match_params": "match1", "name": "test"}],
+ "severity": "warning",
+ },
+ "correlator": {
+ "buffer_size": 1024,
+ "rule_sets": [{"name": "test", "rulename": ["test"]}],
+ "rules": [
+ {
+ "context_correlation": True,
+ "reissue_nonbistate": True,
+ "reparent": True,
+ "rule_name": "test",
+ "rule_type": "stateful",
+ "timeout": 5,
+ },
+ ],
+ },
+ "events": {
+ "buffer_size": 1024,
+ "display_location": True,
+ "filter_match": ["test"],
+ "severity": "warnings",
+ "threshold": 10,
+ },
+ "files": [
+ {
+ "maxfilesize": 1024,
+ "name": "test",
+ "path": "test",
+ "severity": "info",
+ },
+ ],
+ "format": True,
+ "history": {"state": "disabled", "size": 10},
+ "hostnameprefix": "test",
+ "hosts": [
+ {
+ "host": "1.1.1.1",
+ "port": "default",
+ "severity": "critical",
+ "vrf": "default",
+ },
+ ],
+ "ipv4": {"dscp": "af11"},
+ "ipv6": {"precedence": "routine"},
+ "localfilesize": 1024,
+ "monitor": {
+ "discriminator": [{"match_params": "match1", "name": "test1"}],
+ "severity": "errors",
+ },
+ "source_interfaces": [
+ {"interface": "GigabitEthernet0/0/0/0", "vrf": "test"},
+ ],
+ "suppress": {"duplicates": True},
+ "tls_servers": [
+ {
+ "name": "test",
+ "tls_hostname": "test2",
+ "trustpoint": "test2",
+ "vrf": "test",
+ },
+ ],
+ "trap": {"severity": "informational"},
+ }
+ result = self.execute_module(changed=False)
+ self.assertEqual(gathered, result["gathered"])
+
+ def test_iosxr_logging_global_parsed(self):
+ set_module_args(
+ dict(
+ running_config="logging tls-server test\n vrf test\n trustpoint test2\n tls-hostname test2"
+ "\n!\nlogging file test path test maxfilesize 1024 severity info\nlogging ipv4 dscp"
+ " af11\nlogging ipv6 precedence routine\nlogging trap informational\nlogging events"
+ " filter\n match test1\n!\nlogging events threshold "
+ "10\nlogging events buffer-size 1024\nlogging events display-location"
+ "\nlogging events level warnings"
+ "\nlogging format rfc5424\nlogging archive\n device disk0"
+ "\n severity alerts\n file-size 1\n frequency "
+ "daily\n archive-size 1\n archive-length 1\n!\nlogging console "
+ "warning\nlogging console discriminator\n "
+ "match1 test\n!\nlogging history size "
+ "10\nlogging history disable\nlogging monitor errors"
+ "\nlogging monitor discriminator\n match1 test1\n!"
+ "\nlogging buffered 2097152\nlogging buffered warnings\n"
+ "logging buffered discriminator\n match2 test\n!\nlogging "
+ "1.1.1.1 vrf default severity critical port default"
+ "\nlogging correlator rule test type stateful\n reissue-nonbistate\n "
+ "timeout 5\n reparent\n context-correlation\n!"
+ "\n!\nlogging correlator ruleset test\n rulename test1"
+ "\n!\nlogging correlator buffer-size 1024\nlogging "
+ "localfilesize 1024\nlogging source-interface"
+ " GigabitEthernet0/0/0/0 vrf test\nlogging hostnameprefix "
+ "test\nlogging suppress duplicates",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "archive": {
+ "archive_length": 1,
+ "archive_size": 1,
+ "device": "disk0",
+ "file_size": 1,
+ "frequency": "daily",
+ "severity": "alerts",
+ },
+ "buffered": {
+ "discriminator": [{"match_params": "match2", "name": "test"}],
+ "severity": "warnings",
+ "size": 2097152,
+ },
+ "console": {
+ "discriminator": [{"match_params": "match1", "name": "test"}],
+ "severity": "warning",
+ },
+ "correlator": {
+ "buffer_size": 1024,
+ "rule_sets": [{"name": "test", "rulename": ["test1"]}],
+ "rules": [
+ {
+ "context_correlation": True,
+ "reissue_nonbistate": True,
+ "reparent": True,
+ "rule_name": "test",
+ "rule_type": "stateful",
+ "timeout": 5,
+ },
+ ],
+ },
+ "events": {
+ "buffer_size": 1024,
+ "display_location": True,
+ "filter_match": ["test1"],
+ "severity": "warnings",
+ "threshold": 10,
+ },
+ "files": [
+ {
+ "maxfilesize": 1024,
+ "name": "test",
+ "path": "test",
+ "severity": "info",
+ },
+ ],
+ "format": True,
+ "history": {"state": "disabled", "size": 10},
+ "hostnameprefix": "test",
+ "hosts": [
+ {
+ "host": "1.1.1.1",
+ "port": "default",
+ "severity": "critical",
+ "vrf": "default",
+ },
+ ],
+ "ipv4": {"dscp": "af11"},
+ "ipv6": {"precedence": "routine"},
+ "localfilesize": 1024,
+ "monitor": {
+ "discriminator": [{"match_params": "match1", "name": "test1"}],
+ "severity": "errors",
+ },
+ "source_interfaces": [
+ {"interface": "GigabitEthernet0/0/0/0", "vrf": "test"},
+ ],
+ "suppress": {"duplicates": True},
+ "tls_servers": [
+ {
+ "name": "test",
+ "tls_hostname": "test2",
+ "trustpoint": "test2",
+ "vrf": "test",
+ },
+ ],
+ "trap": {"severity": "informational"},
+ }
+
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_n540.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_n540.py
new file mode 100644
index 00000000..d2820cfa
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_n540.py
@@ -0,0 +1,96 @@
+#
+# (c) 2022 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from os import path
+
+from ansible.module_utils._text import to_bytes, to_text
+from mock import MagicMock
+
+from ansible_collections.cisco.iosxr.plugins.cliconf import iosxr
+from ansible_collections.cisco.iosxr.tests.unit.compat import unittest
+
+
+class TestPluginCLIConfIOSXR(unittest.TestCase):
+ """Test class for IOSXR CLI Conf Methods"""
+
+ def setUp(self):
+ self._mock_connection = MagicMock()
+ self._prepare()
+ self._cliconf = iosxr.Cliconf(self._mock_connection)
+ self.maxDiff = None
+
+ def _prepare(self, platform="iosxr"):
+ b_FIXTURE_DIR = b"%s/fixtures/cliconf_ncs540/%s" % (
+ to_bytes(
+ path.dirname(path.abspath(__file__)),
+ errors="surrogate_or_strict",
+ ),
+ to_bytes(platform),
+ )
+
+ def _connection_side_effect(*args, **kwargs):
+ try:
+ if args:
+ value = args[0]
+ else:
+ value = kwargs.get("command")
+ if b"|" in value:
+ value = value.replace(b"|", b"")
+ fixture_path = path.abspath(
+ b"%s/%s" % (b_FIXTURE_DIR, b"_".join(value.split(b" "))),
+ )
+ with open(fixture_path, "rb") as file_desc:
+ return to_text(file_desc.read())
+ except (OSError, IOError):
+ if args:
+ value = args[0]
+ return value
+ elif kwargs.get("command"):
+ value = kwargs.get("command")
+ return value
+ return "NO-OP"
+
+ self._mock_connection.send.side_effect = _connection_side_effect
+
+ def tearDown(self):
+ pass
+
+ def test_get_device_info_iosxr(self):
+ """Test get_device_info for nxos"""
+ device_info = self._cliconf.get_device_info()
+
+ mock_device_info = {
+ "network_os_version": "7.5.2 LNT",
+ "network_os": "iosxr",
+ "network_os_hostname": "iosxr01",
+ "network_os_model": "N540X-6Z18G-SYS-A",
+ }
+
+ self.assertEqual(device_info, mock_device_info)
+
+ def test_get_command_output_iosxr(self):
+ """Test _get_command_with_output for iosxr"""
+ self._prepare()
+ cmd = self._cliconf.get_command_output("show running-config hostname")
+
+ self.assertEqual(cmd, "hostname iosxr01")
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_netconf.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_netconf.py
new file mode 100644
index 00000000..bbd61050
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_netconf.py
@@ -0,0 +1,115 @@
+# (c) 2017 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_netconf
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrNetconfModule(TestIosxrModule):
+
+ module = iosxr_netconf
+
+ def setUp(self):
+ super(TestIosxrNetconfModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_netconf.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_netconf.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ def tearDown(self):
+ super(TestIosxrNetconfModule, self).tearDown()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+
+ def test_iosxr_disable_netconf_service(self):
+ self.get_config.return_value = """
+ netconf-yang agent
+ ssh
+ !
+ ssh server netconf vrf default
+ """
+ self.load_config.return_value = "dummy diff"
+ set_module_args(
+ dict(netconf_port=830, netconf_vrf="default", state="absent"),
+ )
+ result = self.execute_module(changed=True)
+ self.assertEqual(
+ result["commands"],
+ [
+ "no netconf-yang agent ssh",
+ "no ssh server netconf port 830",
+ "no ssh server netconf vrf default",
+ ],
+ )
+
+ def test_iosxr_enable_netconf_service(self):
+ self.get_config.return_value = ""
+ self.load_config.return_value = "dummy diff"
+ set_module_args(
+ dict(netconf_port=830, netconf_vrf="default", state="present"),
+ )
+ result = self.execute_module(changed=True)
+ self.assertEqual(
+ result["commands"],
+ [
+ "netconf-yang agent ssh",
+ "ssh server netconf port 830",
+ "ssh server netconf vrf default",
+ ],
+ )
+
+ def test_iosxr_change_netconf_port(self):
+ self.get_config.return_value = """
+ netconf-yang agent
+ ssh
+ !
+ ssh server netconf vrf default
+ """
+ self.load_config.return_value = "dummy diff"
+ set_module_args(dict(netconf_port=9000, state="present"))
+ result = self.execute_module(changed=True)
+ self.assertEqual(result["commands"], ["ssh server netconf port 9000"])
+
+ def test_iosxr_change_netconf_vrf(self):
+ self.get_config.return_value = """
+ netconf-yang agent
+ ssh
+ !
+ ssh server netconf vrf default
+ """
+ self.load_config.return_value = "dummy diff"
+ set_module_args(dict(netconf_vrf="new_default", state="present"))
+ result = self.execute_module(changed=True)
+ self.assertEqual(
+ result["commands"],
+ ["ssh server netconf vrf new_default"],
+ )
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ntp_global.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ntp_global.py
new file mode 100644
index 00000000..702e2a00
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ntp_global.py
@@ -0,0 +1,902 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ntp_global
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrNtpGlobalModule(TestIosxrModule):
+ module = iosxr_ntp_global
+
+ def setUp(self):
+ super(TestIosxrNtpGlobalModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ntp_global.ntp_global."
+ "Ntp_globalFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrNtpGlobalModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_ntp_global_merged_idempotent(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ ntp
+ max-associations 10
+ interface GigabitEthernet0/0/0/0 vrf siteB
+ multicast key 1
+ !
+ interface GigabitEthernet0/0/0/0
+ broadcast client
+ multicast client 224.0.0.8
+ multicast destination 224.0.0.8
+ !
+ authentication-key 1 md5 encrypted testkey
+ authentication-key 2 md5 encrypted 071B245F5A5B
+ authenticate
+ trusted-key 1
+ trusted-key 2
+ ipv4 dscp af11
+ ipv6 precedence routine
+ peer vrf siteC 192.0.2.1 iburst
+ server vrf siteD 192.0.2.2 burst
+ server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
+ drift file apphost
+ drift aging time 0
+ master 1
+ access-group vrf siteA ipv4 peer PeerAcl2
+ access-group vrf siteA ipv4 serve ServeAcl2
+ access-group ipv4 peer PeerAcl1
+ access-group ipv4 serve ServeAcl1
+ access-group ipv4 serve-only ServeOnlyAcl1
+ access-group ipv4 query-only QueryOnlyAcl1
+ access-group ipv6 peer PeerAcl2
+ source vrf siteE GigabitEthernet0/0/0/0
+ source GigabitEthernet0/0/0/0
+ passive
+ broadcastdelay 1
+ update-calendar
+ log-internal-sync
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ access_group=dict(
+ ipv4=dict(
+ peer="PeerAcl1",
+ query_only="QueryOnlyAcl1",
+ serve="ServeAcl1",
+ serve_only="ServeOnlyAcl1",
+ ),
+ ipv6=dict(peer="PeerAcl2"),
+ vrfs=[
+ dict(
+ ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
+ name="siteA",
+ ),
+ ],
+ ),
+ authenticate=True,
+ authentication_keys=[
+ dict(id=1, key="testkey", encryption=True),
+ dict(id=2, key="071B245F5A5B", encryption=True),
+ ],
+ broadcastdelay=1,
+ drift=dict(aging_time=0, file="apphost"),
+ interfaces=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_client="224.0.0.8",
+ multicast_destination="224.0.0.8",
+ broadcast_client=True,
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_key=1,
+ vrf="siteB",
+ ),
+ ],
+ ipv4=dict(dscp="af11"),
+ ipv6=dict(precedence="routine"),
+ log_internal_sync=True,
+ master=dict(stratum=1),
+ max_associations=10,
+ passive=True,
+ peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
+ servers=[
+ dict(burst=True, server="192.0.2.2", vrf="siteD"),
+ dict(
+ iburst=True,
+ burst=True,
+ server="192.0.2.2",
+ key_id=1,
+ maxpoll=5,
+ minpoll=4,
+ prefer=True,
+ source="GigabitEthernet0/0/0/0",
+ version=2,
+ ),
+ ],
+ source_interface="GigabitEthernet0/0/0/0",
+ source_vrfs=[
+ dict(name="GigabitEthernet0/0/0/0", vrf="siteE"),
+ ],
+ trusted_keys=[dict(key_id=1), dict(key_id=2)],
+ update_calendar=True,
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ntp_global_merged(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ config=dict(
+ access_group=dict(
+ ipv4=dict(
+ peer="PeerAcl1",
+ query_only="QueryOnlyAcl1",
+ serve="ServeAcl1",
+ serve_only="ServeOnlyAcl1",
+ ),
+ ipv6=dict(peer="PeerAcl2"),
+ vrfs=[
+ dict(
+ ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
+ name="siteA",
+ ),
+ ],
+ ),
+ authenticate=True,
+ authentication_keys=[
+ dict(id=1, key="testkey", encryption=True),
+ dict(id=2, key="071B245F5A5B", encryption=True),
+ ],
+ broadcastdelay=1,
+ drift=dict(aging_time=0, file="apphost"),
+ interfaces=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_client="224.0.0.8",
+ multicast_destination="224.0.0.8",
+ broadcast_client=True,
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_key=1,
+ vrf="siteB",
+ ),
+ ],
+ ipv4=dict(dscp="af11"),
+ ipv6=dict(precedence="routine"),
+ log_internal_sync=True,
+ master=dict(stratum=1),
+ max_associations=10,
+ passive=True,
+ peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
+ servers=[
+ dict(burst=True, server="192.0.2.2", vrf="siteD"),
+ dict(
+ iburst=True,
+ burst=True,
+ server="192.0.2.2",
+ key_id=1,
+ maxpoll=5,
+ minpoll=4,
+ prefer=True,
+ source="GigabitEthernet0/0/0/0",
+ version=2,
+ ),
+ ],
+ source_interface="GigabitEthernet0/0/0/0",
+ source_vrfs=[
+ dict(name="GigabitEthernet0/0/0/0", vrf="siteE"),
+ ],
+ trusted_keys=[dict(key_id=1), dict(key_id=2)],
+ update_calendar=True,
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "ntp authentication-key 1 md5 encrypted testkey",
+ "ntp authentication-key 2 md5 encrypted 071B245F5A5B",
+ "ntp peer vrf siteC 192.0.2.1 iburst",
+ "ntp server vrf siteD 192.0.2.2 burst",
+ "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0",
+ "ntp trusted-key 1",
+ "ntp trusted-key 2",
+ "ntp interface GigabitEthernet0/0/0/0 broadcast client",
+ "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8",
+ "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8",
+ "ntp interface GigabitEthernet0/0/0/0 vrf siteB multicast key 1",
+ "ntp vrf siteE source GigabitEthernet0/0/0/0",
+ "ntp access-group vrf siteA ipv4 serve ServeAcl2",
+ "ntp access-group vrf siteA ipv4 peer PeerAcl2",
+ "ntp access-group ipv4 peer PeerAcl1",
+ "ntp access-group ipv4 serve ServeAcl1",
+ "ntp access-group ipv4 serve-only ServeOnlyAcl1",
+ "ntp access-group ipv4 query-only QueryOnlyAcl1",
+ "ntp access-group ipv6 peer PeerAcl2",
+ "ntp authenticate",
+ "ntp log-internal-sync",
+ "ntp broadcastdelay 1",
+ "ntp drift aging time 0",
+ "ntp drift file apphost",
+ "ntp ipv4 dscp af11",
+ "ntp ipv6 precedence routine",
+ "ntp max-associations 10",
+ "ntp master 1",
+ "ntp passive",
+ "ntp update-calendar",
+ "ntp source GigabitEthernet0/0/0/0",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ntp_global_deleted(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ ntp
+ max-associations 10
+ interface GigabitEthernet0/0/0/0 vrf siteB
+ multicast key 1
+ !
+ interface GigabitEthernet0/0/0/0
+ broadcast client
+ multicast client 224.0.0.8
+ multicast destination 224.0.0.8
+ !
+ authentication-key 1 md5 encrypted testkey
+ authentication-key 2 md5 encrypted 071B245F5A5B
+ authenticate
+ trusted-key 1
+ trusted-key 2
+ ipv4 dscp af11
+ ipv6 precedence routine
+ peer vrf siteC 192.0.2.1 iburst
+ server vrf siteD 192.0.2.2 burst
+ server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
+ drift file apphost
+ drift aging time 0
+ master 1
+ access-group vrf siteA ipv4 peer PeerAcl3
+ access-group vrf siteA ipv4 serve ServeAcl2
+ access-group ipv4 peer PeerAcl1
+ access-group ipv4 serve ServeAcl1
+ access-group ipv4 serve-only ServeOnlyAcl1
+ access-group ipv4 query-only QueryOnlyAcl1
+ access-group ipv6 peer PeerAcl2
+ source vrf siteE GigabitEthernet0/0/0/0
+ source GigabitEthernet0/0/0/0
+ passive
+ broadcastdelay 1
+ update-calendar
+ log-internal-sync
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(state="deleted"))
+ commands = [
+ "no ntp authentication-key 1 md5 encrypted testkey",
+ "no ntp authentication-key 2 md5 encrypted 071B245F5A5B",
+ "no ntp peer vrf siteC 192.0.2.1 iburst",
+ "no ntp server vrf siteD 192.0.2.2 burst",
+ "no ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0",
+ "no ntp trusted-key 1",
+ "no ntp trusted-key 2",
+ "no ntp interface GigabitEthernet0/0/0/0 vrf siteB",
+ "no ntp interface GigabitEthernet0/0/0/0",
+ "no ntp vrf siteE source GigabitEthernet0/0/0/0",
+ "no ntp access-group vrf siteA ipv4 serve ServeAcl2",
+ "no ntp access-group vrf siteA ipv4 peer PeerAcl3",
+ "no ntp access-group ipv4 peer PeerAcl1",
+ "no ntp access-group ipv4 serve ServeAcl1",
+ "no ntp access-group ipv4 serve-only ServeOnlyAcl1",
+ "no ntp access-group ipv4 query-only QueryOnlyAcl1",
+ "no ntp access-group ipv6 peer PeerAcl2",
+ "no ntp authenticate",
+ "no ntp log-internal-sync",
+ "no ntp broadcastdelay 1",
+ "no ntp drift aging time 0",
+ "no ntp drift file apphost",
+ "no ntp ipv4 dscp af11",
+ "no ntp ipv6 precedence routine",
+ "no ntp max-associations 10",
+ "no ntp master 1",
+ "no ntp passive",
+ "no ntp update-calendar",
+ "no ntp source GigabitEthernet0/0/0/0",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ntp_global_replaced(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ ntp
+ max-associations 10
+ interface GigabitEthernet0/0/0/0 vrf siteB
+ multicast key 1
+ !
+ interface GigabitEthernet0/0/0/0
+ broadcast client
+ multicast client 224.0.0.8
+ multicast destination 224.0.0.8
+ !
+ authentication-key 1 md5 encrypted testkey
+ authentication-key 2 md5 encrypted 071B245F5A5B
+ authenticate
+ trusted-key 1
+ trusted-key 2
+ ipv4 dscp af11
+ ipv6 precedence routine
+ peer vrf siteC 192.0.2.1 iburst
+ server vrf siteD 192.0.2.2 burst
+ server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
+ drift file apphost
+ drift aging time 0
+ master 1
+ access-group vrf siteA ipv4 peer PeerAcl3
+ access-group vrf siteA ipv4 serve ServeAcl2
+ access-group ipv4 peer PeerAcl1
+ access-group ipv4 serve ServeAcl1
+ access-group ipv4 serve-only ServeOnlyAcl1
+ access-group ipv4 query-only QueryOnlyAcl1
+ access-group ipv6 peer PeerAcl2
+ source vrf siteE GigabitEthernet0/0/0/0
+ source GigabitEthernet0/0/0/0
+ passive
+ broadcastdelay 1
+ update-calendar
+ log-internal-sync
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ access_group=dict(
+ ipv4=dict(
+ peer="PeerAcl1",
+ query_only="QueryOnlyAcl2",
+ serve="ServeAcl1",
+ serve_only="ServeOnlyAcl1",
+ ),
+ ipv6=dict(peer="PeerAcl2"),
+ vrfs=[
+ dict(
+ ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
+ name="siteA",
+ ),
+ ],
+ ),
+ authenticate=True,
+ authentication_keys=[
+ dict(id=1, key="testkey1", encryption=True),
+ dict(id=2, key="071B245F5A5B", encryption=True),
+ ],
+ broadcastdelay=1,
+ drift=dict(aging_time=0, file="apphost"),
+ interfaces=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ multicast_client="224.0.0.8",
+ multicast_destination="224.0.0.8",
+ broadcast_client=True,
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_key=1,
+ vrf="siteB",
+ ),
+ ],
+ ipv4=dict(dscp="af12"),
+ ipv6=dict(precedence="routine"),
+ log_internal_sync=True,
+ master=dict(stratum=1),
+ max_associations=10,
+ passive=True,
+ peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
+ servers=[
+ dict(burst=True, server="192.0.2.3", vrf="siteD"),
+ dict(
+ iburst=True,
+ burst=True,
+ server="192.0.2.2",
+ key_id=1,
+ maxpoll=5,
+ minpoll=4,
+ prefer=True,
+ source="GigabitEthernet0/0/0/1",
+ version=2,
+ ),
+ ],
+ source_interface="GigabitEthernet0/0/0/0",
+ source_vrfs=[
+ dict(name="GigabitEthernet0/0/0/0", vrf="siteE"),
+ ],
+ trusted_keys=[dict(key_id=1), dict(key_id=2)],
+ update_calendar=True,
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "no ntp server vrf siteD 192.0.2.2 burst",
+ "no ntp interface GigabitEthernet0/0/0/0",
+ "ntp authentication-key 1 md5 encrypted testkey1",
+ "ntp server vrf siteD 192.0.2.3 burst",
+ "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/1",
+ "ntp interface GigabitEthernet0/0/0/1 broadcast client",
+ "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8",
+ "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8",
+ "ntp access-group ipv4 query-only QueryOnlyAcl2",
+ "ntp access-group vrf siteA ipv4 peer PeerAcl2",
+ "ntp access-group vrf siteA ipv4 serve ServeAcl2",
+ "ntp ipv4 dscp af12",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_logging_global_rendered(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ config=dict(
+ access_group=dict(
+ ipv4=dict(
+ peer="PeerAcl1",
+ query_only="QueryOnlyAcl1",
+ serve="ServeAcl1",
+ serve_only="ServeOnlyAcl1",
+ ),
+ ipv6=dict(peer="PeerAcl2"),
+ vrfs=[
+ dict(
+ ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
+ name="siteA",
+ ),
+ ],
+ ),
+ authenticate=True,
+ authentication_keys=[
+ dict(id=1, key="testkey", encryption=True),
+ dict(id=2, key="071B245F5A5B", encryption=True),
+ ],
+ broadcastdelay=1,
+ drift=dict(aging_time=0, file="apphost"),
+ interfaces=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_client="224.0.0.8",
+ multicast_destination="224.0.0.8",
+ broadcast_client=True,
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_key=1,
+ vrf="siteB",
+ ),
+ ],
+ ipv4=dict(dscp="af11"),
+ ipv6=dict(precedence="routine"),
+ log_internal_sync=True,
+ master=dict(stratum=1),
+ max_associations=10,
+ passive=True,
+ peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
+ servers=[
+ dict(burst=True, server="192.0.2.2", vrf="siteD"),
+ dict(
+ iburst=True,
+ burst=True,
+ server="192.0.2.2",
+ key_id=1,
+ maxpoll=5,
+ minpoll=4,
+ prefer=True,
+ source="GigabitEthernet0/0/0/0",
+ version=2,
+ ),
+ ],
+ source_interface="GigabitEthernet0/0/0/0",
+ source_vrfs=[
+ dict(name="GigabitEthernet0/0/0/0", vrf="siteE"),
+ ],
+ trusted_keys=[dict(key_id=1), dict(key_id=2)],
+ update_calendar=True,
+ ),
+ state="rendered",
+ ),
+ )
+ commands = [
+ "ntp authentication-key 1 md5 encrypted testkey",
+ "ntp authentication-key 2 md5 encrypted 071B245F5A5B",
+ "ntp peer vrf siteC 192.0.2.1 iburst",
+ "ntp server vrf siteD 192.0.2.2 burst",
+ "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0",
+ "ntp trusted-key 1",
+ "ntp trusted-key 2",
+ "ntp interface GigabitEthernet0/0/0/0 broadcast client",
+ "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8",
+ "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8",
+ "ntp interface GigabitEthernet0/0/0/0 vrf siteB multicast key 1",
+ "ntp vrf siteE source GigabitEthernet0/0/0/0",
+ "ntp access-group vrf siteA ipv4 serve ServeAcl2",
+ "ntp access-group vrf siteA ipv4 peer PeerAcl2",
+ "ntp access-group ipv4 peer PeerAcl1",
+ "ntp access-group ipv4 serve ServeAcl1",
+ "ntp access-group ipv4 serve-only ServeOnlyAcl1",
+ "ntp access-group ipv4 query-only QueryOnlyAcl1",
+ "ntp access-group ipv6 peer PeerAcl2",
+ "ntp authenticate",
+ "ntp log-internal-sync",
+ "ntp broadcastdelay 1",
+ "ntp drift aging time 0",
+ "ntp drift file apphost",
+ "ntp ipv4 dscp af11",
+ "ntp ipv6 precedence routine",
+ "ntp max-associations 10",
+ "ntp master 1",
+ "ntp passive",
+ "ntp update-calendar",
+ "ntp source GigabitEthernet0/0/0/0",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_ntp_global_overridden(self):
+ run_cfg = dedent(
+ """\
+ ntp
+ max-associations 10
+ interface GigabitEthernet0/0/0/0 vrf siteB
+ multicast key 1
+ !
+ interface GigabitEthernet0/0/0/0
+ broadcast client
+ multicast client 224.0.0.8
+ multicast destination 224.0.0.8
+ !
+ authentication-key 1 md5 encrypted testkey
+ authentication-key 2 md5 encrypted 071B245F5A5B
+ authenticate
+ trusted-key 1
+ trusted-key 2
+ ipv4 dscp af11
+ ipv6 precedence routine
+ peer vrf siteC 192.0.2.1 iburst
+ server vrf siteD 192.0.2.2 burst
+ server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
+ drift file apphost
+ drift aging time 0
+ master 1
+ access-group vrf siteA ipv4 peer PeerAcl3
+ access-group vrf siteA ipv4 serve ServeAcl2
+ access-group ipv4 peer PeerAcl1
+ access-group ipv4 serve ServeAcl1
+ access-group ipv4 serve-only ServeOnlyAcl1
+ access-group ipv4 query-only QueryOnlyAcl1
+ access-group ipv6 peer PeerAcl2
+ source vrf siteE GigabitEthernet0/0/0/0
+ source GigabitEthernet0/0/0/0
+ passive
+ broadcastdelay 1
+ update-calendar
+ log-internal-sync
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ access_group=dict(
+ ipv4=dict(
+ peer="PeerAcl1",
+ query_only="QueryOnlyAcl2",
+ serve="ServeAcl1",
+ serve_only="ServeOnlyAcl1",
+ ),
+ ipv6=dict(peer="PeerAcl2"),
+ vrfs=[
+ dict(
+ ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
+ name="siteA",
+ ),
+ ],
+ ),
+ authenticate=True,
+ authentication_keys=[
+ dict(id=1, key="testkey1", encryption=True),
+ dict(id=2, key="071B245F5A5B", encryption=True),
+ ],
+ broadcastdelay=1,
+ drift=dict(aging_time=0, file="apphost"),
+ interfaces=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ multicast_client="224.0.0.8",
+ multicast_destination="224.0.0.8",
+ broadcast_client=True,
+ ),
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ multicast_key=1,
+ vrf="siteB",
+ ),
+ ],
+ ipv4=dict(dscp="af12"),
+ ipv6=dict(precedence="routine"),
+ log_internal_sync=True,
+ master=dict(stratum=1),
+ max_associations=10,
+ passive=True,
+ peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
+ servers=[
+ dict(burst=True, server="192.0.2.3", vrf="siteD"),
+ dict(
+ iburst=True,
+ burst=True,
+ server="192.0.2.2",
+ key_id=1,
+ maxpoll=5,
+ minpoll=4,
+ prefer=True,
+ source="GigabitEthernet0/0/0/1",
+ version=2,
+ ),
+ ],
+ source_interface="GigabitEthernet0/0/0/0",
+ source_vrfs=[
+ dict(name="GigabitEthernet0/0/0/0", vrf="siteE"),
+ ],
+ trusted_keys=[dict(key_id=1), dict(key_id=2)],
+ update_calendar=True,
+ ),
+ state="overridden",
+ ),
+ )
+ commands = [
+ "no ntp server vrf siteD 192.0.2.2 burst",
+ "no ntp interface GigabitEthernet0/0/0/0",
+ "ntp authentication-key 1 md5 encrypted testkey1",
+ "ntp server vrf siteD 192.0.2.3 burst",
+ "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/1",
+ "ntp interface GigabitEthernet0/0/0/1 broadcast client",
+ "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8",
+ "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8",
+ "ntp access-group ipv4 query-only QueryOnlyAcl2",
+ "ntp access-group vrf siteA ipv4 peer PeerAcl2",
+ "ntp access-group vrf siteA ipv4 serve ServeAcl2",
+ "ntp ipv4 dscp af12",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ntp_global_gathered(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ ntp
+ max-associations 10
+ interface GigabitEthernet0/0/0/0
+ broadcast client
+ multicast client 224.0.0.8
+ multicast destination 224.0.0.8
+ !
+ authentication-key 1 md5 encrypted testkey
+ authentication-key 2 md5 encrypted 071B245F5A5B
+ authenticate
+ trusted-key 1
+ trusted-key 2
+ ipv4 dscp af11
+ ipv6 precedence routine
+ peer vrf siteC 192.0.2.1 iburst
+ server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
+ drift file apphost
+ drift aging time 0
+ master 1
+ access-group vrf siteA ipv4 peer PeerAcl3
+ access-group vrf siteA ipv4 serve ServeAcl2
+ access-group ipv4 peer PeerAcl1
+ access-group ipv4 serve ServeAcl1
+ access-group ipv4 serve-only ServeOnlyAcl1
+ access-group ipv4 query-only QueryOnlyAcl1
+ access-group ipv6 peer PeerAcl2
+ source vrf siteE GigabitEthernet0/0/0/0
+ source GigabitEthernet0/0/0/0
+ passive
+ broadcastdelay 1
+ update-calendar
+ log-internal-sync
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ print(self.get_config.return_value)
+ set_module_args(dict(state="gathered"))
+ gathered = {
+ "max_associations": 10,
+ "interfaces": [
+ {
+ "name": "GigabitEthernet0/0/0/0",
+ "broadcast_client": True,
+ "multicast_client": "224.0.0.8",
+ "multicast_destination": "224.0.0.8",
+ },
+ ],
+ "authentication_keys": [
+ {"id": 1, "key": "testkey", "encryption": True},
+ {"id": 2, "key": "071B245F5A5B", "encryption": True},
+ ],
+ "authenticate": True,
+ "trusted_keys": [{"key_id": 1}, {"key_id": 2}],
+ "ipv4": {"dscp": "af11"},
+ "ipv6": {"precedence": "routine"},
+ "peers": [{"peer": "192.0.2.1", "vrf": "siteC", "iburst": True}],
+ "servers": [
+ {
+ "server": "192.0.2.2",
+ "burst": True,
+ "iburst": True,
+ "key_id": 1,
+ "minpoll": 4,
+ "maxpoll": 5,
+ "prefer": True,
+ "version": 2,
+ "source": "GigabitEthernet0/0/0/0",
+ },
+ ],
+ "drift": {"file": "apphost", "aging_time": 0},
+ "master": {"stratum": 1},
+ "access_group": {
+ "vrfs": [
+ {
+ "name": "siteA",
+ "ipv4": {"peer": "PeerAcl3", "serve": "ServeAcl2"},
+ },
+ ],
+ "ipv4": {
+ "peer": "PeerAcl1",
+ "serve": "ServeAcl1",
+ "serve_only": "ServeOnlyAcl1",
+ "query_only": "QueryOnlyAcl1",
+ },
+ "ipv6": {"peer": "PeerAcl2"},
+ },
+ "source_vrfs": [
+ {"name": "GigabitEthernet0/0/0/0", "vrf": "siteE"},
+ ],
+ "source_interface": "GigabitEthernet0/0/0/0",
+ "passive": True,
+ "broadcastdelay": 1,
+ "update_calendar": True,
+ "log_internal_sync": True,
+ }
+ result = self.execute_module(changed=False)
+ self.assertEqual(gathered, result["gathered"])
+
+ def test_iosxr_ntp_global_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="ntp\n max-associations 10\n interface GigabitEthernet0/0/0/0\n broadcast client\n"
+ " multicast client 224.0.0.8\n multicast destination 224.0.0.8\n !\n "
+ "authentication-key 1 md5 encrypted testkey\n authentication-key 2 md5 "
+ "encrypted 071B245F5A5B\n authenticate\n trusted-key 1\n trusted-key 2\n ipv4 dscp "
+ "af11\n ipv6 precedence routine\n peer vrf siteC 192.0.2.1 iburst\n"
+ " server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer "
+ "burst iburst source GigabitEthernet0/0/0/0\n drift file apphost\n drift aging time 0\n"
+ " master 1\n access-group vrf siteA ipv4 peer PeerAcl3\n access-group vrf siteA "
+ "ipv4 serve ServeAcl2\n access-group ipv4 peer PeerAcl1\n access-group ipv4 serve "
+ "ServeAcl1\n access-group ipv4 serve-only ServeOnlyAcl1\n access-group ipv4 "
+ "query-only QueryOnlyAcl1\n access-group ipv6 peer PeerAcl2\n source vrf siteE "
+ "GigabitEthernet0/0/0/0\n source GigabitEthernet0/0/0/0\n"
+ " passive\n broadcastdelay "
+ "1\n update-calendar\n log-internal-sync\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "max_associations": 10,
+ "interfaces": [
+ {
+ "name": "GigabitEthernet0/0/0/0",
+ "broadcast_client": True,
+ "multicast_client": "224.0.0.8",
+ "multicast_destination": "224.0.0.8",
+ },
+ ],
+ "authentication_keys": [
+ {"id": 1, "key": "testkey", "encryption": True},
+ {"id": 2, "key": "071B245F5A5B", "encryption": True},
+ ],
+ "authenticate": True,
+ "trusted_keys": [{"key_id": 1}, {"key_id": 2}],
+ "ipv4": {"dscp": "af11"},
+ "ipv6": {"precedence": "routine"},
+ "peers": [{"peer": "192.0.2.1", "vrf": "siteC", "iburst": True}],
+ "servers": [
+ {
+ "server": "192.0.2.2",
+ "burst": True,
+ "iburst": True,
+ "key_id": 1,
+ "minpoll": 4,
+ "maxpoll": 5,
+ "prefer": True,
+ "version": 2,
+ "source": "GigabitEthernet0/0/0/0",
+ },
+ ],
+ "drift": {"file": "apphost", "aging_time": 0},
+ "master": {"stratum": 1},
+ "access_group": {
+ "vrfs": [{"name": "siteA", "ipv4": {"peer": "PeerAcl3"}}],
+ "ipv4": {
+ "peer": "PeerAcl1",
+ "serve": "ServeAcl1",
+ "serve_only": "ServeOnlyAcl1",
+ "query_only": "QueryOnlyAcl1",
+ },
+ "ipv6": {"peer": "PeerAcl2"},
+ },
+ "source_vrfs": [
+ {"name": "GigabitEthernet0/0/0/0", "vrf": "siteE"},
+ ],
+ "source_interface": "GigabitEthernet0/0/0/0",
+ "passive": True,
+ "broadcastdelay": 1,
+ "update_calendar": True,
+ "log_internal_sync": True,
+ }
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospf_interfaces.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospf_interfaces.py
new file mode 100644
index 00000000..8c976944
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospf_interfaces.py
@@ -0,0 +1,359 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ospf_interfaces
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrOspf_InterfacesModule(TestIosxrModule):
+ module = iosxr_ospf_interfaces
+
+ def setUp(self):
+ super(TestIosxrOspf_InterfacesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+
+ self.mock_edit_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers.CliProvider.edit_config",
+ )
+ self.edit_config = self.mock_edit_config.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospf_interfaces.ospf_interfaces."
+ "Ospf_interfacesFacts.get_ospf_interfaces",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrOspf_InterfacesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_edit_config.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def load_fixtures(self, commands=None):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_ospf_interfaces.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_ospf_interfaces_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB1",
+ area=dict(area_id="0.0.0.3"),
+ ),
+ ],
+ cost=10,
+ authentication=dict(
+ message_digest=dict(keychain="iosxr"),
+ ),
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 cost 10",
+ "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest",
+ "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain iosxr",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospf_interfaces_merged_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB3",
+ area=dict(area_id="0.0.0.3"),
+ ),
+ ],
+ cost=20,
+ authentication=dict(
+ message_digest=dict(keychain="cisco"),
+ ),
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospf_interfaces_replaced(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB3",
+ area=dict(area_id="0.0.0.3"),
+ ),
+ ],
+ cost=40,
+ authentication=dict(
+ message_digest=dict(keychain="ciscoiosxr"),
+ ),
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 40",
+ "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest",
+ "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain ciscoiosxr",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospf_interfaces_replaced_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB3",
+ area=dict(area_id="0.0.0.3"),
+ ),
+ ],
+ cost=20,
+ authentication=dict(
+ message_digest=dict(keychain="cisco"),
+ ),
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospf_interfaces_overridden(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/4",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB4",
+ area=dict(area_id="0.0.0.4"),
+ ),
+ ],
+ cost=40,
+ authentication=dict(
+ message_digest=dict(keychain="iosxr"),
+ ),
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+
+ commands = [
+ "no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0",
+ "router ospf LAB4 area 0.0.0.4 interface GigabitEthernet 0/0/0/4 cost 40",
+ "router ospf LAB4 area 0.0.0.4 interface GigabitEthernet 0/0/0/4 authentication message-digest",
+ "router ospf LAB4 area 0.0.0.4 interface GigabitEthernet 0/0/0/4 authentication message-digest keychain iosxr",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospf_interfaces_overridden_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB3",
+ area=dict(area_id="0.0.0.3"),
+ ),
+ ],
+ cost=20,
+ authentication=dict(
+ message_digest=dict(keychain="cisco"),
+ ),
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospf_interfaces_deleted(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ type="gigabitethernet",
+ ),
+ ],
+ state="deleted",
+ ),
+ )
+ commands = [
+ "no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospf_interfaces_deleted_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ type="gigabitethernet",
+ ),
+ ],
+ state="deleted",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospf_interfaces_parsed(self):
+ set_module_args(
+ dict(
+ running_config="router ospf LAB3\n area 0.0.0.3\n interface GigabitEthernet0/0/0/0\n cost 20\n !\n !\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = [
+ dict(
+ name="GigabitEthernet0/0/0/0",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB3",
+ area=dict(area_id="0.0.0.3"),
+ ),
+ ],
+ cost=20,
+ ),
+ ],
+ ),
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_ospf_interfaces_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ name="GigabitEthernet0/0/0/1",
+ type="gigabitethernet",
+ address_family=[
+ dict(
+ afi="ipv4",
+ processes=[
+ dict(
+ process_id="LAB1",
+ area=dict(area_id="0.0.0.3"),
+ ),
+ ],
+ cost=10,
+ authentication=dict(
+ message_digest=dict(keychain="iosxr"),
+ ),
+ ),
+ ],
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+ commands = [
+ "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 cost 10",
+ "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest",
+ "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain iosxr",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv2.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv2.py
new file mode 100644
index 00000000..6d00a825
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv2.py
@@ -0,0 +1,277 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ospfv2
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrOspfV2Module(TestIosxrModule):
+ module = iosxr_ospfv2
+
+ def setUp(self):
+ super(TestIosxrOspfV2Module, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+
+ self.mock_edit_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers.CliProvider.edit_config",
+ )
+ self.edit_config = self.mock_edit_config.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv2.ospfv2."
+ "Ospfv2Facts.get_ospfv2_data",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrOspfV2Module, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_edit_config.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def load_fixtures(self, commands=None):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_ospfv2.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_ospfv2_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="300",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ log_adjacency_changes=dict(set=True),
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "router ospf 300",
+ "cost 2",
+ "default-metric 10",
+ "area 11 default-cost 5",
+ "log adjacency changes",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv2_merged_idempotent(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospfv2_replaced(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ dict(
+ process_id="40",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "router ospf 30",
+ "no default-metric 10",
+ "router ospf 40",
+ "cost 2",
+ "default-metric 10",
+ "area 11 default-cost 5",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv2_replaced_idempotent(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospfv2_overridden(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="40",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ log_adjacency_changes=dict(set=True),
+ ),
+ ],
+ ),
+ state="overridden",
+ ),
+ )
+
+ commands = [
+ "router ospf 30",
+ "no cost 2",
+ "no default-metric 10",
+ "no area 11 default-cost 5",
+ "router ospf 40",
+ "cost 2",
+ "default-metric 10",
+ "area 11 default-cost 5",
+ "log adjacency changes",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv2_overridden_idempotent(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="overridden",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospfv2_deleted(self):
+ set_module_args(
+ dict(
+ config=dict(processes=[dict(process_id="30", cost=2)]),
+ state="deleted",
+ ),
+ )
+ commands = [
+ "router ospf 30",
+ "no cost 2",
+ "no default-metric 10",
+ "no area 11 default-cost 5",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv2_parsed(self):
+ set_module_args(
+ dict(
+ running_config="router ospf 50\n cost 2\n area 11\n default-cost 5\n !\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "processes": [
+ dict(
+ process_id="50",
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ }
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_ospfv2_rendered(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="60",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ log_adjacency_changes=dict(set=True),
+ ),
+ ],
+ ),
+ state="rendered",
+ ),
+ )
+ commands = [
+ "area 11 default-cost 5",
+ "cost 2",
+ "log adjacency changes",
+ "default-metric 10",
+ "router ospf 60",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv3.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv3.py
new file mode 100644
index 00000000..1b8e491f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ospfv3.py
@@ -0,0 +1,271 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ospfv3
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrOspfV3Module(TestIosxrModule):
+ module = iosxr_ospfv3
+
+ def setUp(self):
+ super(TestIosxrOspfV3Module, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+
+ self.mock_edit_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers.CliProvider.edit_config",
+ )
+ self.edit_config = self.mock_edit_config.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv3.ospfv3."
+ "Ospfv3Facts.get_ospfv3_data",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrOspfV3Module, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_edit_config.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def load_fixtures(self, commands=None):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_ospfv3.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_ospfv3_merged(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="300",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "router ospfv3 300",
+ "cost 2",
+ "default-metric 10",
+ "area 11 default-cost 5",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv3_merged_idempotent(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospfv3_replaced(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ dict(
+ process_id="40",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "router ospfv3 30",
+ "no default-metric 10",
+ "router ospfv3 40",
+ "cost 2",
+ "default-metric 10",
+ "area 11 default-cost 5",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv3_replaced_idempotent(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="replaced",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospfv3_overridden(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="40",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="overridden",
+ ),
+ )
+
+ commands = [
+ "router ospfv3 30",
+ "no cost 2",
+ "no default-metric 10",
+ "no area 11 default-cost 5",
+ "router ospfv3 40",
+ "cost 2",
+ "default-metric 10",
+ "area 11 default-cost 5",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv3_overridden_idempotent(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="30",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="overridden",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_ospfv3_deleted(self):
+ set_module_args(
+ dict(
+ config=dict(processes=[dict(process_id="30", cost=2)]),
+ state="deleted",
+ ),
+ )
+ commands = [
+ "router ospfv3 30",
+ "no cost 2",
+ "no default-metric 10",
+ "no area 11 default-cost 5",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_ospfv3_parsed(self):
+ set_module_args(
+ dict(
+ running_config="router ospfv3 50\n cost 2\n area 11\n default-cost 5\n !\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "processes": [
+ dict(
+ process_id="50",
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ }
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_ospfv3_rendered(self):
+ set_module_args(
+ dict(
+ config=dict(
+ processes=[
+ dict(
+ process_id="60",
+ default_metric=10,
+ cost=2,
+ areas=[dict(area_id="11", default_cost=5)],
+ ),
+ ],
+ ),
+ state="rendered",
+ ),
+ )
+ commands = [
+ "area 11 default-cost 5",
+ "cost 2",
+ "default-metric 10",
+ "router ospfv3 60",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), commands)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ping.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ping.py
new file mode 100644
index 00000000..d0ceda0f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_ping.py
@@ -0,0 +1,180 @@
+#
+# (c) 2022, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ping
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrPingModule(TestIosxrModule):
+ module = iosxr_ping
+
+ def setUp(self):
+ super(TestIosxrPingModule, self).setUp()
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ping.ping.Ping.run_command",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrPingModule, self).tearDown()
+ self.mock_execute_show_command.stop()
+
+ def test_iosxr_ping_count(self):
+ self.execute_show_command.return_value = dedent(
+ """\
+ Type escape sequence to abort.
+ ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds:
+ !
+ Success rate is 100 percent (2/2), round-trip min/avg/max = 25/25/25 ms
+ """,
+ )
+ set_module_args(dict(count=2, dest="8.8.8.8"))
+ result = self.execute_module()
+ mock_res = {
+ "commands": "ping ipv4 8.8.8.8 count 2",
+ "packet_loss": "0%",
+ "packets_rx": 2,
+ "packets_tx": 2,
+ "rtt": {"min": 25, "avg": 25, "max": 25},
+ "changed": False,
+ }
+ self.assertEqual(result, mock_res)
+
+ def test_iosxr_ping_v6(self):
+ self.execute_show_command.return_value = dedent(
+ """\
+ Type escape sequence to abort.
+ ending 2, 100-byte ICMP Echos to 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff, timeout is 2 seconds:
+ !
+ Success rate is 100 percent (2/2), round-trip min/avg/max = 25/25/25 ms
+ """,
+ )
+ set_module_args(
+ dict(
+ count=2,
+ dest="2001:db8:ffff:ffff:ffff:ffff:ffff:ffff",
+ afi="ipv6",
+ ),
+ )
+ result = self.execute_module()
+ mock_res = {
+ "commands": "ping ipv6 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff count 2",
+ "packet_loss": "0%",
+ "packets_rx": 2,
+ "packets_tx": 2,
+ "rtt": {"min": 25, "avg": 25, "max": 25},
+ "changed": False,
+ }
+ self.assertEqual(result, mock_res)
+
+ def test_iosxr_ping_options_all(self):
+ self.execute_show_command.return_value = dedent(
+ """\
+ Type escape sequence to abort.
+ ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds:
+ !
+ Success rate is 100 percent (2/2), round-trip min/avg/max = 25/25/25 ms
+ """,
+ )
+ set_module_args(
+ {
+ "afi": "ipv4",
+ "count": 4,
+ "dest": "8.8.8.8",
+ "df_bit": True,
+ "size": "10",
+ "source": "Loopback88",
+ "state": "present",
+ "sweep": True,
+ "validate": True,
+ "vrf": "DummyVrf",
+ },
+ )
+ result = self.execute_module()
+ mock_res = {
+ "commands": "ping vrf DummyVrf ipv4 8.8.8.8 count 4 df-bit sweep validate size 10 source Loopback88",
+ "packet_loss": "0%",
+ "packets_rx": 2,
+ "packets_tx": 2,
+ "rtt": {"min": 25, "avg": 25, "max": 25},
+ "changed": False,
+ }
+ self.assertEqual(result, mock_res)
+
+ def test_iosxr_ping_state_absent_pass(self):
+ self.execute_show_command.return_value = dedent(
+ """\
+ Type escape sequence to abort.
+ ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds:
+ !
+ Success rate is 90 percent (2/2), round-trip min/avg/max = 25/25/25 ms
+ """,
+ )
+ set_module_args(dict(count=2, dest="8.8.8.8", state="absent"))
+ result = self.execute_module(failed=True)
+ mock_res = {
+ "msg": "Ping succeeded unexpectedly",
+ "commands": "ping ipv4 8.8.8.8 count 2",
+ "packet_loss": "10%",
+ "packets_rx": 2,
+ "packets_tx": 2,
+ "rtt": {"min": 25, "avg": 25, "max": 25},
+ "failed": True,
+ }
+ self.assertEqual(result, mock_res)
+
+ def test_iosxr_ping_state_absent_pass(self):
+ self.execute_show_command.return_value = dedent(
+ """\
+ Type escape sequence to abort.
+ Sending 5, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
+ .....
+ Success rate is 0 percent (0/5)
+ """,
+ )
+ set_module_args(dict(count=2, dest="192.0.2.1", state="absent"))
+ result = self.execute_module(failed=False)
+ print(result)
+ mock_res = {
+ "commands": "ping ipv4 192.0.2.1 count 2",
+ "packet_loss": "100%",
+ "packets_rx": 0,
+ "packets_tx": 5,
+ "rtt": {},
+ "changed": False,
+ }
+ self.assertEqual(result, mock_res)
+
+ def test_iosxr_ping_state_absent_present_fail(self):
+ self.execute_show_command.return_value = dedent(
+ """\
+ Type escape sequence to abort.
+ ending 2, 100-byte ICMP Echos to 8.8.8.8, timeout is 12 seconds:
+ !
+ Success rate is 0 percent (0/2), round-trip min/avg/max = 25/25/25 ms
+ """,
+ )
+ set_module_args(dict(count=2, dest="8.8.8.8", state="present"))
+ result = self.execute_module(failed=True)
+ mock_res = {
+ "msg": "Ping failed unexpectedly",
+ "commands": "ping ipv4 8.8.8.8 count 2",
+ "packet_loss": "100%",
+ "packets_rx": 0,
+ "packets_tx": 2,
+ "rtt": {"min": 25, "avg": 25, "max": 25},
+ "failed": True,
+ }
+ self.assertEqual(result, mock_res)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_prefix_lists.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_prefix_lists.py
new file mode 100644
index 00000000..6dca5d92
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_prefix_lists.py
@@ -0,0 +1,442 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_prefix_lists
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrPrefixListsModule(TestIosxrModule):
+ module = iosxr_prefix_lists
+
+ def setUp(self):
+ super(TestIosxrPrefixListsModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.prefix_lists.prefix_lists."
+ "Prefix_listsFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrPrefixListsModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_prefix_lists_merged_idempotent(self):
+ run_cfg = dedent(
+ """ipv6 prefix-list test2\n 4 remark test\n!
+ \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv6",
+ prefix_lists=[
+ dict(
+ name="test2",
+ entries=[
+ dict(
+ sequence=4,
+ action="remark",
+ description="test",
+ ),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv4",
+ prefix_lists=[
+ dict(
+ name="test1",
+ entries=[
+ dict(
+ sequence=3,
+ action="remark",
+ description="test1",
+ ),
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_prefix_lists_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv6",
+ prefix_lists=[
+ dict(
+ name="test2",
+ entries=[
+ dict(
+ sequence=4,
+ action="remark",
+ description="test",
+ ),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv4",
+ prefix_lists=[
+ dict(
+ name="test1",
+ entries=[
+ dict(
+ sequence=3,
+ action="remark",
+ description="test1",
+ ),
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ dict(
+ name="test3",
+ entries=[
+ dict(
+ sequence=5,
+ action="permit",
+ eq="3",
+ prefix="32.0.0.0/8",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "ipv6 prefix-list test2 4 remark test",
+ "ipv4 prefix-list test1 2 permit 10.0.0.0/24",
+ "ipv4 prefix-list test1 3 remark test1",
+ "ipv4 prefix-list test3 5 permit 32.0.0.0/8 eq 3",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_prefix_lists_replaced(self):
+ run_cfg = dedent(
+ """ipv6 prefix-list test2\n 4 remark test\n!
+ \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!""",
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ prefix_lists=[
+ dict(
+ name="test2",
+ entries=[
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ dict(
+ name="test1",
+ entries=[
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ dict(
+ name="test3",
+ entries=[
+ dict(
+ sequence=5,
+ action="permit",
+ eq="3",
+ prefix="32.0.0.0/8",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "no ipv4 prefix-list test1 3 remark test1",
+ "ipv4 prefix-list test2 2 permit 10.0.0.0/24",
+ "ipv4 prefix-list test3 5 permit 32.0.0.0/8 eq 3",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_prefix_lists_replaced_idempotent(self):
+ run_cfg = dedent(
+ """ipv6 prefix-list test2\n 4 remark test\n!
+ \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!""",
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv6",
+ prefix_lists=[
+ dict(
+ name="test2",
+ entries=[
+ dict(
+ sequence=4,
+ action="remark",
+ description="test",
+ ),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv4",
+ prefix_lists=[
+ dict(
+ name="test1",
+ entries=[
+ dict(
+ sequence=3,
+ action="remark",
+ description="test1",
+ ),
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_prefix_list_deleted(self):
+ run_cfg = dedent(
+ """ipv6 prefix-list test2\n 4 remark test\n!
+ \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!""",
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(state="deleted"))
+
+ commands = ["no ipv4 prefix-list test1", "no ipv6 prefix-list test2"]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_prefix_list_deleted_idempotent(self):
+ run_cfg = dedent(
+ """\
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(config=[], state="deleted"))
+
+ result = self.execute_module(changed=False)
+ self.assertEqual(result["commands"], [])
+
+ def test_iosxr_prefix_list_rendered(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv6",
+ prefix_lists=[
+ dict(
+ name="test2",
+ entries=[
+ dict(
+ sequence=4,
+ action="remark",
+ description="test",
+ ),
+ ],
+ ),
+ ],
+ ),
+ dict(
+ afi="ipv4",
+ prefix_lists=[
+ dict(
+ name="test1",
+ entries=[
+ dict(
+ sequence=3,
+ action="remark",
+ description="test1",
+ ),
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ dict(
+ name="test3",
+ entries=[
+ dict(
+ sequence=5,
+ action="permit",
+ eq="3",
+ prefix="32.0.0.0/8",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="rendered",
+ ),
+ )
+
+ commands = [
+ "ipv6 prefix-list test2 4 remark test",
+ "ipv4 prefix-list test1 2 permit 10.0.0.0/24",
+ "ipv4 prefix-list test1 3 remark test1",
+ "ipv4 prefix-list test3 5 permit 32.0.0.0/8 eq 3",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_prefix_list_parsed(self):
+ set_module_args(
+ dict(
+ running_config="ipv4 prefix-list test1\n 3 remark test1\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = [
+ {
+ "afi": "ipv4",
+ "prefix_lists": [
+ {
+ "name": "test1",
+ "entries": [
+ {
+ "sequence": 3,
+ "action": "remark",
+ "description": "test1",
+ },
+ ],
+ },
+ ],
+ },
+ ]
+
+ self.assertEqual(parsed_list, result["parsed"])
+
+ def test_iosxr_prefix_list_overridden(self):
+ run_cfg = dedent(
+ """ipv6 prefix-list test2\n 4 remark test\n!
+ \nipv4 prefix-list test1\n 3 remark test1\n 2 permit 10.0.0.0/24\n!
+ """,
+ )
+
+ self.get_config.return_value = run_cfg
+
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ afi="ipv4",
+ prefix_lists=[
+ dict(
+ name="test2",
+ entries=[
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ dict(
+ name="test1",
+ entries=[
+ dict(
+ sequence=2,
+ action="permit",
+ prefix="10.0.0.0/24",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "no ipv4 prefix-list test1 3 remark test1",
+ "ipv4 prefix-list test2 2 permit 10.0.0.0/24",
+ "no ipv6 prefix-list test2",
+ ]
+
+ result = self.execute_module(changed=True)
+ self.assertEqual(set(result["commands"]), set(commands))
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_snmp_server.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_snmp_server.py
new file mode 100644
index 00000000..14862519
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_snmp_server.py
@@ -0,0 +1,3612 @@
+# (c) 2021 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from textwrap import dedent
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_snmp_server
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule
+
+
+class TestIosxrSnmpServerModule(TestIosxrModule):
+ module = iosxr_snmp_server
+
+ def setUp(self):
+ super(TestIosxrSnmpServerModule, self).setUp()
+
+ self.mock_get_resource_connection = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
+ "get_resource_connection",
+ )
+ self.get_resource_connection = self.mock_get_resource_connection.start()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.snmp_server.snmp_server."
+ "Snmp_serverFacts.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ def tearDown(self):
+ super(TestIosxrSnmpServerModule, self).tearDown()
+ self.get_resource_connection.stop()
+ self.get_config.stop()
+
+ def test_iosxr_snmp_server_merged_idempotent(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ snmp-server vrf vrf1
+ host 1.1.1.1 traps test1
+ !
+ snmp-server drop report acl IPv4 test1
+ snmp-server drop unknown-user
+ snmp-server ipv4 dscp af11
+ snmp-server ipv6 precedence routine
+ snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl
+ snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1
+ snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1
+ snmp-server queue-length 2
+ snmp-server trap-timeout 3
+ snmp-server trap throttle-time 12
+ snmp-server traps rf
+ snmp-server traps bfd
+ snmp-server traps bgp cbgp2
+ snmp-server traps pim neighbor-change
+ snmp-server traps pim invalid-message-received
+ snmp-server traps pim rp-mapping-change
+ snmp-server traps pim interface-state-change
+ snmp-server traps copy-complete
+ snmp-server traps hsrp
+ snmp-server traps ipsla
+ snmp-server traps msdp peer-state-change
+ snmp-server traps snmp linkup
+ snmp-server traps snmp linkdown
+ snmp-server traps snmp coldstart
+ snmp-server traps snmp warmstart
+ snmp-server traps snmp authentication
+ snmp-server traps vrrp events
+ snmp-server traps flash removal
+ snmp-server traps flash insertion
+ snmp-server traps ipsec tunnel stop
+ snmp-server traps ipsec tunnel start
+ snmp-server traps power
+ snmp-server traps config
+ snmp-server traps entity
+ snmp-server traps sensor
+ snmp-server traps selective-vrf-download role-change
+ snmp-server traps syslog
+ snmp-server traps system
+ snmp-server traps ospf lsa lsa-maxage
+ snmp-server traps ospf lsa lsa-originate
+ snmp-server traps ospf errors bad-packet
+ snmp-server traps ospf errors authentication-failure
+ snmp-server traps ospf errors config-error
+ snmp-server traps ospf errors virt-bad-packet
+ snmp-server traps ospf errors virt-authentication-failure
+ snmp-server traps ospf errors virt-config-error
+ snmp-server traps ospf retransmit packets
+ snmp-server traps ospf retransmit virt-packets
+ snmp-server traps ospf state-change if-state-change
+ snmp-server traps ospf state-change neighbor-state-change
+ snmp-server traps ospf state-change virtif-state-change
+ snmp-server traps ospf state-change virtneighbor-state-change
+ snmp-server traps rsvp all
+ snmp-server traps rsvp new-flow
+ snmp-server traps rsvp lost-flow
+ snmp-server traps l2tun sessions
+ snmp-server traps l2tun tunnel-up
+ snmp-server traps l2tun tunnel-down
+ snmp-server traps vpls all
+ snmp-server traps vpls status
+ snmp-server traps vpls full-clear
+ snmp-server traps vpls full-raise
+ snmp-server traps bulkstat collection
+ snmp-server traps diameter peerup
+ snmp-server traps diameter peerdown
+ snmp-server traps diameter protocolerror
+ snmp-server traps diameter permanentfail
+ snmp-server traps diameter transientfail
+ snmp-server traps l2vpn all
+ snmp-server traps l2vpn vc-up
+ snmp-server traps l2vpn vc-down
+ snmp-server traps bridgemib
+ snmp-server traps ospfv3 errors bad-packet
+ snmp-server traps ospfv3 errors config-error
+ snmp-server traps ospfv3 errors virt-config-error
+ snmp-server traps ospfv3 state-change neighbor-state-change
+ snmp-server traps ospfv3 state-change virtif-state-change
+ snmp-server traps ospfv3 state-change virtneighbor-state-change
+ snmp-server traps ospfv3 state-change restart-status-change
+ snmp-server traps ospfv3 state-change restart-helper-status-change
+ snmp-server traps ospfv3 state-change restart-virtual-helper-status-change
+ snmp-server traps subscriber session-agg node
+ snmp-server traps subscriber session-agg access-interface
+ snmp-server traps addrpool low
+ snmp-server traps addrpool high
+ snmp-server traps cisco-entity-ext
+ snmp-server traps entity-state operstatus
+ snmp-server traps entity-state switchover
+ snmp-server traps entity-redundancy all
+ snmp-server traps entity-redundancy status
+ snmp-server traps entity-redundancy switchover
+ snmp-server chassis-id test2
+ snmp-server contact t1
+ snmp-server location test1
+ snmp-server target list test host 1.1.1.2
+ snmp-server target list test2 vrf vrf2
+ snmp-server context c1
+ snmp-server context c2
+ snmp-server logging threshold oid-processing 1
+ snmp-server logging threshold pdu-processing 1
+ snmp-server mib bulkstat max-procmem-size 101
+ snmp-server mib bulkstat object-list test1
+ !
+ snmp-server mib bulkstat schema mib1
+ object-list test1
+ poll-interval 1
+ !
+ snmp-server mib bulkstat transfer-id test2
+ retry 1
+ buffer-size 1024
+ enable
+ format schemaASCII
+ retain 1
+ schema test2
+ !
+ snmp-server timeouts duplicate 0
+ snmp-server timeouts inQdrop 0
+ snmp-server timeouts subagent 1
+ snmp-server timeouts pdu stats 1
+ snmp-server timeouts threshold 0
+ snmp-server packetsize 490
+ snmp-server correlator rule rule1
+ timeout 5
+ !
+ snmp-server correlator ruleset rule1
+ !
+ snmp-server correlator buffer-size 1024
+ snmp-server trap-source GigabitEthernet0/0/0/2
+ snmp-server throttle-time 60
+ snmp-server community-map cm1 context c1 security-name s1 target-list t1
+ snmp-server inform retries 7
+ snmp-server overload-control 4 6
+ snmp-server ifmib internal cache max-duration 4
+ snmp-server mroutemib send-all-vrf
+ snmp-server notification-log-mib size 5
+ snmp-server notification-log-mib GlobalSize 5
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ hosts=[
+ dict(
+ community="test1",
+ host="1.1.1.1",
+ traps=True,
+ ),
+ ],
+ ),
+ ],
+ users=[
+ dict(
+ Ipv4_acl="test1",
+ Ipv6_acl="test2",
+ group="test2",
+ user="u1",
+ v4_acl="v4acl",
+ ),
+ ],
+ timeouts=dict(
+ duplicate=0,
+ inQdrop=0,
+ pdu_stats=1,
+ subagent=1,
+ threshold=0,
+ ),
+ trap=dict(throttle_time=12),
+ targets=[
+ dict(name="test2", vrf="vrf2"),
+ dict(host="1.1.1.2", name="test"),
+ ],
+ ifmib=dict(internal_cache_max_duration=4),
+ inform=dict(retries=7),
+ chassis_id="test2",
+ packetsize=490,
+ queue_length=2,
+ throttle_time=60,
+ trap_source="GigabitEthernet0/0/0/2",
+ trap_timeout=3,
+ context=["c1", "c2"],
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[dict(name="rule1")],
+ rules=[dict(rule_name="rule1", timeout=5)],
+ ),
+ communities=[
+ dict(
+ name="test2",
+ rw=True,
+ systemowner=True,
+ acl_v4="test",
+ acl_v6="test1",
+ ),
+ ],
+ community_maps=[
+ dict(
+ name="cm1",
+ context="c1",
+ target_list="t1",
+ security_name="s1",
+ ),
+ ],
+ drop=dict(report_IPv4="test1", unknown_user=True),
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ groups=[
+ dict(
+ Ipv4_acl="test",
+ Ipv6_acl="test1",
+ context="test3",
+ group="g2",
+ read="test1",
+ version="v1",
+ write="test2",
+ ),
+ ],
+ location="test1",
+ logging_threshold_oid_processing=1,
+ logging_threshold_pdu_processing=1,
+ mib_bulkstat_max_procmem_size=101,
+ mroutemib_send_all_vrf=True,
+ mib_object_lists=["test1"],
+ overload_control=dict(
+ overload_drop_time=4,
+ overload_throttle_rate=6,
+ ),
+ mib_schema=[
+ dict(
+ name="mib1",
+ object_list="test1",
+ poll_interval=1,
+ ),
+ ],
+ notification_log_mib=dict(GlobalSize=5, size=5),
+ mib_bulkstat_transfer_ids=[
+ dict(
+ buffer_size=1024,
+ enable=True,
+ format_schemaASCI=True,
+ name="test2",
+ retain=1,
+ retry=1,
+ schema="test2",
+ ),
+ ],
+ traps=dict(
+ diameter=dict(
+ peerdown=True,
+ peerup=True,
+ permanentfail=True,
+ protocolerror=True,
+ transientfail=True,
+ ),
+ entity=True,
+ entity_redundancy=dict(
+ all=True,
+ status=True,
+ switchover=True,
+ ),
+ entity_state=dict(operstatus=True, switchover=True),
+ flash=dict(insertion=True, removal=True),
+ hsrp=True,
+ ipsla=True,
+ ipsec=dict(start=True, stop=True),
+ bridgemib=True,
+ bulkstat_collection=True,
+ cisco_entity_ext=True,
+ config=True,
+ copy_complete=True,
+ addrpool=dict(high=True, low=True),
+ bfd=True,
+ bgp=dict(cbgp2=True),
+ l2tun=dict(
+ sessions=True,
+ tunnel_down=True,
+ tunnel_up=True,
+ ),
+ l2vpn=dict(all=True, vc_down=True, vc_up=True),
+ msdp_peer_state_change=True,
+ ospf=dict(
+ errors=dict(
+ authentication_failure=True,
+ bad_packet=True,
+ config_error=True,
+ virt_authentication_failure=True,
+ virt_bad_packet=True,
+ virt_config_error=True,
+ ),
+ lsa=dict(lsa_maxage=True, lsa_originate=True),
+ retransmit=dict(packets=True, virt_packets=True),
+ state_change=dict(
+ if_state_change=True,
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ ),
+ ),
+ ospfv3=dict(
+ errors=dict(
+ bad_packet=True,
+ config_error=True,
+ virt_config_error=True,
+ ),
+ state_change=dict(
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ restart_helper_status_change=True,
+ restart_status_change=True,
+ restart_virtual_helper_status_change=True,
+ ),
+ ),
+ pim=dict(
+ interface_state_change=True,
+ invalid_message_received=True,
+ neighbor_change=True,
+ rp_mapping_change=True,
+ ),
+ power=True,
+ rf=True,
+ rsvp=dict(all=True, lost_flow=True, new_flow=True),
+ selective_vrf_download_role_change=True,
+ sensor=True,
+ snmp=dict(
+ authentication=True,
+ coldstart=True,
+ linkdown=True,
+ linkup=True,
+ warmstart=True,
+ ),
+ subscriber=dict(
+ session_agg_access_interface=True,
+ session_agg_node=True,
+ ),
+ syslog=True,
+ system=True,
+ vpls=dict(
+ all=True,
+ full_clear=True,
+ full_raise=True,
+ status=True,
+ ),
+ vrrp_events=True,
+ ),
+ ),
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_snmp_server_merged(self):
+ self.maxDiff = None
+
+ set_module_args(
+ dict(
+ config=dict(
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ hosts=[
+ dict(
+ community="test1",
+ host="1.1.1.1",
+ traps=True,
+ ),
+ ],
+ ),
+ ],
+ users=[
+ dict(
+ Ipv4_acl="test1",
+ Ipv6_acl="test2",
+ group="test2",
+ user="u1",
+ v4_acl="v4acl",
+ SystemOwner=True,
+ ),
+ ],
+ timeouts=dict(
+ duplicate=0,
+ inQdrop=0,
+ pdu_stats=1,
+ subagent=1,
+ threshold=0,
+ ),
+ trap=dict(throttle_time=12, link_ietf=True),
+ targets=[
+ dict(name="test2", vrf="vrf2"),
+ dict(host="1.1.1.2", name="test"),
+ ],
+ ifmib=dict(internal_cache_max_duration=4),
+ inform=dict(retries=7),
+ chassis_id="test2",
+ packetsize=490,
+ queue_length=2,
+ throttle_time=60,
+ trap_source="GigabitEthernet0/0/0/2",
+ trap_timeout=3,
+ context=["c1", "c2"],
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[dict(name="rule1")],
+ rules=[dict(rule_name="rule1", timeout=5)],
+ ),
+ communities=[
+ dict(
+ name="test2",
+ ro=True,
+ sdrowner=True,
+ acl_v4="test",
+ acl_v6="test1",
+ ),
+ ],
+ community_maps=[
+ dict(
+ name="cm1",
+ context="c1",
+ target_list="t1",
+ security_name="s1",
+ ),
+ ],
+ drop=dict(report_IPv4="test1", unknown_user=True),
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ groups=[
+ dict(
+ Ipv4_acl="test",
+ Ipv6_acl="test1",
+ context="test3",
+ group="g2",
+ read="test1",
+ version="v1",
+ write="test2",
+ ),
+ ],
+ interfaces=[dict(name=" GigabitEthernet0/0/0/2")],
+ location="test1",
+ logging_threshold_oid_processing=1,
+ logging_threshold_pdu_processing=1,
+ mib_bulkstat_max_procmem_size=101,
+ mroutemib_send_all_vrf=True,
+ mib_object_lists=["test1"],
+ overload_control=dict(
+ overload_drop_time=4,
+ overload_throttle_rate=6,
+ ),
+ mib_schema=[
+ dict(
+ name="mib1",
+ object_list="test1",
+ poll_interval=1,
+ ),
+ ],
+ notification_log_mib=dict(GlobalSize=5, size=5),
+ mib_bulkstat_transfer_ids=[
+ dict(
+ buffer_size=1024,
+ enable=True,
+ format_schemaASCI=True,
+ name="test2",
+ retain=1,
+ retry=1,
+ schema="test2",
+ ),
+ ],
+ traps=dict(
+ diameter=dict(
+ peerdown=True,
+ peerup=True,
+ permanentfail=True,
+ protocolerror=True,
+ transientfail=True,
+ ),
+ entity=True,
+ entity_redundancy=dict(
+ all=True,
+ status=True,
+ switchover=True,
+ ),
+ entity_state=dict(operstatus=True, switchover=True),
+ flash=dict(insertion=True, removal=True),
+ hsrp=True,
+ ipsla=True,
+ ipsec=dict(start=True, stop=True),
+ bridgemib=True,
+ bulkstat_collection=True,
+ cisco_entity_ext=True,
+ config=True,
+ copy_complete=True,
+ addrpool=dict(high=True, low=True),
+ bfd=True,
+ bgp=dict(cbgp2=True),
+ l2tun=dict(
+ sessions=True,
+ tunnel_down=True,
+ tunnel_up=True,
+ ),
+ l2vpn=dict(all=True, vc_down=True, vc_up=True),
+ msdp_peer_state_change=True,
+ ospf=dict(
+ errors=dict(
+ authentication_failure=True,
+ bad_packet=True,
+ config_error=True,
+ virt_authentication_failure=True,
+ virt_bad_packet=True,
+ virt_config_error=True,
+ ),
+ lsa=dict(lsa_maxage=True, lsa_originate=True),
+ retransmit=dict(packets=True, virt_packets=True),
+ state_change=dict(
+ if_state_change=True,
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ ),
+ ),
+ ospfv3=dict(
+ errors=dict(
+ bad_packet=True,
+ config_error=True,
+ virt_config_error=True,
+ ),
+ state_change=dict(
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ restart_helper_status_change=True,
+ restart_status_change=True,
+ restart_virtual_helper_status_change=True,
+ ),
+ ),
+ pim=dict(
+ interface_state_change=True,
+ invalid_message_received=True,
+ neighbor_change=True,
+ rp_mapping_change=True,
+ ),
+ power=True,
+ rf=True,
+ rsvp=dict(all=True, lost_flow=True, new_flow=True),
+ selective_vrf_download_role_change=True,
+ sensor=True,
+ snmp=dict(
+ authentication=True,
+ coldstart=True,
+ linkdown=True,
+ linkup=True,
+ warmstart=True,
+ ),
+ subscriber=dict(
+ session_agg_access_interface=True,
+ session_agg_node=True,
+ ),
+ syslog=True,
+ system=True,
+ vpls=dict(
+ all=True,
+ full_clear=True,
+ full_raise=True,
+ status=True,
+ ),
+ vrrp_events=True,
+ isis=dict(
+ adjacency_change=True,
+ area_mismatch=True,
+ attempt_to_exceed_max_sequence=True,
+ authentication_failure=True,
+ authentication_type_failure=True,
+ corrupted_lsp_detected=True,
+ database_overload=True,
+ id_len_mismatch=True,
+ lsp_error_detected=True,
+ lsp_too_large_to_propagate=True,
+ manual_address_drops=True,
+ max_area_addresses_mismatch=True,
+ orig_lsp_buff_size_mismatch=True,
+ own_lsp_purge=True,
+ protocols_supported_mismatch=True,
+ rejected_adjacency=True,
+ sequence_number_skip=True,
+ version_skew=True,
+ ),
+ ),
+ ),
+ state="merged",
+ ),
+ )
+ commands = [
+ "snmp-server chassis-id test2",
+ "snmp-server correlator buffer-size 1024",
+ "snmp-server ipv4 dscp af11",
+ "snmp-server ipv6 precedence routine",
+ "snmp-server location test1",
+ "snmp-server logging threshold oid-processing 1",
+ "snmp-server logging threshold pdu-processing 1",
+ "snmp-server mib bulkstat max-procmem-size 101",
+ "snmp-server mroutemib send-all-vrf",
+ "snmp-server overload-control 4 6",
+ "snmp-server packetsize 490",
+ "snmp-server queue-length 2",
+ "snmp-server throttle-time 60",
+ "snmp-server trap-source GigabitEthernet0/0/0/2",
+ "snmp-server trap-timeout 3",
+ "snmp-server drop report acl IPv4 test1",
+ "snmp-server drop unknown-user",
+ "snmp-server ifmib internal cache max-duration 4",
+ "snmp-server inform retries 7",
+ "snmp-server notification-log-mib size 5",
+ "snmp-server notification-log-mib GlobalSize 5",
+ "snmp-server trap link ietf",
+ "snmp-server trap throttle-time 12",
+ "snmp-server timeouts threshold 0",
+ "snmp-server timeouts pdu stats 1",
+ "snmp-server timeouts subagent 1",
+ "snmp-server timeouts inQdrop 0",
+ "snmp-server timeouts duplicate 0",
+ "snmp-server traps addrpool low",
+ "snmp-server traps addrpool high",
+ "snmp-server traps bfd",
+ "snmp-server traps bgp cbgp2",
+ "snmp-server traps bulkstat collection",
+ "snmp-server traps bridgemib",
+ "snmp-server traps copy-complete",
+ "snmp-server traps cisco-entity-ext",
+ "snmp-server traps config",
+ "snmp-server traps diameter peerdown",
+ "snmp-server traps diameter peerup",
+ "snmp-server traps diameter protocolerror",
+ "snmp-server traps diameter permanentfail",
+ "snmp-server traps diameter transientfail",
+ "snmp-server traps entity",
+ "snmp-server traps entity-redundancy all",
+ "snmp-server traps entity-redundancy status",
+ "snmp-server traps entity-redundancy switchover",
+ "snmp-server traps entity-state operstatus",
+ "snmp-server traps entity-state switchover",
+ "snmp-server traps flash removal",
+ "snmp-server traps flash insertion",
+ "snmp-server traps hsrp",
+ "snmp-server traps ipsla",
+ "snmp-server traps ipsec tunnel start",
+ "snmp-server traps ipsec tunnel stop",
+ "snmp-server traps isis adjacency-change area-mismatch attempt-to-exceed-max-sequence "
+ "authentication-failure authentication-type-failure corrupted-lsp-detected database-overload "
+ "id-len-mismatch lsp-error-detected lsp-too-large-to-propagate manual-address-drops"
+ " max-area-addresses-mismatch orig-lsp-buff-size-mismatch version-skew own-lsp-purge"
+ " rejected-adjacency protocols-supported-mismatch sequence-number-skip",
+ "snmp-server traps l2tun sessions",
+ "snmp-server traps l2tun tunnel-up",
+ "snmp-server traps l2tun tunnel-down",
+ "snmp-server traps l2vpn all",
+ "snmp-server traps l2vpn vc-up",
+ "snmp-server traps l2vpn vc-down",
+ "snmp-server traps msdp peer-state-change",
+ "snmp-server traps ospf retransmit virt-packets",
+ "snmp-server traps ospf retransmit packets",
+ "snmp-server traps ospf lsa lsa-originate",
+ "snmp-server traps ospf lsa lsa-maxage",
+ "snmp-server traps ospf errors bad-packet",
+ "snmp-server traps ospf errors authentication-failure",
+ "snmp-server traps ospf errors config-error",
+ "snmp-server traps ospf errors virt-bad-packet",
+ "snmp-server traps ospf errors virt-authentication-failure",
+ "snmp-server traps ospf errors virt-config-error",
+ "snmp-server traps ospf state-change if-state-change",
+ "snmp-server traps ospf state-change neighbor-state-change",
+ "snmp-server traps ospf state-change virtif-state-change",
+ "snmp-server traps ospf state-change virtneighbor-state-change",
+ "snmp-server traps ospfv3 errors bad-packet",
+ "snmp-server traps ospfv3 errors config-error",
+ "snmp-server traps ospfv3 errors virt-config-error",
+ "snmp-server traps ospfv3 state-change neighbor-state-change",
+ "snmp-server traps ospfv3 state-change virtif-state-change",
+ "snmp-server traps ospfv3 state-change virtneighbor-state-change",
+ "snmp-server traps ospfv3 state-change restart-status-change",
+ "snmp-server traps ospfv3 state-change restart-helper-status-change",
+ "snmp-server traps ospfv3 state-change restart-virtual-helper-status-change",
+ "snmp-server traps power",
+ "snmp-server traps rf",
+ "snmp-server traps pim neighbor-change",
+ "snmp-server traps pim invalid-message-received",
+ "snmp-server traps pim rp-mapping-change",
+ "snmp-server traps pim interface-state-change",
+ "snmp-server traps rsvp lost-flow",
+ "snmp-server traps rsvp new-flow",
+ "snmp-server traps rsvp all",
+ "snmp-server traps selective-vrf-download role-change",
+ "snmp-server traps sensor",
+ "snmp-server traps vrrp events",
+ "snmp-server traps syslog",
+ "snmp-server traps system",
+ "snmp-server traps subscriber session-agg access-interface",
+ "snmp-server traps subscriber session-agg node",
+ "snmp-server traps vpls all",
+ "snmp-server traps vpls full-clear",
+ "snmp-server traps vpls full-raise",
+ "snmp-server traps vpls status",
+ "snmp-server traps snmp linkup",
+ "snmp-server traps snmp linkdown",
+ "snmp-server traps snmp coldstart",
+ "snmp-server traps snmp warmstart",
+ "snmp-server traps snmp authentication",
+ "snmp-server community test2 RO SDROwner IPv4 test IPv6 test1",
+ "snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+ "snmp-server correlator ruleset rule1",
+ "snmp-server correlator rule rule1 timeout 5",
+ "snmp-server context c1",
+ "snmp-server context c2",
+ "snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1",
+ "snmp-server interface GigabitEthernet0/0/0/2",
+ "snmp-server mib bulkstat object-list test1",
+ "snmp-server mib bulkstat schema mib1 object-list test1",
+ "snmp-server mib bulkstat schema mib1 poll-interval 1",
+ "snmp-server mib bulkstat transfer-id test2 buffer-size 1024",
+ "snmp-server mib bulkstat transfer-id test2 enable",
+ "snmp-server mib bulkstat transfer-id test2 format schemaASCII",
+ "snmp-server mib bulkstat transfer-id test2 retain 1",
+ "snmp-server mib bulkstat transfer-id test2 retry 1",
+ "snmp-server mib bulkstat transfer-id test2 schema test2",
+ "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl SystemOwner",
+ "snmp-server target list test2 vrf vrf2",
+ "snmp-server target list test host 1.1.1.2",
+ "snmp-server vrf vrf1",
+ "host 1.1.1.1 traps test1",
+ ]
+ result = self.execute_module(changed=True)
+ print(result["commands"])
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_snmp_server_deleted(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ snmp-server vrf vrf1
+ host 1.1.1.1 traps test1
+ !
+ snmp-server drop report acl IPv4 test1
+ snmp-server drop unknown-user
+ snmp-server ipv4 dscp af11
+ snmp-server ipv6 precedence routine
+ snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl
+ snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1
+ snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1
+ snmp-server queue-length 2
+ snmp-server trap-timeout 3
+ snmp-server trap throttle-time 12
+ snmp-server traps rf
+ snmp-server traps bfd
+ snmp-server traps bgp cbgp2
+ snmp-server traps pim neighbor-change
+ snmp-server traps pim invalid-message-received
+ snmp-server traps pim rp-mapping-change
+ snmp-server traps pim interface-state-change
+ snmp-server traps copy-complete
+ snmp-server traps hsrp
+ snmp-server traps ipsla
+ snmp-server traps msdp peer-state-change
+ snmp-server traps snmp linkup
+ snmp-server traps snmp linkdown
+ snmp-server traps snmp coldstart
+ snmp-server traps snmp warmstart
+ snmp-server traps snmp authentication
+ snmp-server traps vrrp events
+ snmp-server traps flash removal
+ snmp-server traps flash insertion
+ snmp-server traps ipsec tunnel stop
+ snmp-server traps ipsec tunnel start
+ snmp-server traps power
+ snmp-server traps config
+ snmp-server traps entity
+ snmp-server traps sensor
+ snmp-server traps selective-vrf-download role-change
+ snmp-server traps syslog
+ snmp-server traps system
+ snmp-server traps ospf lsa lsa-maxage
+ snmp-server traps ospf lsa lsa-originate
+ snmp-server traps ospf errors bad-packet
+ snmp-server traps ospf errors authentication-failure
+ snmp-server traps ospf errors config-error
+ snmp-server traps ospf errors virt-bad-packet
+ snmp-server traps ospf errors virt-authentication-failure
+ snmp-server traps ospf errors virt-config-error
+ snmp-server traps ospf retransmit packets
+ snmp-server traps ospf retransmit virt-packets
+ snmp-server traps ospf state-change if-state-change
+ snmp-server traps ospf state-change neighbor-state-change
+ snmp-server traps ospf state-change virtif-state-change
+ snmp-server traps ospf state-change virtneighbor-state-change
+ snmp-server traps rsvp all
+ snmp-server traps rsvp new-flow
+ snmp-server traps rsvp lost-flow
+ snmp-server traps l2tun sessions
+ snmp-server traps l2tun tunnel-up
+ snmp-server traps l2tun tunnel-down
+ snmp-server traps vpls all
+ snmp-server traps vpls status
+ snmp-server traps vpls full-clear
+ snmp-server traps vpls full-raise
+ snmp-server traps bulkstat collection
+ snmp-server traps diameter peerup
+ snmp-server traps diameter peerdown
+ snmp-server traps diameter protocolerror
+ snmp-server traps diameter permanentfail
+ snmp-server traps diameter transientfail
+ snmp-server traps l2vpn all
+ snmp-server traps l2vpn vc-up
+ snmp-server traps l2vpn vc-down
+ snmp-server traps bridgemib
+ snmp-server traps ospfv3 errors bad-packet
+ snmp-server traps ospfv3 errors config-error
+ snmp-server traps ospfv3 errors virt-config-error
+ snmp-server traps ospfv3 state-change neighbor-state-change
+ snmp-server traps ospfv3 state-change virtif-state-change
+ snmp-server traps ospfv3 state-change virtneighbor-state-change
+ snmp-server traps ospfv3 state-change restart-status-change
+ snmp-server traps ospfv3 state-change restart-helper-status-change
+ snmp-server traps ospfv3 state-change restart-virtual-helper-status-change
+ snmp-server traps subscriber session-agg node
+ snmp-server traps subscriber session-agg access-interface
+ snmp-server traps addrpool low
+ snmp-server traps addrpool high
+ snmp-server traps cisco-entity-ext
+ snmp-server traps entity-state operstatus
+ snmp-server traps entity-state switchover
+ snmp-server traps entity-redundancy all
+ snmp-server traps entity-redundancy status
+ snmp-server traps entity-redundancy switchover
+ snmp-server chassis-id test2
+ snmp-server contact t1
+ snmp-server location test1
+ snmp-server target list test host 1.1.1.2
+ snmp-server target list test2 vrf vrf2
+ snmp-server context c1
+ snmp-server context c2
+ snmp-server logging threshold oid-processing 1
+ snmp-server logging threshold pdu-processing 1
+ snmp-server mib bulkstat max-procmem-size 101
+ snmp-server mib bulkstat object-list test1
+ !
+ snmp-server timeouts duplicate 0
+ snmp-server timeouts inQdrop 0
+ snmp-server timeouts subagent 1
+ snmp-server timeouts pdu stats 1
+ snmp-server timeouts threshold 0
+ snmp-server packetsize 490
+ snmp-server correlator buffer-size 1024
+ snmp-server trap-source GigabitEthernet0/0/0/2
+ snmp-server throttle-time 60
+ snmp-server community-map cm1 context c1 security-name s1 target-list t1
+ snmp-server inform retries 7
+ snmp-server overload-control 4 6
+ snmp-server interface GigabitEthernet0/0/0/2
+ !
+ snmp-server ifmib internal cache max-duration 4
+ snmp-server mroutemib send-all-vrf
+ snmp-server notification-log-mib size 5
+ snmp-server notification-log-mib GlobalSize 5
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(state="deleted"))
+ commands = [
+ "no snmp-server chassis-id test2",
+ "no snmp-server correlator buffer-size 1024",
+ "no snmp-server contact t1",
+ "no snmp-server ipv4 dscp af11",
+ "no snmp-server ipv6 precedence routine",
+ "no snmp-server location test1",
+ "no snmp-server logging threshold oid-processing 1",
+ "no snmp-server logging threshold pdu-processing 1",
+ "no snmp-server mib bulkstat max-procmem-size 101",
+ "no snmp-server mroutemib send-all-vrf",
+ "no snmp-server overload-control 4 6",
+ "no snmp-server packetsize 490",
+ "no snmp-server queue-length 2",
+ "no snmp-server throttle-time 60",
+ "no snmp-server trap-source GigabitEthernet0/0/0/2",
+ "no snmp-server trap-timeout 3",
+ "no snmp-server drop report acl IPv4 test1",
+ "no snmp-server drop unknown-user",
+ "no snmp-server ifmib internal cache max-duration 4",
+ "no snmp-server inform retries 7",
+ "no snmp-server notification-log-mib size 5",
+ "no snmp-server notification-log-mib GlobalSize 5",
+ "no snmp-server trap throttle-time 12",
+ "no snmp-server timeouts threshold 0",
+ "no snmp-server timeouts pdu stats 1",
+ "no snmp-server timeouts subagent 1",
+ "no snmp-server timeouts inQdrop 0",
+ "no snmp-server timeouts duplicate 0",
+ "no snmp-server traps addrpool low",
+ "no snmp-server traps addrpool high",
+ "no snmp-server traps bfd",
+ "no snmp-server traps bgp cbgp2",
+ "no snmp-server traps bulkstat collection",
+ "no snmp-server traps bridgemib",
+ "no snmp-server traps copy-complete",
+ "no snmp-server traps cisco-entity-ext",
+ "no snmp-server traps config",
+ "no snmp-server traps diameter peerdown",
+ "no snmp-server traps diameter peerup",
+ "no snmp-server traps diameter protocolerror",
+ "no snmp-server traps diameter permanentfail",
+ "no snmp-server traps diameter transientfail",
+ "no snmp-server traps entity",
+ "no snmp-server traps entity-redundancy all",
+ "no snmp-server traps entity-redundancy status",
+ "no snmp-server traps entity-redundancy switchover",
+ "no snmp-server traps entity-state operstatus",
+ "no snmp-server traps entity-state switchover",
+ "no snmp-server traps flash removal",
+ "no snmp-server traps flash insertion",
+ "no snmp-server traps hsrp",
+ "no snmp-server traps ipsla",
+ "no snmp-server traps ipsec tunnel start",
+ "no snmp-server traps ipsec tunnel stop",
+ "no snmp-server traps l2tun sessions",
+ "no snmp-server traps l2tun tunnel-up",
+ "no snmp-server traps l2tun tunnel-down",
+ "no snmp-server traps l2vpn all",
+ "no snmp-server traps l2vpn vc-up",
+ "no snmp-server traps l2vpn vc-down",
+ "no snmp-server traps msdp peer-state-change",
+ "no snmp-server traps ospf retransmit virt-packets",
+ "no snmp-server traps ospf retransmit packets",
+ "no snmp-server traps ospf lsa lsa-originate",
+ "no snmp-server traps ospf lsa lsa-maxage",
+ "no snmp-server traps ospf errors bad-packet",
+ "no snmp-server traps ospf errors authentication-failure",
+ "no snmp-server traps ospf errors config-error",
+ "no snmp-server traps ospf errors virt-bad-packet",
+ "no snmp-server traps ospf errors virt-authentication-failure",
+ "no snmp-server traps ospf errors virt-config-error",
+ "no snmp-server traps ospf state-change if-state-change",
+ "no snmp-server traps ospf state-change neighbor-state-change",
+ "no snmp-server traps ospf state-change virtif-state-change",
+ "no snmp-server traps ospf state-change virtneighbor-state-change",
+ "no snmp-server traps ospfv3 errors bad-packet",
+ "no snmp-server traps ospfv3 errors config-error",
+ "no snmp-server traps ospfv3 errors virt-config-error",
+ "no snmp-server traps ospfv3 state-change neighbor-state-change",
+ "no snmp-server traps ospfv3 state-change virtif-state-change",
+ "no snmp-server traps ospfv3 state-change virtneighbor-state-change",
+ "no snmp-server traps ospfv3 state-change restart-status-change",
+ "no snmp-server traps ospfv3 state-change restart-helper-status-change",
+ "no snmp-server traps ospfv3 state-change restart-virtual-helper-status-change",
+ "no snmp-server traps power",
+ "no snmp-server traps rf",
+ "no snmp-server traps pim neighbor-change",
+ "no snmp-server traps pim invalid-message-received",
+ "no snmp-server traps pim rp-mapping-change",
+ "no snmp-server traps pim interface-state-change",
+ "no snmp-server traps rsvp lost-flow",
+ "no snmp-server traps rsvp new-flow",
+ "no snmp-server traps rsvp all",
+ "no snmp-server traps selective-vrf-download role-change",
+ "no snmp-server traps sensor",
+ "no snmp-server traps vrrp events",
+ "no snmp-server traps syslog",
+ "no snmp-server traps system",
+ "no snmp-server traps subscriber session-agg access-interface",
+ "no snmp-server traps subscriber session-agg node",
+ "no snmp-server traps vpls all",
+ "no snmp-server traps vpls full-clear",
+ "no snmp-server traps vpls full-raise",
+ "no snmp-server traps vpls status",
+ "no snmp-server traps snmp linkup",
+ "no snmp-server traps snmp linkdown",
+ "no snmp-server traps snmp coldstart",
+ "no snmp-server traps snmp warmstart",
+ "no snmp-server traps snmp authentication",
+ "no snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1",
+ "no snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+ "no snmp-server context c1",
+ "no snmp-server context c2",
+ "no snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1",
+ "no snmp-server interface GigabitEthernet0/0/0/2",
+ "no snmp-server mib bulkstat object-list test1",
+ "no snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl",
+ "no snmp-server target list test host 1.1.1.2",
+ "no snmp-server target list test2 vrf vrf2",
+ "no snmp-server vrf vrf1",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_snmp_server_replaced(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ snmp-server vrf vrf1
+ host 1.1.1.1 traps test1
+ !
+ snmp-server drop report acl IPv4 test1
+ snmp-server drop unknown-user
+ snmp-server ipv4 dscp af11
+ snmp-server ipv6 precedence routine
+ snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl
+ snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+ snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1
+ snmp-server queue-length 2
+ snmp-server trap-timeout 3
+ snmp-server trap throttle-time 12
+ snmp-server traps rf
+ snmp-server traps bfd
+ snmp-server traps bgp cbgp2
+ snmp-server traps pim neighbor-change
+ snmp-server traps pim invalid-message-received
+ snmp-server traps pim rp-mapping-change
+ snmp-server traps pim interface-state-change
+ snmp-server traps copy-complete
+ snmp-server traps hsrp
+ snmp-server traps ipsla
+ snmp-server traps msdp peer-state-change
+ snmp-server traps snmp linkup
+ snmp-server traps snmp linkdown
+ snmp-server traps snmp coldstart
+ snmp-server traps snmp warmstart
+ snmp-server traps snmp authentication
+ snmp-server traps vrrp events
+ snmp-server traps flash removal
+ snmp-server traps flash insertion
+ snmp-server traps ipsec tunnel stop
+ snmp-server traps ipsec tunnel start
+ snmp-server traps power
+ snmp-server traps config
+ snmp-server traps entity
+ snmp-server traps sensor
+ snmp-server traps selective-vrf-download role-change
+ snmp-server traps syslog
+ snmp-server traps system
+ snmp-server traps ospf lsa lsa-maxage
+ snmp-server traps ospf lsa lsa-originate
+ snmp-server traps ospf errors bad-packet
+ snmp-server traps ospf errors authentication-failure
+ snmp-server traps ospf errors config-error
+ snmp-server traps ospf errors virt-bad-packet
+ snmp-server traps ospf errors virt-authentication-failure
+ snmp-server traps ospf errors virt-config-error
+ snmp-server traps ospf retransmit packets
+ snmp-server traps ospf retransmit virt-packets
+ snmp-server traps ospf state-change if-state-change
+ snmp-server traps ospf state-change neighbor-state-change
+ snmp-server traps ospf state-change virtif-state-change
+ snmp-server traps ospf state-change virtneighbor-state-change
+ snmp-server traps rsvp all
+ snmp-server traps rsvp new-flow
+ snmp-server traps rsvp lost-flow
+ snmp-server traps l2tun sessions
+ snmp-server traps l2tun tunnel-up
+ snmp-server traps l2tun tunnel-down
+ snmp-server traps vpls all
+ snmp-server traps vpls status
+ snmp-server traps vpls full-clear
+ snmp-server traps vpls full-raise
+ snmp-server traps bulkstat collection
+ snmp-server traps diameter peerup
+ snmp-server traps diameter peerdown
+ snmp-server traps diameter protocolerror
+ snmp-server traps diameter permanentfail
+ snmp-server traps diameter transientfail
+ snmp-server traps l2vpn all
+ snmp-server traps l2vpn vc-up
+ snmp-server traps l2vpn vc-down
+ snmp-server traps bridgemib
+ snmp-server traps ospfv3 errors bad-packet
+ snmp-server traps ospfv3 errors config-error
+ snmp-server traps ospfv3 errors virt-config-error
+ snmp-server traps ospfv3 state-change neighbor-state-change
+ snmp-server traps ospfv3 state-change virtif-state-change
+ snmp-server traps ospfv3 state-change virtneighbor-state-change
+ snmp-server traps ospfv3 state-change restart-status-change
+ snmp-server traps ospfv3 state-change restart-helper-status-change
+ snmp-server traps ospfv3 state-change restart-virtual-helper-status-change
+ snmp-server traps subscriber session-agg node
+ snmp-server traps subscriber session-agg access-interface
+ snmp-server traps addrpool low
+ snmp-server traps addrpool high
+ snmp-server traps cisco-entity-ext
+ snmp-server traps entity-state operstatus
+ snmp-server traps entity-state switchover
+ snmp-server traps entity-redundancy all
+ snmp-server traps entity-redundancy status
+ snmp-server traps entity-redundancy switchover
+ snmp-server chassis-id test2
+ snmp-server contact t1
+ snmp-server location test1
+ snmp-server target list test host 1.1.1.2
+ snmp-server target list test2 vrf vrf2
+ snmp-server context c1
+ snmp-server context c2
+ snmp-server logging threshold oid-processing 1
+ snmp-server logging threshold pdu-processing 1
+ snmp-server mib bulkstat max-procmem-size 101
+ snmp-server mib bulkstat object-list test1
+ !
+ snmp-server mib bulkstat schema mib1
+ object-list test1
+ poll-interval 1
+ !
+ snmp-server mib bulkstat transfer-id test2
+ retry 1
+ buffer-size 1024
+ enable
+ format schemaASCII
+ retain 1
+ schema test2
+ !
+ snmp-server timeouts duplicate 0
+ snmp-server timeouts inQdrop 0
+ snmp-server timeouts subagent 1
+ snmp-server timeouts pdu stats 1
+ snmp-server timeouts threshold 0
+ snmp-server packetsize 490
+ snmp-server correlator rule rule1
+ timeout 5
+ !
+ snmp-server correlator ruleset rule1
+ !
+ snmp-server correlator buffer-size 1024
+ snmp-server trap-source GigabitEthernet0/0/0/2
+ snmp-server throttle-time 60
+ snmp-server community-map cm1 context c1 security-name s1 target-list t1
+ snmp-server inform retries 7
+ snmp-server overload-control 4 6
+ snmp-server ifmib internal cache max-duration 4
+ snmp-server mroutemib send-all-vrf
+ snmp-server notification-log-mib size 5
+ snmp-server notification-log-mib GlobalSize 5
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ vrfs=[
+ dict(
+ vrf="vrf2",
+ hosts=[
+ dict(
+ community="test1",
+ host="1.1.1.1",
+ traps=True,
+ ),
+ ],
+ ),
+ ],
+ users=[
+ dict(
+ Ipv4_acl="test1",
+ Ipv6_acl="test2",
+ group="test2",
+ user="u1",
+ v4_acl="v4acl",
+ ),
+ ],
+ timeouts=dict(
+ duplicate=0,
+ inQdrop=0,
+ pdu_stats=1,
+ subagent=1,
+ threshold=0,
+ ),
+ trap=dict(throttle_time=12),
+ targets=[
+ dict(name="test2", vrf="vrf2"),
+ dict(host="1.1.1.2", name="test"),
+ ],
+ ifmib=dict(internal_cache_max_duration=4),
+ inform=dict(retries=7),
+ chassis_id="test2",
+ packetsize=490,
+ queue_length=2,
+ throttle_time=60,
+ trap_source="GigabitEthernet0/0/0/2",
+ trap_timeout=3,
+ context=["c1", "c2"],
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[dict(name="rule1")],
+ rules=[dict(rule_name="rule1", timeout=5)],
+ ),
+ communities=[
+ dict(
+ name="test2",
+ ro=True,
+ sdrowner=True,
+ acl_v4="test",
+ acl_v6="test1",
+ ),
+ ],
+ community_maps=[
+ dict(
+ name="cm1",
+ context="c1",
+ target_list="t1",
+ security_name="s1",
+ ),
+ ],
+ drop=dict(report_IPv4="test1", unknown_user=True),
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ groups=[
+ dict(
+ Ipv4_acl="test",
+ Ipv6_acl="test1",
+ context="test3",
+ group="g2",
+ read="test1",
+ version="v1",
+ write="test2",
+ ),
+ ],
+ location="test",
+ logging_threshold_oid_processing=2,
+ logging_threshold_pdu_processing=1,
+ mib_bulkstat_max_procmem_size=101,
+ mroutemib_send_all_vrf=True,
+ mib_object_lists=["test1"],
+ overload_control=dict(
+ overload_drop_time=4,
+ overload_throttle_rate=6,
+ ),
+ mib_schema=[
+ dict(
+ name="mib1",
+ object_list="test1",
+ poll_interval=1,
+ ),
+ ],
+ notification_log_mib=dict(GlobalSize=5, size=5),
+ mib_bulkstat_transfer_ids=[
+ dict(
+ buffer_size=1024,
+ enable=True,
+ format_schemaASCI=True,
+ name="test2",
+ retain=1,
+ retry=1,
+ schema="test2",
+ ),
+ ],
+ traps=dict(
+ diameter=dict(
+ peerdown=True,
+ peerup=True,
+ permanentfail=True,
+ protocolerror=True,
+ transientfail=True,
+ ),
+ entity=True,
+ entity_redundancy=dict(
+ all=True,
+ status=True,
+ switchover=True,
+ ),
+ entity_state=dict(operstatus=True, switchover=True),
+ flash=dict(insertion=True, removal=True),
+ ipsec=dict(start=True, stop=True),
+ bridgemib=True,
+ bulkstat_collection=True,
+ cisco_entity_ext=True,
+ config=True,
+ copy_complete=True,
+ addrpool=dict(high=True, low=True),
+ bfd=True,
+ bgp=dict(cbgp2=True),
+ l2tun=dict(
+ sessions=True,
+ tunnel_down=True,
+ tunnel_up=True,
+ ),
+ l2vpn=dict(all=True, vc_down=True, vc_up=True),
+ msdp_peer_state_change=True,
+ ospf=dict(
+ errors=dict(
+ authentication_failure=True,
+ bad_packet=True,
+ config_error=True,
+ virt_authentication_failure=True,
+ virt_bad_packet=True,
+ virt_config_error=True,
+ ),
+ lsa=dict(lsa_maxage=True, lsa_originate=True),
+ retransmit=dict(packets=True, virt_packets=True),
+ state_change=dict(
+ if_state_change=True,
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ ),
+ ),
+ ospfv3=dict(
+ errors=dict(
+ bad_packet=True,
+ config_error=True,
+ virt_config_error=True,
+ ),
+ ),
+ pim=dict(
+ interface_state_change=True,
+ invalid_message_received=True,
+ neighbor_change=True,
+ rp_mapping_change=True,
+ ),
+ power=True,
+ rf=True,
+ rsvp=dict(all=True, lost_flow=True, new_flow=True),
+ selective_vrf_download_role_change=True,
+ sensor=True,
+ snmp=dict(
+ authentication=True,
+ coldstart=True,
+ linkdown=True,
+ linkup=True,
+ warmstart=True,
+ ),
+ subscriber=dict(
+ session_agg_access_interface=True,
+ session_agg_node=True,
+ ),
+ syslog=True,
+ system=True,
+ vpls=dict(
+ all=True,
+ full_clear=True,
+ full_raise=True,
+ status=True,
+ ),
+ vrrp_events=True,
+ ),
+ ),
+ state="replaced",
+ ),
+ )
+ commands = [
+ "no snmp-server contact t1",
+ "no snmp-server traps hsrp",
+ "no snmp-server traps ipsla",
+ "no snmp-server traps ospfv3 state-change neighbor-state-change",
+ "no snmp-server traps ospfv3 state-change virtif-state-change",
+ "no snmp-server traps ospfv3 state-change virtneighbor-state-change",
+ "no snmp-server traps ospfv3 state-change restart-status-change",
+ "no snmp-server traps ospfv3 state-change restart-helper-status-change",
+ "no snmp-server traps ospfv3 state-change restart-virtual-helper-status-change",
+ "no snmp-server vrf vrf1",
+ "snmp-server location test",
+ "snmp-server logging threshold oid-processing 2",
+ "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl",
+ "snmp-server vrf vrf2",
+ "host 1.1.1.1 traps test1",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_snmp_server_replaced_idempotent(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ snmp-server vrf vrf1
+ host 1.1.1.1 traps test1
+ !
+ snmp-server drop report acl IPv4 test1
+ snmp-server drop unknown-user
+ snmp-server ipv4 dscp af11
+ snmp-server ipv6 precedence routine
+ snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl
+ snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1
+ snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1
+ snmp-server queue-length 2
+ snmp-server trap-timeout 3
+ snmp-server trap throttle-time 12
+ snmp-server traps rf
+ snmp-server traps bfd
+ snmp-server traps bgp cbgp2
+ snmp-server traps pim neighbor-change
+ snmp-server traps pim invalid-message-received
+ snmp-server traps pim rp-mapping-change
+ snmp-server traps pim interface-state-change
+ snmp-server traps copy-complete
+ snmp-server traps hsrp
+ snmp-server traps ipsla
+ snmp-server traps msdp peer-state-change
+ snmp-server traps snmp linkup
+ snmp-server traps snmp linkdown
+ snmp-server traps snmp coldstart
+ snmp-server traps snmp warmstart
+ snmp-server traps snmp authentication
+ snmp-server traps vrrp events
+ snmp-server traps flash removal
+ snmp-server traps flash insertion
+ snmp-server traps ipsec tunnel stop
+ snmp-server traps ipsec tunnel start
+ snmp-server traps power
+ snmp-server traps config
+ snmp-server traps entity
+ snmp-server traps sensor
+ snmp-server traps selective-vrf-download role-change
+ snmp-server traps syslog
+ snmp-server traps system
+ snmp-server traps ospf lsa lsa-maxage
+ snmp-server traps ospf lsa lsa-originate
+ snmp-server traps ospf errors bad-packet
+ snmp-server traps ospf errors authentication-failure
+ snmp-server traps ospf errors config-error
+ snmp-server traps ospf errors virt-bad-packet
+ snmp-server traps ospf errors virt-authentication-failure
+ snmp-server traps ospf errors virt-config-error
+ snmp-server traps ospf retransmit packets
+ snmp-server traps ospf retransmit virt-packets
+ snmp-server traps ospf state-change if-state-change
+ snmp-server traps ospf state-change neighbor-state-change
+ snmp-server traps ospf state-change virtif-state-change
+ snmp-server traps ospf state-change virtneighbor-state-change
+ snmp-server traps rsvp all
+ snmp-server traps rsvp new-flow
+ snmp-server traps rsvp lost-flow
+ snmp-server traps l2tun sessions
+ snmp-server traps l2tun tunnel-up
+ snmp-server traps l2tun tunnel-down
+ snmp-server traps vpls all
+ snmp-server traps vpls status
+ snmp-server traps vpls full-clear
+ snmp-server traps vpls full-raise
+ snmp-server traps bulkstat collection
+ snmp-server traps diameter peerup
+ snmp-server traps diameter peerdown
+ snmp-server traps diameter protocolerror
+ snmp-server traps diameter permanentfail
+ snmp-server traps diameter transientfail
+ snmp-server traps l2vpn all
+ snmp-server traps l2vpn vc-up
+ snmp-server traps l2vpn vc-down
+ snmp-server traps bridgemib
+ snmp-server traps ospfv3 errors bad-packet
+ snmp-server traps ospfv3 errors config-error
+ snmp-server traps ospfv3 errors virt-config-error
+ snmp-server traps ospfv3 state-change neighbor-state-change
+ snmp-server traps ospfv3 state-change virtif-state-change
+ snmp-server traps ospfv3 state-change virtneighbor-state-change
+ snmp-server traps ospfv3 state-change restart-status-change
+ snmp-server traps ospfv3 state-change restart-helper-status-change
+ snmp-server traps ospfv3 state-change restart-virtual-helper-status-change
+ snmp-server traps subscriber session-agg node
+ snmp-server traps subscriber session-agg access-interface
+ snmp-server traps addrpool low
+ snmp-server traps addrpool high
+ snmp-server traps cisco-entity-ext
+ snmp-server traps entity-state operstatus
+ snmp-server traps entity-state switchover
+ snmp-server traps entity-redundancy all
+ snmp-server traps entity-redundancy status
+ snmp-server traps entity-redundancy switchover
+ snmp-server chassis-id test2
+ snmp-server location test1
+ snmp-server target list test host 1.1.1.2
+ snmp-server target list test2 vrf vrf2
+ snmp-server context c1
+ snmp-server context c2
+ snmp-server logging threshold oid-processing 1
+ snmp-server logging threshold pdu-processing 1
+ snmp-server mib bulkstat max-procmem-size 101
+ snmp-server mib bulkstat object-list test1
+ !
+ snmp-server mib bulkstat schema mib1
+ object-list test1
+ poll-interval 1
+ !
+ snmp-server mib bulkstat transfer-id test2
+ retry 1
+ buffer-size 1024
+ enable
+ format schemaASCII
+ retain 1
+ schema test2
+ !
+ snmp-server timeouts duplicate 0
+ snmp-server timeouts inQdrop 0
+ snmp-server timeouts subagent 1
+ snmp-server timeouts pdu stats 1
+ snmp-server timeouts threshold 0
+ snmp-server packetsize 490
+ snmp-server correlator rule rule1
+ timeout 5
+ !
+ snmp-server correlator ruleset rule1
+ !
+ snmp-server correlator buffer-size 1024
+ snmp-server trap-source GigabitEthernet0/0/0/2
+ snmp-server throttle-time 60
+ snmp-server community-map cm1 context c1 security-name s1 target-list t1
+ snmp-server inform retries 7
+ snmp-server overload-control 4 6
+ snmp-server ifmib internal cache max-duration 4
+ snmp-server mroutemib send-all-vrf
+ snmp-server notification-log-mib size 5
+ snmp-server notification-log-mib GlobalSize 5
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ hosts=[
+ dict(
+ community="test1",
+ host="1.1.1.1",
+ traps=True,
+ ),
+ ],
+ ),
+ ],
+ users=[
+ dict(
+ Ipv4_acl="test1",
+ Ipv6_acl="test2",
+ group="test2",
+ user="u1",
+ v4_acl="v4acl",
+ version="v1",
+ ),
+ ],
+ timeouts=dict(
+ duplicate=0,
+ inQdrop=0,
+ pdu_stats=1,
+ subagent=1,
+ threshold=0,
+ ),
+ trap=dict(throttle_time=12),
+ targets=[
+ dict(name="test2", vrf="vrf2"),
+ dict(host="1.1.1.2", name="test"),
+ ],
+ ifmib=dict(internal_cache_max_duration=4),
+ inform=dict(retries=7),
+ chassis_id="test2",
+ packetsize=490,
+ queue_length=2,
+ throttle_time=60,
+ trap_source="GigabitEthernet0/0/0/2",
+ trap_timeout=3,
+ context=["c1", "c2"],
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[dict(name="rule1")],
+ rules=[dict(rule_name="rule1", timeout=5)],
+ ),
+ communities=[
+ dict(
+ name="test2",
+ rw=True,
+ systemowner=True,
+ acl_v4="test",
+ acl_v6="test1",
+ ),
+ ],
+ community_maps=[
+ dict(
+ name="cm1",
+ context="c1",
+ target_list="t1",
+ security_name="s1",
+ ),
+ ],
+ drop=dict(report_IPv4="test1", unknown_user=True),
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ groups=[
+ dict(
+ Ipv4_acl="test",
+ Ipv6_acl="test1",
+ context="test3",
+ group="g2",
+ read="test1",
+ version="v1",
+ write="test2",
+ ),
+ ],
+ location="test1",
+ logging_threshold_oid_processing=1,
+ logging_threshold_pdu_processing=1,
+ mib_bulkstat_max_procmem_size=101,
+ mroutemib_send_all_vrf=True,
+ mib_object_lists=["test1"],
+ overload_control=dict(
+ overload_drop_time=4,
+ overload_throttle_rate=6,
+ ),
+ mib_schema=[
+ dict(
+ name="mib1",
+ object_list="test1",
+ poll_interval=1,
+ ),
+ ],
+ notification_log_mib=dict(GlobalSize=5, size=5),
+ mib_bulkstat_transfer_ids=[
+ dict(
+ buffer_size=1024,
+ enable=True,
+ format_schemaASCI=True,
+ name="test2",
+ retain=1,
+ retry=1,
+ schema="test2",
+ ),
+ ],
+ traps=dict(
+ diameter=dict(
+ peerdown=True,
+ peerup=True,
+ permanentfail=True,
+ protocolerror=True,
+ transientfail=True,
+ ),
+ entity=True,
+ entity_redundancy=dict(
+ all=True,
+ status=True,
+ switchover=True,
+ ),
+ entity_state=dict(operstatus=True, switchover=True),
+ flash=dict(insertion=True, removal=True),
+ hsrp=True,
+ ipsla=True,
+ ipsec=dict(start=True, stop=True),
+ bridgemib=True,
+ bulkstat_collection=True,
+ cisco_entity_ext=True,
+ config=True,
+ copy_complete=True,
+ addrpool=dict(high=True, low=True),
+ bfd=True,
+ bgp=dict(cbgp2=True),
+ l2tun=dict(
+ sessions=True,
+ tunnel_down=True,
+ tunnel_up=True,
+ ),
+ l2vpn=dict(all=True, vc_down=True, vc_up=True),
+ msdp_peer_state_change=True,
+ ospf=dict(
+ errors=dict(
+ authentication_failure=True,
+ bad_packet=True,
+ config_error=True,
+ virt_authentication_failure=True,
+ virt_bad_packet=True,
+ virt_config_error=True,
+ ),
+ lsa=dict(lsa_maxage=True, lsa_originate=True),
+ retransmit=dict(packets=True, virt_packets=True),
+ state_change=dict(
+ if_state_change=True,
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ ),
+ ),
+ ospfv3=dict(
+ errors=dict(
+ bad_packet=True,
+ config_error=True,
+ virt_config_error=True,
+ ),
+ state_change=dict(
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ restart_helper_status_change=True,
+ restart_status_change=True,
+ restart_virtual_helper_status_change=True,
+ ),
+ ),
+ pim=dict(
+ interface_state_change=True,
+ invalid_message_received=True,
+ neighbor_change=True,
+ rp_mapping_change=True,
+ ),
+ power=True,
+ rf=True,
+ rsvp=dict(all=True, lost_flow=True, new_flow=True),
+ selective_vrf_download_role_change=True,
+ sensor=True,
+ snmp=dict(
+ authentication=True,
+ coldstart=True,
+ linkdown=True,
+ linkup=True,
+ warmstart=True,
+ ),
+ subscriber=dict(
+ session_agg_access_interface=True,
+ session_agg_node=True,
+ ),
+ syslog=True,
+ system=True,
+ vpls=dict(
+ all=True,
+ full_clear=True,
+ full_raise=True,
+ status=True,
+ ),
+ vrrp_events=True,
+ ),
+ ),
+ state="replaced",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_snmp_server_overridden(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ snmp-server vrf vrf1
+ host 1.1.1.1 traps test1
+ !
+ snmp-server drop report acl IPv4 test1
+ snmp-server drop unknown-user
+ snmp-server ipv4 dscp af11
+ snmp-server ipv6 precedence routine
+ snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl
+ snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+ snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1
+ snmp-server queue-length 2
+ snmp-server trap-timeout 3
+ snmp-server trap throttle-time 12
+ snmp-server traps rf
+ snmp-server traps bfd
+ snmp-server traps bgp cbgp2
+ snmp-server traps pim neighbor-change
+ snmp-server traps pim invalid-message-received
+ snmp-server traps pim rp-mapping-change
+ snmp-server traps pim interface-state-change
+ snmp-server traps copy-complete
+ snmp-server traps hsrp
+ snmp-server traps ipsla
+ snmp-server traps msdp peer-state-change
+ snmp-server traps snmp linkup
+ snmp-server traps snmp linkdown
+ snmp-server traps snmp coldstart
+ snmp-server traps snmp warmstart
+ snmp-server traps snmp authentication
+ snmp-server traps vrrp events
+ snmp-server traps flash removal
+ snmp-server traps flash insertion
+ snmp-server traps ipsec tunnel stop
+ snmp-server traps ipsec tunnel start
+ snmp-server traps power
+ snmp-server traps config
+ snmp-server traps entity
+ snmp-server traps sensor
+ snmp-server traps selective-vrf-download role-change
+ snmp-server traps syslog
+ snmp-server traps system
+ snmp-server traps ospf lsa lsa-maxage
+ snmp-server traps ospf lsa lsa-originate
+ snmp-server traps ospf errors bad-packet
+ snmp-server traps ospf errors authentication-failure
+ snmp-server traps ospf errors config-error
+ snmp-server traps ospf errors virt-bad-packet
+ snmp-server traps ospf errors virt-authentication-failure
+ snmp-server traps ospf errors virt-config-error
+ snmp-server traps ospf retransmit packets
+ snmp-server traps ospf retransmit virt-packets
+ snmp-server traps ospf state-change if-state-change
+ snmp-server traps ospf state-change neighbor-state-change
+ snmp-server traps ospf state-change virtif-state-change
+ snmp-server traps ospf state-change virtneighbor-state-change
+ snmp-server traps rsvp all
+ snmp-server traps rsvp new-flow
+ snmp-server traps rsvp lost-flow
+ snmp-server traps l2tun sessions
+ snmp-server traps l2tun tunnel-up
+ snmp-server traps l2tun tunnel-down
+ snmp-server traps vpls all
+ snmp-server traps vpls status
+ snmp-server traps vpls full-clear
+ snmp-server traps vpls full-raise
+ snmp-server traps bulkstat collection
+ snmp-server traps diameter peerup
+ snmp-server traps diameter peerdown
+ snmp-server traps diameter protocolerror
+ snmp-server traps diameter permanentfail
+ snmp-server traps diameter transientfail
+ snmp-server traps l2vpn all
+ snmp-server traps l2vpn vc-up
+ snmp-server traps l2vpn vc-down
+ snmp-server traps bridgemib
+ snmp-server traps ospfv3 errors bad-packet
+ snmp-server traps ospfv3 errors config-error
+ snmp-server traps ospfv3 errors virt-config-error
+ snmp-server traps ospfv3 state-change neighbor-state-change
+ snmp-server traps ospfv3 state-change virtif-state-change
+ snmp-server traps ospfv3 state-change virtneighbor-state-change
+ snmp-server traps ospfv3 state-change restart-status-change
+ snmp-server traps ospfv3 state-change restart-helper-status-change
+ snmp-server traps ospfv3 state-change restart-virtual-helper-status-change
+ snmp-server traps subscriber session-agg node
+ snmp-server traps subscriber session-agg access-interface
+ snmp-server traps addrpool low
+ snmp-server traps addrpool high
+ snmp-server traps cisco-entity-ext
+ snmp-server traps entity-state operstatus
+ snmp-server traps entity-state switchover
+ snmp-server traps entity-redundancy all
+ snmp-server traps entity-redundancy status
+ snmp-server traps entity-redundancy switchover
+ snmp-server chassis-id test2
+ snmp-server contact t1
+ snmp-server location test1
+ snmp-server target list test host 1.1.1.2
+ snmp-server target list test2 vrf vrf2
+ snmp-server context c1
+ snmp-server context c2
+ snmp-server logging threshold oid-processing 1
+ snmp-server logging threshold pdu-processing 1
+ snmp-server mib bulkstat max-procmem-size 101
+ snmp-server mib bulkstat object-list test1
+ !
+ snmp-server mib bulkstat schema mib1
+ object-list test1
+ poll-interval 1
+ !
+ snmp-server mib bulkstat transfer-id test2
+ retry 1
+ buffer-size 1024
+ enable
+ format schemaASCII
+ retain 1
+ schema test2
+ !
+ snmp-server timeouts duplicate 0
+ snmp-server timeouts inQdrop 0
+ snmp-server timeouts subagent 1
+ snmp-server timeouts pdu stats 1
+ snmp-server timeouts threshold 0
+ snmp-server packetsize 490
+ snmp-server correlator rule rule1
+ timeout 5
+ !
+ snmp-server correlator ruleset rule1
+ !
+ snmp-server correlator buffer-size 1024
+ snmp-server trap-source GigabitEthernet0/0/0/2
+ snmp-server throttle-time 60
+ snmp-server community-map cm1 context c1 security-name s1 target-list t1
+ snmp-server inform retries 7
+ snmp-server overload-control 4 6
+ snmp-server ifmib internal cache max-duration 4
+ snmp-server mroutemib send-all-vrf
+ snmp-server notification-log-mib size 5
+ snmp-server notification-log-mib GlobalSize 5
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ vrfs=[
+ dict(
+ vrf="vrf2",
+ hosts=[
+ dict(
+ community="test1",
+ host="1.1.1.1",
+ traps=True,
+ ),
+ ],
+ ),
+ ],
+ users=[
+ dict(
+ Ipv4_acl="test1",
+ Ipv6_acl="test2",
+ group="test2",
+ user="u1",
+ v4_acl="v4acl",
+ ),
+ ],
+ timeouts=dict(
+ duplicate=0,
+ inQdrop=0,
+ pdu_stats=1,
+ subagent=1,
+ threshold=0,
+ ),
+ trap=dict(throttle_time=12),
+ targets=[
+ dict(name="test2", vrf="vrf2"),
+ dict(host="1.1.1.2", name="test"),
+ ],
+ ifmib=dict(internal_cache_max_duration=4),
+ inform=dict(retries=7),
+ chassis_id="test2",
+ packetsize=490,
+ queue_length=2,
+ throttle_time=60,
+ trap_source="GigabitEthernet0/0/0/2",
+ trap_timeout=3,
+ context=["c1", "c2"],
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[dict(name="rule1")],
+ rules=[dict(rule_name="rule1", timeout=5)],
+ ),
+ communities=[
+ dict(
+ name="test2",
+ ro=True,
+ sdrowner=True,
+ acl_v4="test",
+ acl_v6="test1",
+ ),
+ ],
+ community_maps=[
+ dict(
+ name="cm1",
+ context="c1",
+ target_list="t1",
+ security_name="s1",
+ ),
+ ],
+ drop=dict(report_IPv4="test1", unknown_user=True),
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ groups=[
+ dict(
+ Ipv4_acl="test",
+ Ipv6_acl="test1",
+ context="test3",
+ group="g2",
+ read="test1",
+ version="v1",
+ write="test2",
+ ),
+ ],
+ location="test",
+ logging_threshold_oid_processing=2,
+ logging_threshold_pdu_processing=1,
+ mib_bulkstat_max_procmem_size=101,
+ mroutemib_send_all_vrf=True,
+ mib_object_lists=["test1"],
+ overload_control=dict(
+ overload_drop_time=4,
+ overload_throttle_rate=6,
+ ),
+ mib_schema=[
+ dict(
+ name="mib1",
+ object_list="test1",
+ poll_interval=1,
+ ),
+ ],
+ notification_log_mib=dict(GlobalSize=5, size=5),
+ mib_bulkstat_transfer_ids=[
+ dict(
+ buffer_size=1024,
+ enable=True,
+ format_schemaASCI=True,
+ name="test2",
+ retain=1,
+ retry=1,
+ schema="test2",
+ ),
+ ],
+ traps=dict(
+ diameter=dict(
+ peerdown=True,
+ peerup=True,
+ permanentfail=True,
+ protocolerror=True,
+ transientfail=True,
+ ),
+ entity=True,
+ entity_redundancy=dict(
+ all=True,
+ status=True,
+ switchover=True,
+ ),
+ entity_state=dict(operstatus=True, switchover=True),
+ flash=dict(insertion=True, removal=True),
+ ipsec=dict(start=True, stop=True),
+ bridgemib=True,
+ bulkstat_collection=True,
+ cisco_entity_ext=True,
+ config=True,
+ copy_complete=True,
+ addrpool=dict(high=True, low=True),
+ bfd=True,
+ bgp=dict(cbgp2=True),
+ l2tun=dict(
+ sessions=True,
+ tunnel_down=True,
+ tunnel_up=True,
+ ),
+ l2vpn=dict(all=True, vc_down=True, vc_up=True),
+ msdp_peer_state_change=True,
+ ospf=dict(
+ errors=dict(
+ authentication_failure=True,
+ bad_packet=True,
+ config_error=True,
+ virt_authentication_failure=True,
+ virt_bad_packet=True,
+ virt_config_error=True,
+ ),
+ lsa=dict(lsa_maxage=True, lsa_originate=True),
+ retransmit=dict(packets=True, virt_packets=True),
+ state_change=dict(
+ if_state_change=True,
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ ),
+ ),
+ ospfv3=dict(
+ errors=dict(
+ bad_packet=True,
+ config_error=True,
+ virt_config_error=True,
+ ),
+ ),
+ pim=dict(
+ interface_state_change=True,
+ invalid_message_received=True,
+ neighbor_change=True,
+ rp_mapping_change=True,
+ ),
+ power=True,
+ rf=True,
+ rsvp=dict(all=True, lost_flow=True, new_flow=True),
+ selective_vrf_download_role_change=True,
+ sensor=True,
+ snmp=dict(
+ authentication=True,
+ coldstart=True,
+ linkdown=True,
+ linkup=True,
+ warmstart=True,
+ ),
+ subscriber=dict(
+ session_agg_access_interface=True,
+ session_agg_node=True,
+ ),
+ syslog=True,
+ system=True,
+ vpls=dict(
+ all=True,
+ full_clear=True,
+ full_raise=True,
+ status=True,
+ ),
+ vrrp_events=True,
+ ),
+ ),
+ state="overridden",
+ ),
+ )
+ commands = [
+ "no snmp-server contact t1",
+ "no snmp-server traps hsrp",
+ "no snmp-server traps ipsla",
+ "no snmp-server traps ospfv3 state-change neighbor-state-change",
+ "no snmp-server traps ospfv3 state-change virtif-state-change",
+ "no snmp-server traps ospfv3 state-change virtneighbor-state-change",
+ "no snmp-server traps ospfv3 state-change restart-status-change",
+ "no snmp-server traps ospfv3 state-change restart-helper-status-change",
+ "no snmp-server traps ospfv3 state-change restart-virtual-helper-status-change",
+ "no snmp-server vrf vrf1",
+ "snmp-server location test",
+ "snmp-server logging threshold oid-processing 2",
+ "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl",
+ "snmp-server vrf vrf2",
+ "host 1.1.1.1 traps test1",
+ ]
+ result = self.execute_module(changed=True)
+ self.assertEqual(sorted(result["commands"]), sorted(commands))
+
+ def test_iosxr_snmp_server_overridden_idempotent(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ snmp-server vrf vrf1
+ host 1.1.1.1 traps test1
+ !
+ snmp-server drop report acl IPv4 test1
+ snmp-server drop unknown-user
+ snmp-server ipv4 dscp af11
+ snmp-server ipv6 precedence routine
+ snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl
+ snmp-server community test2 RW SystemOwner IPv4 test IPv6 test1
+ snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1
+ snmp-server queue-length 2
+ snmp-server trap-timeout 3
+ snmp-server trap throttle-time 12
+ snmp-server traps rf
+ snmp-server traps bfd
+ snmp-server traps bgp cbgp2
+ snmp-server traps pim neighbor-change
+ snmp-server traps pim invalid-message-received
+ snmp-server traps pim rp-mapping-change
+ snmp-server traps pim interface-state-change
+ snmp-server traps copy-complete
+ snmp-server traps hsrp
+ snmp-server traps ipsla
+ snmp-server traps msdp peer-state-change
+ snmp-server traps snmp linkup
+ snmp-server traps snmp linkdown
+ snmp-server traps snmp coldstart
+ snmp-server traps snmp warmstart
+ snmp-server traps snmp authentication
+ snmp-server traps vrrp events
+ snmp-server traps flash removal
+ snmp-server traps flash insertion
+ snmp-server traps ipsec tunnel stop
+ snmp-server traps ipsec tunnel start
+ snmp-server traps power
+ snmp-server traps config
+ snmp-server traps entity
+ snmp-server traps sensor
+ snmp-server traps selective-vrf-download role-change
+ snmp-server traps syslog
+ snmp-server traps system
+ snmp-server traps ospf lsa lsa-maxage
+ snmp-server traps ospf lsa lsa-originate
+ snmp-server traps ospf errors bad-packet
+ snmp-server traps ospf errors authentication-failure
+ snmp-server traps ospf errors config-error
+ snmp-server traps ospf errors virt-bad-packet
+ snmp-server traps ospf errors virt-authentication-failure
+ snmp-server traps ospf errors virt-config-error
+ snmp-server traps ospf retransmit packets
+ snmp-server traps ospf retransmit virt-packets
+ snmp-server traps ospf state-change if-state-change
+ snmp-server traps ospf state-change neighbor-state-change
+ snmp-server traps ospf state-change virtif-state-change
+ snmp-server traps ospf state-change virtneighbor-state-change
+ snmp-server traps rsvp all
+ snmp-server traps rsvp new-flow
+ snmp-server traps rsvp lost-flow
+ snmp-server traps l2tun sessions
+ snmp-server traps l2tun tunnel-up
+ snmp-server traps l2tun tunnel-down
+ snmp-server traps vpls all
+ snmp-server traps vpls status
+ snmp-server traps vpls full-clear
+ snmp-server traps vpls full-raise
+ snmp-server traps bulkstat collection
+ snmp-server traps diameter peerup
+ snmp-server traps diameter peerdown
+ snmp-server traps diameter protocolerror
+ snmp-server traps diameter permanentfail
+ snmp-server traps diameter transientfail
+ snmp-server traps l2vpn all
+ snmp-server traps l2vpn vc-up
+ snmp-server traps l2vpn vc-down
+ snmp-server traps bridgemib
+ snmp-server traps ospfv3 errors bad-packet
+ snmp-server traps ospfv3 errors config-error
+ snmp-server traps ospfv3 errors virt-config-error
+ snmp-server traps ospfv3 state-change neighbor-state-change
+ snmp-server traps ospfv3 state-change virtif-state-change
+ snmp-server traps ospfv3 state-change virtneighbor-state-change
+ snmp-server traps ospfv3 state-change restart-status-change
+ snmp-server traps ospfv3 state-change restart-helper-status-change
+ snmp-server traps ospfv3 state-change restart-virtual-helper-status-change
+ snmp-server traps subscriber session-agg node
+ snmp-server traps subscriber session-agg access-interface
+ snmp-server traps addrpool low
+ snmp-server traps addrpool high
+ snmp-server traps cisco-entity-ext
+ snmp-server traps entity-state operstatus
+ snmp-server traps entity-state switchover
+ snmp-server traps entity-redundancy all
+ snmp-server traps entity-redundancy status
+ snmp-server traps entity-redundancy switchover
+ snmp-server chassis-id test2
+ snmp-server location test1
+ snmp-server target list test host 1.1.1.2
+ snmp-server target list test2 vrf vrf2
+ snmp-server context c1
+ snmp-server context c2
+ snmp-server logging threshold oid-processing 1
+ snmp-server logging threshold pdu-processing 1
+ snmp-server mib bulkstat max-procmem-size 101
+ snmp-server mib bulkstat object-list test1
+ !
+ snmp-server mib bulkstat schema mib1
+ object-list test1
+ poll-interval 1
+ !
+ snmp-server mib bulkstat transfer-id test2
+ retry 1
+ buffer-size 1024
+ enable
+ format schemaASCII
+ retain 1
+ schema test2
+ !
+ snmp-server timeouts duplicate 0
+ snmp-server timeouts inQdrop 0
+ snmp-server timeouts subagent 1
+ snmp-server timeouts pdu stats 1
+ snmp-server timeouts threshold 0
+ snmp-server packetsize 490
+ snmp-server correlator rule rule1
+ timeout 5
+ !
+ snmp-server correlator ruleset rule1
+ !
+ snmp-server correlator buffer-size 1024
+ snmp-server trap-source GigabitEthernet0/0/0/2
+ snmp-server throttle-time 60
+ snmp-server community-map cm1 context c1 security-name s1 target-list t1
+ snmp-server inform retries 7
+ snmp-server overload-control 4 6
+ snmp-server ifmib internal cache max-duration 4
+ snmp-server mroutemib send-all-vrf
+ snmp-server notification-log-mib size 5
+ snmp-server notification-log-mib GlobalSize 5
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(
+ dict(
+ config=dict(
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ hosts=[
+ dict(
+ community="test1",
+ host="1.1.1.1",
+ traps=True,
+ ),
+ ],
+ ),
+ ],
+ users=[
+ dict(
+ Ipv4_acl="test1",
+ Ipv6_acl="test2",
+ group="test2",
+ user="u1",
+ v4_acl="v4acl",
+ version="v1",
+ ),
+ ],
+ timeouts=dict(
+ duplicate=0,
+ inQdrop=0,
+ pdu_stats=1,
+ subagent=1,
+ threshold=0,
+ ),
+ trap=dict(throttle_time=12),
+ targets=[
+ dict(name="test2", vrf="vrf2"),
+ dict(host="1.1.1.2", name="test"),
+ ],
+ ifmib=dict(internal_cache_max_duration=4),
+ inform=dict(retries=7),
+ chassis_id="test2",
+ packetsize=490,
+ queue_length=2,
+ throttle_time=60,
+ trap_source="GigabitEthernet0/0/0/2",
+ trap_timeout=3,
+ context=["c1", "c2"],
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[dict(name="rule1")],
+ rules=[dict(rule_name="rule1", timeout=5)],
+ ),
+ communities=[
+ dict(
+ name="test2",
+ rw=True,
+ systemowner=True,
+ acl_v4="test",
+ acl_v6="test1",
+ ),
+ ],
+ community_maps=[
+ dict(
+ name="cm1",
+ context="c1",
+ target_list="t1",
+ security_name="s1",
+ ),
+ ],
+ drop=dict(report_IPv4="test1", unknown_user=True),
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ groups=[
+ dict(
+ Ipv4_acl="test",
+ Ipv6_acl="test1",
+ context="test3",
+ group="g2",
+ read="test1",
+ version="v1",
+ write="test2",
+ ),
+ ],
+ location="test1",
+ logging_threshold_oid_processing=1,
+ logging_threshold_pdu_processing=1,
+ mib_bulkstat_max_procmem_size=101,
+ mroutemib_send_all_vrf=True,
+ mib_object_lists=["test1"],
+ overload_control=dict(
+ overload_drop_time=4,
+ overload_throttle_rate=6,
+ ),
+ mib_schema=[
+ dict(
+ name="mib1",
+ object_list="test1",
+ poll_interval=1,
+ ),
+ ],
+ notification_log_mib=dict(GlobalSize=5, size=5),
+ mib_bulkstat_transfer_ids=[
+ dict(
+ buffer_size=1024,
+ enable=True,
+ format_schemaASCI=True,
+ name="test2",
+ retain=1,
+ retry=1,
+ schema="test2",
+ ),
+ ],
+ traps=dict(
+ diameter=dict(
+ peerdown=True,
+ peerup=True,
+ permanentfail=True,
+ protocolerror=True,
+ transientfail=True,
+ ),
+ entity=True,
+ entity_redundancy=dict(
+ all=True,
+ status=True,
+ switchover=True,
+ ),
+ entity_state=dict(operstatus=True, switchover=True),
+ flash=dict(insertion=True, removal=True),
+ hsrp=True,
+ ipsla=True,
+ ipsec=dict(start=True, stop=True),
+ bridgemib=True,
+ bulkstat_collection=True,
+ cisco_entity_ext=True,
+ config=True,
+ copy_complete=True,
+ addrpool=dict(high=True, low=True),
+ bfd=True,
+ bgp=dict(cbgp2=True),
+ l2tun=dict(
+ sessions=True,
+ tunnel_down=True,
+ tunnel_up=True,
+ ),
+ l2vpn=dict(all=True, vc_down=True, vc_up=True),
+ msdp_peer_state_change=True,
+ ospf=dict(
+ errors=dict(
+ authentication_failure=True,
+ bad_packet=True,
+ config_error=True,
+ virt_authentication_failure=True,
+ virt_bad_packet=True,
+ virt_config_error=True,
+ ),
+ lsa=dict(lsa_maxage=True, lsa_originate=True),
+ retransmit=dict(packets=True, virt_packets=True),
+ state_change=dict(
+ if_state_change=True,
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ ),
+ ),
+ ospfv3=dict(
+ errors=dict(
+ bad_packet=True,
+ config_error=True,
+ virt_config_error=True,
+ ),
+ state_change=dict(
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ restart_helper_status_change=True,
+ restart_status_change=True,
+ restart_virtual_helper_status_change=True,
+ ),
+ ),
+ pim=dict(
+ interface_state_change=True,
+ invalid_message_received=True,
+ neighbor_change=True,
+ rp_mapping_change=True,
+ ),
+ power=True,
+ rf=True,
+ rsvp=dict(all=True, lost_flow=True, new_flow=True),
+ selective_vrf_download_role_change=True,
+ sensor=True,
+ snmp=dict(
+ authentication=True,
+ coldstart=True,
+ linkdown=True,
+ linkup=True,
+ warmstart=True,
+ ),
+ subscriber=dict(
+ session_agg_access_interface=True,
+ session_agg_node=True,
+ ),
+ syslog=True,
+ system=True,
+ vpls=dict(
+ all=True,
+ full_clear=True,
+ full_raise=True,
+ status=True,
+ ),
+ vrrp_events=True,
+ ),
+ ),
+ state="overridden",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_snmp_server_rendered(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ config=dict(
+ vrfs=[
+ dict(
+ vrf="vrf1",
+ hosts=[
+ dict(
+ community="test1",
+ host="1.1.1.1",
+ traps=True,
+ ),
+ ],
+ ),
+ ],
+ users=[
+ dict(
+ Ipv4_acl="test1",
+ Ipv6_acl="test2",
+ group="test2",
+ user="u1",
+ v4_acl="v4acl",
+ ),
+ ],
+ timeouts=dict(
+ duplicate=0,
+ inQdrop=0,
+ pdu_stats=1,
+ subagent=1,
+ threshold=0,
+ ),
+ trap=dict(throttle_time=12),
+ targets=[
+ dict(name="test2", vrf="vrf2"),
+ dict(host="1.1.1.2", name="test"),
+ ],
+ ifmib=dict(internal_cache_max_duration=4),
+ inform=dict(retries=7),
+ chassis_id="test2",
+ packetsize=490,
+ queue_length=2,
+ throttle_time=60,
+ trap_source="GigabitEthernet0/0/0/2",
+ trap_timeout=3,
+ context=["c1", "c2"],
+ correlator=dict(
+ buffer_size=1024,
+ rule_sets=[dict(name="rule1")],
+ rules=[dict(rule_name="rule1", timeout=5)],
+ ),
+ communities=[
+ dict(
+ name="test2",
+ ro=True,
+ sdrowner=True,
+ acl_v4="test",
+ acl_v6="test1",
+ ),
+ ],
+ community_maps=[
+ dict(
+ name="cm1",
+ context="c1",
+ target_list="t1",
+ security_name="s1",
+ ),
+ ],
+ drop=dict(report_IPv4="test1", unknown_user=True),
+ ipv6=dict(precedence="routine"),
+ ipv4=dict(dscp="af11"),
+ groups=[
+ dict(
+ Ipv4_acl="test",
+ Ipv6_acl="test1",
+ context="test3",
+ group="g2",
+ read="test1",
+ version="v1",
+ write="test2",
+ ),
+ ],
+ interfaces=[dict(name=" GigabitEthernet0/0/0/2")],
+ location="test1",
+ logging_threshold_oid_processing=1,
+ logging_threshold_pdu_processing=1,
+ mib_bulkstat_max_procmem_size=101,
+ mroutemib_send_all_vrf=True,
+ mib_object_lists=["test1"],
+ overload_control=dict(
+ overload_drop_time=4,
+ overload_throttle_rate=6,
+ ),
+ mib_schema=[
+ dict(
+ name="mib1",
+ object_list="test1",
+ poll_interval=1,
+ ),
+ ],
+ notification_log_mib=dict(GlobalSize=5, size=5),
+ mib_bulkstat_transfer_ids=[
+ dict(
+ buffer_size=1024,
+ enable=True,
+ format_schemaASCI=True,
+ name="test2",
+ retain=1,
+ retry=1,
+ schema="test2",
+ ),
+ ],
+ traps=dict(
+ diameter=dict(
+ peerdown=True,
+ peerup=True,
+ permanentfail=True,
+ protocolerror=True,
+ transientfail=True,
+ ),
+ entity=True,
+ entity_redundancy=dict(
+ all=True,
+ status=True,
+ switchover=True,
+ ),
+ entity_state=dict(operstatus=True, switchover=True),
+ flash=dict(insertion=True, removal=True),
+ hsrp=True,
+ ipsla=True,
+ ipsec=dict(start=True, stop=True),
+ bridgemib=True,
+ bulkstat_collection=True,
+ cisco_entity_ext=True,
+ config=True,
+ copy_complete=True,
+ addrpool=dict(high=True, low=True),
+ bfd=True,
+ bgp=dict(cbgp2=True),
+ l2tun=dict(
+ sessions=True,
+ tunnel_down=True,
+ tunnel_up=True,
+ ),
+ l2vpn=dict(all=True, vc_down=True, vc_up=True),
+ msdp_peer_state_change=True,
+ ospf=dict(
+ errors=dict(
+ authentication_failure=True,
+ bad_packet=True,
+ config_error=True,
+ virt_authentication_failure=True,
+ virt_bad_packet=True,
+ virt_config_error=True,
+ ),
+ lsa=dict(lsa_maxage=True, lsa_originate=True),
+ retransmit=dict(packets=True, virt_packets=True),
+ state_change=dict(
+ if_state_change=True,
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ ),
+ ),
+ ospfv3=dict(
+ errors=dict(
+ bad_packet=True,
+ config_error=True,
+ virt_config_error=True,
+ ),
+ state_change=dict(
+ neighbor_state_change=True,
+ virtif_state_change=True,
+ virtneighbor_state_change=True,
+ restart_helper_status_change=True,
+ restart_status_change=True,
+ restart_virtual_helper_status_change=True,
+ ),
+ ),
+ pim=dict(
+ interface_state_change=True,
+ invalid_message_received=True,
+ neighbor_change=True,
+ rp_mapping_change=True,
+ ),
+ power=True,
+ rf=True,
+ rsvp=dict(all=True, lost_flow=True, new_flow=True),
+ selective_vrf_download_role_change=True,
+ sensor=True,
+ snmp=dict(
+ authentication=True,
+ coldstart=True,
+ linkdown=True,
+ linkup=True,
+ warmstart=True,
+ ),
+ subscriber=dict(
+ session_agg_access_interface=True,
+ session_agg_node=True,
+ ),
+ syslog=True,
+ system=True,
+ vpls=dict(
+ all=True,
+ full_clear=True,
+ full_raise=True,
+ status=True,
+ ),
+ vrrp_events=True,
+ ),
+ ),
+ state="rendered",
+ ),
+ )
+ commands = [
+ "snmp-server chassis-id test2",
+ "snmp-server correlator buffer-size 1024",
+ "snmp-server ipv4 dscp af11",
+ "snmp-server ipv6 precedence routine",
+ "snmp-server location test1",
+ "snmp-server logging threshold oid-processing 1",
+ "snmp-server logging threshold pdu-processing 1",
+ "snmp-server mib bulkstat max-procmem-size 101",
+ "snmp-server mroutemib send-all-vrf",
+ "snmp-server overload-control 4 6",
+ "snmp-server packetsize 490",
+ "snmp-server queue-length 2",
+ "snmp-server throttle-time 60",
+ "snmp-server trap-source GigabitEthernet0/0/0/2",
+ "snmp-server trap-timeout 3",
+ "snmp-server drop report acl IPv4 test1",
+ "snmp-server drop unknown-user",
+ "snmp-server ifmib internal cache max-duration 4",
+ "snmp-server inform retries 7",
+ "snmp-server notification-log-mib size 5",
+ "snmp-server notification-log-mib GlobalSize 5",
+ "snmp-server trap throttle-time 12",
+ "snmp-server timeouts threshold 0",
+ "snmp-server timeouts pdu stats 1",
+ "snmp-server timeouts subagent 1",
+ "snmp-server timeouts inQdrop 0",
+ "snmp-server timeouts duplicate 0",
+ "snmp-server traps addrpool low",
+ "snmp-server traps addrpool high",
+ "snmp-server traps bfd",
+ "snmp-server traps bgp cbgp2",
+ "snmp-server traps bulkstat collection",
+ "snmp-server traps bridgemib",
+ "snmp-server traps copy-complete",
+ "snmp-server traps cisco-entity-ext",
+ "snmp-server traps config",
+ "snmp-server traps diameter peerdown",
+ "snmp-server traps diameter peerup",
+ "snmp-server traps diameter protocolerror",
+ "snmp-server traps diameter permanentfail",
+ "snmp-server traps diameter transientfail",
+ "snmp-server traps entity",
+ "snmp-server traps entity-redundancy all",
+ "snmp-server traps entity-redundancy status",
+ "snmp-server traps entity-redundancy switchover",
+ "snmp-server traps entity-state operstatus",
+ "snmp-server traps entity-state switchover",
+ "snmp-server traps flash removal",
+ "snmp-server traps flash insertion",
+ "snmp-server traps hsrp",
+ "snmp-server traps ipsla",
+ "snmp-server traps ipsec tunnel start",
+ "snmp-server traps ipsec tunnel stop",
+ "snmp-server traps l2tun sessions",
+ "snmp-server traps l2tun tunnel-up",
+ "snmp-server traps l2tun tunnel-down",
+ "snmp-server traps l2vpn all",
+ "snmp-server traps l2vpn vc-up",
+ "snmp-server traps l2vpn vc-down",
+ "snmp-server traps msdp peer-state-change",
+ "snmp-server traps ospf retransmit virt-packets",
+ "snmp-server traps ospf retransmit packets",
+ "snmp-server traps ospf lsa lsa-originate",
+ "snmp-server traps ospf lsa lsa-maxage",
+ "snmp-server traps ospf errors bad-packet",
+ "snmp-server traps ospf errors authentication-failure",
+ "snmp-server traps ospf errors config-error",
+ "snmp-server traps ospf errors virt-bad-packet",
+ "snmp-server traps ospf errors virt-authentication-failure",
+ "snmp-server traps ospf errors virt-config-error",
+ "snmp-server traps ospf state-change if-state-change",
+ "snmp-server traps ospf state-change neighbor-state-change",
+ "snmp-server traps ospf state-change virtif-state-change",
+ "snmp-server traps ospf state-change virtneighbor-state-change",
+ "snmp-server traps ospfv3 errors bad-packet",
+ "snmp-server traps ospfv3 errors config-error",
+ "snmp-server traps ospfv3 errors virt-config-error",
+ "snmp-server traps ospfv3 state-change neighbor-state-change",
+ "snmp-server traps ospfv3 state-change virtif-state-change",
+ "snmp-server traps ospfv3 state-change virtneighbor-state-change",
+ "snmp-server traps ospfv3 state-change restart-status-change",
+ "snmp-server traps ospfv3 state-change restart-helper-status-change",
+ "snmp-server traps ospfv3 state-change restart-virtual-helper-status-change",
+ "snmp-server traps power",
+ "snmp-server traps rf",
+ "snmp-server traps pim neighbor-change",
+ "snmp-server traps pim invalid-message-received",
+ "snmp-server traps pim rp-mapping-change",
+ "snmp-server traps pim interface-state-change",
+ "snmp-server traps rsvp lost-flow",
+ "snmp-server traps rsvp new-flow",
+ "snmp-server traps rsvp all",
+ "snmp-server traps selective-vrf-download role-change",
+ "snmp-server traps sensor",
+ "snmp-server traps vrrp events",
+ "snmp-server traps syslog",
+ "snmp-server traps system",
+ "snmp-server traps subscriber session-agg access-interface",
+ "snmp-server traps subscriber session-agg node",
+ "snmp-server traps vpls all",
+ "snmp-server traps vpls full-clear",
+ "snmp-server traps vpls full-raise",
+ "snmp-server traps vpls status",
+ "snmp-server traps snmp linkup",
+ "snmp-server traps snmp linkdown",
+ "snmp-server traps snmp coldstart",
+ "snmp-server traps snmp warmstart",
+ "snmp-server traps snmp authentication",
+ "snmp-server community test2 RO SDROwner IPv4 test IPv6 test1",
+ "snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+ "snmp-server correlator ruleset rule1",
+ "snmp-server correlator rule rule1 timeout 5",
+ "snmp-server context c1",
+ "snmp-server context c2",
+ "snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1",
+ "snmp-server interface GigabitEthernet0/0/0/2",
+ "snmp-server mib bulkstat object-list test1",
+ "snmp-server mib bulkstat schema mib1 object-list test1",
+ "snmp-server mib bulkstat schema mib1 poll-interval 1",
+ "snmp-server mib bulkstat transfer-id test2 buffer-size 1024",
+ "snmp-server mib bulkstat transfer-id test2 enable",
+ "snmp-server mib bulkstat transfer-id test2 format schemaASCII",
+ "snmp-server mib bulkstat transfer-id test2 retain 1",
+ "snmp-server mib bulkstat transfer-id test2 retry 1",
+ "snmp-server mib bulkstat transfer-id test2 schema test2",
+ "snmp-server user u1 test2 IPv4 test1 IPv6 test2 v4acl",
+ "snmp-server target list test2 vrf vrf2",
+ "snmp-server target list test host 1.1.1.2",
+ "snmp-server vrf vrf1",
+ "host 1.1.1.1 traps test1",
+ ]
+ result = self.execute_module(changed=False)
+ self.assertEqual(sorted(result["rendered"]), sorted(commands))
+
+ def test_iosxr_snmp_server_gathered(self):
+ self.maxDiff = None
+ run_cfg = dedent(
+ """\
+ snmp-server vrf vrf1
+ host 1.1.1.1 traps test1
+ !
+ snmp-server drop report acl IPv4 test1
+ snmp-server drop unknown-user
+ snmp-server ipv4 dscp af11
+ snmp-server ipv6 precedence routine
+ snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2 v4acl
+ snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+ snmp-server group g2 v1 read test1 write test2 context test3 IPv4 test IPv6 test1
+ snmp-server queue-length 2
+ snmp-server trap-timeout 3
+ snmp-server trap throttle-time 12
+ snmp-server traps rf
+ snmp-server traps bfd
+ snmp-server traps bgp cbgp2
+ snmp-server traps pim neighbor-change
+ snmp-server traps pim invalid-message-received
+ snmp-server traps pim rp-mapping-change
+ snmp-server traps pim interface-state-change
+ snmp-server traps copy-complete
+ snmp-server traps hsrp
+ snmp-server traps ipsla
+ snmp-server traps msdp peer-state-change
+ snmp-server traps snmp linkup
+ snmp-server traps snmp linkdown
+ snmp-server traps snmp coldstart
+ snmp-server traps snmp warmstart
+ snmp-server traps snmp authentication
+ snmp-server traps vrrp events
+ snmp-server traps flash removal
+ snmp-server traps flash insertion
+ snmp-server traps ipsec tunnel stop
+ snmp-server traps ipsec tunnel start
+ snmp-server traps power
+ snmp-server traps config
+ snmp-server traps entity
+ snmp-server traps sensor
+ snmp-server traps selective-vrf-download role-change
+ snmp-server traps syslog
+ snmp-server traps system
+ snmp-server traps ospf lsa lsa-maxage
+ snmp-server traps ospf lsa lsa-originate
+ snmp-server traps ospf errors bad-packet
+ snmp-server traps ospf errors authentication-failure
+ snmp-server traps ospf errors config-error
+ snmp-server traps ospf errors virt-bad-packet
+ snmp-server traps ospf errors virt-authentication-failure
+ snmp-server traps ospf errors virt-config-error
+ snmp-server traps ospf retransmit packets
+ snmp-server traps ospf retransmit virt-packets
+ snmp-server traps ospf state-change if-state-change
+ snmp-server traps ospf state-change neighbor-state-change
+ snmp-server traps ospf state-change virtif-state-change
+ snmp-server traps ospf state-change virtneighbor-state-change
+ snmp-server traps rsvp all
+ snmp-server traps rsvp new-flow
+ snmp-server traps rsvp lost-flow
+ snmp-server traps l2tun sessions
+ snmp-server traps l2tun tunnel-up
+ snmp-server traps l2tun tunnel-down
+ snmp-server traps vpls all
+ snmp-server traps vpls status
+ snmp-server traps vpls full-clear
+ snmp-server traps vpls full-raise
+ snmp-server traps bulkstat collection
+ snmp-server traps diameter peerup
+ snmp-server traps diameter peerdown
+ snmp-server traps diameter protocolerror
+ snmp-server traps diameter permanentfail
+ snmp-server traps diameter transientfail
+ snmp-server traps l2vpn all
+ snmp-server traps l2vpn vc-up
+ snmp-server traps l2vpn vc-down
+ snmp-server traps bridgemib
+ snmp-server traps ospfv3 errors bad-packet
+ snmp-server traps ospfv3 errors config-error
+ snmp-server traps ospfv3 errors virt-config-error
+ snmp-server traps ospfv3 state-change neighbor-state-change
+ snmp-server traps ospfv3 state-change virtif-state-change
+ snmp-server traps ospfv3 state-change virtneighbor-state-change
+ snmp-server traps ospfv3 state-change restart-status-change
+ snmp-server traps ospfv3 state-change restart-helper-status-change
+ snmp-server traps ospfv3 state-change restart-virtual-helper-status-change
+ snmp-server traps subscriber session-agg node
+ snmp-server traps subscriber session-agg access-interface
+ snmp-server traps addrpool low
+ snmp-server traps addrpool high
+ snmp-server traps cisco-entity-ext
+ snmp-server traps entity-state operstatus
+ snmp-server traps entity-state switchover
+ snmp-server traps entity-redundancy all
+ snmp-server traps entity-redundancy status
+ snmp-server traps entity-redundancy switchover
+ snmp-server chassis-id test2
+ snmp-server contact t1
+ snmp-server location test1
+ snmp-server target list test host 1.1.1.2
+ snmp-server target list test2 vrf vrf2
+ snmp-server context c1
+ snmp-server logging threshold oid-processing 1
+ snmp-server logging threshold pdu-processing 1
+ snmp-server mib bulkstat max-procmem-size 101
+ snmp-server mib bulkstat object-list test1
+ !
+ snmp-server mib bulkstat schema mib1
+ object-list test1
+ poll-interval 1
+ !
+ snmp-server mib bulkstat transfer-id test2
+ retry 1
+ buffer-size 1024
+ enable
+ format schemaASCII
+ retain 1
+ schema test2
+ !
+ snmp-server timeouts duplicate 0
+ snmp-server timeouts inQdrop 0
+ snmp-server timeouts subagent 1
+ snmp-server timeouts pdu stats 1
+ snmp-server timeouts threshold 0
+ snmp-server packetsize 490
+ snmp-server correlator rule rule1
+ timeout 5
+ !
+ snmp-server correlator ruleset rule1
+ !
+ snmp-server correlator buffer-size 1024
+ snmp-server trap-source GigabitEthernet0/0/0/2
+ snmp-server throttle-time 60
+ snmp-server community-map cm1 context c1 security-name s1 target-list t1
+ snmp-server inform retries 7
+ snmp-server overload-control 4 6
+ snmp-server ifmib internal cache max-duration 4
+ snmp-server mroutemib send-all-vrf
+ snmp-server notification-log-mib size 5
+ snmp-server notification-log-mib GlobalSize 5
+ !
+ """,
+ )
+ self.get_config.return_value = run_cfg
+ set_module_args(dict(state="gathered"))
+ gathered = {
+ "vrfs": [
+ {
+ "vrf": "vrf1",
+ "hosts": [
+ {
+ "host": "1.1.1.1",
+ "traps": True,
+ "community": "test1",
+ },
+ ],
+ },
+ ],
+ "drop": {"report_IPv4": "test1", "unknown_user": True},
+ "ipv4": {"dscp": "af11"},
+ "ipv6": {"precedence": "routine"},
+ "users": [
+ {
+ "user": "u1",
+ "group": "test2",
+ "acl_v4": "test1",
+ "acl_v6": "test2",
+ "v4_acl": "v4acl",
+ "version": "v1",
+ },
+ ],
+ "communities": [
+ {
+ "name": "test2",
+ "ro": True,
+ "acl_v4": "test",
+ "acl_v6": "test1",
+ "sdrowner": True,
+ },
+ ],
+ "groups": [
+ {
+ "group": "g2",
+ "acl_v4": "test",
+ "acl_v6": "test1",
+ "context": "test3",
+ "read": "test1",
+ "write": "test2",
+ "version": "v1",
+ },
+ ],
+ "queue_length": 2,
+ "trap_timeout": 3,
+ "trap": {"throttle_time": 12},
+ "traps": {
+ "rf": True,
+ "bfd": True,
+ "bgp": {"cbgp2": True},
+ "pim": {
+ "neighbor_change": True,
+ "invalid_message_received": True,
+ "rp_mapping_change": True,
+ "interface_state_change": True,
+ },
+ "copy_complete": True,
+ "hsrp": True,
+ "ipsla": True,
+ "msdp_peer_state_change": True,
+ "snmp": {
+ "linkup": True,
+ "linkdown": True,
+ "coldstart": True,
+ "warmstart": True,
+ "authentication": True,
+ },
+ "vrrp_events": True,
+ "flash": {"removal": True, "insertion": True},
+ "ipsec": {"stop": True, "start": True},
+ "power": True,
+ "config": True,
+ "entity": True,
+ "sensor": True,
+ "selective_vrf_download_role_change": True,
+ "syslog": True,
+ "system": True,
+ "ospf": {
+ "lsa": {"lsa_maxage": True, "lsa_originate": True},
+ "errors": {
+ "bad_packet": True,
+ "authentication_failure": True,
+ "config_error": True,
+ "virt_bad_packet": True,
+ "virt_authentication_failure": True,
+ "virt_config_error": True,
+ },
+ "retransmit": {"packets": True, "virt_packets": True},
+ "state_change": {
+ "if_state_change": True,
+ "neighbor_state_change": True,
+ "virtif_state_change": True,
+ "virtneighbor_state_change": True,
+ },
+ },
+ "rsvp": {"all": True, "new_flow": True, "lost_flow": True},
+ "l2tun": {
+ "sessions": True,
+ "tunnel_up": True,
+ "tunnel_down": True,
+ },
+ "vpls": {
+ "all": True,
+ "status": True,
+ "full_clear": True,
+ "full_raise": True,
+ },
+ "bulkstat_collection": True,
+ "diameter": {
+ "peerup": True,
+ "peerdown": True,
+ "protocolerror": True,
+ "permanentfail": True,
+ "transientfail": True,
+ },
+ "l2vpn": {"all": True, "vc_up": True, "vc_down": True},
+ "bridgemib": True,
+ "ospfv3": {
+ "errors": {
+ "bad_packet": True,
+ "config_error": True,
+ "virt_config_error": True,
+ },
+ "state_change": {
+ "neighbor_state_change": True,
+ "virtif_state_change": True,
+ "virtneighbor_state_change": True,
+ "restart_status_change": True,
+ "restart_helper_status_change": True,
+ "restart_virtual_helper_status_change": True,
+ },
+ },
+ "subscriber": {
+ "session_agg_node": True,
+ "session_agg_access_interface": True,
+ },
+ "addrpool": {"low": True, "high": True},
+ "cisco_entity_ext": True,
+ "entity_state": {"operstatus": True, "switchover": True},
+ "entity_redundancy": {
+ "all": True,
+ "status": True,
+ "switchover": True,
+ },
+ },
+ "chassis_id": "test2",
+ "contact": "t1",
+ "location": "test1",
+ "targets": [
+ {"name": "test", "host": "1.1.1.2"},
+ {"name": "test2", "vrf": "vrf2"},
+ ],
+ "context": ["c1"],
+ "logging_threshold_oid_processing": 1,
+ "logging_threshold_pdu_processing": 1,
+ "mib_bulkstat_max_procmem_size": 101,
+ "mib_object_lists": ["test1"],
+ "mib_schema": [
+ {"name": "mib1", "object_list": "test1", "poll_interval": 1},
+ ],
+ "mib_bulkstat_transfer_ids": [
+ {
+ "name": "test2",
+ "retry": 1,
+ "buffer_size": 1024,
+ "enable": True,
+ "format_schemaASCI": True,
+ "retain": 1,
+ "schema": "test2",
+ },
+ ],
+ "timeouts": {
+ "duplicate": 0,
+ "inQdrop": 0,
+ "subagent": 1,
+ "pdu_stats": 1,
+ "threshold": 0,
+ },
+ "packetsize": 490,
+ "correlator": {
+ "rules": [
+ {"rule_name": "rule1"},
+ {"rule_name": "rule1", "timeout": 5},
+ ],
+ "rule_sets": [{"name": "rule1"}],
+ "buffer_size": 1024,
+ },
+ "trap_source": "GigabitEthernet0/0/0/2",
+ "throttle_time": 60,
+ "community_maps": [
+ {
+ "name": "cm1",
+ "context": "c1",
+ "security_name": "s1",
+ "target_list": "t1",
+ },
+ ],
+ "inform": {"retries": 7},
+ "overload_control": {
+ "overload_drop_time": 4,
+ "overload_throttle_rate": 6,
+ },
+ "ifmib": {"internal_cache_max_duration": 4},
+ "mroutemib_send_all_vrf": True,
+ "notification_log_mib": {"size": 5, "GlobalSize": 5},
+ }
+ result = self.execute_module(changed=False)
+ self.assertEqual(gathered, result["gathered"])
+
+ def test_iosxr_snmp_server_parsed(self):
+ self.maxDiff = None
+ set_module_args(
+ dict(
+ running_config="snmp-server vrf test1\n host 1.1.1.1 traps test1\n host 1.1.1.2 traps test1\n "
+ "context test2\n!\nsnmp-server drop report acl IPv6 test\nsnmp-server drop unknown-user"
+ "\nsnmp-server host 1.1.1.1 traps test udp-port 1\nsnmp-server host 1.1.1.2 informs "
+ "version 2c test\nsnmp-server host 1.1.1.3 traps test\nsnmp-server user test1 test2 v1 "
+ "IPv4 test1 IPv6 test2 SDROwner\nsnmp-server "
+ "community test RO IPv4 test IPv6 test\nsnmp-"
+ "server community test1 RO\nsnmp-server group "
+ "test v1 notify test1\nsnmp-server group test1 "
+ "v1 read test1 write test2 context test3 IPv4 test"
+ " IPv6 test1\nsnmp-server group test2 v1 "
+ "notify test read test1\nsnmp-server group test4 "
+ "v1 notify t1 context test\nsnmp-server queue-length "
+ "1\nsnmp-server trap-timeout 1\nsnmp-server trap "
+ "throttle-time 10\nsnmp-server traps rf\nsnmp-server traps "
+ "bfd\nsnmp-server traps bgp cbgp2\nsnmp-server "
+ "traps bgp updown\nsnmp-server traps ntp\nsnmp-server "
+ "traps pim neighbor-change\nsnmp-server traps "
+ "pim invalid-message-received\nsnmp-server traps pim "
+ "rp-mapping-change\nsnmp-server traps pim interface-state-change"
+ "\nsnmp-server traps copy-complete\nsnmp-server "
+ "traps hsrp\nsnmp-server traps ipsla\nsnmp-server traps msdp "
+ "peer-state-change\nsnmp-server traps vrrp events\nsnmp-server "
+ "traps flash removal\nsnmp-server traps flash insertion\nsnmp-server "
+ "traps ipsec tunnel stop\nsnmp-server traps ipsec tunnel start\nsnmp-server "
+ "traps power\nsnmp-server traps config\nsnmp-server traps entity\nsnmp-server "
+ "traps isakmp tunnel stop\nsnmp-server traps isakmp tunnel start\nsnmp-server "
+ "traps isis database-overload manual-address-drops corrupted-lsp-detected "
+ "attempt-to-exceed-max-sequence id-len-mismatch max-area-addresses-mismatch"
+ " own-lsp-purge sequence-number-skip authentication-type-failure "
+ "authentication-failure version-skew area-mismatch rejected-adjacency "
+ "lsp-too-large-to-propagate orig-lsp-buff-size-mismatch protocols-supported-mismatch"
+ " adjacency-change lsp-error-detected\nsnmp-server traps sensor\nsnmp-server"
+ " traps selective-vrf-download role-change\nsnmp-server traps syslog"
+ "\nsnmp-server traps system\nsnmp-server traps ospf lsa lsa-maxage"
+ "\nsnmp-server traps ospf lsa lsa-originate\nsnmp-server traps ospf"
+ " errors bad-packet\nsnmp-server traps ospf errors authentication-failure"
+ "\nsnmp-server traps ospf errors config-error\nsnmp-server traps ospf"
+ " errors virt-bad-packet\nsnmp-server traps ospf errors "
+ "virt-authentication-failure\nsnmp-server traps ospf errors"
+ " virt-config-error\nsnmp-server traps ospf retransmit"
+ " packets\nsnmp-server traps ospf retransmit virt-packets"
+ "\nsnmp-server traps ospf state-change if-state-change"
+ "\nsnmp-server traps ospf state-change neighbor-state-change"
+ "\nsnmp-server traps ospf state-change virtif-state-change\n"
+ "snmp-server traps ospf state-change virtneighbor-state-change"
+ "\nsnmp-server traps rsvp all\nsnmp-server traps rsvp new-flow\n"
+ "snmp-server traps rsvp lost-flow\nsnmp-server traps l2tun sessions\n"
+ "snmp-server traps l2tun tunnel-up\nsnmp-server traps l2tun tunnel-down"
+ "\nsnmp-server traps l2tun pseudowire status\nsnmp-server traps vpls all\n"
+ "snmp-server traps vpls status\nsnmp-server traps vpls full-clear\nsnmp-server "
+ "traps vpls full-raise\nsnmp-server traps snmp linkup\nsnmp-server traps snmp "
+ "linkdown\nsnmp-server traps snmp coldstart\nsnmp-server traps snmp warmstart"
+ "\nsnmp-server traps snmp authentication\nsnmp-server traps bulkstat transfer"
+ "\nsnmp-server traps bulkstat collection\nsnmp-server traps diameter peerup\
+ nsnmp-server traps diameter peerdown\nsnmp-server traps diameter protocolerror"
+ "\nsnmp-server traps diameter permanentfail\nsnmp-server traps diameter transientfail"
+ "\nsnmp-server traps l2vpn all\nsnmp-server traps l2vpn cisco\nsnmp-server traps "
+ "l2vpn vc-up\nsnmp-server traps l2vpn vc-down\nsnmp-server traps bridgemib\nsnmp-"
+ "server traps ospfv3 errors bad-packet\nsnmp-server traps ospfv3 errors config-error"
+ "\nsnmp-server traps ospfv3 errors virt-bad-packet\nsnmp-server traps ospfv3 errors "
+ "virt-config-error\nsnmp-server traps ospfv3 state-change if-state-change\nsnmp-"
+ "server traps ospfv3 state-change neighbor-state-change\nsnmp-server traps ospfv3 "
+ "state-change nssa-state-change\nsnmp-server traps ospfv3 state-change "
+ "virtif-state-change\nsnmp-server traps ospfv3 state-change "
+ "virtneighbor-state-change\nsnmp-server traps ospfv3 state-change "
+ "restart-status-change\nsnmp-server traps ospfv3 state-change "
+ "restart-helper-status-change\nsnmp-server traps ospfv3 state-change "
+ "restart-virtual-helper-status-change\nsnmp-server traps fru-ctrl"
+ "\nsnmp-server traps subscriber session-agg node\nsnmp-server traps "
+ "subscriber session-agg access-interface\nsnmp-server traps addrpool "
+ "low\nsnmp-server traps addrpool high\nsnmp-server traps cisco-entity-ext"
+ "\nsnmp-server traps entity-state operstatus\nsnmp-server traps entity-state "
+ "switchover\nsnmp-server traps entity-redundancy all"
+ "\nsnmp-server traps entity-redundancy "
+ "status\nsnmp-server traps entity-redundancy switchover\nsnmp-server chassis-id test2"
+ "\nsnmp-server contact test\nsnmp-server location test\nsnmp-server target list test1 "
+ "vrf vrf1\nsnmp-server target list test1 host 1.1.1.1\nsnmp-server context test\n"
+ "snmp-server context test2\nsnmp-server logging threshold oid-processing 0\n"
+ "snmp-server logging threshold pdu-processing 0\nsnmp-server mib bulkstat max-"
+ "procmem-size 100\nsnmp-server mib bulkstat object-list test\n!\nsnmp-server mib "
+ "bulkstat transfer-id test1\n retry 1\n buffer-size 1024\n enable\n format schemaASCII\n"
+ " retain 1\n schema test\n!\nsnmp-server timeouts duplicate 0\nsnmp-server timeouts"
+ " inQdrop 0\nsnmp-server timeouts subagent 1\nsnmp-server timeouts pdu stats"
+ " 1\nsnmp-server timeouts threshold 0\nsnmp-server packetsize 485\nsnmp-server"
+ " correlator buffer-size 1024\nsnmp-server trap-source GigabitEthernet0/0/0/1"
+ "\nsnmp-server throttle-time 50\nsnmp-server community-map test context test "
+ "security-name test2\nsnmp-server community-map test1 context test security-name "
+ "test2\nsnmp-server inform pending 1\nsnmp-server inform retries 1\nsnmp-server "
+ "inform timeout 1\nsnmp-server oid-poll-stats\nsnmp-server overload-control 0 0"
+ "\nsnmp-server trap authentication vrf disable\nsnmp-server "
+ "interface GigabitEthernet0/0/0/0\n notification linkupdown disable\n "
+ "index persistence\n!\nsnmp-server ifmib ifalias long\nsnmp-server "
+ "ifindex persist\nsnmp-server ifmib internal cache max-duration "
+ "0\nsnmp-server ifmib ipsubscriber\nsnmp-server ifmib stats cache"
+ "\nsnmp-server trap link ietf\nsnmp-server location test\nsnmp-server"
+ " mroutemib send-all-vrf\nsnmp-server notification-log-mib size 1\nsnmp-server "
+ "notification-log-mib default\nsnmp-server notification-log-mib disable\nsnmp-server"
+ " notification-log-mib GlobalSize 1",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = {
+ "vrfs": [
+ {
+ "vrf": "test1",
+ "context": ["test2"],
+ "hosts": [
+ {
+ "host": "1.1.1.1",
+ "traps": True,
+ "community": "test1",
+ },
+ {
+ "host": "1.1.1.2",
+ "traps": True,
+ "community": "test1",
+ },
+ ],
+ },
+ ],
+ "drop": {"report_IPv6": "test", "unknown_user": True},
+ "hosts": [
+ {
+ "host": "1.1.1.1",
+ "traps": True,
+ "community": "test",
+ "udp_port": 1,
+ },
+ {
+ "host": "1.1.1.2",
+ "informs": True,
+ "community": "test",
+ "version": "2c",
+ },
+ {"host": "1.1.1.3", "traps": True, "community": "test"},
+ ],
+ "users": [
+ {
+ "user": "test1",
+ "group": "test2",
+ "acl_v4": "test1",
+ "acl_v6": "test2",
+ "v4_acl": "SDROwner",
+ "version": "v1",
+ },
+ ],
+ "communities": [
+ {
+ "name": "test",
+ "ro": True,
+ "acl_v4": "test",
+ "acl_v6": "test",
+ },
+ {"name": "test1", "ro": True},
+ ],
+ "groups": [
+ {"group": "test", "notify": "test1", "version": "v1"},
+ {
+ "group": "test1",
+ "acl_v4": "test",
+ "acl_v6": "test1",
+ "context": "test3",
+ "read": "test1",
+ "write": "test2",
+ "version": "v1",
+ },
+ {
+ "group": "test2",
+ "notify": "test",
+ "read": "test1",
+ "version": "v1",
+ },
+ {
+ "group": "test4",
+ "context": "test",
+ "notify": "t1",
+ "version": "v1",
+ },
+ ],
+ "queue_length": 1,
+ "trap_timeout": 1,
+ "trap": {
+ "throttle_time": 10,
+ "authentication_vrf_disable": True,
+ "link_ietf": True,
+ },
+ "traps": {
+ "rf": True,
+ "bfd": True,
+ "bgp": {"cbgp2": True},
+ "pim": {
+ "neighbor_change": True,
+ "invalid_message_received": True,
+ "rp_mapping_change": True,
+ "interface_state_change": True,
+ },
+ "copy_complete": True,
+ "hsrp": True,
+ "ipsla": True,
+ "msdp_peer_state_change": True,
+ "vrrp_events": True,
+ "flash": {"removal": True, "insertion": True},
+ "ipsec": {"stop": True, "start": True},
+ "power": True,
+ "config": True,
+ "entity": True,
+ "isakmp": {"stop": True, "start": True},
+ "isis": {
+ "id_len_mismatch": True,
+ "database_overload": True,
+ "manual_address_drops": True,
+ "corrupted_lsp_detected": True,
+ "attempt_to_exceed_max_sequence": True,
+ "max_area_addresses_mismatch": True,
+ "own_lsp_purge": True,
+ "sequence_number_skip": True,
+ "authentication_type_failure": True,
+ "authentication_failure": True,
+ "version_skew": True,
+ "area_mismatch": True,
+ "rejected_adjacency": True,
+ "lsp_too_large_to_propagate": True,
+ "orig_lsp_buff_size_mismatch": True,
+ "protocols_supported_mismatch": True,
+ "adjacency_change": True,
+ "lsp_error_detected": True,
+ },
+ "sensor": True,
+ "selective_vrf_download_role_change": True,
+ "syslog": True,
+ "system": True,
+ "ospf": {
+ "lsa": {"lsa_maxage": True, "lsa_originate": True},
+ "errors": {
+ "bad_packet": True,
+ "authentication_failure": True,
+ "config_error": True,
+ "virt_bad_packet": True,
+ "virt_authentication_failure": True,
+ "virt_config_error": True,
+ },
+ "retransmit": {"packets": True, "virt_packets": True},
+ "state_change": {
+ "if_state_change": True,
+ "neighbor_state_change": True,
+ "virtif_state_change": True,
+ "virtneighbor_state_change": True,
+ },
+ },
+ "rsvp": {"all": True, "new_flow": True, "lost_flow": True},
+ "l2tun": {
+ "sessions": True,
+ "tunnel_up": True,
+ "tunnel_down": True,
+ },
+ "vpls": {
+ "all": True,
+ "status": True,
+ "full_clear": True,
+ "full_raise": True,
+ },
+ "snmp": {
+ "linkup": True,
+ "linkdown": True,
+ "coldstart": True,
+ "warmstart": True,
+ "authentication": True,
+ },
+ "bulkstat_transfer": True,
+ "bulkstat_collection": True,
+ "diameter": {
+ "protocolerror": True,
+ "permanentfail": True,
+ "transientfail": True,
+ },
+ "l2vpn": {
+ "all": True,
+ "cisco": True,
+ "vc_up": True,
+ "vc_down": True,
+ },
+ "bridgemib": True,
+ "ospfv3": {
+ "errors": {
+ "bad_packet": True,
+ "config_error": True,
+ "virt_bad_packet": True,
+ "virt_config_error": True,
+ },
+ "state_change": {
+ "if_state_change": True,
+ "neighbor_state_change": True,
+ "nssa_state_change": True,
+ "virtif_state_change": True,
+ "virtneighbor_state_change": True,
+ "restart_status_change": True,
+ "restart_helper_status_change": True,
+ "restart_virtual_helper_status_change": True,
+ },
+ },
+ "fru_ctrl": True,
+ "subscriber": {
+ "session_agg_node": True,
+ "session_agg_access_interface": True,
+ },
+ "addrpool": {"low": True, "high": True},
+ "cisco_entity_ext": True,
+ "entity_state": {"operstatus": True, "switchover": True},
+ "entity_redundancy": {
+ "all": True,
+ "status": True,
+ "switchover": True,
+ },
+ },
+ "chassis_id": "test2",
+ "contact": "test",
+ "location": "test",
+ "targets": [
+ {"name": "test1", "vrf": "vrf1"},
+ {"name": "test1", "host": "1.1.1.1"},
+ ],
+ "context": ["test", "test2"],
+ "logging_threshold_oid_processing": 0,
+ "logging_threshold_pdu_processing": 0,
+ "mib_bulkstat_max_procmem_size": 100,
+ "mib_object_lists": ["test"],
+ "mib_bulkstat_transfer_ids": [
+ {
+ "name": "test1",
+ "retry": 1,
+ "buffer_size": 1024,
+ "enable": True,
+ "format_schemaASCI": True,
+ "retain": 1,
+ "schema": "test",
+ },
+ ],
+ "timeouts": {
+ "duplicate": 0,
+ "inQdrop": 0,
+ "subagent": 1,
+ "pdu_stats": 1,
+ "threshold": 0,
+ },
+ "packetsize": 485,
+ "correlator": {"buffer_size": 1024},
+ "trap_source": "GigabitEthernet0/0/0/1",
+ "throttle_time": 50,
+ "community_maps": [
+ {"name": "test", "context": "test", "security_name": "test2"},
+ {"name": "test1", "context": "test", "security_name": "test2"},
+ ],
+ "inform": {"pending": 1, "retries": 1, "timeout": 1},
+ "oid_poll_stats": True,
+ "overload_control": {
+ "overload_drop_time": 0,
+ "overload_throttle_rate": 0,
+ },
+ "interfaces": [
+ {
+ "name": "GigabitEthernet0/0/0/0",
+ "notification_linkupdown_disable": True,
+ },
+ ],
+ "ifmib": {
+ "ifalias_long": True,
+ "internal_cache_max_duration": 0,
+ "ipsubscriber": True,
+ "stats": True,
+ },
+ "ifindex": True,
+ "mroutemib_send_all_vrf": True,
+ "notification_log_mib": {
+ "size": 1,
+ "default": True,
+ "disable": True,
+ "GlobalSize": 1,
+ },
+ }
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_static_routes.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_static_routes.py
new file mode 100644
index 00000000..ba91d7f3
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_static_routes.py
@@ -0,0 +1,380 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_static_routes
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrStaticRoutesModule(TestIosxrModule):
+ module = iosxr_static_routes
+
+ def setUp(self):
+ super(TestIosxrStaticRoutesModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network.Config.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_get_resource_connection_config = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base.get_resource_connection",
+ )
+ self.get_resource_connection_config = self.mock_get_resource_connection_config.start()
+
+ self.mock_get_resource_connection_facts = patch(
+ "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts.get_resource_connection",
+ )
+ self.get_resource_connection_facts = self.mock_get_resource_connection_facts.start()
+
+ self.mock_execute_show_command = patch(
+ "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.static_routes.static_routes.Static_routesFacts.get_device_data",
+ )
+ self.execute_show_command = self.mock_execute_show_command.start()
+
+ def tearDown(self):
+ super(TestIosxrStaticRoutesModule, self).tearDown()
+ self.mock_get_resource_connection_config.stop()
+ self.mock_get_resource_connection_facts.stop()
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_execute_show_command.stop()
+
+ def load_fixtures(self, commands=None):
+ def load_from_file(*args, **kwargs):
+ return load_fixture("iosxr_static_routes_config.cfg")
+
+ self.execute_show_command.side_effect = load_from_file
+
+ def test_iosxr_static_routes_merged(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ vrf="dev_site",
+ address_families=[
+ dict(
+ afi="ipv6",
+ safi="unicast",
+ routes=[
+ dict(
+ dest="1200:10::/64",
+ next_hops=[
+ dict(
+ interface="GigabitEthernet0/0/0/1",
+ admin_distance=55,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ commands = [
+ "router static",
+ "vrf dev_site",
+ "address-family ipv6 unicast",
+ "1200:10::/64 GigabitEthernet0/0/0/1 55",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_static_routes_merged_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ vrf="DEV_SITE",
+ address_families=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ routes=[
+ dict(
+ dest="192.0.2.48/28",
+ next_hops=[
+ dict(
+ interface="192.0.2.12",
+ description="DEV",
+ dest_vrf="test_1",
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="merged",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_static_routes_default(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ address_families=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ routes=[
+ dict(
+ dest="192.168.1.0/24",
+ next_hops=[
+ dict(
+ interface="GigabitEthernet0/0/0/2",
+ track="ip_sla_2",
+ vrflabel=1200,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+ commands = [
+ "router static",
+ "address-family ipv4 unicast",
+ "192.168.1.0/24 GigabitEthernet0/0/0/2 track ip_sla_2 vrflabel 1200",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_static_routes_default_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ address_families=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ routes=[
+ dict(
+ dest="192.0.2.32/28",
+ next_hops=[
+ dict(
+ forward_router_address="192.0.2.11",
+ admin_distance=100,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_static_routes_replaced(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ address_families=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ routes=[
+ dict(
+ dest="192.0.2.16/28",
+ next_hops=[
+ dict(
+ forward_router_address="192.0.2.11",
+ admin_distance=100,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ commands = [
+ "router static",
+ "address-family ipv4 unicast",
+ "no 192.0.2.16/28 192.0.2.10 FastEthernet0/0/0/1",
+ "no 192.0.2.16/28 FastEthernet0/0/0/5",
+ "192.0.2.16/28 192.0.2.11 100",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_static_routes_replaced_idempotent(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ address_families=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ routes=[
+ dict(
+ dest="192.0.2.16/28",
+ next_hops=[
+ dict(
+ interface="FastEthernet0/0/0/5",
+ track="ip_sla_1",
+ ),
+ dict(
+ interface="FastEthernet0/0/0/1",
+ forward_router_address="192.0.2.10",
+ tag=10,
+ description="LAB",
+ metric=120,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="replaced",
+ ),
+ )
+ self.execute_module(changed=False, commands=[])
+
+ def test_iosxr_static_routes_overridden(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(
+ vrf="DEV_SITE_NEW",
+ address_families=[
+ dict(
+ afi="ipv4",
+ safi="unicast",
+ routes=[
+ dict(
+ dest="192.0.4.16/28",
+ next_hops=[
+ dict(
+ interface="FastEthernet0/0/0/5",
+ track="ip_sla_1",
+ ),
+ dict(
+ interface="FastEthernet0/0/0/1",
+ forward_router_address="192.0.2.10",
+ tag=10,
+ description="LAB",
+ metric=120,
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ],
+ state="overridden",
+ ),
+ )
+ commands = [
+ "router static",
+ "no address-family ipv4 unicast",
+ "no address-family ipv6 unicast",
+ "no vrf DEV_SITE",
+ "vrf DEV_SITE_NEW",
+ "address-family ipv4 unicast",
+ "192.0.4.16/28 192.0.2.10 FastEthernet0/0/0/1 description LAB metric 120 tag 10",
+ "192.0.4.16/28 FastEthernet0/0/0/5 track ip_sla_1",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_static_routes_deleted_afi(self):
+ set_module_args(
+ dict(
+ config=[
+ dict(address_families=[dict(afi="ipv4", safi="unicast")]),
+ ],
+ state="deleted",
+ ),
+ )
+
+ commands = ["router static", "no address-family ipv4 unicast"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_static_routes_deleted_vrf(self):
+ set_module_args(dict(config=[dict(vrf="DEV_SITE")], state="deleted"))
+
+ commands = ["router static", "no vrf DEV_SITE"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_static_routes_deleted_all(self):
+ set_module_args(dict(state="deleted"))
+
+ commands = ["no router static"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_static_routes_parsed(self):
+ set_module_args(
+ dict(
+ running_config="router static\n address-family ipv4 unicast\n 0.0.0.0/0 172.31.32.1\n "
+ "10.0.0.0/8 Null0 200\n 11.0.0.0/8 Loopback888\n 203.0.113.0/24 TenGigE0/0/0/0\n !\n!",
+ state="parsed",
+ ),
+ )
+ result = self.execute_module(changed=False)
+ parsed_list = [
+ {
+ "address_families": [
+ {
+ "afi": "ipv4",
+ "routes": [
+ {
+ "dest": "0.0.0.0/0",
+ "next_hops": [
+ {"forward_router_address": "172.31.32.1"},
+ ],
+ },
+ {
+ "dest": "10.0.0.0/8",
+ "next_hops": [
+ {
+ "admin_distance": 200,
+ "interface": "Null0",
+ },
+ ],
+ },
+ {
+ "dest": "11.0.0.0/8",
+ "next_hops": [{"interface": "Loopback888"}],
+ },
+ {
+ "dest": "203.0.113.0/24",
+ "next_hops": [{"interface": "TenGigE0/0/0/0"}],
+ },
+ ],
+ "safi": "unicast",
+ },
+ ],
+ },
+ ]
+ self.assertEqual(parsed_list, result["parsed"])
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_system.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_system.py
new file mode 100644
index 00000000..4e09671e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_system.py
@@ -0,0 +1,123 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_system
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrSystemModule(TestIosxrModule):
+
+ module = iosxr_system
+
+ def setUp(self):
+ super(TestIosxrSystemModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_system.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_system.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_is_cliconf = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_system.is_cliconf",
+ )
+ self.is_cliconf = self.mock_is_cliconf.start()
+
+ def tearDown(self):
+ super(TestIosxrSystemModule, self).tearDown()
+
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+
+ def load_fixtures(self, commands=None):
+ self.get_config.return_value = load_fixture("iosxr_system_config.cfg")
+ self.load_config.return_value = dict(diff=None, session="session")
+ self.is_cliconf.return_value = True
+
+ def test_iosxr_system_hostname_changed(self):
+ set_module_args(dict(hostname="foo"))
+ commands = ["hostname foo", "no domain lookup disable"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_system_domain_name(self):
+ set_module_args(dict(domain_name="test.com"))
+ commands = ["domain name test.com", "no domain lookup disable"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_system_domain_search(self):
+ set_module_args(dict(domain_search=["ansible.com", "redhat.com"]))
+ commands = [
+ "domain list ansible.com",
+ "no domain list cisco.com",
+ "no domain lookup disable",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_system_lookup_source(self):
+ set_module_args(dict(lookup_source="Ethernet1"))
+ commands = [
+ "domain lookup source-interface Ethernet1",
+ "no domain lookup disable",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_system_lookup_enabled(self):
+ set_module_args(dict(lookup_enabled=True))
+ commands = ["no domain lookup disable"]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_system_name_servers(self):
+ name_servers = ["8.8.8.8", "8.8.4.4", "1.1.1.1"]
+ set_module_args(dict(name_servers=name_servers))
+ self.execute_module(changed=True)
+
+ def test_iosxr_system_state_absent(self):
+ set_module_args(dict(state="absent"))
+ commands = [
+ "no hostname",
+ "no domain name",
+ "no domain lookup disable",
+ "no domain lookup source-interface MgmtEth0/0/CPU0/0",
+ "no domain list redhat.com",
+ "no domain list cisco.com",
+ "no domain name-server 8.8.8.8",
+ "no domain name-server 8.8.4.4",
+ ]
+ self.execute_module(changed=True, commands=commands)
+
+ def test_iosxr_system_no_change(self):
+ set_module_args(
+ dict(
+ hostname="iosxr01",
+ domain_name="eng.ansible.com",
+ lookup_enabled=False,
+ ),
+ )
+ self.execute_module()
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_user.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_user.py
new file mode 100644
index 00000000..3bb6f504
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_user.py
@@ -0,0 +1,131 @@
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.cisco.iosxr.plugins.modules import iosxr_user
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+from ansible_collections.cisco.iosxr.tests.unit.modules.utils import set_module_args
+
+from .iosxr_module import TestIosxrModule, load_fixture
+
+
+class TestIosxrUserModule(TestIosxrModule):
+
+ module = iosxr_user
+
+ def setUp(self):
+ super(TestIosxrUserModule, self).setUp()
+
+ self.mock_get_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_user.get_config",
+ )
+ self.get_config = self.mock_get_config.start()
+
+ self.mock_load_config = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_user.load_config",
+ )
+ self.load_config = self.mock_load_config.start()
+
+ self.mock_is_cliconf = patch(
+ "ansible_collections.cisco.iosxr.plugins.modules.iosxr_user.is_cliconf",
+ )
+ self.is_cliconf = self.mock_is_cliconf.start()
+
+ def tearDown(self):
+ super(TestIosxrUserModule, self).tearDown()
+
+ self.mock_get_config.stop()
+ self.mock_load_config.stop()
+ self.mock_is_cliconf.stop()
+
+ def load_fixtures(self, commands=None, transport="cli"):
+ self.get_config.return_value = load_fixture("iosxr_user_config.cfg")
+ self.load_config.return_value = dict(diff=None, session="session")
+ self.is_cliconf.return_value = True
+
+ def test_iosxr_user_delete(self):
+ set_module_args(dict(name="ansible", state="absent"))
+ result = self.execute_module(changed=True)
+ self.assertEqual(result["commands"], ["no username ansible"])
+
+ def test_iosxr_user_password(self):
+ set_module_args(dict(name="ansible", configured_password="test"))
+ result = self.execute_module(changed=True)
+ self.assertEqual(result["commands"], ["username ansible secret test"])
+
+ def test_iosxr_user_purge(self):
+ set_module_args(dict(purge=True))
+ result = self.execute_module(changed=True)
+ self.assertEqual(result["commands"], ["no username ansible"])
+
+ def test_iosxr_user_group(self):
+ set_module_args(dict(name="ansible", group="sysadmin"))
+ result = self.execute_module(changed=True)
+ self.assertEqual(
+ result["commands"],
+ ["username ansible group sysadmin"],
+ )
+
+ def test_iosxr_user_update_password_changed(self):
+ set_module_args(
+ dict(
+ name="test",
+ configured_password="test",
+ update_password="on_create",
+ ),
+ )
+ result = self.execute_module(changed=True)
+ self.assertEqual(
+ result["commands"],
+ ["username test", "username test secret test"],
+ )
+
+ def test_iosxr_user_update_password_on_create_ok(self):
+ set_module_args(
+ dict(
+ name="ansible",
+ configured_password="test",
+ update_password="on_create",
+ ),
+ )
+ self.execute_module()
+
+ def test_iosxr_user_update_password_always(self):
+ set_module_args(
+ dict(
+ name="ansible",
+ configured_password="test",
+ update_password="always",
+ ),
+ )
+ result = self.execute_module(changed=True)
+ self.assertEqual(result["commands"], ["username ansible secret test"])
+
+ def test_iosxr_user_admin_mode(self):
+ set_module_args(
+ dict(name="ansible-2", configured_password="test-2", admin=True),
+ )
+ result = self.execute_module(changed=True)
+ self.assertEqual(
+ result["commands"],
+ ["username ansible-2", "username ansible-2 secret test-2"],
+ )
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_utils.py b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_utils.py
new file mode 100644
index 00000000..7707adf4
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/network/iosxr/test_iosxr_utils.py
@@ -0,0 +1,28 @@
+#
+# (c) 2022, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import Version
+from ansible_collections.cisco.iosxr.tests.unit.compat import unittest
+
+
+class TestIosxrUtils(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_VersionOperation(self):
+ self.assertEqual(Version("3.0.1") < Version("3.1.0"), True)
+ self.assertEqual(Version("0.0.1") < Version("3.1.0"), True)
+ self.assertEqual(Version("3.0.1") < Version("3.0.1"), False)
+ self.assertEqual(Version("3.0.1") <= Version("3.0.1"), True)
+ self.assertEqual(Version("4.0.1") > Version("3.0.1"), True)
+ self.assertEqual(Version("4.1.1") > Version("4.1.0"), True)
+ self.assertEqual(Version("4.1.1") == Version("4.1.1"), True)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/modules/utils.py b/ansible_collections/cisco/iosxr/tests/unit/modules/utils.py
new file mode 100644
index 00000000..d63a8692
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/modules/utils.py
@@ -0,0 +1,55 @@
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+import json
+
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+
+from ansible_collections.cisco.iosxr.tests.unit.compat import unittest
+from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
+
+
+def set_module_args(args):
+ if "_ansible_remote_tmp" not in args:
+ args["_ansible_remote_tmp"] = "/tmp"
+ if "_ansible_keep_remote_files" not in args:
+ args["_ansible_keep_remote_files"] = False
+
+ args = json.dumps({"ANSIBLE_MODULE_ARGS": args})
+ basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+class AnsibleExitJson(Exception):
+ pass
+
+
+class AnsibleFailJson(Exception):
+ pass
+
+
+def exit_json(*args, **kwargs):
+ if "changed" not in kwargs:
+ kwargs["changed"] = False
+ raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+ kwargs["failed"] = True
+ raise AnsibleFailJson(kwargs)
+
+
+class ModuleTestCase(unittest.TestCase):
+ def setUp(self):
+ self.mock_module = patch.multiple(
+ basic.AnsibleModule,
+ exit_json=exit_json,
+ fail_json=fail_json,
+ )
+ self.mock_module.start()
+ self.mock_sleep = patch("time.sleep")
+ self.mock_sleep.start()
+ set_module_args({})
+ self.addCleanup(self.mock_module.stop)
+ self.addCleanup(self.mock_sleep.stop)
diff --git a/ansible_collections/cisco/iosxr/tests/unit/requirements.txt b/ansible_collections/cisco/iosxr/tests/unit/requirements.txt
new file mode 100644
index 00000000..a9772bea
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/tests/unit/requirements.txt
@@ -0,0 +1,42 @@
+boto3
+placebo
+pycrypto
+passlib
+pypsrp
+python-memcached
+pytz
+pyvmomi
+redis
+requests
+setuptools > 0.6 # pytest-xdist installed via requirements does not work with very old setuptools (sanity_ok)
+unittest2 ; python_version < '2.7'
+importlib ; python_version < '2.7'
+netaddr
+ipaddress
+netapp-lib
+solidfire-sdk-python
+
+# requirements for F5 specific modules
+f5-sdk ; python_version >= '2.7'
+f5-icontrol-rest ; python_version >= '2.7'
+deepdiff
+
+# requirement for Fortinet specific modules
+pyFMG
+
+# requirement for aci_rest module
+xmljson
+
+# requirement for winrm connection plugin tests
+pexpect
+
+# requirement for the linode module
+linode-python # APIv3
+linode_api4 ; python_version > '2.6' # APIv4
+
+# requirement for the gitlab module
+python-gitlab
+httmock
+
+# requirment for kubevirt modules
+openshift ; python_version >= '2.7'