@@ -57,16 +57,17 @@ func TestWorkerSliceGatewaySuite(t *testing.T) {
5757}
5858
5959var WorkerSliceGatewayTestbed = map [string ]func (* testing.T ){
60- "TestWorkerSliceGatewayReconciliation_Success" : testWorkerSliceGatewayReconciliationSuccess ,
61- "TestWorkerSliceGatewayReconciliation_IfSliceConfigNotFound" : testWorkerSliceGatewayReconciliationIfSliceConfigNotFound ,
62- "TestWorkerSliceGatewayReconciliation_IfGatewayNotFound" : testWorkerSliceGatewayReconciliationIfGatewayNotFound ,
63- "TestWorkerSliceGatewayReconciliation_Delete" : testWorkerSliceGatewayReconciliationDelete ,
64- "TestWorkerSliceGatewayReconciliation_DeleteForcefully" : testWorkerSliceGatewayReconciliationDeleteForcefully ,
65- "TestCreateMinimumWorkerSliceGateways_IfAlreadyExists" : testCreateMinimumWorkerSliceGatewaysAlreadyExists ,
66- "TestCreateMinimumWorkerSliceGateways_HubAndSpokeSkipsSpokeToSpoke" : testCreateMinimumWorkerSliceGatewaysHubAndSpokeSkipsSpokeToSpoke ,
67- "TestCreateMinimumWorkerSliceGateways_IfNotExists" : testCreateMinimumWorkerSliceGatewaysNotExists ,
68- "TestDeleteWorkerSliceGatewaysByLabel_IfExists" : testDeleteWorkerSliceGatewaysByLabelExists ,
69- "TestNodeIpReconciliationOfWorkerSliceGateways_IfExists" : testNodeIpReconciliationOfWorkerSliceGatewaysExists ,
60+ "TestWorkerSliceGatewayReconciliation_Success" : testWorkerSliceGatewayReconciliationSuccess ,
61+ "TestWorkerSliceGatewayReconciliation_IfSliceConfigNotFound" : testWorkerSliceGatewayReconciliationIfSliceConfigNotFound ,
62+ "TestWorkerSliceGatewayReconciliation_IfGatewayNotFound" : testWorkerSliceGatewayReconciliationIfGatewayNotFound ,
63+ "TestWorkerSliceGatewayReconciliation_Delete" : testWorkerSliceGatewayReconciliationDelete ,
64+ "TestWorkerSliceGatewayReconciliation_DeleteForcefully" : testWorkerSliceGatewayReconciliationDeleteForcefully ,
65+ "TestCreateMinimumWorkerSliceGateways_IfAlreadyExists" : testCreateMinimumWorkerSliceGatewaysAlreadyExists ,
66+ "TestCreateMinimumWorkerSliceGateways_HubAndSpokeSkipsSpokeToSpoke" : testCreateMinimumWorkerSliceGatewaysHubAndSpokeSkipsSpokeToSpoke ,
67+ "TestCreateMinimumWorkerSliceGateways_HubAndSpokeCleansUpSpokeToSpoke" : testCreateMinimumWorkerSliceGatewaysHubAndSpokeCleansUpSpokeToSpoke ,
68+ "TestCreateMinimumWorkerSliceGateways_IfNotExists" : testCreateMinimumWorkerSliceGatewaysNotExists ,
69+ "TestDeleteWorkerSliceGatewaysByLabel_IfExists" : testDeleteWorkerSliceGatewaysByLabelExists ,
70+ "TestNodeIpReconciliationOfWorkerSliceGateways_IfExists" : testNodeIpReconciliationOfWorkerSliceGatewaysExists ,
7071}
7172
7273func testWorkerSliceGatewayReconciliationSuccess (t * testing.T ) {
@@ -369,6 +370,69 @@ func testCreateMinimumWorkerSliceGatewaysHubAndSpokeSkipsSpokeToSpoke(t *testing
369370 mMock .AssertExpectations (t )
370371}
371372
373+ // testCreateMinimumWorkerSliceGatewaysHubAndSpokeCleansUpSpokeToSpoke verifies
374+ // that when a slice already has a spoke<->spoke gateway pair (e.g. left over from
375+ // a FullMesh->HubAndSpoke change), cleanup deletes it purely because its edge is
376+ // no longer in the desired hub-and-spoke set. The stale pair is given the CORRECT
377+ // gateway number and both clusters are still slice members, so the ONLY reason it
378+ // gets removed is the topology edge check.
379+ func testCreateMinimumWorkerSliceGatewaysHubAndSpokeCleansUpSpokeToSpoke (t * testing.T ) {
380+ _ , _ , _ , workerSliceGatewayService , requestObj , clientMock , _ , ctx , mMock := setupWorkerSliceGatewayTest ("slice_gateway" , "namespace" )
381+ label := map [string ]string {}
382+ clusterNames := []string {"cluster-1" , "cluster-2" , "cluster-3" }
383+ clusterMap := map [string ]int {
384+ "cluster-1" : 1 ,
385+ "cluster-2" : 2 ,
386+ "cluster-3" : 3 ,
387+ }
388+ topology := & controllerv1alpha1.TopologySpec {
389+ Mode : controllerv1alpha1 .TopologyModeHubAndSpoke ,
390+ Hubs : []string {"cluster-1" },
391+ }
392+ mMock .On ("WithProject" , mock .AnythingOfType ("string" )).Return (& metrics.MetricRecorder {}).Once ()
393+ // existing spoke<->spoke pair (cluster-2 <-> cluster-3) with the CORRECT gateway
394+ // number; both clusters are still members, so it survives the membership and
395+ // number checks and is removed only because its edge is not desired.
396+ spokeToSpokeNumber := ((3 - 1 )* (3 - 2 ))/ 2 + 2 // calculateGatewayNumber(2, 3) = 3
397+ pairWorkerSliceGateway := & workerv1alpha1.WorkerSliceGatewayList {}
398+ clientMock .On ("List" , ctx , pairWorkerSliceGateway , mock .Anything , client .InNamespace (requestObj .Namespace )).Return (nil ).Run (func (args mock.Arguments ) {
399+ arg := args .Get (1 ).(* workerv1alpha1.WorkerSliceGatewayList )
400+ arg .Items = []workerv1alpha1.WorkerSliceGateway {
401+ {
402+ Spec : workerv1alpha1.WorkerSliceGatewaySpec {
403+ LocalGatewayConfig : workerv1alpha1.SliceGatewayConfig {ClusterName : "cluster-2" },
404+ RemoteGatewayConfig : workerv1alpha1.SliceGatewayConfig {ClusterName : "cluster-3" },
405+ GatewayNumber : spokeToSpokeNumber ,
406+ },
407+ },
408+ {
409+ Spec : workerv1alpha1.WorkerSliceGatewaySpec {
410+ LocalGatewayConfig : workerv1alpha1.SliceGatewayConfig {ClusterName : "cluster-3" },
411+ RemoteGatewayConfig : workerv1alpha1.SliceGatewayConfig {ClusterName : "cluster-2" },
412+ GatewayNumber : spokeToSpokeNumber ,
413+ },
414+ },
415+ }
416+ }).Once ()
417+ clientMock .On ("Delete" , ctx , mock .Anything ).Return (nil ).Twice ()
418+ clientMock .On ("Create" , ctx , mock .AnythingOfType ("*v1.Event" )).Return (nil ).Once ()
419+ mMock .On ("RecordCounterMetric" , mock .Anything , mock .Anything ).Return ().Once ()
420+ clientMock .On ("Update" , ctx , mock .AnythingOfType ("*v1.Event" )).Return (nil ).Once ()
421+ mMock .On ("RecordCounterMetric" , mock .Anything , mock .Anything ).Return ().Once ()
422+ // create pass for the two desired hub<->spoke edges: clusters fetched, gateways
423+ // already exist -> nothing created.
424+ cluster := & controllerv1alpha1.Cluster {}
425+ clientMock .On ("Get" , ctx , mock .AnythingOfType ("types.NamespacedName" ), cluster ).Return (nil ).Times (3 )
426+ gateway := & workerv1alpha1.WorkerSliceGateway {}
427+ clientMock .On ("Get" , ctx , mock .AnythingOfType ("types.NamespacedName" ), gateway ).Return (nil ).Times (4 )
428+
429+ result , err := workerSliceGatewayService .CreateMinimumWorkerSliceGateways (ctx , "red" , clusterNames , requestObj .Namespace , label , clusterMap , "10.10.10.10/16" , "/16" , nil , topology )
430+ require .Equal (t , ctrl.Result {}, result )
431+ require .Nil (t , err )
432+ clientMock .AssertExpectations (t )
433+ mMock .AssertExpectations (t )
434+ }
435+
372436func testCreateMinimumWorkerSliceGatewaysNotExists (t * testing.T ) {
373437 _ , _ , jobMock , workerSliceGatewayService , requestObj , clientMock , _ , ctx , mMock := setupWorkerSliceGatewayTest ("slice_gateway" , "namespace" )
374438 label := map [string ]string {
0 commit comments