1#
2# (c) 2016 Red Hat Inc.
3#
4# This file is part of Ansible
5#
6# Ansible is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# Ansible is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
18
19# Make coding more python3-ish
20from __future__ import absolute_import, division, print_function
21
22__metaclass__ = type
23
24from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import (
25    patch,
26)
27from ansible_collections.openvswitch.openvswitch.plugins.modules import (
28    openvswitch_port,
29)
30from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import (
31    set_module_args,
32)
33from .ovs_module import TestOpenVSwitchModule, load_fixture
34
35test_name_side_effect_matrix = {
36    "test_openvswitch_port_absent_idempotent": [(0, "", "")],
37    "test_openvswitch_port_absent_removes_port": [
38        (0, "list_ports_test_br.cfg", ""),
39        (0, "get_port_eth2_tag.cfg", ""),
40        (0, "get_port_eth2_external_ids.cfg", ""),
41        (0, "", ""),
42    ],
43    "test_openvswitch_port_present_idempotent": [
44        (0, "list_ports_test_br.cfg", ""),
45        (0, "get_port_eth2_tag.cfg", ""),
46        (0, "get_port_eth2_external_ids.cfg", ""),
47        (0, "", ""),
48    ],
49    "test_openvswitch_port_present_creates_port": [
50        (0, "", ""),
51        (0, "", ""),
52        (0, "", ""),
53    ],
54    "test_openvswitch_port_present_changes_tag": [
55        (0, "list_ports_test_br.cfg", ""),
56        (0, "get_port_eth2_tag.cfg", ""),
57        (0, "get_port_eth2_external_ids.cfg", ""),
58        (0, "", ""),
59    ],
60    "test_openvswitch_port_present_changes_external_id": [
61        (0, "list_ports_test_br.cfg", ""),
62        (0, "get_port_eth2_tag.cfg", ""),
63        (0, "get_port_eth2_external_ids.cfg", ""),
64        (0, "", ""),
65    ],
66    "test_openvswitch_port_present_adds_external_id": [
67        (0, "list_ports_test_br.cfg", ""),
68        (0, "get_port_eth2_tag.cfg", ""),
69        (0, "get_port_eth2_external_ids.cfg", ""),
70        (0, "", ""),
71    ],
72    "test_openvswitch_port_present_clears_external_id": [
73        (0, "list_ports_test_br.cfg", ""),
74        (0, "get_port_eth2_tag.cfg", ""),
75        (0, "get_port_eth2_external_ids.cfg", ""),
76        (0, "", ""),
77    ],
78    "test_openvswitch_port_present_runs_set_mode": [
79        (0, "", ""),
80        (0, "", ""),
81        (0, "", ""),
82    ],
83}
84
85
86class TestOpenVSwitchPortModule(TestOpenVSwitchModule):
87
88    module = openvswitch_port
89
90    def setUp(self):
91        super(TestOpenVSwitchPortModule, self).setUp()
92
93        self.mock_run_command = patch(
94            "ansible.module_utils.basic.AnsibleModule.run_command"
95        )
96        self.run_command = self.mock_run_command.start()
97        self.mock_get_bin_path = patch(
98            "ansible.module_utils.basic.AnsibleModule.get_bin_path"
99        )
100        self.get_bin_path = self.mock_get_bin_path.start()
101
102    def tearDown(self):
103        super(TestOpenVSwitchPortModule, self).tearDown()
104
105        self.mock_run_command.stop()
106        self.mock_get_bin_path.stop()
107
108    def load_fixtures(self, test_name):
109        test_side_effects = []
110        for s in test_name_side_effect_matrix[test_name]:
111            rc = s[0]
112            out = s[1] if s[1] == "" else str(load_fixture(s[1]))
113            err = s[2]
114            side_effect_with_fixture_loaded = (rc, out, err)
115            test_side_effects.append(side_effect_with_fixture_loaded)
116        self.run_command.side_effect = test_side_effects
117
118        self.get_bin_path.return_value = "/usr/bin/ovs-vsctl"
119
120    def test_openvswitch_port_absent_idempotent(self):
121        set_module_args(dict(state="absent", bridge="test-br", port="eth2"))
122        self.execute_module(
123            test_name="test_openvswitch_port_absent_idempotent"
124        )
125
126    def test_openvswitch_port_absent_removes_port(self):
127        set_module_args(dict(state="absent", bridge="test-br", port="eth2"))
128        commands = ["/usr/bin/ovs-vsctl -t 5 del-port test-br eth2"]
129        self.execute_module(
130            changed=True,
131            commands=commands,
132            test_name="test_openvswitch_port_absent_removes_port",
133        )
134
135    def test_openvswitch_port_present_idempotent(self):
136        set_module_args(
137            dict(
138                state="present",
139                bridge="test-br",
140                port="eth2",
141                tag=10,
142                external_ids={"foo": "bar"},
143            )
144        )
145        self.execute_module(
146            test_name="test_openvswitch_port_present_idempotent"
147        )
148
149    def test_openvswitch_port_present_creates_port(self):
150        set_module_args(
151            dict(
152                state="present",
153                bridge="test-br",
154                port="eth2",
155                tag=10,
156                external_ids={"foo": "bar"},
157            )
158        )
159        commands = [
160            "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10",
161            "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar",
162        ]
163        self.execute_module(
164            changed=True,
165            commands=commands,
166            test_name="test_openvswitch_port_present_creates_port",
167        )
168
169    def test_openvswitch_port_present_changes_tag(self):
170        set_module_args(
171            dict(
172                state="present",
173                bridge="test-br",
174                port="eth2",
175                tag=20,
176                external_ids={"foo": "bar"},
177            )
178        )
179        commands = ["/usr/bin/ovs-vsctl -t 5 set port eth2 tag=20"]
180        self.execute_module(
181            changed=True,
182            commands=commands,
183            test_name="test_openvswitch_port_present_changes_tag",
184        )
185
186    def test_openvswitch_port_present_changes_external_id(self):
187        set_module_args(
188            dict(
189                state="present",
190                bridge="test-br",
191                port="eth2",
192                tag=10,
193                external_ids={"foo": "baz"},
194            )
195        )
196        commands = [
197            "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=baz"
198        ]
199        self.execute_module(
200            changed=True,
201            commands=commands,
202            test_name="test_openvswitch_port_present_changes_external_id",
203        )
204
205    def test_openvswitch_port_present_adds_external_id(self):
206        set_module_args(
207            dict(
208                state="present",
209                bridge="test-br",
210                port="eth2",
211                tag=10,
212                external_ids={"foo2": "bar2"},
213            )
214        )
215        commands = [
216            "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo2=bar2"
217        ]
218        self.execute_module(
219            changed=True,
220            commands=commands,
221            test_name="test_openvswitch_port_present_adds_external_id",
222        )
223
224    def test_openvswitch_port_present_clears_external_id(self):
225        set_module_args(
226            dict(
227                state="present",
228                bridge="test-br",
229                port="eth2",
230                tag=10,
231                external_ids={"foo": None},
232            )
233        )
234        commands = [
235            "/usr/bin/ovs-vsctl -t 5 remove port eth2 external_ids foo"
236        ]
237        self.execute_module(
238            changed=True,
239            commands=commands,
240            test_name="test_openvswitch_port_present_clears_external_id",
241        )
242
243    def test_openvswitch_port_present_runs_set_mode(self):
244        set_module_args(
245            dict(
246                state="present",
247                bridge="test-br",
248                port="eth2",
249                tag=10,
250                external_ids={"foo": "bar"},
251                set="port eth2 other_config:stp-path-cost=10",
252            )
253        )
254        commands = [
255            "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10 -- set"
256            " port eth2 other_config:stp-path-cost=10",
257            "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar",
258        ]
259        self.execute_module(
260            changed=True,
261            commands=commands,
262            test_name="test_openvswitch_port_present_runs_set_mode",
263        )
264
265    def test_openvswitch_port_present_runs_set_mode_multiple(self):
266        set_module_args(
267            dict(
268                state="present",
269                bridge="test-br",
270                port="eth2",
271                tag=10,
272                external_ids={"foo": "bar"},
273                set=[
274                    "port eth2 other_config:stp-path-cost=10",
275                    "port eth2 type=patch",
276                ],
277            )
278        )
279        commands = [
280            "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10 -- set"
281            " port eth2 other_config:stp-path-cost=10 -- set port eth2 type=patch",
282            "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar",
283        ]
284        self.execute_module(
285            changed=True,
286            commands=commands,
287            test_name="test_openvswitch_port_present_runs_set_mode",
288        )
289