mirror of
https://github.com/ansible-collections/community.docker.git
synced 2026-03-15 11:53:31 +00:00
Move modules and module_utils unit tests to correct place (#81)
* Move modules and module_utils unit tests to correct place. * Update ignore.txt * Fix imports. * Fix typos. * Fix more typos.
This commit is contained in:
parent
fe2eded15a
commit
910f3adff2
0
tests/unit/plugins/module_utils/__init__.py
Normal file
0
tests/unit/plugins/module_utils/__init__.py
Normal file
518
tests/unit/plugins/module_utils/test_common.py
Normal file
518
tests/unit/plugins/module_utils/test_common.py
Normal file
@ -0,0 +1,518 @@
|
|||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ansible_collections.community.docker.plugins.module_utils.common import (
|
||||||
|
compare_dict_allow_more_present,
|
||||||
|
compare_generic,
|
||||||
|
convert_duration_to_nanosecond,
|
||||||
|
parse_healthcheck
|
||||||
|
)
|
||||||
|
|
||||||
|
DICT_ALLOW_MORE_PRESENT = (
|
||||||
|
{
|
||||||
|
'av': {},
|
||||||
|
'bv': {'a': 1},
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'av': {'a': 1},
|
||||||
|
'bv': {'a': 1, 'b': 2},
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'av': {'a': 1},
|
||||||
|
'bv': {'b': 2},
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'av': {'a': 1},
|
||||||
|
'bv': {'a': None, 'b': 1},
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'av': {'a': None},
|
||||||
|
'bv': {'b': 1},
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
COMPARE_GENERIC = [
|
||||||
|
########################################################################################
|
||||||
|
# value
|
||||||
|
{
|
||||||
|
'a': 1,
|
||||||
|
'b': 2,
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'value',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': 'hello',
|
||||||
|
'b': 'hello',
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'value',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': None,
|
||||||
|
'b': 'hello',
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'value',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': None,
|
||||||
|
'b': None,
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'value',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': 1,
|
||||||
|
'b': 2,
|
||||||
|
'method': 'ignore',
|
||||||
|
'type': 'value',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': None,
|
||||||
|
'b': 2,
|
||||||
|
'method': 'ignore',
|
||||||
|
'type': 'value',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
########################################################################################
|
||||||
|
# list
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'list',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'list',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'list',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'y',
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'list',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'list',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'list',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'list',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'z',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
'x',
|
||||||
|
'z',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'list',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'y',
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'method': 'ignore',
|
||||||
|
'type': 'list',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
########################################################################################
|
||||||
|
# set
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'y',
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'set',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'set',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'set',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'z',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
'x',
|
||||||
|
'z',
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'set',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
'x',
|
||||||
|
'a',
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
'y',
|
||||||
|
'z',
|
||||||
|
],
|
||||||
|
'method': 'ignore',
|
||||||
|
'type': 'set',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
########################################################################################
|
||||||
|
# set(dict)
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'y': 1},
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'x': 1},
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'x': 1, 'y': 2},
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1},
|
||||||
|
{'x': 2, 'y': 3},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'x': 1},
|
||||||
|
{'x': 2, 'y': 3},
|
||||||
|
],
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'x': 1, 'z': 2},
|
||||||
|
{'x': 2, 'y': 3},
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1, 'y': 2},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'x': 1},
|
||||||
|
{'x': 2, 'y': 3},
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1, 'y': 3},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'x': 1},
|
||||||
|
{'x': 1, 'y': 3, 'z': 4},
|
||||||
|
],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': [
|
||||||
|
{'x': 1},
|
||||||
|
{'x': 2, 'y': 3},
|
||||||
|
],
|
||||||
|
'b': [
|
||||||
|
{'x': 1},
|
||||||
|
],
|
||||||
|
'method': 'ignore',
|
||||||
|
'type': 'set(dict)',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
########################################################################################
|
||||||
|
# dict
|
||||||
|
{
|
||||||
|
'a': {'x': 1},
|
||||||
|
'b': {'y': 1},
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'dict',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': {'x': 1},
|
||||||
|
'b': {'x': 1, 'y': 2},
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'dict',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': {'x': 1},
|
||||||
|
'b': {'x': 1},
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'dict',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': {'x': 1, 'z': 2},
|
||||||
|
'b': {'x': 1, 'y': 2},
|
||||||
|
'method': 'strict',
|
||||||
|
'type': 'dict',
|
||||||
|
'result': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'a': {'x': 1, 'z': 2},
|
||||||
|
'b': {'x': 1, 'y': 2},
|
||||||
|
'method': 'ignore',
|
||||||
|
'type': 'dict',
|
||||||
|
'result': True
|
||||||
|
},
|
||||||
|
] + [{
|
||||||
|
'a': entry['av'],
|
||||||
|
'b': entry['bv'],
|
||||||
|
'method': 'allow_more_present',
|
||||||
|
'type': 'dict',
|
||||||
|
'result': entry['result']
|
||||||
|
} for entry in DICT_ALLOW_MORE_PRESENT]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("entry", DICT_ALLOW_MORE_PRESENT)
|
||||||
|
def test_dict_allow_more_present(entry):
|
||||||
|
assert compare_dict_allow_more_present(entry['av'], entry['bv']) == entry['result']
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("entry", COMPARE_GENERIC)
|
||||||
|
def test_compare_generic(entry):
|
||||||
|
assert compare_generic(entry['a'], entry['b'], entry['method'], entry['type']) == entry['result']
|
||||||
|
|
||||||
|
|
||||||
|
def test_convert_duration_to_nanosecond():
|
||||||
|
nanoseconds = convert_duration_to_nanosecond('5s')
|
||||||
|
assert nanoseconds == 5000000000
|
||||||
|
nanoseconds = convert_duration_to_nanosecond('1m5s')
|
||||||
|
assert nanoseconds == 65000000000
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
convert_duration_to_nanosecond([1, 2, 3])
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
convert_duration_to_nanosecond('10x')
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_healthcheck():
|
||||||
|
result, disabled = parse_healthcheck({
|
||||||
|
'test': 'sleep 1',
|
||||||
|
'interval': '1s',
|
||||||
|
})
|
||||||
|
assert disabled is False
|
||||||
|
assert result == {
|
||||||
|
'test': ['CMD-SHELL', 'sleep 1'],
|
||||||
|
'interval': 1000000000
|
||||||
|
}
|
||||||
|
|
||||||
|
result, disabled = parse_healthcheck({
|
||||||
|
'test': ['NONE'],
|
||||||
|
})
|
||||||
|
assert result is None
|
||||||
|
assert disabled
|
||||||
|
|
||||||
|
result, disabled = parse_healthcheck({
|
||||||
|
'test': 'sleep 1',
|
||||||
|
'interval': '1s423ms'
|
||||||
|
})
|
||||||
|
assert result == {
|
||||||
|
'test': ['CMD-SHELL', 'sleep 1'],
|
||||||
|
'interval': 1423000000
|
||||||
|
}
|
||||||
|
assert disabled is False
|
||||||
|
|
||||||
|
result, disabled = parse_healthcheck({
|
||||||
|
'test': 'sleep 1',
|
||||||
|
'interval': '1h1m2s3ms4us'
|
||||||
|
})
|
||||||
|
assert result == {
|
||||||
|
'test': ['CMD-SHELL', 'sleep 1'],
|
||||||
|
'interval': 3662003004000
|
||||||
|
}
|
||||||
|
assert disabled is False
|
||||||
0
tests/unit/plugins/modules/__init__.py
Normal file
0
tests/unit/plugins/modules/__init__.py
Normal file
22
tests/unit/plugins/modules/test_docker_container.py
Normal file
22
tests/unit/plugins/modules/test_docker_container.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from ansible_collections.community.docker.plugins.modules.docker_container import TaskParameters
|
||||||
|
|
||||||
|
|
||||||
|
class TestTaskParameters(unittest.TestCase):
|
||||||
|
"""Unit tests for TaskParameters."""
|
||||||
|
|
||||||
|
def test_parse_exposed_ports_tcp_udp(self):
|
||||||
|
"""
|
||||||
|
Ensure _parse_exposed_ports does not cancel ports with the same
|
||||||
|
number but different protocol.
|
||||||
|
"""
|
||||||
|
task_params = TaskParameters.__new__(TaskParameters)
|
||||||
|
task_params.exposed_ports = None
|
||||||
|
result = task_params._parse_exposed_ports([80, '443', '443/udp'])
|
||||||
|
self.assertTrue((80, 'tcp') in result)
|
||||||
|
self.assertTrue((443, 'tcp') in result)
|
||||||
|
self.assertTrue((443, 'udp') in result)
|
||||||
31
tests/unit/plugins/modules/test_docker_network.py
Normal file
31
tests/unit/plugins/modules/test_docker_network.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
"""Unit tests for docker_network."""
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ansible_collections.community.docker.plugins.modules.docker_network import validate_cidr
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("cidr,expected", [
|
||||||
|
('192.168.0.1/16', 'ipv4'),
|
||||||
|
('192.168.0.1/24', 'ipv4'),
|
||||||
|
('192.168.0.1/32', 'ipv4'),
|
||||||
|
('fdd1:ac8c:0557:7ce2::/64', 'ipv6'),
|
||||||
|
('fdd1:ac8c:0557:7ce2::/128', 'ipv6'),
|
||||||
|
])
|
||||||
|
def test_validate_cidr_positives(cidr, expected):
|
||||||
|
assert validate_cidr(cidr) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("cidr", [
|
||||||
|
'192.168.0.1',
|
||||||
|
'192.168.0.1/34',
|
||||||
|
'192.168.0.1/asd',
|
||||||
|
'fdd1:ac8c:0557:7ce2::',
|
||||||
|
])
|
||||||
|
def test_validate_cidr_negatives(cidr):
|
||||||
|
with pytest.raises(ValueError) as e:
|
||||||
|
validate_cidr(cidr)
|
||||||
|
assert '"{0}" is not a valid CIDR'.format(cidr) == str(e.value)
|
||||||
510
tests/unit/plugins/modules/test_docker_swarm_service.py
Normal file
510
tests/unit/plugins/modules/test_docker_swarm_service.py
Normal file
@ -0,0 +1,510 @@
|
|||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
class APIErrorMock(Exception):
|
||||||
|
def __init__(self, message, response=None, explanation=None):
|
||||||
|
self.message = message
|
||||||
|
self.response = response
|
||||||
|
self.explanation = explanation
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def docker_module_mock(mocker):
|
||||||
|
docker_module_mock = mocker.MagicMock()
|
||||||
|
docker_utils_module_mock = mocker.MagicMock()
|
||||||
|
docker_errors_module_mock = mocker.MagicMock()
|
||||||
|
docker_errors_module_mock.APIError = APIErrorMock
|
||||||
|
mock_modules = {
|
||||||
|
'docker': docker_module_mock,
|
||||||
|
'docker.utils': docker_utils_module_mock,
|
||||||
|
'docker.errors': docker_errors_module_mock,
|
||||||
|
}
|
||||||
|
return mocker.patch.dict('sys.modules', **mock_modules)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def docker_swarm_service():
|
||||||
|
from ansible_collections.community.docker.plugins.modules import docker_swarm_service
|
||||||
|
|
||||||
|
return docker_swarm_service
|
||||||
|
|
||||||
|
|
||||||
|
def test_retry_on_out_of_sequence_error(mocker, docker_swarm_service):
|
||||||
|
run_mock = mocker.MagicMock(
|
||||||
|
side_effect=APIErrorMock(
|
||||||
|
message='',
|
||||||
|
response=None,
|
||||||
|
explanation='rpc error: code = Unknown desc = update out of sequence',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
manager = docker_swarm_service.DockerServiceManager(client=None)
|
||||||
|
manager.run = run_mock
|
||||||
|
with pytest.raises(APIErrorMock):
|
||||||
|
manager.run_safe()
|
||||||
|
assert run_mock.call_count == 3
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_retry_on_general_api_error(mocker, docker_swarm_service):
|
||||||
|
run_mock = mocker.MagicMock(
|
||||||
|
side_effect=APIErrorMock(message='', response=None, explanation='some error')
|
||||||
|
)
|
||||||
|
manager = docker_swarm_service.DockerServiceManager(client=None)
|
||||||
|
manager.run = run_mock
|
||||||
|
with pytest.raises(APIErrorMock):
|
||||||
|
manager.run_safe()
|
||||||
|
assert run_mock.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_docker_environment(mocker, docker_swarm_service):
|
||||||
|
env_file_result = {'TEST1': 'A', 'TEST2': 'B', 'TEST3': 'C'}
|
||||||
|
env_dict = {'TEST3': 'CC', 'TEST4': 'D'}
|
||||||
|
env_string = "TEST3=CC,TEST4=D"
|
||||||
|
|
||||||
|
env_list = ['TEST3=CC', 'TEST4=D']
|
||||||
|
expected_result = sorted(['TEST1=A', 'TEST2=B', 'TEST3=CC', 'TEST4=D'])
|
||||||
|
mocker.patch.object(
|
||||||
|
docker_swarm_service, 'parse_env_file', return_value=env_file_result
|
||||||
|
)
|
||||||
|
mocker.patch.object(
|
||||||
|
docker_swarm_service,
|
||||||
|
'format_environment',
|
||||||
|
side_effect=lambda d: ['{0}={1}'.format(key, value) for key, value in d.items()],
|
||||||
|
)
|
||||||
|
# Test with env dict and file
|
||||||
|
result = docker_swarm_service.get_docker_environment(
|
||||||
|
env_dict, env_files=['dummypath']
|
||||||
|
)
|
||||||
|
assert result == expected_result
|
||||||
|
# Test with env list and file
|
||||||
|
result = docker_swarm_service.get_docker_environment(
|
||||||
|
env_list,
|
||||||
|
env_files=['dummypath']
|
||||||
|
)
|
||||||
|
assert result == expected_result
|
||||||
|
# Test with env string and file
|
||||||
|
result = docker_swarm_service.get_docker_environment(
|
||||||
|
env_string, env_files=['dummypath']
|
||||||
|
)
|
||||||
|
assert result == expected_result
|
||||||
|
|
||||||
|
assert result == expected_result
|
||||||
|
# Test with empty env
|
||||||
|
result = docker_swarm_service.get_docker_environment(
|
||||||
|
[], env_files=None
|
||||||
|
)
|
||||||
|
assert result == []
|
||||||
|
# Test with empty env_files
|
||||||
|
result = docker_swarm_service.get_docker_environment(
|
||||||
|
None, env_files=[]
|
||||||
|
)
|
||||||
|
assert result == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_nanoseconds_from_raw_option(docker_swarm_service):
|
||||||
|
value = docker_swarm_service.get_nanoseconds_from_raw_option('test', None)
|
||||||
|
assert value is None
|
||||||
|
|
||||||
|
value = docker_swarm_service.get_nanoseconds_from_raw_option('test', '1m30s535ms')
|
||||||
|
assert value == 90535000000
|
||||||
|
|
||||||
|
value = docker_swarm_service.get_nanoseconds_from_raw_option('test', 10000000000)
|
||||||
|
assert value == 10000000000
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
docker_swarm_service.get_nanoseconds_from_raw_option('test', [])
|
||||||
|
|
||||||
|
|
||||||
|
def test_has_dict_changed(docker_swarm_service):
|
||||||
|
assert not docker_swarm_service.has_dict_changed(
|
||||||
|
{"a": 1},
|
||||||
|
{"a": 1},
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_dict_changed(
|
||||||
|
{"a": 1},
|
||||||
|
{"a": 1, "b": 2}
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_dict_changed(
|
||||||
|
{"a": 1},
|
||||||
|
{"a": 2, "b": 2}
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_dict_changed(
|
||||||
|
{"a": 1, "b": 1},
|
||||||
|
{"a": 1}
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_dict_changed(
|
||||||
|
None,
|
||||||
|
{"a": 2, "b": 2}
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_dict_changed(
|
||||||
|
{},
|
||||||
|
{"a": 2, "b": 2}
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_dict_changed(
|
||||||
|
{"a": 1},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_dict_changed(
|
||||||
|
{"a": 1},
|
||||||
|
None
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_dict_changed(
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_dict_changed(
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_dict_changed(
|
||||||
|
{},
|
||||||
|
None
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_dict_changed(
|
||||||
|
None,
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_has_list_changed(docker_swarm_service):
|
||||||
|
|
||||||
|
# List comparisons without dictionaries
|
||||||
|
# I could improve the indenting, but pycodestyle wants this instead
|
||||||
|
assert not docker_swarm_service.has_list_changed(None, None)
|
||||||
|
assert not docker_swarm_service.has_list_changed(None, [])
|
||||||
|
assert not docker_swarm_service.has_list_changed(None, [1, 2])
|
||||||
|
|
||||||
|
assert not docker_swarm_service.has_list_changed([], None)
|
||||||
|
assert not docker_swarm_service.has_list_changed([], [])
|
||||||
|
assert docker_swarm_service.has_list_changed([], [1, 2])
|
||||||
|
|
||||||
|
assert docker_swarm_service.has_list_changed([1, 2], None)
|
||||||
|
assert docker_swarm_service.has_list_changed([1, 2], [])
|
||||||
|
|
||||||
|
assert docker_swarm_service.has_list_changed([1, 2, 3], [1, 2])
|
||||||
|
assert docker_swarm_service.has_list_changed([1, 2], [1, 2, 3])
|
||||||
|
|
||||||
|
# Check list sorting
|
||||||
|
assert not docker_swarm_service.has_list_changed([1, 2], [2, 1])
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
[1, 2],
|
||||||
|
[2, 1],
|
||||||
|
sort_lists=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check type matching
|
||||||
|
assert docker_swarm_service.has_list_changed([None, 1], [2, 1])
|
||||||
|
assert docker_swarm_service.has_list_changed([2, 1], [None, 1])
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
"command --with args",
|
||||||
|
['command', '--with', 'args']
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
['sleep', '3400'],
|
||||||
|
[u'sleep', u'3600'],
|
||||||
|
sort_lists=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# List comparisons with dictionaries
|
||||||
|
assert not docker_swarm_service.has_list_changed(
|
||||||
|
[{'a': 1}],
|
||||||
|
[{'a': 1}],
|
||||||
|
sort_key='a'
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.has_list_changed(
|
||||||
|
[{'a': 1}, {'a': 2}],
|
||||||
|
[{'a': 1}, {'a': 2}],
|
||||||
|
sort_key='a'
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
docker_swarm_service.has_list_changed(
|
||||||
|
[{'a': 1}, {'a': 2}],
|
||||||
|
[{'a': 1}, {'a': 2}]
|
||||||
|
)
|
||||||
|
|
||||||
|
# List sort checking with sort key
|
||||||
|
assert not docker_swarm_service.has_list_changed(
|
||||||
|
[{'a': 1}, {'a': 2}],
|
||||||
|
[{'a': 2}, {'a': 1}],
|
||||||
|
sort_key='a'
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
[{'a': 1}, {'a': 2}],
|
||||||
|
[{'a': 2}, {'a': 1}],
|
||||||
|
sort_lists=False
|
||||||
|
)
|
||||||
|
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
[{'a': 1}, {'a': 2}, {'a': 3}],
|
||||||
|
[{'a': 2}, {'a': 1}],
|
||||||
|
sort_key='a'
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
[{'a': 1}, {'a': 2}],
|
||||||
|
[{'a': 1}, {'a': 2}, {'a': 3}],
|
||||||
|
sort_lists=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# Additional dictionary elements
|
||||||
|
assert not docker_swarm_service.has_list_changed(
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2},
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2, "protocol": "tcp"},
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
],
|
||||||
|
sort_key='dst'
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_list_changed(
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
{"src": 1, "dst": 3, "protocol": "tcp"},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
{"src": 1, "dst": 3, "protocol": "tcp"},
|
||||||
|
],
|
||||||
|
sort_key='dst'
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
{"src": 1, "dst": 2},
|
||||||
|
{"src": 3, "dst": 4},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 3, "protocol": "udp"},
|
||||||
|
{"src": 1, "dst": 2, "protocol": "tcp"},
|
||||||
|
{"src": 3, "dst": 4, "protocol": "tcp"},
|
||||||
|
],
|
||||||
|
sort_key='dst'
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 3, "protocol": "tcp"},
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2, "protocol": "tcp"},
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
],
|
||||||
|
sort_key='dst'
|
||||||
|
)
|
||||||
|
assert docker_swarm_service.has_list_changed(
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
{"src": 1, "dst": 2, "protocol": "tcp", "extra": {"test": "foo"}},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{"src": 1, "dst": 2, "protocol": "udp"},
|
||||||
|
{"src": 1, "dst": 2, "protocol": "tcp"},
|
||||||
|
],
|
||||||
|
sort_key='dst'
|
||||||
|
)
|
||||||
|
assert not docker_swarm_service.has_list_changed(
|
||||||
|
[{'id': '123', 'aliases': []}],
|
||||||
|
[{'id': '123'}],
|
||||||
|
sort_key='id'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_have_networks_changed(docker_swarm_service):
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[],
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[{'id': 1}],
|
||||||
|
[{'id': 1}]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert docker_swarm_service.have_networks_changed(
|
||||||
|
[{'id': 1}],
|
||||||
|
[{'id': 1}, {'id': 2}]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[{'id': 1}, {'id': 2}],
|
||||||
|
[{'id': 1}, {'id': 2}]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[{'id': 1}, {'id': 2}],
|
||||||
|
[{'id': 2}, {'id': 1}]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': []}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias1']}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias1', 'alias2']}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias1']}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias1', 'alias2']}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias1', 'alias2']}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias1', 'alias2']}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias2', 'alias1']}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1, 'options': {}},
|
||||||
|
{'id': 2, 'aliases': ['alias1', 'alias2']}],
|
||||||
|
[
|
||||||
|
{'id': 1},
|
||||||
|
{'id': 2, 'aliases': ['alias2', 'alias1']}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1, 'options': {'option1': 'value1'}},
|
||||||
|
{'id': 2, 'aliases': ['alias1', 'alias2']}],
|
||||||
|
[
|
||||||
|
{'id': 1, 'options': {'option1': 'value1'}},
|
||||||
|
{'id': 2, 'aliases': ['alias2', 'alias1']}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert docker_swarm_service.have_networks_changed(
|
||||||
|
[
|
||||||
|
{'id': 1, 'options': {'option1': 'value1'}},
|
||||||
|
{'id': 2, 'aliases': ['alias1', 'alias2']}],
|
||||||
|
[
|
||||||
|
{'id': 1, 'options': {'option1': 'value2'}},
|
||||||
|
{'id': 2, 'aliases': ['alias2', 'alias1']}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_docker_networks(docker_swarm_service):
|
||||||
|
network_names = [
|
||||||
|
'network_1',
|
||||||
|
'network_2',
|
||||||
|
'network_3',
|
||||||
|
'network_4',
|
||||||
|
]
|
||||||
|
networks = [
|
||||||
|
network_names[0],
|
||||||
|
{'name': network_names[1]},
|
||||||
|
{'name': network_names[2], 'aliases': ['networkalias1']},
|
||||||
|
{'name': network_names[3], 'aliases': ['networkalias2'], 'options': {'foo': 'bar'}},
|
||||||
|
]
|
||||||
|
network_ids = {
|
||||||
|
network_names[0]: '1',
|
||||||
|
network_names[1]: '2',
|
||||||
|
network_names[2]: '3',
|
||||||
|
network_names[3]: '4',
|
||||||
|
}
|
||||||
|
parsed_networks = docker_swarm_service.get_docker_networks(
|
||||||
|
networks,
|
||||||
|
network_ids
|
||||||
|
)
|
||||||
|
assert len(parsed_networks) == 4
|
||||||
|
for i, network in enumerate(parsed_networks):
|
||||||
|
assert 'name' not in network
|
||||||
|
assert 'id' in network
|
||||||
|
expected_name = network_names[i]
|
||||||
|
assert network['id'] == network_ids[expected_name]
|
||||||
|
if i == 2:
|
||||||
|
assert network['aliases'] == ['networkalias1']
|
||||||
|
if i == 3:
|
||||||
|
assert network['aliases'] == ['networkalias2']
|
||||||
|
if i == 3:
|
||||||
|
assert 'foo' in network['options']
|
||||||
|
# Test missing name
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
docker_swarm_service.get_docker_networks([{'invalid': 'err'}], {'err': 1})
|
||||||
|
# test for invalid aliases type
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
docker_swarm_service.get_docker_networks(
|
||||||
|
[{'name': 'test', 'aliases': 1}],
|
||||||
|
{'test': 1}
|
||||||
|
)
|
||||||
|
# Test invalid aliases elements
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
docker_swarm_service.get_docker_networks(
|
||||||
|
[{'name': 'test', 'aliases': [1]}],
|
||||||
|
{'test': 1}
|
||||||
|
)
|
||||||
|
# Test for invalid options type
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
docker_swarm_service.get_docker_networks(
|
||||||
|
[{'name': 'test', 'options': 1}],
|
||||||
|
{'test': 1}
|
||||||
|
)
|
||||||
|
# Test for invalid networks type
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
docker_swarm_service.get_docker_networks(
|
||||||
|
1,
|
||||||
|
{'test': 1}
|
||||||
|
)
|
||||||
|
# Test for non existing networks
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
docker_swarm_service.get_docker_networks(
|
||||||
|
[{'name': 'idontexist'}],
|
||||||
|
{'test': 1}
|
||||||
|
)
|
||||||
|
# Test empty values
|
||||||
|
assert docker_swarm_service.get_docker_networks([], {}) == []
|
||||||
|
assert docker_swarm_service.get_docker_networks(None, {}) is None
|
||||||
|
# Test invalid options
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
docker_swarm_service.get_docker_networks(
|
||||||
|
[{'name': 'test', 'nonexisting_option': 'foo'}],
|
||||||
|
{'test': '1'}
|
||||||
|
)
|
||||||
36
tests/unit/plugins/modules/test_docker_volume.py
Normal file
36
tests/unit/plugins/modules/test_docker_volume.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Copyright (c) 2018 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_collections.community.docker.plugins.modules import docker_volume
|
||||||
|
from ansible_collections.community.docker.plugins.module_utils import common
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.usefixtures('patch_ansible_module')
|
||||||
|
|
||||||
|
TESTCASE_DOCKER_VOLUME = [
|
||||||
|
{
|
||||||
|
'name': 'daemon_config',
|
||||||
|
'state': 'present'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_DOCKER_VOLUME, indirect=['patch_ansible_module'])
|
||||||
|
def test_create_volume_on_invalid_docker_version(mocker, capfd):
|
||||||
|
mocker.patch.object(common, 'HAS_DOCKER_PY', True)
|
||||||
|
mocker.patch.object(common, 'docker_version', '1.8.0')
|
||||||
|
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
docker_volume.main()
|
||||||
|
|
||||||
|
out, dummy = capfd.readouterr()
|
||||||
|
results = json.loads(out)
|
||||||
|
assert results['failed']
|
||||||
|
assert 'Error: Docker SDK for Python version is 1.8.0 ' in results['msg']
|
||||||
|
assert 'Minimum version required is 1.10.0.' in results['msg']
|
||||||
Loading…
Reference in New Issue
Block a user