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