1# (c) 2021 Red Hat Inc.
2#
3# This file is part of Ansible
4#
5# Ansible is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ansible is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17
18# Make coding more python3-ish
19
20from __future__ import absolute_import, division, print_function
21
22__metaclass__ = type
23
24from textwrap import dedent
25from ansible_collections.cisco.iosxr.tests.unit.compat.mock import patch
26from ansible_collections.cisco.iosxr.plugins.modules import iosxr_ntp_global
27from ansible_collections.cisco.iosxr.tests.unit.modules.utils import (
28    set_module_args,
29)
30from .iosxr_module import TestIosxrModule
31
32
33class TestIosxrNtpGlobalModule(TestIosxrModule):
34    module = iosxr_ntp_global
35
36    def setUp(self):
37        super(TestIosxrNtpGlobalModule, self).setUp()
38
39        self.mock_get_resource_connection = patch(
40            "ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module_base."
41            "get_resource_connection"
42        )
43        self.get_resource_connection = (
44            self.mock_get_resource_connection.start()
45        )
46
47        self.mock_get_config = patch(
48            "ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ntp_global.ntp_global."
49            "Ntp_globalFacts.get_config"
50        )
51        self.get_config = self.mock_get_config.start()
52
53    def tearDown(self):
54        super(TestIosxrNtpGlobalModule, self).tearDown()
55        self.get_resource_connection.stop()
56        self.get_config.stop()
57
58    def test_iosxr_ntp_global_merged_idempotent(self):
59        self.maxDiff = None
60        run_cfg = dedent(
61            """\
62                ntp
63                 max-associations 10
64                 interface GigabitEthernet0/0/0/0 vrf siteB
65                  multicast key 1
66                 !
67                 interface GigabitEthernet0/0/0/0
68                  broadcast client
69                  multicast client 224.0.0.8
70                  multicast destination 224.0.0.8
71                 !
72                 authentication-key 1 md5 encrypted testkey
73                 authentication-key 2 md5 encrypted 071B245F5A5B
74                 authenticate
75                 trusted-key 1
76                 trusted-key 2
77                 ipv4 dscp af11
78                 ipv6 precedence routine
79                 peer vrf siteC 192.0.2.1 iburst
80                 server vrf siteD 192.0.2.2 burst
81                 server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
82                 drift file apphost
83                 drift aging time 0
84                 master 1
85                 access-group vrf siteA ipv4 peer PeerAcl2
86                 access-group vrf siteA ipv4 serve ServeAcl2
87                 access-group ipv4 peer PeerAcl1
88                 access-group ipv4 serve ServeAcl1
89                 access-group ipv4 serve-only ServeOnlyAcl1
90                 access-group ipv4 query-only QueryOnlyAcl1
91                 access-group ipv6 peer PeerAcl2
92                 source vrf siteE GigabitEthernet0/0/0/0
93                 source GigabitEthernet0/0/0/0
94                 passive
95                 broadcastdelay 1
96                 update-calendar
97                 log-internal-sync
98                !
99            """
100        )
101        self.get_config.return_value = run_cfg
102        set_module_args(
103            dict(
104                config=dict(
105                    access_group=dict(
106                        ipv4=dict(
107                            peer="PeerAcl1",
108                            query_only="QueryOnlyAcl1",
109                            serve="ServeAcl1",
110                            serve_only="ServeOnlyAcl1",
111                        ),
112                        ipv6=dict(peer="PeerAcl2"),
113                        vrfs=[
114                            dict(
115                                ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
116                                name="siteA",
117                            )
118                        ],
119                    ),
120                    authenticate=True,
121                    authentication_keys=[
122                        dict(id=1, key="testkey", encryption=True),
123                        dict(id=2, key="071B245F5A5B", encryption=True),
124                    ],
125                    broadcastdelay=1,
126                    drift=dict(aging_time=0, file="apphost"),
127                    interfaces=[
128                        dict(
129                            name="GigabitEthernet0/0/0/0",
130                            multicast_client="224.0.0.8",
131                            multicast_destination="224.0.0.8",
132                            broadcast_client=True,
133                        ),
134                        dict(
135                            name="GigabitEthernet0/0/0/0",
136                            multicast_key=1,
137                            vrf="siteB",
138                        ),
139                    ],
140                    ipv4=dict(dscp="af11"),
141                    ipv6=dict(precedence="routine"),
142                    log_internal_sync=True,
143                    master=dict(stratum=1),
144                    max_associations=10,
145                    passive=True,
146                    peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
147                    servers=[
148                        dict(burst=True, server="192.0.2.2", vrf="siteD"),
149                        dict(
150                            iburst=True,
151                            burst=True,
152                            server="192.0.2.2",
153                            key_id=1,
154                            maxpoll=5,
155                            minpoll=4,
156                            prefer=True,
157                            source="GigabitEthernet0/0/0/0",
158                            version=2,
159                        ),
160                    ],
161                    source_interface="GigabitEthernet0/0/0/0",
162                    source_vrfs=[
163                        dict(name="GigabitEthernet0/0/0/0", vrf="siteE")
164                    ],
165                    trusted_keys=[dict(key_id=1), dict(key_id=2)],
166                    update_calendar=True,
167                ),
168                state="merged",
169            )
170        )
171        self.execute_module(changed=False, commands=[])
172
173    def test_iosxr_ntp_global_merged(self):
174        self.maxDiff = None
175        set_module_args(
176            dict(
177                config=dict(
178                    access_group=dict(
179                        ipv4=dict(
180                            peer="PeerAcl1",
181                            query_only="QueryOnlyAcl1",
182                            serve="ServeAcl1",
183                            serve_only="ServeOnlyAcl1",
184                        ),
185                        ipv6=dict(peer="PeerAcl2"),
186                        vrfs=[
187                            dict(
188                                ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
189                                name="siteA",
190                            )
191                        ],
192                    ),
193                    authenticate=True,
194                    authentication_keys=[
195                        dict(id=1, key="testkey", encryption=True),
196                        dict(id=2, key="071B245F5A5B", encryption=True),
197                    ],
198                    broadcastdelay=1,
199                    drift=dict(aging_time=0, file="apphost"),
200                    interfaces=[
201                        dict(
202                            name="GigabitEthernet0/0/0/0",
203                            multicast_client="224.0.0.8",
204                            multicast_destination="224.0.0.8",
205                            broadcast_client=True,
206                        ),
207                        dict(
208                            name="GigabitEthernet0/0/0/0",
209                            multicast_key=1,
210                            vrf="siteB",
211                        ),
212                    ],
213                    ipv4=dict(dscp="af11"),
214                    ipv6=dict(precedence="routine"),
215                    log_internal_sync=True,
216                    master=dict(stratum=1),
217                    max_associations=10,
218                    passive=True,
219                    peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
220                    servers=[
221                        dict(burst=True, server="192.0.2.2", vrf="siteD"),
222                        dict(
223                            iburst=True,
224                            burst=True,
225                            server="192.0.2.2",
226                            key_id=1,
227                            maxpoll=5,
228                            minpoll=4,
229                            prefer=True,
230                            source="GigabitEthernet0/0/0/0",
231                            version=2,
232                        ),
233                    ],
234                    source_interface="GigabitEthernet0/0/0/0",
235                    source_vrfs=[
236                        dict(name="GigabitEthernet0/0/0/0", vrf="siteE")
237                    ],
238                    trusted_keys=[dict(key_id=1), dict(key_id=2)],
239                    update_calendar=True,
240                ),
241                state="merged",
242            )
243        )
244        commands = [
245            "ntp authentication-key 1 md5 encrypted testkey",
246            "ntp authentication-key 2 md5 encrypted 071B245F5A5B",
247            "ntp peer vrf siteC 192.0.2.1 iburst",
248            "ntp server vrf siteD 192.0.2.2 burst",
249            "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0",
250            "ntp trusted-key 1",
251            "ntp trusted-key 2",
252            "ntp interface GigabitEthernet0/0/0/0 broadcast client",
253            "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8",
254            "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8",
255            "ntp interface GigabitEthernet0/0/0/0 vrf siteB multicast key 1",
256            "ntp vrf siteE source GigabitEthernet0/0/0/0",
257            "ntp access-group vrf siteA ipv4 serve ServeAcl2",
258            "ntp access-group vrf siteA ipv4 peer PeerAcl2",
259            "ntp access-group ipv4 peer PeerAcl1",
260            "ntp access-group ipv4 serve ServeAcl1",
261            "ntp access-group ipv4 serve-only ServeOnlyAcl1",
262            "ntp access-group ipv4 query-only QueryOnlyAcl1",
263            "ntp access-group ipv6 peer PeerAcl2",
264            "ntp authenticate",
265            "ntp log-internal-sync",
266            "ntp broadcastdelay 1",
267            "ntp drift aging time 0",
268            "ntp drift file apphost",
269            "ntp ipv4 dscp af11",
270            "ntp ipv6 precedence routine",
271            "ntp max-associations 10",
272            "ntp master 1",
273            "ntp passive",
274            "ntp update-calendar",
275            "ntp source GigabitEthernet0/0/0/0",
276        ]
277        result = self.execute_module(changed=True)
278        self.assertEqual(sorted(result["commands"]), sorted(commands))
279
280    def test_iosxr_ntp_global_deleted(self):
281        self.maxDiff = None
282        run_cfg = dedent(
283            """\
284                ntp
285                 max-associations 10
286                 interface GigabitEthernet0/0/0/0 vrf siteB
287                  multicast key 1
288                 !
289                 interface GigabitEthernet0/0/0/0
290                  broadcast client
291                  multicast client 224.0.0.8
292                  multicast destination 224.0.0.8
293                 !
294                 authentication-key 1 md5 encrypted testkey
295                 authentication-key 2 md5 encrypted 071B245F5A5B
296                 authenticate
297                 trusted-key 1
298                 trusted-key 2
299                 ipv4 dscp af11
300                 ipv6 precedence routine
301                 peer vrf siteC 192.0.2.1 iburst
302                 server vrf siteD 192.0.2.2 burst
303                 server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
304                 drift file apphost
305                 drift aging time 0
306                 master 1
307                 access-group vrf siteA ipv4 peer PeerAcl3
308                 access-group vrf siteA ipv4 serve ServeAcl2
309                 access-group ipv4 peer PeerAcl1
310                 access-group ipv4 serve ServeAcl1
311                 access-group ipv4 serve-only ServeOnlyAcl1
312                 access-group ipv4 query-only QueryOnlyAcl1
313                 access-group ipv6 peer PeerAcl2
314                 source vrf siteE GigabitEthernet0/0/0/0
315                 source GigabitEthernet0/0/0/0
316                 passive
317                 broadcastdelay 1
318                 update-calendar
319                 log-internal-sync
320                !
321            """
322        )
323        self.get_config.return_value = run_cfg
324        set_module_args(dict(state="deleted"))
325        commands = [
326            "no ntp authentication-key 1 md5 encrypted testkey",
327            "no ntp authentication-key 2 md5 encrypted 071B245F5A5B",
328            "no ntp peer vrf siteC 192.0.2.1 iburst",
329            "no ntp server vrf siteD 192.0.2.2 burst",
330            "no ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0",
331            "no ntp trusted-key 1",
332            "no ntp trusted-key 2",
333            "no ntp interface GigabitEthernet0/0/0/0 vrf siteB",
334            "no ntp interface GigabitEthernet0/0/0/0",
335            "no ntp vrf siteE source GigabitEthernet0/0/0/0",
336            "no ntp access-group vrf siteA ipv4 serve ServeAcl2",
337            "no ntp access-group vrf siteA ipv4 peer PeerAcl3",
338            "no ntp access-group ipv4 peer PeerAcl1",
339            "no ntp access-group ipv4 serve ServeAcl1",
340            "no ntp access-group ipv4 serve-only ServeOnlyAcl1",
341            "no ntp access-group ipv4 query-only QueryOnlyAcl1",
342            "no ntp access-group ipv6 peer PeerAcl2",
343            "no ntp authenticate",
344            "no ntp log-internal-sync",
345            "no ntp broadcastdelay 1",
346            "no ntp drift aging time 0",
347            "no ntp drift file apphost",
348            "no ntp ipv4 dscp af11",
349            "no ntp ipv6 precedence routine",
350            "no ntp max-associations 10",
351            "no ntp master 1",
352            "no ntp passive",
353            "no ntp update-calendar",
354            "no ntp source GigabitEthernet0/0/0/0",
355        ]
356        result = self.execute_module(changed=True)
357        self.assertEqual(sorted(result["commands"]), sorted(commands))
358
359    def test_iosxr_ntp_global_replaced(self):
360        self.maxDiff = None
361        run_cfg = dedent(
362            """\
363                ntp
364                 max-associations 10
365                 interface GigabitEthernet0/0/0/0 vrf siteB
366                  multicast key 1
367                 !
368                 interface GigabitEthernet0/0/0/0
369                  broadcast client
370                  multicast client 224.0.0.8
371                  multicast destination 224.0.0.8
372                 !
373                 authentication-key 1 md5 encrypted testkey
374                 authentication-key 2 md5 encrypted 071B245F5A5B
375                 authenticate
376                 trusted-key 1
377                 trusted-key 2
378                 ipv4 dscp af11
379                 ipv6 precedence routine
380                 peer vrf siteC 192.0.2.1 iburst
381                 server vrf siteD 192.0.2.2 burst
382                 server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
383                 drift file apphost
384                 drift aging time 0
385                 master 1
386                 access-group vrf siteA ipv4 peer PeerAcl3
387                 access-group vrf siteA ipv4 serve ServeAcl2
388                 access-group ipv4 peer PeerAcl1
389                 access-group ipv4 serve ServeAcl1
390                 access-group ipv4 serve-only ServeOnlyAcl1
391                 access-group ipv4 query-only QueryOnlyAcl1
392                 access-group ipv6 peer PeerAcl2
393                 source vrf siteE GigabitEthernet0/0/0/0
394                 source GigabitEthernet0/0/0/0
395                 passive
396                 broadcastdelay 1
397                 update-calendar
398                 log-internal-sync
399                !
400            """
401        )
402        self.get_config.return_value = run_cfg
403        set_module_args(
404            dict(
405                config=dict(
406                    access_group=dict(
407                        ipv4=dict(
408                            peer="PeerAcl1",
409                            query_only="QueryOnlyAcl2",
410                            serve="ServeAcl1",
411                            serve_only="ServeOnlyAcl1",
412                        ),
413                        ipv6=dict(peer="PeerAcl2"),
414                        vrfs=[
415                            dict(
416                                ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
417                                name="siteA",
418                            )
419                        ],
420                    ),
421                    authenticate=True,
422                    authentication_keys=[
423                        dict(id=1, key="testkey1", encryption=True),
424                        dict(id=2, key="071B245F5A5B", encryption=True),
425                    ],
426                    broadcastdelay=1,
427                    drift=dict(aging_time=0, file="apphost"),
428                    interfaces=[
429                        dict(
430                            name="GigabitEthernet0/0/0/1",
431                            multicast_client="224.0.0.8",
432                            multicast_destination="224.0.0.8",
433                            broadcast_client=True,
434                        ),
435                        dict(
436                            name="GigabitEthernet0/0/0/0",
437                            multicast_key=1,
438                            vrf="siteB",
439                        ),
440                    ],
441                    ipv4=dict(dscp="af12"),
442                    ipv6=dict(precedence="routine"),
443                    log_internal_sync=True,
444                    master=dict(stratum=1),
445                    max_associations=10,
446                    passive=True,
447                    peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
448                    servers=[
449                        dict(burst=True, server="192.0.2.3", vrf="siteD"),
450                        dict(
451                            iburst=True,
452                            burst=True,
453                            server="192.0.2.2",
454                            key_id=1,
455                            maxpoll=5,
456                            minpoll=4,
457                            prefer=True,
458                            source="GigabitEthernet0/0/0/1",
459                            version=2,
460                        ),
461                    ],
462                    source_interface="GigabitEthernet0/0/0/0",
463                    source_vrfs=[
464                        dict(name="GigabitEthernet0/0/0/0", vrf="siteE")
465                    ],
466                    trusted_keys=[dict(key_id=1), dict(key_id=2)],
467                    update_calendar=True,
468                ),
469                state="replaced",
470            )
471        )
472        commands = [
473            "no ntp server vrf siteD 192.0.2.2 burst",
474            "no ntp interface GigabitEthernet0/0/0/0",
475            "ntp authentication-key 1 md5 encrypted testkey1",
476            "ntp server vrf siteD 192.0.2.3 burst",
477            "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/1",
478            "ntp interface GigabitEthernet0/0/0/1 broadcast client",
479            "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8",
480            "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8",
481            "ntp access-group ipv4 query-only QueryOnlyAcl2",
482            "ntp access-group vrf siteA ipv4 peer PeerAcl2",
483            "ntp access-group vrf siteA ipv4 serve ServeAcl2",
484            "ntp ipv4 dscp af12",
485        ]
486        result = self.execute_module(changed=True)
487        self.assertEqual(sorted(result["commands"]), sorted(commands))
488
489    def test_iosxr_logging_global_rendered(self):
490        self.maxDiff = None
491        set_module_args(
492            dict(
493                config=dict(
494                    access_group=dict(
495                        ipv4=dict(
496                            peer="PeerAcl1",
497                            query_only="QueryOnlyAcl1",
498                            serve="ServeAcl1",
499                            serve_only="ServeOnlyAcl1",
500                        ),
501                        ipv6=dict(peer="PeerAcl2"),
502                        vrfs=[
503                            dict(
504                                ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
505                                name="siteA",
506                            )
507                        ],
508                    ),
509                    authenticate=True,
510                    authentication_keys=[
511                        dict(id=1, key="testkey", encryption=True),
512                        dict(id=2, key="071B245F5A5B", encryption=True),
513                    ],
514                    broadcastdelay=1,
515                    drift=dict(aging_time=0, file="apphost"),
516                    interfaces=[
517                        dict(
518                            name="GigabitEthernet0/0/0/0",
519                            multicast_client="224.0.0.8",
520                            multicast_destination="224.0.0.8",
521                            broadcast_client=True,
522                        ),
523                        dict(
524                            name="GigabitEthernet0/0/0/0",
525                            multicast_key=1,
526                            vrf="siteB",
527                        ),
528                    ],
529                    ipv4=dict(dscp="af11"),
530                    ipv6=dict(precedence="routine"),
531                    log_internal_sync=True,
532                    master=dict(stratum=1),
533                    max_associations=10,
534                    passive=True,
535                    peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
536                    servers=[
537                        dict(burst=True, server="192.0.2.2", vrf="siteD"),
538                        dict(
539                            iburst=True,
540                            burst=True,
541                            server="192.0.2.2",
542                            key_id=1,
543                            maxpoll=5,
544                            minpoll=4,
545                            prefer=True,
546                            source="GigabitEthernet0/0/0/0",
547                            version=2,
548                        ),
549                    ],
550                    source_interface="GigabitEthernet0/0/0/0",
551                    source_vrfs=[
552                        dict(name="GigabitEthernet0/0/0/0", vrf="siteE")
553                    ],
554                    trusted_keys=[dict(key_id=1), dict(key_id=2)],
555                    update_calendar=True,
556                ),
557                state="rendered",
558            )
559        )
560        commands = [
561            "ntp authentication-key 1 md5 encrypted testkey",
562            "ntp authentication-key 2 md5 encrypted 071B245F5A5B",
563            "ntp peer vrf siteC 192.0.2.1 iburst",
564            "ntp server vrf siteD 192.0.2.2 burst",
565            "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/0",
566            "ntp trusted-key 1",
567            "ntp trusted-key 2",
568            "ntp interface GigabitEthernet0/0/0/0 broadcast client",
569            "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8",
570            "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8",
571            "ntp interface GigabitEthernet0/0/0/0 vrf siteB multicast key 1",
572            "ntp vrf siteE source GigabitEthernet0/0/0/0",
573            "ntp access-group vrf siteA ipv4 serve ServeAcl2",
574            "ntp access-group vrf siteA ipv4 peer PeerAcl2",
575            "ntp access-group ipv4 peer PeerAcl1",
576            "ntp access-group ipv4 serve ServeAcl1",
577            "ntp access-group ipv4 serve-only ServeOnlyAcl1",
578            "ntp access-group ipv4 query-only QueryOnlyAcl1",
579            "ntp access-group ipv6 peer PeerAcl2",
580            "ntp authenticate",
581            "ntp log-internal-sync",
582            "ntp broadcastdelay 1",
583            "ntp drift aging time 0",
584            "ntp drift file apphost",
585            "ntp ipv4 dscp af11",
586            "ntp ipv6 precedence routine",
587            "ntp max-associations 10",
588            "ntp master 1",
589            "ntp passive",
590            "ntp update-calendar",
591            "ntp source GigabitEthernet0/0/0/0",
592        ]
593        result = self.execute_module(changed=False)
594        self.assertEqual(sorted(result["rendered"]), sorted(commands))
595
596    def test_iosxr_ntp_global_overridden(self):
597        run_cfg = dedent(
598            """\
599                ntp
600                 max-associations 10
601                 interface GigabitEthernet0/0/0/0 vrf siteB
602                  multicast key 1
603                 !
604                 interface GigabitEthernet0/0/0/0
605                  broadcast client
606                  multicast client 224.0.0.8
607                  multicast destination 224.0.0.8
608                 !
609                 authentication-key 1 md5 encrypted testkey
610                 authentication-key 2 md5 encrypted 071B245F5A5B
611                 authenticate
612                 trusted-key 1
613                 trusted-key 2
614                 ipv4 dscp af11
615                 ipv6 precedence routine
616                 peer vrf siteC 192.0.2.1 iburst
617                 server vrf siteD 192.0.2.2 burst
618                 server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
619                 drift file apphost
620                 drift aging time 0
621                 master 1
622                 access-group vrf siteA ipv4 peer PeerAcl3
623                 access-group vrf siteA ipv4 serve ServeAcl2
624                 access-group ipv4 peer PeerAcl1
625                 access-group ipv4 serve ServeAcl1
626                 access-group ipv4 serve-only ServeOnlyAcl1
627                 access-group ipv4 query-only QueryOnlyAcl1
628                 access-group ipv6 peer PeerAcl2
629                 source vrf siteE GigabitEthernet0/0/0/0
630                 source GigabitEthernet0/0/0/0
631                 passive
632                 broadcastdelay 1
633                 update-calendar
634                 log-internal-sync
635                !
636            """
637        )
638        self.get_config.return_value = run_cfg
639        set_module_args(
640            dict(
641                config=dict(
642                    access_group=dict(
643                        ipv4=dict(
644                            peer="PeerAcl1",
645                            query_only="QueryOnlyAcl2",
646                            serve="ServeAcl1",
647                            serve_only="ServeOnlyAcl1",
648                        ),
649                        ipv6=dict(peer="PeerAcl2"),
650                        vrfs=[
651                            dict(
652                                ipv4=dict(peer="PeerAcl2", serve="ServeAcl2"),
653                                name="siteA",
654                            )
655                        ],
656                    ),
657                    authenticate=True,
658                    authentication_keys=[
659                        dict(id=1, key="testkey1", encryption=True),
660                        dict(id=2, key="071B245F5A5B", encryption=True),
661                    ],
662                    broadcastdelay=1,
663                    drift=dict(aging_time=0, file="apphost"),
664                    interfaces=[
665                        dict(
666                            name="GigabitEthernet0/0/0/1",
667                            multicast_client="224.0.0.8",
668                            multicast_destination="224.0.0.8",
669                            broadcast_client=True,
670                        ),
671                        dict(
672                            name="GigabitEthernet0/0/0/0",
673                            multicast_key=1,
674                            vrf="siteB",
675                        ),
676                    ],
677                    ipv4=dict(dscp="af12"),
678                    ipv6=dict(precedence="routine"),
679                    log_internal_sync=True,
680                    master=dict(stratum=1),
681                    max_associations=10,
682                    passive=True,
683                    peers=[dict(iburst=True, peer="192.0.2.1", vrf="siteC")],
684                    servers=[
685                        dict(burst=True, server="192.0.2.3", vrf="siteD"),
686                        dict(
687                            iburst=True,
688                            burst=True,
689                            server="192.0.2.2",
690                            key_id=1,
691                            maxpoll=5,
692                            minpoll=4,
693                            prefer=True,
694                            source="GigabitEthernet0/0/0/1",
695                            version=2,
696                        ),
697                    ],
698                    source_interface="GigabitEthernet0/0/0/0",
699                    source_vrfs=[
700                        dict(name="GigabitEthernet0/0/0/0", vrf="siteE")
701                    ],
702                    trusted_keys=[dict(key_id=1), dict(key_id=2)],
703                    update_calendar=True,
704                ),
705                state="overridden",
706            )
707        )
708        commands = [
709            "no ntp server vrf siteD 192.0.2.2 burst",
710            "no ntp interface GigabitEthernet0/0/0/0",
711            "ntp authentication-key 1 md5 encrypted testkey1",
712            "ntp server vrf siteD 192.0.2.3 burst",
713            "ntp server 192.0.2.2 burst iburst key 1 minpoll 4 maxpoll 5 prefer version 2 source GigabitEthernet0/0/0/1",
714            "ntp interface GigabitEthernet0/0/0/1 broadcast client",
715            "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8",
716            "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8",
717            "ntp access-group ipv4 query-only QueryOnlyAcl2",
718            "ntp access-group vrf siteA ipv4 peer PeerAcl2",
719            "ntp access-group vrf siteA ipv4 serve ServeAcl2",
720            "ntp ipv4 dscp af12",
721        ]
722        result = self.execute_module(changed=True)
723        self.assertEqual(sorted(result["commands"]), sorted(commands))
724
725    def test_iosxr_ntp_global_gathered(self):
726        self.maxDiff = None
727        run_cfg = dedent(
728            """\
729                ntp
730                 max-associations 10
731                 interface GigabitEthernet0/0/0/0
732                  broadcast client
733                  multicast client 224.0.0.8
734                  multicast destination 224.0.0.8
735                 !
736                 authentication-key 1 md5 encrypted testkey
737                 authentication-key 2 md5 encrypted 071B245F5A5B
738                 authenticate
739                 trusted-key 1
740                 trusted-key 2
741                 ipv4 dscp af11
742                 ipv6 precedence routine
743                 peer vrf siteC 192.0.2.1 iburst
744                 server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer burst iburst source GigabitEthernet0/0/0/0
745                 drift file apphost
746                 drift aging time 0
747                 master 1
748                 access-group vrf siteA ipv4 peer PeerAcl3
749                 access-group vrf siteA ipv4 serve ServeAcl2
750                 access-group ipv4 peer PeerAcl1
751                 access-group ipv4 serve ServeAcl1
752                 access-group ipv4 serve-only ServeOnlyAcl1
753                 access-group ipv4 query-only QueryOnlyAcl1
754                 access-group ipv6 peer PeerAcl2
755                 source vrf siteE GigabitEthernet0/0/0/0
756                 source GigabitEthernet0/0/0/0
757                 passive
758                 broadcastdelay 1
759                 update-calendar
760                 log-internal-sync
761                !
762            """
763        )
764        self.get_config.return_value = run_cfg
765        print(self.get_config.return_value)
766        set_module_args(dict(state="gathered"))
767        gathered = {
768            "max_associations": 10,
769            "interfaces": [
770                {
771                    "name": "GigabitEthernet0/0/0/0",
772                    "broadcast_client": True,
773                    "multicast_client": "224.0.0.8",
774                    "multicast_destination": "224.0.0.8",
775                }
776            ],
777            "authentication_keys": [
778                {"id": 1, "key": "testkey", "encryption": True},
779                {"id": 2, "key": "071B245F5A5B", "encryption": True},
780            ],
781            "authenticate": True,
782            "trusted_keys": [{"key_id": 1}, {"key_id": 2}],
783            "ipv4": {"dscp": "af11"},
784            "ipv6": {"precedence": "routine"},
785            "peers": [{"peer": "192.0.2.1", "vrf": "siteC", "iburst": True}],
786            "servers": [
787                {
788                    "server": "192.0.2.2",
789                    "burst": True,
790                    "iburst": True,
791                    "key_id": 1,
792                    "minpoll": 4,
793                    "maxpoll": 5,
794                    "prefer": True,
795                    "version": 2,
796                    "source": "GigabitEthernet0/0/0/0",
797                }
798            ],
799            "drift": {"file": "apphost", "aging_time": 0},
800            "master": {"stratum": 1},
801            "access_group": {
802                "vrfs": [
803                    {
804                        "name": "siteA",
805                        "ipv4": {"peer": "PeerAcl3", "serve": "ServeAcl2"},
806                    }
807                ],
808                "ipv4": {
809                    "peer": "PeerAcl1",
810                    "serve": "ServeAcl1",
811                    "serve_only": "ServeOnlyAcl1",
812                    "query_only": "QueryOnlyAcl1",
813                },
814                "ipv6": {"peer": "PeerAcl2"},
815            },
816            "source_vrfs": [
817                {"name": "GigabitEthernet0/0/0/0", "vrf": "siteE"}
818            ],
819            "source_interface": "GigabitEthernet0/0/0/0",
820            "passive": True,
821            "broadcastdelay": 1,
822            "update_calendar": True,
823            "log_internal_sync": True,
824        }
825        result = self.execute_module(changed=False)
826        self.assertEqual(gathered, result["gathered"])
827
828    def test_iosxr_ntp_global_parsed(self):
829        self.maxDiff = None
830        set_module_args(
831            dict(
832                running_config="ntp\n max-associations 10\n interface GigabitEthernet0/0/0/0\n  broadcast client\n"
833                "  multicast client 224.0.0.8\n  multicast destination 224.0.0.8\n !\n "
834                "authentication-key 1 md5 encrypted testkey\n authentication-key 2 md5 "
835                "encrypted 071B245F5A5B\n authenticate\n trusted-key 1\n trusted-key 2\n ipv4 dscp "
836                "af11\n ipv6 precedence routine\n peer vrf siteC 192.0.2.1 iburst\n"
837                " server 192.0.2.2 version 2 key 1 minpoll 4 maxpoll 5 prefer "
838                "burst iburst source GigabitEthernet0/0/0/0\n drift file apphost\n drift aging time 0\n"
839                " master 1\n access-group vrf siteA ipv4 peer PeerAcl3\n access-group vrf siteA "
840                "ipv4 serve  ServeAcl2\n access-group ipv4 peer PeerAcl1\n access-group ipv4 serve "
841                "ServeAcl1\n access-group ipv4 serve-only ServeOnlyAcl1\n access-group ipv4 "
842                "query-only QueryOnlyAcl1\n access-group ipv6 peer PeerAcl2\n source vrf siteE "
843                "GigabitEthernet0/0/0/0\n source GigabitEthernet0/0/0/0\n"
844                " passive\n broadcastdelay "
845                "1\n update-calendar\n log-internal-sync\n!",
846                state="parsed",
847            )
848        )
849        result = self.execute_module(changed=False)
850        parsed_list = {
851            "max_associations": 10,
852            "interfaces": [
853                {
854                    "name": "GigabitEthernet0/0/0/0",
855                    "broadcast_client": True,
856                    "multicast_client": "224.0.0.8",
857                    "multicast_destination": "224.0.0.8",
858                }
859            ],
860            "authentication_keys": [
861                {"id": 1, "key": "testkey", "encryption": True},
862                {"id": 2, "key": "071B245F5A5B", "encryption": True},
863            ],
864            "authenticate": True,
865            "trusted_keys": [{"key_id": 1}, {"key_id": 2}],
866            "ipv4": {"dscp": "af11"},
867            "ipv6": {"precedence": "routine"},
868            "peers": [{"peer": "192.0.2.1", "vrf": "siteC", "iburst": True}],
869            "servers": [
870                {
871                    "server": "192.0.2.2",
872                    "burst": True,
873                    "iburst": True,
874                    "key_id": 1,
875                    "minpoll": 4,
876                    "maxpoll": 5,
877                    "prefer": True,
878                    "version": 2,
879                    "source": "GigabitEthernet0/0/0/0",
880                }
881            ],
882            "drift": {"file": "apphost", "aging_time": 0},
883            "master": {"stratum": 1},
884            "access_group": {
885                "vrfs": [{"name": "siteA", "ipv4": {"peer": "PeerAcl3"}}],
886                "ipv4": {
887                    "peer": "PeerAcl1",
888                    "serve": "ServeAcl1",
889                    "serve_only": "ServeOnlyAcl1",
890                    "query_only": "QueryOnlyAcl1",
891                },
892                "ipv6": {"peer": "PeerAcl2"},
893            },
894            "source_vrfs": [
895                {"name": "GigabitEthernet0/0/0/0", "vrf": "siteE"}
896            ],
897            "source_interface": "GigabitEthernet0/0/0/0",
898            "passive": True,
899            "broadcastdelay": 1,
900            "update_calendar": True,
901            "log_internal_sync": True,
902        }
903        self.assertEqual(parsed_list, result["parsed"])
904