1#
2# (c) 2019, Ansible by Red Hat, inc
3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4#
5
6from __future__ import absolute_import, division, print_function
7
8__metaclass__ = type
9
10from ansible_collections.cisco.ios.plugins.module_utils.network.ios.providers.cli.config.bgp.process import (
11    Provider,
12)
13from ansible_collections.cisco.ios.plugins.modules import ios_bgp
14from .ios_module import TestIosModule, load_fixture
15
16
17class TestIosBgpModule(TestIosModule):
18    module = ios_bgp
19
20    def setUp(self):
21        super(TestIosBgpModule, self).setUp()
22        self._bgp_config = load_fixture("ios_bgp_config.cfg")
23
24    def test_ios_bgp(self):
25        obj = Provider(
26            params=dict(
27                config=dict(
28                    bgp_as=64496,
29                    router_id="192.0.2.2",
30                    networks=None,
31                    address_family=None,
32                ),
33                operation="merge",
34            )
35        )
36        commands = obj.render(self._bgp_config)
37        self.assertEqual(
38            commands, ["router bgp 64496", "bgp router-id 192.0.2.2", "exit"]
39        )
40
41    def test_ios_bgp_idempotent(self):
42        obj = Provider(
43            params=dict(
44                config=dict(
45                    bgp_as=64496,
46                    router_id="192.0.2.1",
47                    networks=None,
48                    address_family=None,
49                ),
50                operation="merge",
51            )
52        )
53        commands = obj.render(self._bgp_config)
54        self.assertEqual(commands, [])
55
56    def test_ios_bgp_remove(self):
57        obj = Provider(
58            params=dict(
59                config=dict(bgp_as=64496, networks=None, address_family=None),
60                operation="delete",
61            )
62        )
63        commands = obj.render(self._bgp_config)
64        self.assertEqual(commands, ["no router bgp 64496"])
65
66    def test_ios_bgp_neighbor(self):
67        obj = Provider(
68            params=dict(
69                config=dict(
70                    bgp_as=64496,
71                    neighbors=[dict(neighbor="192.51.100.2", remote_as=64496)],
72                    networks=None,
73                    address_family=None,
74                ),
75                operation="merge",
76            )
77        )
78        commands = obj.render(self._bgp_config)
79        self.assertEqual(
80            commands,
81            [
82                "router bgp 64496",
83                "neighbor 192.51.100.2 remote-as 64496",
84                "exit",
85            ],
86        )
87
88    def test_ios_bgp_neighbor_idempotent(self):
89        obj = Provider(
90            params=dict(
91                config=dict(
92                    bgp_as=64496,
93                    neighbors=[
94                        dict(
95                            neighbor="192.51.100.1",
96                            remote_as=64496,
97                            timers=dict(
98                                keepalive=120,
99                                holdtime=360,
100                                min_neighbor_holdtime=360,
101                            ),
102                        )
103                    ],
104                    networks=None,
105                    address_family=None,
106                ),
107                operation="merge",
108            )
109        )
110        commands = obj.render(self._bgp_config)
111        self.assertEqual(commands, [])
112
113    def test_ios_bgp_network(self):
114        obj = Provider(
115            params=dict(
116                config=dict(
117                    bgp_as=64496,
118                    networks=[
119                        dict(
120                            prefix="192.0.1.0", masklen=23, route_map="RMAP_1"
121                        )
122                    ],
123                    address_family=None,
124                ),
125                operation="merge",
126            )
127        )
128        commands = obj.render(self._bgp_config)
129        self.assertEqual(
130            sorted(commands),
131            sorted(
132                [
133                    "router bgp 64496",
134                    "network 192.0.1.0 mask 255.255.254.0 route-map RMAP_1",
135                    "exit",
136                ]
137            ),
138        )
139
140    def test_ios_bgp_network_idempotent(self):
141        obj = Provider(
142            params=dict(
143                config=dict(
144                    bgp_as=64496,
145                    networks=[
146                        dict(
147                            prefix="192.0.2.0", masklen=23, route_map="RMAP_1"
148                        ),
149                        dict(
150                            prefix="198.51.100.0",
151                            masklen=25,
152                            route_map="RMAP_2",
153                        ),
154                    ],
155                    address_family=None,
156                ),
157                operation="merge",
158            )
159        )
160        commands = obj.render(self._bgp_config)
161        self.assertEqual(commands, [])
162
163    def test_ios_bgp_address_family_redistribute(self):
164        rd_1 = dict(protocol="ospf", id="233", metric=90, route_map=None)
165
166        config = dict(
167            bgp_as=64496,
168            address_family=[
169                dict(afi="ipv4", safi="unicast", redistribute=[rd_1])
170            ],
171            networks=None,
172        )
173
174        obj = Provider(params=dict(config=config, operation="merge"))
175
176        commands = obj.render(self._bgp_config)
177        cmd = [
178            "router bgp 64496",
179            "address-family ipv4",
180            "redistribute ospf 233 metric 90",
181            "exit-address-family",
182            "exit",
183        ]
184        self.assertEqual(sorted(commands), sorted(cmd))
185
186    def test_ios_bgp_address_family_redistribute_idempotent(self):
187        rd_1 = dict(protocol="eigrp", metric=10, route_map="RMAP_3", id=None)
188        rd_2 = dict(protocol="static", metric=100, id=None, route_map=None)
189
190        config = dict(
191            bgp_as=64496,
192            address_family=[
193                dict(afi="ipv4", safi="unicast", redistribute=[rd_1, rd_2])
194            ],
195            networks=None,
196        )
197
198        obj = Provider(params=dict(config=config, operation="merge"))
199
200        commands = obj.render(self._bgp_config)
201        self.assertEqual(commands, [])
202
203    def test_ios_bgp_address_family_neighbors(self):
204        af_nbr_1 = dict(
205            neighbor="192.51.100.1", maximum_prefix=35, activate=True
206        )
207        af_nbr_2 = dict(
208            neighbor="192.51.100.3", route_reflector_client=True, activate=True
209        )
210
211        config = dict(
212            bgp_as=64496,
213            address_family=[
214                dict(
215                    afi="ipv4",
216                    safi="multicast",
217                    neighbors=[af_nbr_1, af_nbr_2],
218                )
219            ],
220            networks=None,
221        )
222
223        obj = Provider(params=dict(config=config, operation="merge"))
224
225        commands = obj.render(self._bgp_config)
226        cmd = [
227            "router bgp 64496",
228            "address-family ipv4 multicast",
229            "neighbor 192.51.100.1 activate",
230            "neighbor 192.51.100.1 maximum-prefix 35",
231            "neighbor 192.51.100.3 activate",
232            "neighbor 192.51.100.3 route-reflector-client",
233            "exit-address-family",
234            "exit",
235        ]
236        self.assertEqual(sorted(commands), sorted(cmd))
237
238    def test_ios_bgp_address_family_neighbors_idempotent(self):
239        af_nbr_1 = dict(
240            neighbor="203.0.113.1", remove_private_as=True, maximum_prefix=100
241        )
242
243        config = dict(
244            bgp_as=64496,
245            address_family=[
246                dict(afi="ipv4", safi="unicast", neighbors=[af_nbr_1])
247            ],
248            networks=None,
249        )
250
251        obj = Provider(params=dict(config=config, operation="merge"))
252
253        commands = obj.render(self._bgp_config)
254        self.assertEqual(commands, [])
255
256    def test_ios_bgp_address_family_networks(self):
257        net = dict(prefix="1.0.0.0", masklen=8, route_map="RMAP_1")
258        net2 = dict(prefix="192.168.1.0", masklen=24, route_map="RMAP_2")
259
260        config = dict(
261            bgp_as=64496,
262            address_family=[
263                dict(afi="ipv4", safi="multicast", networks=[net, net2])
264            ],
265            networks=None,
266        )
267
268        obj = Provider(params=dict(config=config, operation="merge"))
269
270        commands = obj.render(self._bgp_config)
271        cmd = [
272            "router bgp 64496",
273            "address-family ipv4 multicast",
274            "network 1.0.0.0 mask 255.0.0.0 route-map RMAP_1",
275            "network 192.168.1.0 mask 255.255.255.0 route-map RMAP_2",
276            "exit-address-family",
277            "exit",
278        ]
279        self.assertEqual(sorted(commands), sorted(cmd))
280
281    def test_ios_bgp_address_family_networks_idempotent(self):
282        net = dict(prefix="203.0.113.0", masklen=27, route_map="RMAP_1")
283        net2 = dict(prefix="192.0.2.0", masklen=26, route_map="RMAP_2")
284
285        config = dict(
286            bgp_as=64496,
287            address_family=[
288                dict(afi="ipv4", safi="multicast", networks=[net, net2])
289            ],
290            networks=None,
291        )
292
293        obj = Provider(params=dict(config=config, operation="merge"))
294
295        commands = obj.render(self._bgp_config)
296        self.assertEqual(commands, [])
297
298    def test_ios_bgp_operation_override(self):
299        net_1 = dict(prefix="1.0.0.0", masklen=8, route_map="RMAP_1")
300        net_2 = dict(prefix="192.168.1.0", masklen=24, route_map="RMAP_2")
301        nbr_1 = dict(
302            neighbor="192.51.100.1",
303            remote_as=64496,
304            update_source="GigabitEthernet0/1",
305        )
306        nbr_2 = dict(
307            neighbor="192.51.100.3",
308            remote_as=64496,
309            timers=dict(
310                keepalive=300, holdtime=360, min_neighbor_holdtime=360
311            ),
312        )
313        af_nbr_1 = dict(neighbor="192.51.100.1", maximum_prefix=35)
314        af_nbr_2 = dict(neighbor="192.51.100.3", route_reflector_client=True)
315
316        af_1 = dict(afi="ipv4", safi="unicast", neighbors=[af_nbr_1, af_nbr_2])
317        af_2 = dict(afi="ipv4", safi="multicast", networks=[net_1, net_2])
318        config = dict(
319            bgp_as=64496,
320            neighbors=[nbr_1, nbr_2],
321            address_family=[af_1, af_2],
322            networks=None,
323        )
324
325        obj = Provider(params=dict(config=config, operation="override"))
326        commands = obj.render(self._bgp_config)
327
328        cmd = [
329            "no router bgp 64496",
330            "router bgp 64496",
331            "neighbor 192.51.100.1 remote-as 64496",
332            "neighbor 192.51.100.1 update-source GigabitEthernet0/1",
333            "neighbor 192.51.100.3 remote-as 64496",
334            "neighbor 192.51.100.3 timers 300 360 360",
335            "address-family ipv4",
336            "neighbor 192.51.100.1 maximum-prefix 35",
337            "neighbor 192.51.100.3 route-reflector-client",
338            "exit-address-family",
339            "address-family ipv4 multicast",
340            "network 1.0.0.0 mask 255.0.0.0 route-map RMAP_1",
341            "network 192.168.1.0 mask 255.255.255.0 route-map RMAP_2",
342            "exit-address-family",
343            "exit",
344        ]
345
346        self.assertEqual(sorted(commands), sorted(cmd))
347
348    def test_ios_bgp_operation_replace(self):
349        rd = dict(protocol="ospf", id=223, metric=110, route_map=None)
350        net = dict(prefix="203.0.113.0", masklen=27, route_map="RMAP_1")
351        net2 = dict(prefix="192.0.2.0", masklen=26, route_map="RMAP_2")
352
353        af_1 = dict(afi="ipv4", safi="unicast", redistribute=[rd])
354        af_2 = dict(afi="ipv4", safi="multicast", networks=[net, net2])
355
356        config = dict(bgp_as=64496, address_family=[af_1, af_2], networks=None)
357        obj = Provider(params=dict(config=config, operation="replace"))
358        commands = obj.render(self._bgp_config)
359
360        cmd = [
361            "router bgp 64496",
362            "address-family ipv4",
363            "redistribute ospf 223 metric 110",
364            "no redistribute eigrp",
365            "no redistribute static",
366            "exit-address-family",
367            "exit",
368        ]
369
370        self.assertEqual(sorted(commands), sorted(cmd))
371
372    def test_ios_bgp_operation_replace_with_new_as(self):
373        rd = dict(protocol="ospf", id=223, metric=110, route_map=None)
374
375        af_1 = dict(afi="ipv4", safi="unicast", redistribute=[rd])
376
377        config = dict(bgp_as=64497, address_family=[af_1], networks=None)
378        obj = Provider(params=dict(config=config, operation="replace"))
379        commands = obj.render(self._bgp_config)
380
381        cmd = [
382            "no router bgp 64496",
383            "router bgp 64497",
384            "address-family ipv4",
385            "redistribute ospf 223 metric 110",
386            "exit-address-family",
387            "exit",
388        ]
389
390        self.assertEqual(sorted(commands), sorted(cmd))
391