collection 교체

This commit is contained in:
정훈 변
2024-02-23 16:37:40 +09:00
parent b494779b5b
commit 3fd554eee9
38862 changed files with 220204 additions and 6600073 deletions

View File

@@ -1,34 +0,0 @@
# (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__"

View File

@@ -1,127 +0,0 @@
# (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 _io
import sys
# 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

View File

@@ -1,39 +0,0 @@
# (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 *

View File

@@ -1,36 +1,24 @@
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
from ansible.errors import AnsibleParserError
from ansible.parsing.dataloader import DataLoader
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
assert isinstance(file_mapping, dict)
super(DictDataLoader, self).__init__()

View File

@@ -1,12 +1,10 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
MagicMock,
)
from unittest.mock import MagicMock
from ansible.utils.path import unfrackpath
mock_unfrackpath_noop = MagicMock(
spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x
)
mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x)

View File

@@ -1,34 +1,23 @@
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import sys
import json
import sys
import unittest
from contextlib import contextmanager
from io import BytesIO, StringIO
from ansible_collections.ansible.netcommon.tests.unit.compat import unittest
from ansible.module_utils.six import PY3
from ansible.module_utils._text import to_bytes
from ansible.module_utils.six import PY3
@contextmanager

View File

@@ -14,10 +14,10 @@
# 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
@@ -37,6 +37,4 @@ class TextVaultSecret(VaultSecret):
@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
)
return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors)

View File

@@ -1,12 +1,14 @@
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.loader import AnsibleLoader
from ansible.parsing.yaml.dumper import AnsibleDumper
from ansible.parsing.yaml.loader import AnsibleLoader
class YamlTestUtils(object):
@@ -15,7 +17,8 @@ class YamlTestUtils(object):
def _loader(self, stream):
"""Vault related tests will want to override this.
Vault cases should setup a AnsibleLoader that has the vault password."""
Vault cases should setup a AnsibleLoader that has the vault password.
"""
return AnsibleLoader(stream)
def _dump_stream(self, obj, stream, dumper=None):
@@ -44,9 +47,7 @@ class YamlTestUtils(object):
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
)
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)
@@ -58,9 +59,7 @@ class YamlTestUtils(object):
loader_3 = self._loader(stream_3)
obj_3 = loader_3.get_data()
string_from_object_dump_3 = self._dump_string(
obj_3, dumper=AnsibleDumper
)
string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper)
self.assertEqual(obj, obj_3)
# should be transitive, but...
@@ -92,12 +91,8 @@ class YamlTestUtils(object):
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
)
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,
@@ -119,12 +114,8 @@ class YamlTestUtils(object):
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
)
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
@@ -134,11 +125,7 @@ class YamlTestUtils(object):
)
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
assert (
yaml_string
== yaml_string_obj_from_stream

View File

@@ -1,79 +0,0 @@
# 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 sys
from io import BytesIO
import pytest
import ansible.module_utils.basic
from ansible.module_utils.six import PY3, string_types
from ansible.module_utils._text import to_bytes
from ansible.module_utils.common._collections_compat import MutableMapping
@pytest.fixture
def stdin(mocker, request):
old_args = ansible.module_utils.basic._ANSIBLE_ARGS
ansible.module_utils.basic._ANSIBLE_ARGS = None
old_argv = sys.argv
sys.argv = ["ansible_unittest"]
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 stdin pytest fixture")
fake_stdin = BytesIO(to_bytes(args, errors="surrogate_or_strict"))
if PY3:
mocker.patch(
"ansible.module_utils.basic.sys.stdin", mocker.MagicMock()
)
mocker.patch("ansible.module_utils.basic.sys.stdin.buffer", fake_stdin)
else:
mocker.patch("ansible.module_utils.basic.sys.stdin", fake_stdin)
yield fake_stdin
ansible.module_utils.basic._ANSIBLE_ARGS = old_args
sys.argv = old_argv
@pytest.fixture
def am(stdin, request):
old_args = ansible.module_utils.basic._ANSIBLE_ARGS
ansible.module_utils.basic._ANSIBLE_ARGS = None
old_argv = sys.argv
sys.argv = ["ansible_unittest"]
argspec = {}
if hasattr(request, "param"):
if isinstance(request.param, dict):
argspec = request.param
am = ansible.module_utils.basic.AnsibleModule(argument_spec=argspec)
am._name = "ansible_unittest"
yield am
ansible.module_utils.basic._ANSIBLE_ARGS = old_args
sys.argv = old_argv

View File

@@ -1,34 +1,20 @@
# -*- coding: utf-8 -*-
#
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import re
import pytest
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
config,
)
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import config
RUNNING = """interface Ethernet1
@@ -109,9 +95,7 @@ def test_config_items():
net_config = config.NetworkConfig(indent=3, contents=RUNNING)
assert len(net_config.items) == 10
net_config = config.NetworkConfig(
indent=3, contents=RUNNING, ignore_lines=[r"\s*no .*"]
)
net_config = config.NetworkConfig(indent=3, contents=RUNNING, ignore_lines=[r"\s*no .*"])
assert len(net_config.items) == 6
net_config = config.NetworkConfig(
@@ -126,9 +110,7 @@ def test_config_items():
def test_config_get_block():
net_config = config.NetworkConfig(indent=3, contents=RUNNING)
with pytest.raises(
AssertionError, match="path argument must be a list object"
):
with pytest.raises(AssertionError, match="path argument must be a list object"):
net_config.get_block("interface Ethernet2")
with pytest.raises(ValueError, match="path does not exist in config"):
@@ -157,9 +139,7 @@ def test_updates_repeat_lines():
configdiffobjs = candidate_obj.difference(running_obj)
diff_list = config.dumps(configdiffobjs, "commands").split("\n")
want_src_list = WANT_SRC_1.strip().split("\n")
for generated_diff_line, candidate_diff_line in zip(
diff_list, want_src_list
):
for generated_diff_line, candidate_diff_line in zip(diff_list, want_src_list):
assert generated_diff_line == candidate_diff_line.strip()
@@ -189,8 +169,6 @@ def test_updates_repeat_parents():
configdiffobjs = candidate_obj.difference(running_obj)
diff_list = config.dumps(configdiffobjs, "commands").split("\n")
for generated_diff_line, candidate_diff_line in zip(
diff_list, expected_diff
):
for generated_diff_line, candidate_diff_line in zip(diff_list, expected_diff):
print(generated_diff_line, candidate_diff_line)
assert generated_diff_line == candidate_diff_line.strip()

View File

@@ -1,31 +1,21 @@
# -*- coding: utf-8 -*-
#
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.tests.unit.compat import unittest
import unittest
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import (
Conditional,
)
test_results = ["result_1", "result_2", "result_3"]
c1 = Conditional("result[1] == result_2")
c2 = Conditional("result[2] not == result_2")
@@ -43,7 +33,3 @@ class TestNotKeyword(unittest.TestCase):
def test_conditionals_w_not_keyword(self):
assert c1(test_results) and c2(test_results) and c3(test_results)
if __name__ == "__main__":
unittest.main()

View File

@@ -1,46 +1,32 @@
# -*- coding: utf-8 -*-
#
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import pytest
from copy import deepcopy
from unittest.mock import MagicMock
import pytest
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
MagicMock,
)
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
utils,
)
from ansible.module_utils.common.network import (
is_masklen,
is_netmask,
to_ipv6_network,
to_ipv6_subnet,
to_masklen,
to_netmask,
to_subnet,
to_ipv6_network,
to_ipv6_subnet,
is_masklen,
is_netmask,
)
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
def test_to_list():
for scalar in ("string", 1, True, False, None):
@@ -180,9 +166,7 @@ def test_dict_diff():
with pytest.raises(AssertionError, match="`base` must be of type <dict>"):
utils.dict_diff(None, {})
with pytest.raises(
AssertionError, match="`comparable` must be of type <dict>"
):
with pytest.raises(AssertionError, match="`comparable` must be of type <dict>"):
utils.dict_diff({}, object())
# But None is okay
@@ -336,9 +320,7 @@ def test_param_list_to_dict():
dict(vlan_id=10, name="voice"),
dict(vlan_id=99, name="guest"),
]
assert utils.param_list_to_dict(
params, unique_key="vlan_id", remove_key=False
) == {
assert utils.param_list_to_dict(params, unique_key="vlan_id", remove_key=False) == {
1: dict(vlan_id=1, name="management"),
10: dict(vlan_id=10, name="voice"),
99: dict(vlan_id=99, name="guest"),
@@ -384,9 +366,7 @@ def test_conditional():
assert utils.conditional("max(1)", 1)
assert utils.conditional("exactly(1)", 1)
assert utils.conditional("gt(5)", "7", int)
with pytest.raises(
AssertionError, match="invalid expression: cannot contain spaces"
):
with pytest.raises(AssertionError, match="invalid expression: cannot contain spaces"):
utils.conditional("1 ", 1)
with pytest.raises(ValueError, match="unknown operator: floop"):
utils.conditional("floop(4)", 4)
@@ -470,19 +450,11 @@ def test_is_netmask():
def test_to_ipv6_network():
assert "2001:db8::" == to_ipv6_network("2001:db8::")
assert "2001:0db8:85a3::" == to_ipv6_network(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334"
)
assert "2001:0db8:85a3::" == to_ipv6_network(
"2001:0db8:85a3:0:0:8a2e:0370:7334"
)
assert "2001:0db8:85a3::" == to_ipv6_network("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
assert "2001:0db8:85a3::" == to_ipv6_network("2001:0db8:85a3:0:0:8a2e:0370:7334")
def test_to_ipv6_subnet():
assert "2001:db8::" == to_ipv6_subnet("2001:db8::")
assert "2001:0db8:85a3:4242::" == to_ipv6_subnet(
"2001:0db8:85a3:4242:0000:8a2e:0370:7334"
)
assert "2001:0db8:85a3:4242::" == to_ipv6_subnet(
"2001:0db8:85a3:4242:0:8a2e:0370:7334"
)
assert "2001:0db8:85a3:4242::" == to_ipv6_subnet("2001:0db8:85a3:4242:0000:8a2e:0370:7334")
assert "2001:0db8:85a3:4242::" == to_ipv6_subnet("2001:0db8:85a3:4242:0:8a2e:0370:7334")

View File

@@ -1,40 +0,0 @@
# 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.six import string_types
from ansible.module_utils._text import to_bytes
from ansible.module_utils.common._collections_compat import MutableMapping
@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))

View File

@@ -1,23 +1,11 @@
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
@@ -53,10 +41,7 @@ def load_fixture(name):
class TestCliModule(ModuleTestCase):
def execute_module(
self, failed=False, changed=False, commands=None, sort=True
):
def execute_module(self, failed=False, changed=False, commands=None, sort=True):
self.load_fixtures(commands)
if failed:
@@ -74,9 +59,7 @@ class TestCliModule(ModuleTestCase):
result["commands"],
)
else:
self.assertEqual(
commands, result["commands"], result["commands"]
)
self.assertEqual(commands, result["commands"], result["commands"])
return result

View File

@@ -1,38 +1,22 @@
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
patch,
MagicMock,
)
from unittest.mock import MagicMock, patch
from ansible_collections.ansible.netcommon.plugins.modules import cli_config
from ansible_collections.ansible.netcommon.tests.unit.modules.utils import (
set_module_args,
)
from ansible_collections.ansible.netcommon.tests.unit.modules.utils import set_module_args
from .cli_module import TestCliModule
class TestCliConfigModule(TestCliModule):
module = cli_config
def setUp(self):
@@ -51,9 +35,7 @@ class TestCliConfigModule(TestCliModule):
self.mock_connection.stop()
@patch(
"ansible_collections.ansible.netcommon.plugins.modules.cli_config.run"
)
@patch("ansible_collections.ansible.netcommon.plugins.modules.cli_config.run")
def test_cli_config_backup_returns__backup__(self, run_mock):
args = dict(backup=True)
set_module_args(args)
@@ -84,9 +66,7 @@ class TestCliConfigModule(TestCliModule):
diff.get.side_effect = ["set interface eth0 ip address dhcp", None]
self.conn.get_diff.return_value = diff
set_module_args({"config": "set interface eth0 ip address dhcp"})
self.execute_module(
changed=True, commands=["set interface eth0 ip address dhcp"]
)
self.execute_module(changed=True, commands=["set interface eth0 ip address dhcp"])
self.conn.edit_config.assert_called_once_with(
candidate=["set interface eth0 ip address dhcp"],
commit=True,
@@ -98,9 +78,7 @@ class TestCliConfigModule(TestCliModule):
self.conn.get_diff.return_value = diff
set_module_args({"config": "set banner\nnew banner"})
self.execute_module(changed=True)
self.conn.edit_banner.assert_called_once_with(
candidate='"new banner"', commit=True
)
self.conn.edit_banner.assert_called_once_with(candidate='"new banner"', commit=True)
def test_cli_config_replace(self):
self.conn.get_capabilities.return_value = """{
@@ -109,9 +87,7 @@ class TestCliConfigModule(TestCliModule):
"supports_replace": true
}
}"""
self.conn.edit_config.return_value = {
"diff": "set interface eth0 ip address dhcp"
}
self.conn.edit_config.return_value = {"diff": "set interface eth0 ip address dhcp"}
args = {"config": "set interface eth0 ip address dhcp"}
@@ -149,9 +125,7 @@ class TestCliConfigModule(TestCliModule):
}
set_module_args(args)
result = self.execute_module(failed=True)
self.assertEqual(
result["msg"], "Option replace is not supported on this platform"
)
self.assertEqual(result["msg"], "Option replace is not supported on this platform")
def test_cli_config_replace_unspecified(self):
self.conn.get_capabilities.return_value = """{
@@ -172,9 +146,7 @@ class TestCliConfigModule(TestCliModule):
)
def test_cli_config_rollback(self):
self.conn.rollback.return_value = {
"diff": "set interface eth0 ip address dhcp"
}
self.conn.rollback.return_value = {"diff": "set interface eth0 ip address dhcp"}
args = {"rollback": 123456}
set_module_args(args)

View File

@@ -1,10 +1,12 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
import unittest
from unittest.mock import patch
from ansible_collections.ansible.netcommon.tests.unit.compat import unittest
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import patch
from ansible.module_utils import basic
from ansible.module_utils._text import to_bytes

View File

@@ -1,38 +0,0 @@
Cisco Nexus Operating System (NX-OS) Software
TAC support: http://www.cisco.com/tac
Documents: http://www.cisco.com/en/US/products/ps9372/tsd_products_support_series_home.html
Copyright (c) 2002-2018, Cisco Systems, Inc. All rights reserved.
The copyrights to certain works contained herein are owned by
other third parties and are used and distributed under license.
Some parts of this software are covered under the GNU Public
License. A copy of the license is available at
http://www.gnu.org/licenses/gpl.html.
Nexus 9000v is a demo version of the Nexus Operating System
Software
BIOS: version
NXOS: version 9.2(2)
BIOS compile time:
NXOS image file is: bootflash:///nxos.9.2.2.bin
NXOS compile time: 11/4/2018 21:00:00 [11/05/2018 06:11:06]
Hardware
cisco Nexus9000 9000v Chassis
with 8035024 kB of memory.
Processor Board ID 970MUM0NTLV
Device name: nxos101
bootflash: 3509454 kB
Kernel uptime is 33 day(s), 17 hour(s), 29 minute(s), 8 second(s)
Last reset
Reason: Unknown
System version:
Service:
plugin
Core Plugin, Ethernet Plugin
Active Package(s):

View File

@@ -1,5 +0,0 @@
---
- example: 'NXOS: version 9.2(2)'
getval: '\s+NXOS: version (?P<version>\S+)'
result:
version: "{{ version }}"

View File

@@ -1,595 +0,0 @@
# (c) 2020 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 os
import tempfile
from ansible.playbook.task import Task
from ansible.template import Templar
from ansible_collections.ansible.netcommon.tests.unit.compat import unittest
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
MagicMock,
patch,
)
from ansible_collections.ansible.netcommon.tests.unit.mock.loader import (
DictDataLoader,
)
from ansible_collections.ansible.netcommon.plugins.action.cli_parse import (
ActionModule,
)
from ansible_collections.ansible.netcommon.plugins.action.cli_parse import (
ARGSPEC_CONDITIONALS,
)
from ansible_collections.ansible.netcommon.plugins.modules.cli_parse import (
DOCUMENTATION,
)
from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import (
check_argspec,
)
from ansible_collections.ansible.utils.plugins.plugin_utils.base.cli_parser import (
CliParserBase,
)
from ansible.module_utils.connection import (
ConnectionError as AnsibleConnectionError,
)
class TestCli_Parse(unittest.TestCase):
def setUp(self):
task = MagicMock(Task)
play_context = MagicMock()
play_context.check_mode = False
connection = MagicMock()
fake_loader = DictDataLoader({})
templar = Templar(loader=fake_loader)
self._plugin = ActionModule(
task=task,
connection=connection,
play_context=play_context,
loader=fake_loader,
templar=templar,
shared_loader_obj=None,
)
self._plugin._task.action = "cli_parse"
@staticmethod
def _load_fixture(filename):
"""Load a fixture from the filesystem
:param filename: The name of the file to load
:type filename: str
:return: The file contents
:rtype: str
"""
fixture_name = os.path.join(
os.path.dirname(__file__), "fixtures", filename
)
with open(fixture_name) as fhand:
return fhand.read()
def test_fn_debug(self):
"""Confirm debug doesn't fail and return None"""
msg = "some message"
result = self._plugin._debug(msg)
self.assertEqual(result, None)
def test_fn_ail_json(self):
"""Confirm fail json replaces basic.py in msg"""
msg = "text (basic.py)"
with self.assertRaises(Exception) as error:
self._plugin._fail_json(msg)
self.assertEqual("text cli_parse", str(error.exception))
def test_fn_check_argspec_pass(self):
"""Confirm a valid argspec passes"""
kwargs = {
"text": "text",
"parser": {
"name": "ansible.utils.textfsm",
"command": "show version",
},
}
valid, result, updated_params = check_argspec(
DOCUMENTATION, "cli_parse module", schema_conditionals={}, **kwargs
)
self.assertEqual(valid, True)
def test_fn_check_argspec_fail_no_test_or_command(self):
"""Confirm failed argpsec w/o text or command"""
kwargs = {
"parser": {
"name": "ansible.utils.textfsm",
"command": "show version",
}
}
valid, result, updated_params = check_argspec(
DOCUMENTATION,
"cli_parse module",
schema_conditionals=ARGSPEC_CONDITIONALS,
**kwargs
)
# NOTE: Ansible 2.11+ returns result["errors"] as a list
error_msg = "one of the following is required: command, text"
if isinstance(result["errors"], list):
self.assertIn(error_msg, result["errors"])
else:
self.assertEqual(error_msg, result["errors"])
def test_fn_check_argspec_fail_no_parser_name(self):
"""Confirm failed argspec no parser name"""
kwargs = {"text": "anything", "parser": {"command": "show version"}}
valid, result, updated_params = check_argspec(
DOCUMENTATION,
"cli_parse module",
schema_conditionals=ARGSPEC_CONDITIONALS,
**kwargs
)
# NOTE: Ansible 2.11+ returns result["errors"] as a list
error_msg = "missing required arguments: name found in parser"
if isinstance(result["errors"], list):
self.assertIn(error_msg, result["errors"])
else:
self.assertEqual(error_msg, result["errors"])
def test_fn_extended_check_argspec_parser_name_not_coll(self):
"""Confirm failed argpsec parser not collection format"""
self._plugin._task.args = {
"text": "anything",
"parser": {
"command": "show version",
"name": "not_collection_format",
},
}
self._plugin._extended_check_argspec()
self.assertTrue(self._plugin._result["failed"])
self.assertIn("including collection", self._plugin._result["msg"])
def test_fn_extended_check_argspec_missing_tpath_or_command(self):
"""Confirm failed argpsec missing template_path
or command when text provided
"""
self._plugin._task.args = {
"text": "anything",
"parser": {"name": "a.b.c"},
}
self._plugin._extended_check_argspec()
self.assertTrue(self._plugin._result["failed"])
self.assertIn(
"provided when parsing text", self._plugin._result["msg"]
)
def test_fn_load_parser_pass(self):
"""Confirm each each of the parsers loads from the filesystem"""
parser_names = ["native", "ntc_templates", "pyats"]
for parser_name in parser_names:
self._plugin._task.args = {
"text": "anything",
"parser": {"name": "ansible.netcommon." + parser_name},
}
parser = self._plugin._load_parser(task_vars=None)
self.assertEqual(type(parser).__name__, "CliParser")
self.assertTrue(hasattr(parser, "parse"))
self.assertTrue(callable(parser.parse))
def test_fn_load_parser_fail(self):
"""Confirm missing parser fails gracefully"""
self._plugin._task.args = {
"text": "anything",
"parser": {"name": "a.b.c"},
}
parser = self._plugin._load_parser(task_vars=None)
self.assertIsNone(parser)
self.assertTrue(self._plugin._result["failed"])
self.assertIn("No module named", self._plugin._result["msg"])
def test_fn_set_parser_command_missing(self):
"""Confirm parser/command is set if missing
and command provided
"""
self._plugin._task.args = {
"command": "anything",
"parser": {"name": "a.b.c"},
}
self._plugin._set_parser_command()
self.assertEqual(
self._plugin._task.args["parser"]["command"], "anything"
)
def test_fn_set_parser_command_present(self):
"""Confirm parser/command is not changed if provided"""
self._plugin._task.args = {
"command": "anything",
"parser": {"command": "something", "name": "a.b.c"},
}
self._plugin._set_parser_command()
self.assertEqual(
self._plugin._task.args["parser"]["command"], "something"
)
def test_fn_set_parser_command_absent(self):
"""Confirm parser/command is not added"""
self._plugin._task.args = {"parser": {}}
self._plugin._set_parser_command()
self.assertNotIn("command", self._plugin._task.args["parser"])
def test_fn_set_text_present(self):
"""Check task args text is set to stdout"""
expected = "output"
self._plugin._result["stdout"] = expected
self._plugin._task.args = {}
self._plugin._set_text()
self.assertEqual(self._plugin._task.args["text"], expected)
def test_fn_set_text_absent(self):
"""Check task args text is set to stdout"""
self._plugin._result["stdout"] = None
self._plugin._task.args = {}
self._plugin._set_text()
self.assertNotIn("text", self._plugin._task.args)
def test_fn_os_from_task_vars(self):
"""Confirm os is set based on task vars"""
checks = [
("ansible_network_os", "cisco.nxos.nxos", "nxos"),
("ansible_network_os", "NXOS", "nxos"),
("ansible_distribution", "Fedora", "fedora"),
(None, None, ""),
]
for check in checks:
self._plugin._task_vars = {check[0]: check[1]}
result = self._plugin._os_from_task_vars()
self.assertEqual(result, check[2])
def test_fn_update_template_path_not_exist(self):
"""Check the creation of the template_path if
it doesn't exist in the user provided data
"""
self._plugin._task.args = {
"parser": {"command": "a command", "name": "a.b.c"}
}
self._plugin._task_vars = {"ansible_network_os": "cisco.nxos.nxos"}
with self.assertRaises(Exception) as error:
self._plugin._update_template_path("yaml")
self.assertIn(
"Could not find or access 'nxos_a_command.yaml'",
str(error.exception),
)
def test_fn_update_template_path_not_exist_os(self):
"""Check the creation of the template_path if
it doesn't exist in the user provided data
name based on os provided in task
"""
self._plugin._task.args = {
"parser": {"command": "a command", "name": "a.b.c", "os": "myos"}
}
with self.assertRaises(Exception) as error:
self._plugin._update_template_path("yaml")
self.assertIn(
"Could not find or access 'myos_a_command.yaml'",
str(error.exception),
)
def test_fn_update_template_path_mock_find_needle(self):
"""Check the creation of the template_path
mock the find needle fn so the template doesn't
need to be in the default template folder
"""
template_path = os.path.join(
os.path.dirname(__file__), "fixtures", "nxos_show_version.yaml"
)
self._plugin._find_needle = MagicMock()
self._plugin._find_needle.return_value = template_path
self._plugin._task.args = {
"parser": {"command": "show version", "os": "nxos"}
}
self._plugin._update_template_path("yaml")
self.assertEqual(
self._plugin._task.args["parser"]["template_path"], template_path
)
def test_fn_get_template_contents_pass(self):
"""Check the retrieval of the template contents"""
temp = tempfile.NamedTemporaryFile()
contents = "abcdef"
with open(temp.name, "w") as fileh:
fileh.write(contents)
self._plugin._task.args = {"parser": {"template_path": temp.name}}
result = self._plugin._get_template_contents()
self.assertEqual(result, contents)
def test_fn_get_template_contents_missing(self):
"""Check the retrieval of the template contents"""
self._plugin._task.args = {"parser": {"template_path": "non-exist"}}
with self.assertRaises(Exception) as error:
self._plugin._get_template_contents()
self.assertIn(
"Failed to open template 'non-exist'", str(error.exception)
)
def test_fn_get_template_contents_not_specified(self):
"""Check the none when template_path not specified"""
self._plugin._task.args = {"parser": {}}
result = self._plugin._get_template_contents()
self.assertIsNone(result)
def test_fn_prune_result_pass(self):
"""Test the removal of stdout and stdout_lines from the _result"""
self._plugin._result["stdout"] = "abc"
self._plugin._result["stdout_lines"] = "abc"
self._plugin._prune_result()
self.assertNotIn("stdout", self._plugin._result)
self.assertNotIn("stdout_lines", self._plugin._result)
def test_fn_prune_result_not_exist(self):
"""Test the removal of stdout and stdout_lines from the _result"""
self._plugin._prune_result()
self.assertNotIn("stdout", self._plugin._result)
self.assertNotIn("stdout_lines", self._plugin._result)
def test_fn_run_command_lx_rc0(self):
"""Check run command for non network"""
response = "abc"
self._plugin._connection.socket_path = None
self._plugin._low_level_execute_command = MagicMock()
self._plugin._low_level_execute_command.return_value = {
"rc": 0,
"stdout": response,
"stdout_lines": response,
}
self._plugin._task.args = {"command": "ls"}
self._plugin._run_command()
self.assertEqual(self._plugin._result["stdout"], response)
self.assertEqual(self._plugin._result["stdout_lines"], response)
def test_fn_run_command_lx_rc1(self):
"""Check run command for non network"""
response = "abc"
self._plugin._connection.socket_path = None
self._plugin._low_level_execute_command = MagicMock()
self._plugin._low_level_execute_command.return_value = {
"rc": 1,
"stdout": None,
"stdout_lines": None,
"stderr": response,
}
self._plugin._task.args = {"command": "ls"}
self._plugin._run_command()
self.assertTrue(self._plugin._result["failed"])
self.assertEqual(self._plugin._result["msg"], response)
@patch("ansible.module_utils.connection.Connection.__rpc__")
def test_fn_run_command_network(self, mock_rpc):
"""Check run command for network"""
expected = "abc"
mock_rpc.return_value = expected
self._plugin._connection.socket_path = (
tempfile.NamedTemporaryFile().name
)
self._plugin._task.args = {"command": "command"}
self._plugin._run_command()
self.assertEqual(self._plugin._result["stdout"], expected)
self.assertEqual(self._plugin._result["stdout_lines"], [expected])
def test_fn_run_command_not_specified(self):
"""Check run command for network"""
self._plugin._task.args = {"command": None}
result = self._plugin._run_command()
self.assertIsNone(result)
@patch("ansible.module_utils.connection.Connection.__rpc__")
def test_fn_run_pass_w_fact(self, mock_rpc):
"""Check full module run with valid params"""
mock_out = self._load_fixture("nxos_show_version.txt")
mock_rpc.return_value = mock_out
self._plugin._connection.socket_path = (
tempfile.NamedTemporaryFile().name
)
template_path = os.path.join(
os.path.dirname(__file__), "fixtures", "nxos_show_version.yaml"
)
self._plugin._task.args = {
"command": "show version",
"parser": {
"name": "ansible.netcommon.native",
"template_path": template_path,
},
"set_fact": "new_fact",
}
task_vars = {"inventory_hostname": "mockdevice"}
result = self._plugin.run(task_vars=task_vars)
self.assertEqual(result["stdout"], mock_out)
self.assertEqual(result["stdout_lines"], mock_out.splitlines())
self.assertEqual(result["parsed"]["version"], "9.2(2)")
self.assertEqual(
result["ansible_facts"]["new_fact"]["version"], "9.2(2)"
)
@patch("ansible.module_utils.connection.Connection.__rpc__")
def test_fn_run_pass_wo_fact(self, mock_rpc):
"""Check full module run with valid params"""
mock_out = self._load_fixture("nxos_show_version.txt")
mock_rpc.return_value = mock_out
self._plugin._connection.socket_path = (
tempfile.NamedTemporaryFile().name
)
template_path = os.path.join(
os.path.dirname(__file__), "fixtures", "nxos_show_version.yaml"
)
self._plugin._task.args = {
"command": "show version",
"parser": {
"name": "ansible.netcommon.native",
"template_path": template_path,
},
}
task_vars = {"inventory_hostname": "mockdevice"}
result = self._plugin.run(task_vars=task_vars)
self.assertEqual(result["stdout"], mock_out)
self.assertEqual(result["stdout_lines"], mock_out.splitlines())
self.assertEqual(result["parsed"]["version"], "9.2(2)")
self.assertNotIn("ansible_facts", result)
def test_fn_run_fail_argspec(self):
"""Check full module run with invalid params"""
self._plugin._task.args = {
"text": "anything",
"parser": {
"command": "show version",
"name": "not_collection_format",
},
}
self._plugin.run(task_vars=None)
self.assertTrue(self._plugin._result["failed"])
self.assertIn("including collection", self._plugin._result["msg"])
def test_fn_run_fail_command(self):
"""Confirm clean fail with rc 1"""
self._plugin._connection.socket_path = None
self._plugin._low_level_execute_command = MagicMock()
self._plugin._low_level_execute_command.return_value = {
"rc": 1,
"stdout": None,
"stdout_lines": None,
"stderr": None,
}
self._plugin._task.args = {
"command": "ls",
"parser": {"name": "a.b.c"},
}
task_vars = {"inventory_hostname": "mockdevice"}
result = self._plugin.run(task_vars=task_vars)
expected = {
"failed": True,
"msg": None,
"stdout": None,
"stdout_lines": None,
}
self.assertEqual(result, expected)
def test_fn_run_fail_missing_parser(self):
"""Confirm clean fail with missing parser"""
self._plugin._task.args = {"text": None, "parser": {"name": "a.b.c"}}
task_vars = {"inventory_hostname": "mockdevice"}
result = self._plugin.run(task_vars=task_vars)
self.assertEqual(result["failed"], True)
self.assertIn("Error loading parser", result["msg"])
@patch("ansible.module_utils.connection.Connection.__rpc__")
def test_fn_run_pass_empty_parser(self, mock_rpc):
"""Check full module run with valid params"""
mock_out = self._load_fixture("nxos_show_version.txt")
mock_rpc.return_value = mock_out
self._plugin._connection.socket_path = (
tempfile.NamedTemporaryFile().name
)
template_path = os.path.join(
os.path.dirname(__file__), "fixtures", "nxos_empty_parser.yaml"
)
self._plugin._task.args = {
"command": "show version",
"parser": {
"name": "ansible.netcommon.native",
"template_path": template_path,
},
}
task_vars = {"inventory_hostname": "mockdevice"}
result = self._plugin.run(task_vars=task_vars)
self.assertEqual(result["failed"], True)
self.assertIn("Native parser returned an error", result["msg"])
@patch("ansible.module_utils.connection.Connection.__rpc__")
def test_fn_run_pass_missing_parser_constants(self, mock_rpc):
"""Check full module run using parser w/o
DEFAULT_TEMPLATE_EXTENSION or PROVIDE_TEMPLATE_CONTENTS
defined in the parser
"""
mock_out = self._load_fixture("nxos_show_version.txt")
class CliParser(CliParserBase):
def parse(self, *_args, **kwargs):
return {"parsed": mock_out}
self._plugin._load_parser = MagicMock()
self._plugin._load_parser.return_value = CliParser(None, None, None)
mock_out = self._load_fixture("nxos_show_version.txt")
mock_rpc.return_value = mock_out
self._plugin._connection.socket_path = (
tempfile.NamedTemporaryFile().name
)
template_path = os.path.join(
os.path.dirname(__file__), "fixtures", "nxos_empty_parser.yaml"
)
self._plugin._task.args = {
"command": "show version",
"parser": {
"name": "ansible.netcommon.native",
"template_path": template_path,
},
}
task_vars = {"inventory_hostname": "mockdevice"}
result = self._plugin.run(task_vars=task_vars)
self.assertEqual(result["stdout"], mock_out)
self.assertEqual(result["stdout_lines"], mock_out.splitlines())
self.assertEqual(result["parsed"], mock_out)
@patch("ansible.module_utils.connection.Connection.__rpc__")
def test_fn_run_pass_missing_parser_in_parser(self, mock_rpc):
"""Check full module run using parser w/o
a parser function defined in the parser
defined in the parser
"""
mock_out = self._load_fixture("nxos_show_version.txt")
class CliParser(CliParserBase):
pass
self._plugin._load_parser = MagicMock()
self._plugin._load_parser.return_value = CliParser(None, None, None)
mock_out = self._load_fixture("nxos_show_version.txt")
mock_rpc.return_value = mock_out
self._plugin._connection.socket_path = (
tempfile.NamedTemporaryFile().name
)
template_path = os.path.join(
os.path.dirname(__file__), "fixtures", "nxos_empty_parser.yaml"
)
self._plugin._task.args = {
"command": "show version",
"parser": {
"name": "ansible.netcommon.native",
"template_path": template_path,
},
}
task_vars = {"inventory_hostname": "mockdevice"}
with self.assertRaises(Exception) as error:
self._plugin.run(task_vars=task_vars)
self.assertIn("Unhandled", str(error.exception))
@patch("ansible.module_utils.connection.Connection.__rpc__")
def test_fn_run_net_device_error(self, mock_rpc):
"""Check full module run mock error from network device"""
msg = "I was mocked"
mock_rpc.side_effect = AnsibleConnectionError(msg)
self._plugin._connection.socket_path = (
tempfile.NamedTemporaryFile().name
)
self._plugin._task.args = {
"command": "show version",
"parser": {"name": "ansible.netcommon.native"},
}
task_vars = {"inventory_hostname": "mockdevice"}
result = self._plugin.run(task_vars=task_vars)
self.assertEqual(result["failed"], True)
self.assertEqual([msg], result["msg"])

View File

@@ -1,26 +1,26 @@
# (c) 2021 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
import tempfile
from unittest.mock import MagicMock
import pytest
from ansible.errors import AnsibleError
from ansible.playbook.role import Role
from ansible.playbook.task import Task
from ansible.plugins.loader import action_loader
from ansible.template import Templar
import pytest
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
MagicMock,
)
from ansible_collections.ansible.netcommon.tests.unit.mock.loader import (
DictDataLoader,
)
from ansible_collections.ansible.netcommon.tests.unit.mock.loader import DictDataLoader
@pytest.fixture
@@ -65,8 +65,9 @@ def test_backup_options(plugin, backup_dir, backup_file, role_path):
# This doesn't need to be conditional, but doing so tests the equivalent
# `if backup_options:` in the action plugin itself.
backup_options = None
if backup_dir or backup_file:
plugin._task.args["backup_options"] = {
backup_options = {
"dir_path": backup_dir,
"filename": backup_file,
}
@@ -81,7 +82,7 @@ def test_backup_options(plugin, backup_dir, backup_file, role_path):
try:
# result is updated in place, nothing is returned
plugin._handle_backup_option(result, task_vars)
plugin._handle_backup_option(result, task_vars, backup_options)
assert not result.get("failed")
with open(result["backup_path"]) as backup_file_obj:
@@ -99,9 +100,7 @@ def test_backup_options(plugin, backup_dir, backup_file, role_path):
else:
backup_path = os.path.join(
backup_path,
"example.com_config.{0}@{1}".format(
result["date"], result["time"]
),
"example.com_config.{0}@{1}".format(result["date"], result["time"]),
)
# check that expected and returned backup paths match
@@ -110,7 +109,7 @@ def test_backup_options(plugin, backup_dir, backup_file, role_path):
if backup_file:
# check for idempotency
result = {"__backup__": content}
plugin._handle_backup_option(result, task_vars)
plugin._handle_backup_option(result, task_vars, backup_options)
assert not result.get("failed")
assert result["changed"] is False
@@ -122,10 +121,8 @@ def test_backup_options(plugin, backup_dir, backup_file, role_path):
def test_backup_no_content(plugin):
result = {}
task_vars = {}
with pytest.raises(
AnsibleError, match="Failed while reading configuration backup"
):
plugin._handle_backup_option(result, task_vars)
with pytest.raises(AnsibleError, match="Failed while reading configuration backup"):
plugin._handle_backup_option(result, task_vars, backup_options=None)
def test_backup_options_error(plugin):
@@ -133,13 +130,11 @@ def test_backup_options_error(plugin):
task_vars = {}
with tempfile.NamedTemporaryFile() as existing_file:
plugin._task.args = {
"backup_options": {
"dir_path": existing_file.name,
"filename": "backup_file",
}
backup_options = {
"dir_path": existing_file.name,
"filename": "backup_file",
}
plugin._handle_backup_option(result, task_vars)
plugin._handle_backup_option(result, task_vars, backup_options)
assert result["failed"] is True
assert result["msg"] == (

View File

@@ -1,19 +1,22 @@
# (c) 2020 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
import unittest
import pytest
from ansible_collections.ansible.netcommon.tests.unit.compat import unittest
from ansible_collections.ansible.netcommon.plugins.sub_plugins.cli_parser.pyats_parser import (
CliParser,
)
pyats = pytest.importorskip("pyats")
@@ -77,9 +80,7 @@ class TestPyatsParser(unittest.TestCase):
self._debug_msgs.append(msg)
def _load_fixture(self, filename):
cfg_path = os.path.join(
os.path.dirname(__file__), "fixtures", filename
)
cfg_path = os.path.join(os.path.dirname(__file__), "fixtures", filename)
with open(cfg_path) as f:
return f.read()
@@ -110,9 +111,7 @@ class TestPyatsParser(unittest.TestCase):
debug=self._debug,
)
result = parser.parse()
error = {
"errors": ["The pyats parser requires parser/command be provided."]
}
error = {"errors": ["The pyats parser requires parser/command be provided."]}
self.assertEqual(result, error)
def test_pyats_parser_ano_shortname(self):

View File

@@ -0,0 +1,126 @@
#
# (c) 2016 Red Hat Inc.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
from unittest.mock import MagicMock
import pytest
from ansible.errors import AnsibleConnectionFailure
from ansible.plugins.loader import cliconf_loader
INFO = dict(network_os="default")
OPERATIONS = {
"supports_diff_replace": False,
"supports_commit": False,
"supports_rollback": False,
"supports_defaults": False,
"supports_onbox_diff": False,
"supports_commit_comment": False,
"supports_multiline_delimiter": False,
"supports_diff_match": False,
"supports_diff_ignore_lines": False,
"supports_generate_diff": False,
"supports_replace": False,
}
RPC = [
"edit_config",
"enable_response_logging",
"get",
"get_capabilities",
"get_config",
"disable_response_logging",
"run_commands",
]
@pytest.fixture(name="cliconf")
def plugin_fixture():
cliconf = cliconf_loader.get("ansible.netcommon.default", None)
return cliconf
def test_get_device_info(cliconf):
info = cliconf.get_device_info()
assert info == INFO
# Test cached info works
assert info == cliconf.get_device_info()
def test_get_device_operations(cliconf):
ops = cliconf.get_device_operations()
assert ops == OPERATIONS
def test_get_capabilities(cliconf):
cap = json.loads(cliconf.get_capabilities())
assert cap == dict(
rpc=RPC,
device_info=INFO,
network_api="cliconf",
device_operations=OPERATIONS,
)
@pytest.mark.parametrize("method", ["get_config", "edit_config", "commit", "discard_changes"])
def test_unsupported_method(cliconf, method):
cliconf._play_context = MagicMock()
cliconf._play_context.network_os = "default"
with pytest.raises(
AnsibleConnectionFailure, match=f"{method} is not supported by network_os default"
):
getattr(cliconf, method)()
def test_get(cliconf):
return_value = "ABC FakeOS v1.23.4"
conn = MagicMock()
conn.send.return_value = return_value
cliconf._connection = conn
resp = cliconf.get("show version")
assert resp == return_value
def test_get_no_command(cliconf):
with pytest.raises(ValueError, match="must provide value of command to execute"):
cliconf.get()
@pytest.mark.parametrize("commands", ["show version", {"command": "show version"}])
def test_run_commands(cliconf, commands):
return_value = "ABC FakeOS v1.23.4"
conn = MagicMock()
conn.send.return_value = return_value
cliconf._connection = conn
resp = cliconf.run_commands([commands])
assert resp == [return_value]
@pytest.mark.parametrize("check_rc", [True, False])
def test_run_commands_check_rc(cliconf, check_rc):
error = AnsibleConnectionFailure("Invalid command: [sow]")
cliconf.send_command = MagicMock(side_effect=error)
if check_rc:
with pytest.raises(AnsibleConnectionFailure):
resp = cliconf.run_commands(["sow version"], check_rc=check_rc)
else:
resp = cliconf.run_commands(["sow version"], check_rc=check_rc)
assert resp == [error]
def test_run_commands_no_commands(cliconf):
with pytest.raises(ValueError, match="'commands' value is required"):
cliconf.run_commands()

View File

@@ -1,138 +1,131 @@
# (c) 2020 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from unittest.mock import MagicMock, patch
import pytest
from ansible.module_utils._text import to_bytes
from ansible.errors import AnsibleError, AnsibleFileNotFound
from ansible.module_utils._text import to_bytes
from ansible.playbook.play_context import PlayContext
from ansible.plugins.loader import connection_loader
from ansible_collections.ansible.netcommon.tests.unit.compat import unittest
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
patch,
MagicMock,
)
from ansible_collections.ansible.netcommon.plugins.connection import libssh
pylibsshext = pytest.importorskip("pylibsshext")
class TestConnectionClass(unittest.TestCase):
@patch("pylibsshext.session.Session")
@patch("ansible.plugins.connection.ConnectionBase._connect")
def test_libssh_connect(self, mocked_super, mock_session):
pc = PlayContext()
pc.remote_addr = "localhost"
pc.password = "test"
pc.port = 8080
pc.timeout = 60
pc.remote_user = "user1"
@pytest.fixture(name="conn")
def plugin_fixture():
pc = PlayContext()
pc.port = 8080
pc.timeout = 60
conn = connection_loader.get(
"ansible.netcommon.libssh", pc, "/dev/null"
)
conn = connection_loader.get("ansible.netcommon.libssh", pc, "/dev/null")
return conn
conn.ssh = mock_session
mock_connect = MagicMock()
conn.ssh.connect = mock_connect
conn._connect()
conn.ssh.connect.assert_called_with(
host="localhost",
host_key_checking=False,
look_for_keys=True,
password="test",
port=8080,
timeout=60,
user="user1",
private_key=None,
)
def test_libssh_close(self):
pc = PlayContext()
conn = connection_loader.get(
"ansible.netcommon.libssh", pc, "/dev/null"
)
conn.ssh = MagicMock()
conn.sftp = MagicMock()
conn.chan = MagicMock()
def test_libssh_connect(conn, monkeypatch):
"""Test the libssh connection plugin.
conn.close()
:param monkeypatch: pytest fixture
"""
conn.set_options(
direct={
"remote_addr": "localhost",
"remote_user": "user1",
"password": "test",
"host_key_checking": False,
}
)
conn.sftp.close.assert_called_with()
conn.chan.close.assert_called_with()
conn.sftp.close.assert_called_with()
mock_session = MagicMock()
monkeypatch.setattr(libssh, "Session", mock_session)
mock_ssh = MagicMock()
mock_session.return_value = mock_ssh
conn._connect()
mock_ssh.connect.assert_called_with(
host="localhost",
host_key_checking=False,
look_for_keys=True,
password="test",
password_prompt=None,
port=8080,
timeout=60,
user="user1",
private_key=None,
)
@patch("ansible.plugins.connection.ConnectionBase.exec_command")
def test_libssh_exec_command(self, mocked_super):
pc = PlayContext()
conn = connection_loader.get(
"ansible.netcommon.libssh", pc, "/dev/null"
)
with self.assertRaises(AnsibleError):
conn.exec_command(cmd="ls", in_data=True)
mock_chan = MagicMock()
mock_chan.request_shell = MagicMock()
mock_chan.exec_command = MagicMock()
mock_chan.exec_command.return_value = MagicMock(
returncode=0, stdout="echo hello", stderr=""
)
def test_libssh_close(conn):
conn.ssh = MagicMock()
conn.sftp = MagicMock()
conn.chan = MagicMock()
attr = {"new_channel.return_value": mock_chan}
mock_ssh = MagicMock(**attr)
conn.ssh = mock_ssh
conn.close()
rc, out, err = conn.exec_command(cmd="echo hello")
conn.sftp.close.assert_called_with()
conn.chan.close.assert_called_with()
conn.ssh.close.assert_called_with()
self.assertEqual((rc, out, err), (0, "echo hello", ""))
@patch("ansible.plugins.connection.ConnectionBase.put_file")
def test_libssh_put_file_not_exist(self, mocked_super):
pc = PlayContext()
conn = connection_loader.get(
"ansible.netcommon.libssh", pc, "/dev/null"
)
with self.assertRaises(AnsibleFileNotFound):
conn.put_file(in_path="", out_path="")
@patch("ansible.plugins.connection.ConnectionBase.exec_command")
def test_libssh_exec_command(mocked_super, conn):
with pytest.raises(AnsibleError):
conn.exec_command(cmd="ls", in_data=True)
@patch("os.path.exists")
@patch("ansible.plugins.connection.ConnectionBase.put_file")
def test_libssh_put_file(self, mocked_super, mock_exists):
pc = PlayContext()
conn = connection_loader.get(
"ansible.netcommon.libssh", pc, "/dev/null"
)
mock_chan = MagicMock()
mock_chan.request_shell = MagicMock()
mock_chan.exec_command = MagicMock()
mock_chan.exec_command.return_value = MagicMock(returncode=0, stdout="echo hello", stderr="")
mock_sftp = MagicMock()
attr = {"sftp.return_value": mock_sftp}
mock_ssh = MagicMock(**attr)
conn.ssh = mock_ssh
attr = {"new_channel.return_value": mock_chan}
mock_ssh = MagicMock(**attr)
conn.ssh = mock_ssh
file_path = "test_libssh.py"
conn.put_file(in_path=file_path, out_path=file_path)
mock_sftp.put.assert_called_with(
to_bytes(file_path), to_bytes(file_path)
)
rc, out, err = conn.exec_command(cmd="echo hello")
@patch("pylibsshext.session.Session")
@patch("ansible.plugins.connection.ConnectionBase.fetch_file")
def test_libssh_fetch_file(self, mocked_super, mock_session):
pc = PlayContext()
pc.remote_addr = "localhost"
conn = connection_loader.get(
"ansible.netcommon.libssh", pc, "/dev/null"
)
assert (rc, out, err) == (0, "echo hello", "")
conn.ssh = mock_session
mock_connect = MagicMock()
conn.ssh.connect = mock_connect
file_path = "test_libssh.py"
conn.fetch_file(in_path=file_path, out_path=file_path)
conn.sftp.get.assert_called_with(
to_bytes(file_path), to_bytes(file_path)
)
@patch("ansible.plugins.connection.ConnectionBase.put_file")
def test_libssh_put_file_not_exist(mocked_super, conn):
with pytest.raises(AnsibleFileNotFound):
conn.put_file(in_path="", out_path="")
@patch("os.path.exists")
@patch("ansible.plugins.connection.ConnectionBase.put_file")
def test_libssh_put_file(mocked_super, mock_exists, conn):
mock_sftp = MagicMock()
attr = {"sftp.return_value": mock_sftp}
mock_ssh = MagicMock(**attr)
conn.ssh = mock_ssh
file_path = "test_libssh.py"
conn.put_file(in_path=file_path, out_path=file_path)
mock_sftp.put.assert_called_with(to_bytes(file_path), to_bytes(file_path))
@patch("ansible.plugins.connection.ConnectionBase.fetch_file")
def test_libssh_fetch_file(mocked_super, conn, monkeypatch):
mock_session = MagicMock()
monkeypatch.setattr(libssh, "Session", mock_session)
mock_ssh = MagicMock()
mock_session.return_value = mock_ssh
file_path = "test_libssh.py"
conn.fetch_file(in_path=file_path, out_path=file_path)
conn.sftp.get.assert_called_with(
to_bytes(file_path),
to_bytes(file_path),
)

View File

@@ -1,36 +1,21 @@
#
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import sys
from unittest.mock import MagicMock, PropertyMock, patch
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
patch,
MagicMock,
PropertyMock,
)
from ansible.playbook.play_context import PlayContext
import pytest
from ansible.playbook.play_context import PlayContext
pytest.importorskip("ncclient")
@@ -45,19 +30,10 @@ def import_mock(name, *args):
return builtin_import(name, *args)
PY3 = sys.version_info[0] == 3
if PY3:
with patch("builtins.__import__", side_effect=import_mock):
from ansible_collections.ansible.netcommon.plugins.connection import (
netconf,
)
from ansible.plugins.loader import connection_loader
else:
with patch("__builtin__.__import__", side_effect=import_mock):
from ansible_collections.ansible.netcommon.plugins.connection import (
netconf,
)
from ansible.plugins.loader import connection_loader
with patch("builtins.__import__", side_effect=import_mock):
from ansible.plugins.loader import connection_loader
from ansible_collections.ansible.netcommon.plugins.connection import netconf
def test_netconf_init():
@@ -69,9 +45,7 @@ def test_netconf_init():
assert conn._connected is False
@patch(
"ansible_collections.ansible.netcommon.plugins.connection.netconf.netconf_loader"
)
@patch("ansible_collections.ansible.netcommon.plugins.connection.netconf.netconf_loader")
def test_netconf__connect(mock_netconf_loader):
pc = PlayContext()
conn = connection_loader.get("ansible.netcommon.netconf", pc, "/dev/null")

View File

@@ -1,45 +1,38 @@
#
# (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/>.
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
from ansible_collections.ansible.netcommon.tests.unit.compat.mock import (
MagicMock,
)
from unittest.mock import MagicMock
import pytest
from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils._text import to_text
from ansible.playbook.play_context import PlayContext
from ansible.plugins.loader import connection_loader
import pytest
from ansible_collections.ansible.netcommon.plugins.connection.network_cli import terminal_loader
@pytest.fixture(name="conn")
def plugin_fixture():
def plugin_fixture(monkeypatch):
pc = PlayContext()
pc.network_os = "ios"
conn = connection_loader.get(
"ansible.netcommon.network_cli", pc, "/dev/null"
)
pc.network_os = "fakeos"
def get(*args, **kwargs):
return MagicMock()
monkeypatch.setattr(terminal_loader, "get", get)
conn = connection_loader.get("ansible.netcommon.network_cli", pc, "/dev/null")
return conn
@@ -55,10 +48,8 @@ def test_network_cli_invalid_os(network_os):
@pytest.mark.parametrize("look_for_keys", [True, False, None])
@pytest.mark.parametrize("password", ["password", None])
@pytest.mark.parametrize("private_key_file", ["/path/to/key/file", None])
@pytest.mark.parametrize("ssh_type", ["paramiko", "libssh"])
def test_look_for_keys(
conn, look_for_keys, password, private_key_file, ssh_type
):
@pytest.mark.parametrize("ssh_type", ["paramiko", "libssh", "auto"])
def test_look_for_keys(conn, look_for_keys, password, private_key_file, ssh_type):
conn.set_options(
direct={
"ssh_type": ssh_type,
@@ -81,7 +72,7 @@ def test_look_for_keys(
assert conn.ssh_type_conn.get_option("look_for_keys") is True
@pytest.mark.parametrize("ssh_type", ["paramiko", "libssh"])
@pytest.mark.parametrize("ssh_type", ["paramiko", "libssh", "auto"])
def test_options_pass_through(conn, ssh_type):
conn.set_options(
direct={
@@ -104,9 +95,25 @@ def test_options_pass_through(conn, ssh_type):
assert conn.ssh_type_conn.get_option("proxy_command") == "do a proxy"
@pytest.mark.parametrize(
"become_method,become_pass", [("enable", "password"), (None, None)]
)
@pytest.mark.parametrize("has_libssh", (True, False))
def test_network_cli_ssh_type_auto(conn, has_libssh):
"""Test that ssh_type: auto resolves to the correct option."""
from ansible_collections.ansible.netcommon.plugins.connection import network_cli
network_cli.HAS_PYLIBSSH = has_libssh
conn.set_options(
direct={
"ssh_type": "auto",
}
)
if has_libssh:
assert conn.ssh_type == "libssh"
else:
assert conn.ssh_type == "paramiko"
@pytest.mark.parametrize("become_method,become_pass", [("enable", "password"), (None, None)])
def test_network_cli__connect(conn, become_method, become_pass):
conn.ssh = MagicMock()
conn.receive = MagicMock()
@@ -127,9 +134,7 @@ def test_network_cli__connect(conn, become_method, become_pass):
assert conn._terminal.on_become.called is False
@pytest.mark.parametrize(
"command", ["command", json.dumps({"command": "command"})]
)
@pytest.mark.parametrize("command", ["command", json.dumps({"command": "command"})])
def test_network_cli_exec_command(conn, command):
mock_send = MagicMock(return_value=b"command response")
conn.send = mock_send
@@ -145,16 +150,19 @@ def test_network_cli_exec_command(conn, command):
@pytest.mark.parametrize(
"response",
[
b"device#command\ncommand response\n\ndevice#",
[b"device#command\ncommand response\n\ndevice#"],
[b"device#command\ncommand ", b"response\n\ndevice#"],
pytest.param(
b"ERROR: error message device#",
[b"ERROR: error message device#"],
marks=pytest.mark.xfail(raises=AnsibleConnectionFailure),
),
],
)
def test_network_cli_send(conn, response):
@pytest.mark.parametrize("ssh_type", ["paramiko", "libssh", "auto"])
def test_network_cli_send(conn, response, ssh_type):
conn.set_options(
direct={
"ssh_type": ssh_type,
"terminal_stderr_re": [{"pattern": "^ERROR"}],
"terminal_stdout_re": [{"pattern": "device#"}],
}
@@ -165,7 +173,10 @@ def test_network_cli_send(conn, response):
conn._ssh_shell = mock__shell
conn._connected = True
mock__shell.recv.side_effect = [response, None]
if conn.ssh_type == "paramiko":
mock__shell.recv.side_effect = [*response, None]
elif conn.ssh_type == "libssh":
mock__shell.read_bulk_response.side_effect = [*response, None]
conn.send(b"command")
mock__shell.sendall.assert_called_with(b"command\r")

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# 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 unittest
from ansible_collections.ansible.netcommon.plugins.plugin_utils.comp_type5 import comp_type5
class TestComp_type5(unittest.TestCase):
def setUp(self):
pass
def test_comp_type5_plugin_1(self):
unencrypted_password = "cisco@123"
encrypted_password = "$1$avs$uSTOEMh65qzvpb9yBMpzd/"
args = [unencrypted_password, encrypted_password, False]
result = comp_type5(*args)
self.assertEqual(
True,
result,
)
def test_comp_type5_plugin_2(self):
unencrypted_password = "cisco@123"
encrypted_password = "$1$avs$uSTOEMh65qzvpb9yBMpzd/"
args = [unencrypted_password, encrypted_password, True]
result = comp_type5(*args)
self.assertEqual(
encrypted_password,
result,
)

View File

@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# 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 unittest
from ansible_collections.ansible.netcommon.plugins.plugin_utils.hash_salt import hash_salt
class Testhash_salt(unittest.TestCase):
def setUp(self):
pass
def test_hash_salt_plugin_1(self):
password = "$1$avs$uSTOEMh65qzvpb9yBMpzd/TESTPASS"
args = [password[0:-8]]
result = hash_salt(*args)
self.assertEqual(
"avs",
result,
)

View File

@@ -16,20 +16,20 @@
# Make coding more python3-ish
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import os
import sys
import unittest
from ansible_collections.ansible.netcommon.plugins.plugin_utils.comp_type5 import comp_type5
from ansible_collections.ansible.netcommon.plugins.plugin_utils.hash_salt import hash_salt
from ansible_collections.ansible.netcommon.plugins.plugin_utils.parse_xml import parse_xml
from ansible_collections.ansible.netcommon.plugins.plugin_utils.type5_pw import type5_pw
from ansible_collections.ansible.netcommon.plugins.plugin_utils.vlan_expander import vlan_expander
from ansible_collections.ansible.netcommon.plugins.plugin_utils.vlan_parser import vlan_parser
from ansible_collections.ansible.netcommon.tests.unit.compat import unittest
from ansible_collections.ansible.netcommon.plugins.filter.network import (
parse_xml,
type5_pw,
hash_salt,
comp_type5,
vlan_parser,
vlan_expander,
)
fixture_path = os.path.join(os.path.dirname(__file__), "fixtures", "network")
@@ -96,9 +96,7 @@ class TestNetworkParseFilter(unittest.TestCase):
"XPath expression not supported in this version",
)
def test_parse_xml_to_dict(self):
spec_file_path = os.path.join(
fixture_path, "show_vlans_xml_with_key_spec.yml"
)
spec_file_path = os.path.join(fixture_path, "show_vlans_xml_with_key_spec.yml")
parsed = parse_xml(output_xml, spec_file_path)
expected = {
"vlans": {
@@ -151,9 +149,7 @@ class TestNetworkParseFilter(unittest.TestCase):
"XPath expression not supported in this version",
)
def test_parse_xml_with_condition_spec(self):
spec_file_path = os.path.join(
fixture_path, "show_vlans_xml_with_condition_spec.yml"
)
spec_file_path = os.path.join(fixture_path, "show_vlans_xml_with_condition_spec.yml")
parsed = parse_xml(output_xml, spec_file_path)
expected = {
"vlans": [
@@ -170,13 +166,9 @@ class TestNetworkParseFilter(unittest.TestCase):
self.assertEqual(parsed, expected)
def test_parse_xml_with_single_value_spec(self):
spec_file_path = os.path.join(
fixture_path, "show_vlans_xml_single_value_spec.yml"
)
spec_file_path = os.path.join(fixture_path, "show_vlans_xml_single_value_spec.yml")
parsed = parse_xml(output_xml, spec_file_path)
expected = {
"vlans": ["test-1", "test-2", "test-3", "test-4", "test-5"]
}
expected = {"vlans": ["test-1", "test-2", "test-3", "test-4", "test-5"]}
self.assertEqual(parsed, expected)
def test_parse_xml_validate_input(self):
@@ -185,15 +177,12 @@ class TestNetworkParseFilter(unittest.TestCase):
with self.assertRaises(Exception) as e:
parse_xml(output_xml, "junk_path")
self.assertEqual(
"unable to locate parse_xml template: junk_path", str(e.exception)
)
self.assertEqual("unable to locate parse_xml template: junk_path", str(e.exception))
with self.assertRaises(Exception) as e:
parse_xml(output, spec_file_path)
self.assertEqual(
"parse_xml works on string input, but given input of : %s"
% type(output),
"parse_xml works on string input, but given input of : %s" % type(output),
str(e.exception),
)
@@ -212,7 +201,6 @@ class TestNetworkType5(unittest.TestCase):
self.assertEqual(len(parsed), 30)
def test_wrong_data_type(self):
with self.assertRaises(Exception) as e:
type5_pw([])
self.assertEqual(
@@ -242,7 +230,6 @@ class TestNetworkType5(unittest.TestCase):
)
def test_bad_salt_char(self):
with self.assertRaises(Exception) as e:
type5_pw("password", "*()")
self.assertEqual(
@@ -314,6 +301,7 @@ class TestVlanExapander(unittest.TestCase):
def test_no_ranges(self):
raw_list = "1,3,5"
expanded_list = [1, 3, 5]
print(vlan_expander(raw_list))
self.assertEqual(vlan_expander(raw_list), expanded_list)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# 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 unittest
from ansible_collections.ansible.netcommon.plugins.plugin_utils.type5_pw import type5_pw
class TestType5_pw(unittest.TestCase):
def setUp(self):
pass
def test_type5_pw_plugin_1(self):
password = "cisco"
salt = "nTc1"
args = [password, salt]
result = type5_pw(*args)
self.assertEqual(
"$1$nTc1$Z28sUTcWfXlvVe2x.3XAa.TESTPASS",
result + "TESTPASS",
)
def test_type5_pw_plugin_2(self):
password = "cisco"
args = [password]
result = type5_pw(*args)
self.assertEqual(
len(result),
30,
)

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# 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 unittest
from ansible_collections.ansible.netcommon.plugins.plugin_utils.vlan_expander import vlan_expander
class TestVlanExtender(unittest.TestCase):
def setUp(self):
pass
def test_vlan_extender_plugin_1(self):
data = "1,13-19,24,26,34-56"
args = [data]
result = vlan_expander(*args)
self.assertEqual(
result,
[
1,
13,
14,
15,
16,
17,
18,
19,
24,
26,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
],
)
def test_vlan_extender_plugin_2(self):
data = "13-19"
args = [data]
result = vlan_expander(*args)
self.assertEqual(
result,
[
13,
14,
15,
16,
17,
18,
19,
],
)

View File

@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# Copyright 2023 Red Hat
# 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 unittest
from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.netcommon.plugins.plugin_utils.vlan_parser import vlan_parser
class TestVlanParser(unittest.TestCase):
def setUp(self):
pass
def test_vlan_parser_plugin_1(self):
data = [
1,
13,
14,
15,
16,
17,
18,
19,
24,
26,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
]
args = [data]
result = vlan_parser(*args)
self.assertEqual(
result[0],
"1,13-19,24,26,34-56",
)
def test_vlan_parser_plugin_2(self):
data = [1, 2, 3]
args = [data]
result = vlan_parser(*args)
self.assertEqual(
result[0],
"1-3",
)
def test_vlan_parser_fail_wrong_data(self):
data = "13"
args = [data]
with self.assertRaises(AnsibleFilterError) as error:
vlan_parser(*args)
self.assertIn(
"Input is not valid for vlan_parser",
str(error.exception),
)
def test_vlan_parser_fail_out_range(self):
data = [
1,
2013,
2014,
2015,
2016,
2017,
2018,
2019,
2024,
2026,
4034,
4035,
4036,
4037,
4038,
4039,
4040,
4041,
4042,
4311,
]
args = [data]
with self.assertRaises(AnsibleFilterError) as error:
vlan_parser(*args)
self.assertIn(
"Valid VLAN range is 1-4094",
str(error.exception),
)

View File

@@ -0,0 +1,31 @@
# (c) 2023 Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import pytest
from ansible_collections.ansible.netcommon.plugins.plugin_utils.version import Version
@pytest.mark.parametrize("left", ["6.0.0", 6, 6.0])
@pytest.mark.parametrize("right", ["4.0.0", 4, 4.0])
def test_versions_different(left, right):
assert Version(str(left)) > right
@pytest.mark.parametrize("value", ["6.0.0", 6, 6.0])
def test_versions_same(value):
assert Version(str(value)) == value
def test_version_error():
with pytest.raises(TypeError):
Version("1.2.3") < [1, 2, 3]
# with pytest.raises(TypeError):
Version("1.2.3") == [1, 2, 3]