@@ -134,10 +134,11 @@ func TestMultigresClusterReconciler_Reconcile_Success(t *testing.T) {
134134 coreTpl , cellTpl , shardTpl , baseCluster , clusterName , namespace , finalizerName := setupFixtures ()
135135
136136 tests := map [string ]struct {
137- multigrescluster * multigresv1alpha1.MultigresCluster
138- existingObjects []client.Object
139- preReconcileUpdate func (testing.TB , * multigresv1alpha1.MultigresCluster )
140- validate func (testing.TB , client.Client )
137+ multigrescluster * multigresv1alpha1.MultigresCluster
138+ existingObjects []client.Object
139+ preReconcileUpdate func (testing.TB , * multigresv1alpha1.MultigresCluster )
140+ skipClusterCreation bool
141+ validate func (testing.TB , client.Client )
141142 }{
142143 "Create: Adds Finalizer" : {
143144 preReconcileUpdate : func (t testing.TB , c * multigresv1alpha1.MultigresCluster ) {
@@ -412,7 +413,7 @@ func TestMultigresClusterReconciler_Reconcile_Success(t *testing.T) {
412413 },
413414 }
414415 },
415- // Using defaults
416+ existingObjects : []client. Object { coreTpl , cellTpl , shardTpl },
416417 validate : func (t testing.TB , c client.Client ) {
417418 ctx := t .Context ()
418419 cell := & multigresv1alpha1.Cell {}
@@ -446,6 +447,22 @@ func TestMultigresClusterReconciler_Reconcile_Success(t *testing.T) {
446447 }
447448 },
448449 },
450+ "Create: No Global Topo Config" : {
451+ preReconcileUpdate : func (t testing.TB , c * multigresv1alpha1.MultigresCluster ) {
452+ c .Spec .GlobalTopoServer = multigresv1alpha1.GlobalTopoServerSpec {} // Empty
453+ c .Spec .TemplateDefaults = multigresv1alpha1.TemplateDefaults {} // Empty
454+ c .Spec .MultiAdmin = multigresv1alpha1.MultiAdminConfig {} // Empty
455+ },
456+ // Using defaults (coreTpl presence doesn't hurt)
457+ validate : func (t testing.TB , c client.Client ) {
458+ // Verify Cell got empty topo address
459+ cell := & multigresv1alpha1.Cell {}
460+ _ = c .Get (t .Context (), types.NamespacedName {Name : clusterName + "-zone-a" , Namespace : namespace }, cell )
461+ if got , want := cell .Spec .GlobalTopoServer .Address , "" ; got != want {
462+ t .Errorf ("Expected empty topo address mismatch got %q, want %q" , got , want )
463+ }
464+ },
465+ },
449466 "Status: Aggregation Logic" : {
450467 preReconcileUpdate : func (t testing.TB , c * multigresv1alpha1.MultigresCluster ) {
451468 c .Spec .Databases = append (c .Spec .Databases , multigresv1alpha1.DatabaseConfig {Name : "db2" , TableGroups : []multigresv1alpha1.TableGroupConfig {}})
@@ -490,7 +507,8 @@ func TestMultigresClusterReconciler_Reconcile_Success(t *testing.T) {
490507 },
491508 },
492509 "Object Not Found (Clean Exit)" : {
493- existingObjects : []client.Object {},
510+ skipClusterCreation : true ,
511+ existingObjects : []client.Object {},
494512 },
495513 }
496514
@@ -504,14 +522,6 @@ func TestMultigresClusterReconciler_Reconcile_Success(t *testing.T) {
504522 objects = []client.Object {coreTpl , cellTpl , shardTpl }
505523 }
506524
507- clientBuilder := fake .NewClientBuilder ().
508- WithScheme (scheme ).
509- WithObjects (objects ... ).
510- WithStatusSubresource (& multigresv1alpha1.MultigresCluster {}, & multigresv1alpha1.Cell {}, & multigresv1alpha1.TableGroup {})
511- baseClient := clientBuilder .Build ()
512-
513- finalClient := baseClient
514-
515525 // Apply defaults if no specific cluster is provided
516526 cluster := tc .multigrescluster
517527 if cluster == nil {
@@ -523,39 +533,18 @@ func TestMultigresClusterReconciler_Reconcile_Success(t *testing.T) {
523533 tc .preReconcileUpdate (t , cluster )
524534 }
525535
526- // Capture if deletion is intended BEFORE calling Create,
527- // because Create strips DeletionTimestamp from the local struct in some client implementations (or API logic mimics it).
528- shouldDelete := false
529- if cluster .GetDeletionTimestamp () != nil && ! cluster .GetDeletionTimestamp ().IsZero () {
530- shouldDelete = true
536+ // Inject cluster into existingObjects if creation is not skipped
537+ if ! tc .skipClusterCreation {
538+ objects = append (objects , cluster )
531539 }
532540
533- if ! strings .Contains (name , "Object Not Found" ) {
534- check := & multigresv1alpha1.MultigresCluster {}
535- err := baseClient .Get (t .Context (), types.NamespacedName {Name : cluster .Name , Namespace : cluster .Namespace }, check )
536- if apierrors .IsNotFound (err ) {
537- if err := baseClient .Create (t .Context (), cluster ); err != nil {
538- t .Fatalf ("failed to create initial cluster: %v" , err )
539- }
541+ clientBuilder := fake .NewClientBuilder ().
542+ WithScheme (scheme ).
543+ WithObjects (objects ... ).
544+ WithStatusSubresource (& multigresv1alpha1.MultigresCluster {}, & multigresv1alpha1.Cell {}, & multigresv1alpha1.TableGroup {})
545+ baseClient := clientBuilder .Build ()
540546
541- // Ensure DeletionTimestamp is set in the API if the test requires it.
542- // client.Create strips this field, so we must invoke Delete() to re-apply it.
543- if shouldDelete {
544- // 1. Refresh object to avoid ResourceVersion conflict
545- if err := baseClient .Get (t .Context (), types.NamespacedName {Name : cluster .Name , Namespace : cluster .Namespace }, cluster ); err != nil {
546- t .Fatalf ("failed to refresh cluster before delete: %v" , err )
547- }
548- // 2. Delete it
549- if err := baseClient .Delete (t .Context (), cluster ); err != nil {
550- t .Fatalf ("failed to set deletion timestamp: %v" , err )
551- }
552- // 3. Refresh again to ensure the controller sees the deletion timestamp
553- if err := baseClient .Get (t .Context (), types.NamespacedName {Name : cluster .Name , Namespace : cluster .Namespace }, cluster ); err != nil {
554- t .Fatalf ("failed to refresh cluster after deletion: %v" , err )
555- }
556- }
557- }
558- }
547+ finalClient := baseClient
559548
560549 reconciler := & MultigresClusterReconciler {
561550 Client : finalClient ,
@@ -594,11 +583,12 @@ func TestMultigresClusterReconciler_Reconcile_Failure(t *testing.T) {
594583 errBoom := errors .New ("boom" )
595584
596585 tests := map [string ]struct {
597- multigrescluster * multigresv1alpha1.MultigresCluster
598- existingObjects []client.Object
599- failureConfig * testutil.FailureConfig
600- preReconcileUpdate func (testing.TB , * multigresv1alpha1.MultigresCluster )
601- validate func (testing.TB , client.Client )
586+ multigrescluster * multigresv1alpha1.MultigresCluster
587+ existingObjects []client.Object
588+ failureConfig * testutil.FailureConfig
589+ preReconcileUpdate func (testing.TB , * multigresv1alpha1.MultigresCluster )
590+ skipClusterCreation bool
591+ validate func (testing.TB , client.Client )
602592 }{
603593 "Delete: Block Finalization if Cells Exist" : {
604594 preReconcileUpdate : func (t testing.TB , c * multigresv1alpha1.MultigresCluster ) {
@@ -918,21 +908,6 @@ func TestMultigresClusterReconciler_Reconcile_Failure(t *testing.T) {
918908 objects = []client.Object {coreTpl , cellTpl , shardTpl }
919909 }
920910
921- clientBuilder := fake .NewClientBuilder ().
922- WithScheme (scheme ).
923- WithObjects (objects ... ).
924- WithStatusSubresource (& multigresv1alpha1.MultigresCluster {}, & multigresv1alpha1.Cell {}, & multigresv1alpha1.TableGroup {})
925- baseClient := clientBuilder .Build ()
926-
927- var finalClient client.Client
928- finalClient = baseClient
929- if tc .failureConfig != nil {
930- finalClient = testutil .NewFakeClientWithFailures (baseClient , tc .failureConfig )
931- }
932- // In Failure tests, finalClient is assigned a new value (the wrapper), so we explicitly cast baseClient
933- // to client.Client interface if needed, or rely on type compatibility.
934- // Since failureConfig wrapper implements client.Client, we assign it.
935-
936911 // Apply defaults if no specific cluster is provided
937912 cluster := tc .multigrescluster
938913 if cluster == nil {
@@ -944,38 +919,23 @@ func TestMultigresClusterReconciler_Reconcile_Failure(t *testing.T) {
944919 tc .preReconcileUpdate (t , cluster )
945920 }
946921
947- // Capture if deletion is intended BEFORE calling Create,
948- // because Create strips DeletionTimestamp from the local struct in some client implementations (or API logic mimics it).
949- shouldDelete := false
950- if cluster . GetDeletionTimestamp () != nil && ! cluster . GetDeletionTimestamp (). IsZero () {
951- shouldDelete = true
922+ // Inject cluster into existingObjects if creation is not skipped
923+ // This handles initializing the fake client with the cluster state,
924+ // including DeletionTimestamp if set by preReconcileUpdate.
925+ if ! tc . skipClusterCreation {
926+ objects = append ( objects , cluster )
952927 }
953928
954- if ! strings .Contains (name , "Object Not Found" ) {
955- check := & multigresv1alpha1.MultigresCluster {}
956- err := baseClient .Get (t .Context (), types.NamespacedName {Name : cluster .Name , Namespace : cluster .Namespace }, check )
957- if apierrors .IsNotFound (err ) {
958- if err := baseClient .Create (t .Context (), cluster ); err != nil {
959- t .Fatalf ("failed to create initial cluster: %v" , err )
960- }
929+ clientBuilder := fake .NewClientBuilder ().
930+ WithScheme (scheme ).
931+ WithObjects (objects ... ).
932+ WithStatusSubresource (& multigresv1alpha1.MultigresCluster {}, & multigresv1alpha1.Cell {}, & multigresv1alpha1.TableGroup {})
933+ baseClient := clientBuilder .Build ()
961934
962- // Ensure DeletionTimestamp is set in the API if the test requires it.
963- // client.Create strips this field, so we must invoke Delete() to re-apply it.
964- if shouldDelete {
965- // 1. Refresh object to avoid ResourceVersion conflict
966- if err := baseClient .Get (t .Context (), types.NamespacedName {Name : cluster .Name , Namespace : cluster .Namespace }, cluster ); err != nil {
967- t .Fatalf ("failed to refresh cluster before delete: %v" , err )
968- }
969- // 2. Delete it
970- if err := baseClient .Delete (t .Context (), cluster ); err != nil {
971- t .Fatalf ("failed to set deletion timestamp: %v" , err )
972- }
973- // 3. Refresh again to ensure the controller sees the deletion timestamp
974- if err := baseClient .Get (t .Context (), types.NamespacedName {Name : cluster .Name , Namespace : cluster .Namespace }, cluster ); err != nil {
975- t .Fatalf ("failed to refresh cluster after deletion: %v" , err )
976- }
977- }
978- }
935+ var finalClient client.Client
936+ finalClient = client .Client (baseClient )
937+ if tc .failureConfig != nil {
938+ finalClient = testutil .NewFakeClientWithFailures (baseClient , tc .failureConfig )
979939 }
980940
981941 reconciler := & MultigresClusterReconciler {
0 commit comments