@@ -400,6 +400,10 @@ def is_dashboard_ready(self) -> bool:
400400 if dashboard_uri is None :
401401 return False
402402
403+ # Check if dashboard_uri is an error message rather than a valid URL
404+ if not dashboard_uri .startswith (("http://" , "https://" )):
405+ return False
406+
403407 try :
404408 # Don't follow redirects - we want to see the redirect response
405409 # A 302 redirect from OAuth proxy indicates the dashboard is ready
@@ -463,6 +467,7 @@ def wait_ready(self, timeout: Optional[int] = None, dashboard_check: bool = True
463467 time += 5
464468 print ("Requested cluster is up and running!" )
465469
470+ dashboard_wait_logged = False
466471 while dashboard_check :
467472 if timeout and time >= timeout :
468473 raise TimeoutError (
@@ -471,6 +476,15 @@ def wait_ready(self, timeout: Optional[int] = None, dashboard_check: bool = True
471476 if self .is_dashboard_ready ():
472477 print ("Dashboard is ready!" )
473478 break
479+ if not dashboard_wait_logged :
480+ dashboard_uri = self .cluster_dashboard_uri ()
481+ if not dashboard_uri .startswith (("http://" , "https://" )):
482+ print (f"Waiting for dashboard route/HTTPRoute to be created..." )
483+ else :
484+ print (
485+ f"Waiting for dashboard to become accessible: { dashboard_uri } "
486+ )
487+ dashboard_wait_logged = True
474488 sleep (5 )
475489 time += 5
476490
@@ -1191,11 +1205,12 @@ def _get_dashboard_url_from_httproute(
11911205 if items :
11921206 httproute = items [0 ]
11931207 else :
1194- # No HTTPRoute found
11951208 return None
11961209 except Exception :
11971210 # No cluster-wide permissions, try namespace-specific search
1211+ # Include the cluster's namespace first, then platform namespaces
11981212 search_namespaces = [
1213+ namespace , # The cluster's own namespace
11991214 "redhat-ods-applications" ,
12001215 "opendatahub" ,
12011216 "default" ,
@@ -1220,7 +1235,6 @@ def _get_dashboard_url_from_httproute(
12201235 continue
12211236
12221237 if not httproute :
1223- # No HTTPRoute found
12241238 return None
12251239
12261240 # Extract Gateway reference and construct dashboard URL
@@ -1244,11 +1258,43 @@ def _get_dashboard_url_from_httproute(
12441258 name = gateway_name ,
12451259 )
12461260
1261+ # Try to get hostname from multiple locations:
1262+ # 1. spec.listeners[].hostname (standard Gateway API)
1263+ # 2. OpenShift Route that exposes the Gateway (external access)
1264+ # 3. status.addresses[].value (internal service address - fallback)
1265+ hostname = None
1266+
1267+ # First try spec.listeners[].hostname
12471268 listeners = gateway .get ("spec" , {}).get ("listeners" , [])
1248- if not listeners :
1249- return None
1269+ if listeners :
1270+ hostname = listeners [0 ].get ("hostname" )
1271+
1272+ # If no hostname in listeners, try to find OpenShift Route exposing the Gateway
1273+ if not hostname :
1274+ try :
1275+ routes = api_instance .list_namespaced_custom_object (
1276+ group = "route.openshift.io" ,
1277+ version = "v1" ,
1278+ namespace = gateway_namespace ,
1279+ plural = "routes" ,
1280+ )
1281+ for route in routes .get ("items" , []):
1282+ # Look for a route that matches the gateway name
1283+ if route ["metadata" ]["name" ] == gateway_name :
1284+ hostname = route .get ("spec" , {}).get ("host" )
1285+ break
1286+ except Exception :
1287+ pass # Continue to next fallback
1288+
1289+ # If still no hostname, try status.addresses (internal address - may only work in-cluster)
1290+ if not hostname :
1291+ addresses = gateway .get ("status" , {}).get ("addresses" , [])
1292+ if addresses :
1293+ addr_value = addresses [0 ].get ("value" )
1294+ # Skip internal cluster DNS names for external access
1295+ if addr_value and not addr_value .endswith (".svc.cluster.local" ):
1296+ hostname = addr_value
12501297
1251- hostname = listeners [0 ].get ("hostname" )
12521298 if not hostname :
12531299 return None
12541300
0 commit comments