11# It's intended to check for reconcile data races.
22import json
33import time
4- from typing import Optional
4+ from typing import List , Optional
55
66import kubernetes .client
77import pytest
8- from kubetester import create_or_update_secret , find_fixture , try_load
8+ from kubetester import create_or_update_configmap , create_or_update_secret , find_fixture , read_service , try_load
99from kubetester .kubetester import KubernetesTester , ensure_ent_version
1010from kubetester .kubetester import fixture as yaml_fixture
1111from kubetester .mongodb import MongoDB
1212from kubetester .mongodb_multi import MongoDBMulti
1313from kubetester .mongodb_user import MongoDBUser
14+ from kubetester .multicluster_client import MultiClusterClient
1415from kubetester .operator import Operator
1516from kubetester .opsmanager import MongoDBOpsManager
1617from kubetester .phase import Phase
1718from tests .conftest import (
1819 get_central_cluster_client ,
1920 get_custom_mdb_version ,
2021 get_member_cluster_names ,
22+ update_coredns_hosts ,
2123)
2224from tests .constants import MULTI_CLUSTER_OPERATOR_NAME , TELEMETRY_CONFIGMAP_NAME
2325from tests .multicluster .conftest import cluster_spec_list
2426
27+ # Global variable to store the external base URL for OM once set up
28+ _om_external_base_url : Optional [str ] = None
29+
2530
2631@pytest .fixture (scope = "module" )
2732def ops_manager (
@@ -35,6 +40,8 @@ def ops_manager(
3540 resource .api = kubernetes .client .CustomObjectsApi (central_cluster_client )
3641 resource .set_version (custom_version )
3742 resource .set_appdb_version (custom_appdb_version )
43+ # Enable external connectivity so member clusters can reach OM
44+ resource ["spec" ]["externalConnectivity" ] = {"type" : "LoadBalancer" }
3845
3946 try_load (resource )
4047 return resource
@@ -71,16 +78,27 @@ def get_replica_set(ops_manager, namespace: str, idx: int) -> MongoDB:
7178
7279
7380def get_mdbmc (ops_manager , namespace : str , idx : int ) -> MongoDBMulti :
81+ global _om_external_base_url
82+
7483 name = f"mdb-{ idx } -mc"
84+ central_client = get_central_cluster_client ()
7585 resource = MongoDBMulti .from_yaml (
7686 yaml_fixture ("mongodb-multi-cluster.yaml" ),
7787 namespace = namespace ,
7888 name = name ,
79- ).configure (ops_manager , name , api_client = get_central_cluster_client () )
89+ ).configure (ops_manager , name , api_client = central_client )
8090 resource .set_version (ensure_ent_version (get_custom_mdb_version ()))
81- resource .api = kubernetes .client .CustomObjectsApi (get_central_cluster_client () )
91+ resource .api = kubernetes .client .CustomObjectsApi (central_client )
8292 resource ["spec" ]["clusterSpecList" ] = cluster_spec_list (get_member_cluster_names (), [1 , 1 , 1 ])
8393
94+ # Update the configmap to use the external base URL so member clusters can reach OM
95+ if _om_external_base_url :
96+ config_map_name = f"{ name } -config"
97+ config_data = KubernetesTester .read_configmap (namespace , config_map_name , api_client = central_client )
98+ config_data ["baseUrl" ] = _om_external_base_url
99+ KubernetesTester .delete_configmap (namespace , config_map_name , api_client = central_client )
100+ create_or_update_configmap (namespace , config_map_name , config_data , api_client = central_client )
101+
84102 try_load (resource )
85103 return resource
86104
@@ -157,6 +175,55 @@ def test_om_ready(ops_manager: MongoDBOpsManager):
157175 ops_manager .om_status ().assert_reaches_phase (Phase .Running , timeout = 1800 )
158176
159177
178+ @pytest .mark .e2e_om_reconcile_race_with_telemetry
179+ def test_setup_om_external_connectivity (
180+ ops_manager : MongoDBOpsManager ,
181+ central_cluster_client : kubernetes .client .ApiClient ,
182+ member_cluster_clients : List [MultiClusterClient ],
183+ ):
184+ """
185+ Set up external connectivity for Ops Manager so that MongoDBMulti pods
186+ in member clusters can reach OM to download the agent binaries.
187+ """
188+ global _om_external_base_url
189+
190+ ops_manager .load ()
191+ external_svc_name = ops_manager .external_svc_name ()
192+ svc = read_service (ops_manager .namespace , external_svc_name , api_client = central_cluster_client )
193+
194+ # Get the external IP from the LoadBalancer service
195+ ip = svc .status .load_balancer .ingress [0 ].ip
196+
197+ # Create the interconnected domain for this OM instance
198+ interconnected_domain = f"om.{ ops_manager .namespace } .interconnected"
199+
200+ # Update CoreDNS in each member cluster to resolve the interconnected domain to the OM external IP
201+ for c in member_cluster_clients :
202+ update_coredns_hosts (
203+ host_mappings = [(ip , interconnected_domain )],
204+ api_client = c .api_client ,
205+ cluster_name = c .cluster_name ,
206+ )
207+
208+ # Also update CoreDNS in the central cluster for consistency
209+ update_coredns_hosts (
210+ host_mappings = [(ip , interconnected_domain )],
211+ api_client = central_cluster_client ,
212+ cluster_name = "central-cluster" ,
213+ )
214+
215+ # Set the external base URL that MongoDBMulti resources will use
216+ _om_external_base_url = f"http://{ interconnected_domain } :8080"
217+
218+ # Update OM's centralUrl to use the external address so agents communicate correctly
219+ ops_manager ["spec" ]["configuration" ] = ops_manager ["spec" ].get ("configuration" , {})
220+ ops_manager ["spec" ]["configuration" ]["mms.centralUrl" ] = _om_external_base_url
221+ ops_manager .update ()
222+
223+ # Wait for OM to reconcile with the new configuration
224+ ops_manager .om_status ().assert_reaches_phase (Phase .Running , timeout = 600 , ignore_errors = True )
225+
226+
160227@pytest .mark .e2e_om_reconcile_race_with_telemetry
161228def test_om2_ready (ops_manager2 : MongoDBOpsManager ):
162229 ops_manager2 .appdb_status ().assert_reaches_phase (Phase .Running , timeout = 1800 )
0 commit comments