@@ -487,3 +487,77 @@ def test_oci_instance_ip_parametrized(
487
487
ip = oci_instance .ip
488
488
# the following will only run if no error is raised
489
489
assert ip == expected_ip
490
+
491
+
492
+ class TestConfigureSecondaryVnic :
493
+ def test_configure_secondary_vnic_success (self , oci_instance :OciInstance ):
494
+ with mock .patch .object (
495
+ OciInstance , "secondary_vnic_private_ip" , new_callable = mock .PropertyMock
496
+ ) as mock_secondary_ip :
497
+ mock_secondary_ip .return_value = "10.0.0.5"
498
+ # Provide a side_effect matching the four execute() calls
499
+ oci_instance .execute = mock .Mock (side_effect = [
500
+ mock .Mock (stdout = '[{"macAddr": "00:16:3e:aa:bb:cc","privateIp":"10.0.0.4",'
501
+ '"subnetCidrBlock":"10.0.0.0/24"},'
502
+ '{"macAddr":"00:16:3e:ee:ff:gg","privateIp":"10.0.0.5",'
503
+ '"subnetCidrBlock":"10.0.1.0/24"}]' ),
504
+ mock .Mock (stdout = "eth1" ),
505
+ mock .Mock (stdout = "" ),
506
+ mock .Mock (stdout = "10.0.0.5" ),
507
+ ])
508
+ ip = oci_instance .configure_secondary_vnic ()
509
+ assert ip == "10.0.0.5"
510
+
511
+ def test_configure_secondary_vnic_no_secondary (self , oci_instance :OciInstance ):
512
+ with mock .patch .object (
513
+ OciInstance , "secondary_vnic_private_ip" , new_callable = mock .PropertyMock
514
+ ) as mock_secondary_ip :
515
+ mock_secondary_ip .return_value = None
516
+ with pytest .raises (ValueError , match = "Cannot configure secondary VNIC" ):
517
+ oci_instance .configure_secondary_vnic ()
518
+
519
+ # patch out time.sleep
520
+ @mock .patch ("time.sleep" , mock .MagicMock ())
521
+ def test_configure_secondary_vnic_unavailable_imds (self , oci_instance :OciInstance ):
522
+ with mock .patch .object (
523
+ OciInstance , "secondary_vnic_private_ip" , new_callable = mock .PropertyMock
524
+ ) as mock_secondary_ip :
525
+ mock_secondary_ip .return_value = "10.0.0.5"
526
+ # Return empty IMDS data each time
527
+ oci_instance .execute = mock .Mock (side_effect = [mock .Mock (stdout = "[]" )] * 60 )
528
+ with pytest .raises (PycloudlibError , match = "Failed to fetch secondary VNIC data" ):
529
+ oci_instance .configure_secondary_vnic ()
530
+
531
+ def test_configure_secondary_vnic_no_interface_found (self , oci_instance :OciInstance ):
532
+ with mock .patch .object (
533
+ OciInstance , "secondary_vnic_private_ip" , new_callable = mock .PropertyMock
534
+ ) as mock_secondary_ip :
535
+ mock_secondary_ip .return_value = "10.0.0.5"
536
+ # IMDS returns one entry
537
+ oci_instance .execute = mock .Mock (side_effect = [
538
+ mock .Mock (stdout = '[{"macAddr": "00:16:3e:aa:bb:cc","privateIp":"10.0.0.4",'
539
+ '"subnetCidrBlock":"10.0.0.0/24"},'
540
+ '{"macAddr":"00:16:3e:ee:ff:gg","privateIp":"10.0.0.5",'
541
+ '"subnetCidrBlock":"10.0.1.0/24"}]' ),
542
+ mock .Mock (stdout = "" ), # No interface found
543
+ ])
544
+ with pytest .raises (ValueError , match = "No interface found for MAC address" ):
545
+ oci_instance .configure_secondary_vnic ()
546
+
547
+ def test_configure_secondary_vnic_ip_not_assigned (self , oci_instance :OciInstance ):
548
+ with mock .patch .object (
549
+ OciInstance , "secondary_vnic_private_ip" , new_callable = mock .PropertyMock
550
+ ) as mock_secondary_ip :
551
+ mock_secondary_ip .return_value = "10.0.0.5"
552
+ # Returns the single IMDS entry, then interface, then IP add, then empty IP check
553
+ oci_instance .execute = mock .Mock (side_effect = [
554
+ mock .Mock (stdout = '[{"macAddr": "00:16:3e:aa:bb:cc","privateIp":"10.0.0.4",'
555
+ '"subnetCidrBlock":"10.0.0.0/24"},'
556
+ '{"macAddr":"00:16:3e:ee:ff:gg","privateIp":"10.0.0.5",'
557
+ '"subnetCidrBlock":"10.0.1.0/24"}]' ),
558
+ mock .Mock (stdout = "eth1" ),
559
+ mock .Mock (stdout = "" ),
560
+ mock .Mock (stdout = "" ), # Nothing found
561
+ ])
562
+ with pytest .raises (ValueError , match = "was not successfully assigned" ):
563
+ oci_instance .configure_secondary_vnic ()
0 commit comments