Repository: provectus/kafka-ui
Issue: Show IP and port of brokers in UI/API
Labels: type/enhancement
good first issue
scope/backend
scope/frontend
status/accepted
status/pending-frontend

Good morning, thank you very much for the great work you are doing.
I just wanted to know if there is a possibility to also show the port of the brokers on the /clusters/clusterName/brokers endpoint.
It would be so useful for scenarios where brokers are added to the cluster with random port mappings, so that you can connect to the brokers by querying the Kafka-UI API first. 
Morover, those same data could be displayed in the UI (/ui/clusters/Local/brokers) along with each broker ID.

Thank you so much.


Issue comments:
Hello there Alepacox! 👋

Thank you and congratulations 🎉 for opening your very first issue in this project! 💖

In case you want to claim this issue, please comment down below! We will try to get back to you as soon as we can. 👀
Hey, thanks for the suggestion. This seems like a good feature, we'll get this implemented :)
I'm glad to hear that, thank you so much!

Pull request review comments:

Patch that resolved the issue:
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/mapper/ConsumerGroupMapper.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/mapper/ConsumerGroupMapper.java
index b821d920cf7..192058449f6 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/mapper/ConsumerGroupMapper.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/mapper/ConsumerGroupMapper.java
@@ -93,7 +93,7 @@ private static <T extends ConsumerGroupDTO> T convertToConsumerGroup(
   }
 
   private static BrokerDTO mapCoordinator(Node node) {
-    return new BrokerDTO().host(node.host()).id(node.id());
+    return new BrokerDTO().host(node.host()).id(node.id()).port(node.port());
   }
 
   private static ConsumerGroupStateDTO mapConsumerGroupState(
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/BrokerService.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/BrokerService.java
index e51d60e2b61..0f5085eb334 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/BrokerService.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/BrokerService.java
@@ -78,6 +78,7 @@ public Flux<BrokerDTO> getBrokers(KafkaCluster cluster) {
               BrokerDTO broker = new BrokerDTO();
               broker.setId(node.id());
               broker.setHost(node.host());
+              broker.setPort(node.port());
               return broker;
             }).collect(Collectors.toList()))
         .flatMapMany(Flux::fromIterable);
diff --git a/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml b/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml
index 277c6d71520..b2d5a685891 100644
--- a/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml
+++ b/kafka-ui-contract/src/main/resources/swagger/kafka-ui-api.yaml
@@ -1910,6 +1910,8 @@ components:
           type: integer
         host:
           type: string
+        port:
+          type: integer
       required:
         - id
 


Test patch:
diff --git a/kafka-ui-api/src/test/java/com/provectus/kafka/ui/service/BrokerServiceTest.java b/kafka-ui-api/src/test/java/com/provectus/kafka/ui/service/BrokerServiceTest.java
new file mode 100644
index 00000000000..816ec61eee3
--- /dev/null
+++ b/kafka-ui-api/src/test/java/com/provectus/kafka/ui/service/BrokerServiceTest.java
@@ -0,0 +1,59 @@
+package com.provectus.kafka.ui.service;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import com.provectus.kafka.ui.AbstractBaseTest;
+import com.provectus.kafka.ui.mapper.ClusterMapperImpl;
+import com.provectus.kafka.ui.mapper.DescribeLogDirsMapper;
+import com.provectus.kafka.ui.model.BrokerDTO;
+import com.provectus.kafka.ui.model.KafkaCluster;
+import java.util.Properties;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.context.ContextConfiguration;
+import reactor.test.StepVerifier;
+
+@ContextConfiguration(initializers = {AbstractBaseTest.Initializer.class})
+class BrokerServiceTest extends AbstractBaseTest {
+  private final KafkaCluster kafkaCluster =
+      KafkaCluster.builder()
+          .name(LOCAL)
+          .bootstrapServers(kafka.getBootstrapServers())
+          .properties(new Properties())
+          .build();
+
+  private BrokerService brokerService;
+
+  @BeforeEach
+  void init() {
+    AdminClientServiceImpl adminClientService = new AdminClientServiceImpl();
+    adminClientService.setClientTimeout(5_000);
+    brokerService =
+        new BrokerService(new MetricsCache(), adminClientService, new DescribeLogDirsMapper(), new ClusterMapperImpl());
+  }
+
+  @Test
+  void getBrokersNominal() {
+    BrokerDTO brokerdto = new BrokerDTO();
+    brokerdto.setId(1);
+    brokerdto.setHost("localhost");
+    String port = kafka.getBootstrapServers().substring(kafka.getBootstrapServers().lastIndexOf(":") + 1);
+    brokerdto.setPort(Integer.parseInt(port));
+
+    StepVerifier.create(brokerService.getBrokers(kafkaCluster))
+        .expectNext(brokerdto)
+        .verifyComplete();
+  }
+
+  @Test
+  void getBrokersNull() {
+    assertThatThrownBy(() -> brokerService.getBrokers(null)).isInstanceOf(NullPointerException.class);
+  }
+
+  @Test
+  void getBrokersEmpty() {
+    assertThatThrownBy(() -> brokerService.getBrokers(KafkaCluster.builder().build())).isInstanceOf(
+        NullPointerException.class);
+  }
+
+}
\ No newline at end of file