33import io .fabric8 .kubernetes .api .model .ContainerStatus ;
44import io .fabric8 .kubernetes .api .model .Pod ;
55import io .fabric8 .kubernetes .client .KubernetesClient ;
6+ import io .strimzi .api .kafka .model .kafka .Kafka ;
7+ import io .strimzi .mcp .dto .BootstrapServersResult ;
8+ import io .strimzi .mcp .dto .BootstrapServersResult .BootstrapServerInfo ;
69import io .strimzi .mcp .dto .ClusterPodsResult ;
710import io .strimzi .mcp .dto .KafkaClustersResult ;
811import io .strimzi .mcp .service .StrimziDiscoveryService .KafkaClusterInfo ;
@@ -234,4 +237,95 @@ private Map<String, Integer> calculateComponentBreakdown(List<ClusterPodsResult.
234237 Collectors .collectingAndThen (Collectors .counting (), Math ::toIntExact )
235238 ));
236239 }
240+
241+ /**
242+ * Get bootstrap servers for a Kafka cluster from its Custom Resource.
243+ */
244+ public BootstrapServersResult getBootstrapServers (String namespace , String clusterName ) {
245+ String normalizedNamespace = discoveryService .normalizeNamespace (namespace );
246+ String normalizedClusterName = discoveryService .normalizeClusterName (clusterName );
247+
248+ // Auto-discover namespace if not specified
249+ if (normalizedNamespace == null ) {
250+ List <String > discoveredNamespaces = discoveryService .discoverStrimziNamespaces ();
251+ if (discoveredNamespaces .size () == 1 ) {
252+ normalizedNamespace = discoveredNamespaces .get (0 );
253+ LOG .infof ("Auto-discovered Strimzi in namespace: %s" , normalizedNamespace );
254+ } else if (!discoveredNamespaces .isEmpty ()) {
255+ String namespaceList = String .join (", " , discoveredNamespaces );
256+ return BootstrapServersResult .error (null , normalizedClusterName ,
257+ String .format ("Found Strimzi in multiple namespaces: %s. " +
258+ "Please specify: 'Get bootstrap servers for %s in the %s namespace'" ,
259+ namespaceList , normalizedClusterName , discoveredNamespaces .get (0 )));
260+ } else {
261+ return BootstrapServersResult .error (null , normalizedClusterName ,
262+ "No Strimzi installation found. Please ensure Kafka is deployed." );
263+ }
264+ }
265+
266+ if (normalizedClusterName == null ) {
267+ return BootstrapServersResult .error (normalizedNamespace , null ,
268+ "Cluster name is required. Please specify a cluster name like 'my-cluster'" );
269+ }
270+
271+ LOG .infof ("KafkaClusterService: getBootstrapServers (namespace=%s, cluster=%s)" ,
272+ normalizedNamespace , normalizedClusterName );
273+
274+ try {
275+ Kafka kafka = kubernetesClient .resources (Kafka .class )
276+ .inNamespace (normalizedNamespace )
277+ .withName (normalizedClusterName )
278+ .get ();
279+
280+ if (kafka == null ) {
281+ return BootstrapServersResult .notFound (normalizedNamespace , normalizedClusterName );
282+ }
283+
284+ List <BootstrapServerInfo > bootstrapServers = extractBootstrapServers (kafka );
285+
286+ if (bootstrapServers .isEmpty ()) {
287+ return BootstrapServersResult .empty (normalizedNamespace , normalizedClusterName );
288+ }
289+
290+ return BootstrapServersResult .of (normalizedNamespace , normalizedClusterName , bootstrapServers );
291+
292+ } catch (Exception e ) {
293+ LOG .errorf (e , "Error retrieving bootstrap servers for cluster %s in namespace %s" ,
294+ normalizedClusterName , normalizedNamespace );
295+ return BootstrapServersResult .error (normalizedNamespace , normalizedClusterName , e .getMessage ());
296+ }
297+ }
298+
299+ private List <BootstrapServerInfo > extractBootstrapServers (Kafka kafka ) {
300+ List <BootstrapServerInfo > servers = new ArrayList <>();
301+
302+ if (kafka .getStatus () == null || kafka .getStatus ().getListeners () == null ) {
303+ return servers ;
304+ }
305+
306+ // Extract from listeners status
307+ kafka .getStatus ().getListeners ().forEach (listener -> {
308+ String listenerName = listener .getName ();
309+ String listenerType = listener .getType ();
310+
311+ if (listener .getAddresses () != null ) {
312+ listener .getAddresses ().forEach (address -> {
313+ String host = address .getHost ();
314+ Integer port = address .getPort ();
315+
316+ if (host != null && port != null ) {
317+ servers .add (new BootstrapServerInfo (
318+ host ,
319+ port ,
320+ listenerName ,
321+ listenerType ,
322+ String .format ("%s:%d" , host , port )
323+ ));
324+ }
325+ });
326+ }
327+ });
328+
329+ return servers ;
330+ }
237331}
0 commit comments