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.frr.frr.plugins.module_utils.network.frr.providers.cli.config.bgp.process import (
11    Provider,
12)
13from ansible_collections.frr.frr.plugins.modules import frr_bgp
14from .frr_module import TestFrrModule, load_fixture
15
16
17class TestFrrBgpModule(TestFrrModule):
18    module = frr_bgp
19
20    def setUp(self):
21        super(TestFrrBgpModule, self).setUp()
22        self._bgp_config = load_fixture("frr_bgp_config")
23
24    def test_frr_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_frr_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_frr_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_frr_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_frr_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(keepalive=120, holdtime=360),
98                        )
99                    ],
100                    networks=None,
101                    address_family=None,
102                ),
103                operation="merge",
104            )
105        )
106        commands = obj.render(self._bgp_config)
107        self.assertEqual(commands, [])
108
109    def test_frr_bgp_network(self):
110        obj = Provider(
111            params=dict(
112                config=dict(
113                    bgp_as=64496,
114                    networks=[
115                        dict(
116                            prefix="192.0.2.0", masklen=24, route_map="RMAP_1"
117                        )
118                    ],
119                    address_family=None,
120                ),
121                operation="merge",
122            )
123        )
124        commands = obj.render(self._bgp_config)
125        self.assertEqual(
126            sorted(commands),
127            sorted(
128                [
129                    "router bgp 64496",
130                    "network 192.0.2.0/24 route-map RMAP_1",
131                    "exit",
132                ]
133            ),
134        )
135
136    def test_frr_bgp_network_idempotent(self):
137        obj = Provider(
138            params=dict(
139                config=dict(
140                    bgp_as=64496,
141                    networks=[
142                        dict(
143                            prefix="192.0.1.0", masklen=24, route_map="RMAP_1"
144                        ),
145                        dict(
146                            prefix="198.51.100.0",
147                            masklen=24,
148                            route_map="RMAP_2",
149                        ),
150                    ],
151                    address_family=None,
152                ),
153                operation="merge",
154            )
155        )
156        commands = obj.render(self._bgp_config)
157        self.assertEqual(commands, [])
158
159    def test_frr_bgp_address_family_redistribute(self):
160        rd_1 = dict(protocol="ospf", id="233", metric=90, route_map=None)
161
162        config = dict(
163            bgp_as=64496,
164            address_family=[
165                dict(afi="ipv4", safi="unicast", redistribute=[rd_1])
166            ],
167            networks=None,
168        )
169
170        obj = Provider(params=dict(config=config, operation="merge"))
171
172        commands = obj.render(self._bgp_config)
173        cmd = [
174            "router bgp 64496",
175            "address-family ipv4 unicast",
176            "redistribute ospf 233 metric 90",
177            "exit-address-family",
178            "exit",
179        ]
180        self.assertEqual(sorted(commands), sorted(cmd))
181
182    def test_frr_bgp_address_family_redistribute_idempotent(self):
183        rd_1 = dict(protocol="eigrp", metric=10, route_map="RMAP_3", id=None)
184        rd_2 = dict(protocol="static", metric=100, id=None, route_map=None)
185
186        config = dict(
187            bgp_as=64496,
188            address_family=[
189                dict(afi="ipv4", safi="unicast", redistribute=[rd_1, rd_2])
190            ],
191            networks=None,
192        )
193
194        obj = Provider(params=dict(config=config, operation="merge"))
195
196        commands = obj.render(self._bgp_config)
197        self.assertEqual(commands, [])
198
199    def test_frr_bgp_address_family_neighbors(self):
200        af_nbr_1 = dict(
201            neighbor="192.51.100.1", maximum_prefix=35, activate=True
202        )
203        af_nbr_2 = dict(
204            neighbor="192.51.100.3", route_reflector_client=True, activate=True
205        )
206
207        config = dict(
208            bgp_as=64496,
209            address_family=[
210                dict(
211                    afi="ipv4",
212                    safi="multicast",
213                    neighbors=[af_nbr_1, af_nbr_2],
214                )
215            ],
216            networks=None,
217        )
218
219        obj = Provider(params=dict(config=config, operation="merge"))
220
221        commands = obj.render(self._bgp_config)
222        cmd = [
223            "router bgp 64496",
224            "address-family ipv4 multicast",
225            "neighbor 192.51.100.1 activate",
226            "neighbor 192.51.100.1 maximum-prefix 35",
227            "neighbor 192.51.100.3 activate",
228            "neighbor 192.51.100.3 route-reflector-client",
229            "exit-address-family",
230            "exit",
231        ]
232        self.assertEqual(sorted(commands), sorted(cmd))
233
234    def test_frr_bgp_address_family_neighbors_idempotent(self):
235        af_nbr_1 = dict(
236            neighbor="2.2.2.2", remove_private_as=True, maximum_prefix=100
237        )
238
239        config = dict(
240            bgp_as=64496,
241            address_family=[
242                dict(afi="ipv4", safi="unicast", neighbors=[af_nbr_1])
243            ],
244            networks=None,
245        )
246
247        obj = Provider(params=dict(config=config, operation="merge"))
248
249        commands = obj.render(self._bgp_config)
250        self.assertEqual(commands, [])
251
252    def test_frr_bgp_address_family_networks(self):
253        net = dict(prefix="1.0.0.0", masklen=8, route_map="RMAP_1")
254        net2 = dict(prefix="192.168.1.0", masklen=24, route_map="RMAP_2")
255
256        config = dict(
257            bgp_as=64496,
258            address_family=[
259                dict(afi="ipv4", safi="multicast", networks=[net, net2])
260            ],
261            networks=None,
262        )
263
264        obj = Provider(params=dict(config=config, operation="merge"))
265
266        commands = obj.render(self._bgp_config)
267        cmd = [
268            "router bgp 64496",
269            "address-family ipv4 multicast",
270            "network 1.0.0.0/8 route-map RMAP_1",
271            "network 192.168.1.0/24 route-map RMAP_2",
272            "exit-address-family",
273            "exit",
274        ]
275        self.assertEqual(sorted(commands), sorted(cmd))
276
277    def test_frr_bgp_address_family_networks_idempotent(self):
278        net = dict(prefix="10.0.0.0", masklen=8, route_map="RMAP_1")
279        net2 = dict(prefix="20.0.0.0", masklen=8, route_map="RMAP_2")
280
281        config = dict(
282            bgp_as=64496,
283            address_family=[
284                dict(afi="ipv4", safi="multicast", networks=[net, net2])
285            ],
286            networks=None,
287        )
288
289        obj = Provider(params=dict(config=config, operation="merge"))
290
291        commands = obj.render(self._bgp_config)
292        self.assertEqual(commands, [])
293
294    def test_frr_bgp_operation_override(self):
295        net_1 = dict(prefix="1.0.0.0", masklen=8, route_map="RMAP_1")
296        net_2 = dict(prefix="192.168.1.0", masklen=24, route_map="RMAP_2")
297        nbr_1 = dict(
298            neighbor="192.51.100.1",
299            remote_as=64496,
300            advertisement_interval=120,
301        )
302        nbr_2 = dict(
303            neighbor="192.51.100.3",
304            remote_as=64496,
305            timers=dict(keepalive=300, holdtime=360),
306        )
307        af_nbr_1 = dict(neighbor="192.51.100.1", maximum_prefix=35)
308        af_nbr_2 = dict(neighbor="192.51.100.3", route_reflector_client=True)
309
310        af_1 = dict(afi="ipv4", safi="unicast", neighbors=[af_nbr_1, af_nbr_2])
311        af_2 = dict(afi="ipv4", safi="multicast", networks=[net_1, net_2])
312        config = dict(
313            bgp_as=64496,
314            neighbors=[nbr_1, nbr_2],
315            address_family=[af_1, af_2],
316            networks=None,
317        )
318
319        obj = Provider(params=dict(config=config, operation="override"))
320        commands = obj.render(self._bgp_config)
321
322        cmd = [
323            "no router bgp 64496",
324            "router bgp 64496",
325            "neighbor 192.51.100.1 remote-as 64496",
326            "neighbor 192.51.100.1 advertisement-interval 120",
327            "neighbor 192.51.100.3 remote-as 64496",
328            "neighbor 192.51.100.3 timers 300 360",
329            "address-family ipv4 unicast",
330            "neighbor 192.51.100.1 maximum-prefix 35",
331            "neighbor 192.51.100.3 route-reflector-client",
332            "exit-address-family",
333            "address-family ipv4 multicast",
334            "network 1.0.0.0/8 route-map RMAP_1",
335            "network 192.168.1.0/24 route-map RMAP_2",
336            "exit-address-family",
337            "exit",
338        ]
339
340        self.assertEqual(sorted(commands), sorted(cmd))
341
342    def test_frr_bgp_operation_replace(self):
343        rd = dict(protocol="ospf", id=223, metric=110, route_map=None)
344        net = dict(prefix="10.0.0.0", masklen=8, route_map="RMAP_1")
345        net2 = dict(prefix="20.0.0.0", masklen=8, route_map="RMAP_2")
346
347        af_1 = dict(afi="ipv4", safi="unicast", redistribute=[rd])
348        af_2 = dict(afi="ipv4", safi="multicast", networks=[net, net2])
349
350        config = dict(bgp_as=64496, address_family=[af_1, af_2], networks=None)
351        obj = Provider(params=dict(config=config, operation="replace"))
352        commands = obj.render(self._bgp_config)
353
354        cmd = [
355            "router bgp 64496",
356            "address-family ipv4 unicast",
357            "redistribute ospf 223 metric 110",
358            "no redistribute eigrp",
359            "no redistribute static",
360            "exit-address-family",
361            "exit",
362        ]
363
364        self.assertEqual(sorted(commands), sorted(cmd))
365
366    def test_frr_bgp_operation_replace_with_new_as(self):
367        rd = dict(protocol="ospf", id=223, metric=110, route_map=None)
368
369        af_1 = dict(afi="ipv4", safi="unicast", redistribute=[rd])
370
371        config = dict(bgp_as=64497, address_family=[af_1], networks=None)
372        obj = Provider(params=dict(config=config, operation="replace"))
373        commands = obj.render(self._bgp_config)
374
375        cmd = [
376            "no router bgp 64496",
377            "router bgp 64497",
378            "address-family ipv4 unicast",
379            "redistribute ospf 223 metric 110",
380            "exit-address-family",
381            "exit",
382        ]
383
384        self.assertEqual(sorted(commands), sorted(cmd))
385