@@ -72,9 +72,21 @@ def fake_scaleway_group(scaleway_group, monkeypatch):
7272 mock_client .server_action .return_value = None
7373 mock_client .update_server .return_value = None
7474 mock_client .delete_server .return_value = None
75+ mock_client .delete_volume .return_value = None # For fallback from Block API
76+
77+ # Mock Block Storage API client
78+ # By default, simulate that volumes are not found in Block API (like l_ssd volumes)
79+ # This will trigger fallback to Instance API, maintaining compatibility with existing tests
80+ mock_block_client = MagicMock ()
81+ mock_block_client .delete_volume .side_effect = Exception (
82+ "404 not_found: Volume not in Block API"
83+ )
7584
7685 # Patch the client property
7786 monkeypatch .setattr (ScalewayBackend , "client" , property (lambda self : mock_client ))
87+ monkeypatch .setattr (
88+ ScalewayBackend , "block_client" , property (lambda self : mock_block_client )
89+ )
7890
7991 # Mock wait_for_server_state to return immediately
8092 def mock_wait (self , server_id , target_state , timeout = 300 ):
@@ -549,6 +561,119 @@ def test_delete_not_found(scaleway_runner, fake_scaleway_group, caplog):
549561 assert result == 1
550562
551563
564+ def test_delete_with_block_storage_volume (
565+ scaleway_runner , fake_scaleway_group , caplog , monkeypatch
566+ ):
567+ """Test instance deletion with block storage (sbs_volume) using Block API."""
568+ backend = fake_scaleway_group .backend
569+ scaleway_runner .instance_id = "test-server-id"
570+ scaleway_runner .save ()
571+
572+ # Mock server with block storage volume
573+ mock_volume = MagicMock ()
574+ mock_volume .id = "test-block-volume-id"
575+ mock_server = MagicMock ()
576+ mock_server .id = "test-server-id"
577+ mock_server .state = ServerState .RUNNING
578+ mock_server .volumes = {"0" : mock_volume }
579+
580+ # Mock Instance API client
581+ mock_client = MagicMock ()
582+ mock_client .get_server .return_value = MagicMock (server = mock_server )
583+ mock_client .delete_server .return_value = None
584+ mock_client .delete_volume .return_value = None
585+ mock_client .server_action .return_value = None
586+
587+ # Mock Block Storage API client
588+ mock_block_client = MagicMock ()
589+ mock_block_client .delete_volume .return_value = None
590+
591+ # Patch both clients
592+ monkeypatch .setattr (ScalewayBackend , "client" , property (lambda self : mock_client ))
593+ monkeypatch .setattr (
594+ ScalewayBackend , "block_client" , property (lambda self : mock_block_client )
595+ )
596+
597+ # Mock wait_for_server_state
598+ def mock_wait (self , server_id , target_state , timeout = 300 ):
599+ return mock_server
600+
601+ monkeypatch .setattr (ScalewayBackend , "wait_for_server_state" , mock_wait )
602+
603+ result = backend .delete (scaleway_runner )
604+
605+ # Verify Block Storage API was called first
606+ mock_block_client .delete_volume .assert_called_once_with (
607+ zone = backend .config .zone ,
608+ volume_id = "test-block-volume-id" ,
609+ )
610+ # Verify Instance API delete_volume was NOT called
611+ mock_client .delete_volume .assert_not_called ()
612+ # Verify successful deletion was logged
613+ assert (
614+ "Block storage volume test-block-volume-id deleted successfully" in caplog .text
615+ )
616+ assert result == 1
617+
618+
619+ def test_delete_with_volume_fallback_to_instance_api (
620+ scaleway_runner , fake_scaleway_group , caplog , monkeypatch
621+ ):
622+ """Test volume deletion fallback from Block API to Instance API for l_ssd volumes."""
623+ backend = fake_scaleway_group .backend
624+ scaleway_runner .instance_id = "test-server-id"
625+ scaleway_runner .save ()
626+
627+ # Mock server with l_ssd volume
628+ mock_volume = MagicMock ()
629+ mock_volume .id = "test-lssd-volume-id"
630+ mock_server = MagicMock ()
631+ mock_server .id = "test-server-id"
632+ mock_server .state = ServerState .RUNNING
633+ mock_server .volumes = {"0" : mock_volume }
634+
635+ # Mock Instance API client
636+ mock_client = MagicMock ()
637+ mock_client .get_server .return_value = MagicMock (server = mock_server )
638+ mock_client .delete_server .return_value = None
639+ mock_client .delete_volume .return_value = None
640+ mock_client .server_action .return_value = None
641+
642+ # Mock Block Storage API client to return 404 (volume not found in Block API)
643+ mock_block_client = MagicMock ()
644+ mock_block_client .delete_volume .side_effect = Exception (
645+ "404 not_found: Volume not found in Block API"
646+ )
647+
648+ # Patch both clients
649+ monkeypatch .setattr (ScalewayBackend , "client" , property (lambda self : mock_client ))
650+ monkeypatch .setattr (
651+ ScalewayBackend , "block_client" , property (lambda self : mock_block_client )
652+ )
653+
654+ # Mock wait_for_server_state
655+ def mock_wait (self , server_id , target_state , timeout = 300 ):
656+ return mock_server
657+
658+ monkeypatch .setattr (ScalewayBackend , "wait_for_server_state" , mock_wait )
659+
660+ result = backend .delete (scaleway_runner )
661+
662+ # Verify Block Storage API was called first
663+ mock_block_client .delete_volume .assert_called_once_with (
664+ zone = backend .config .zone ,
665+ volume_id = "test-lssd-volume-id" ,
666+ )
667+ # Verify Instance API was called as fallback
668+ mock_client .delete_volume .assert_called_once_with (
669+ zone = backend .config .zone ,
670+ volume_id = "test-lssd-volume-id" ,
671+ )
672+ # Verify successful deletion through Instance API was logged
673+ assert "Instance volume test-lssd-volume-id deleted successfully" in caplog .text
674+ assert result == 1
675+
676+
552677def test_list_with_auto_create (fake_scaleway_group , monkeypatch ):
553678 """Test list() creates runners for servers not in database."""
554679 backend = fake_scaleway_group .backend
0 commit comments