This is an automated email from the ASF dual-hosted git repository.

cryptoe pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new cec7f0cf0b3 feat: Add endpoint to fetch configured peon pod template 
names (#19712)
cec7f0cf0b3 is described below

commit cec7f0cf0b3b98262af707d8899692599c019fa7
Author: Armanit Garg <[email protected]>
AuthorDate: Tue Jul 21 22:50:27 2026 +0530

    feat: Add endpoint to fetch configured peon pod template names (#19712)
    
    * feat: Add endpoint to fetch configured peon pod template specs
    
    * only return names, not specs
---
 docs/development/extensions-core/k8s-jobs.md       | 69 +++++++++++++++++++
 .../k8s/overlord/KubernetesOverlordModule.java     |  2 +
 .../KubernetesTaskRunnerPodTemplateResource.java   | 77 ++++++++++++++++++++++
 .../DynamicConfigPodTemplateSelector.java          | 11 ++++
 .../overlord/taskadapter/PodTemplateSelector.java  |  8 +++
 .../taskadapter/PodTemplateTaskAdapter.java        |  5 ++
 ...ubernetesTaskRunnerPodTemplateResourceTest.java | 62 +++++++++++++++++
 .../DynamicConfigPodTemplateSelectorTest.java      | 21 ++++++
 .../taskadapter/TestPodTemplateSelector.java       |  9 +++
 9 files changed, 264 insertions(+)

diff --git a/docs/development/extensions-core/k8s-jobs.md 
b/docs/development/extensions-core/k8s-jobs.md
index 448309a87fd..8ba0e215922 100644
--- a/docs/development/extensions-core/k8s-jobs.md
+++ b/docs/development/extensions-core/k8s-jobs.md
@@ -344,6 +344,75 @@ Host: http://ROUTER_IP:ROUTER_PORT
 ```
 </details>
 
+#### Get pod template names
+
+Retrieves the names of the peon pod templates currently configured on the 
Overlord for the Kubernetes
+task runner. Returns a JSON array of the configured template names (the keys 
of the
+`druid.indexer.runner.k8s.podTemplate.*` runtime properties, such as `base` 
and per task type names).
+
+This endpoint is only available when the [Custom Template Pod 
Adapter](#custom-template-pod-adapter) is
+configured (`druid.indexer.runner.k8s.adapter.type: customTemplateAdapter`). 
For any other adapter it
+returns a `404` response.
+
+##### URL
+
+`GET` `/druid/indexer/v1/k8s/taskrunner/podTemplates`
+
+##### Responses
+
+<Tabs>
+
+<TabItem value="13" label="200 SUCCESS">
+
+
+*Successfully retrieved pod template names*
+
+</TabItem>
+
+<TabItem value="14" label="404 NOT FOUND">
+
+
+*The configured pod adapter is not the custom template pod adapter*
+
+</TabItem>
+</Tabs>
+
+---
+
+##### Sample request
+
+<Tabs>
+
+<TabItem value="15" label="cURL">
+
+```shell
+curl 
"http://ROUTER_IP:ROUTER_PORT/druid/indexer/v1/k8s/taskrunner/podTemplates";
+```
+</TabItem>
+
+<TabItem value="16" label="HTTP">
+
+```HTTP
+GET /druid/indexer/v1/k8s/taskrunner/podTemplates HTTP/1.1
+Host: http://ROUTER_IP:ROUTER_PORT
+```
+
+</TabItem>
+</Tabs>
+
+##### Sample response
+
+<details>
+<summary>View the response</summary>
+
+```json
+[
+  "base",
+  "index_kafka"
+]
+```
+</details>
+
 ## Pod adapters
 The logic defining how the pod template is built for your Kubernetes Job 
depends on which pod adapter you have specified.
 
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesOverlordModule.java
 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesOverlordModule.java
index b45aa6fb846..8271fcfb723 100644
--- 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesOverlordModule.java
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/KubernetesOverlordModule.java
@@ -64,6 +64,7 @@ import 
org.apache.druid.k8s.overlord.common.httpclient.vertx.DruidKubernetesVert
 import 
org.apache.druid.k8s.overlord.common.httpclient.vertx.DruidKubernetesVertxHttpClientFactory;
 import 
org.apache.druid.k8s.overlord.execution.KubernetesTaskExecutionConfigResource;
 import 
org.apache.druid.k8s.overlord.execution.KubernetesTaskRunnerDynamicConfig;
+import 
org.apache.druid.k8s.overlord.execution.KubernetesTaskRunnerPodTemplateResource;
 import org.apache.druid.k8s.overlord.runnerstrategy.RunnerStrategy;
 import 
org.apache.druid.k8s.overlord.taskadapter.DynamicConfigPodTemplateSelector;
 import org.apache.druid.k8s.overlord.taskadapter.MultiContainerTaskAdapter;
@@ -129,6 +130,7 @@ public class KubernetesOverlordModule implements DruidModule
           .in(LazySingleton.class);
 
     Jerseys.addResource(binder, KubernetesTaskExecutionConfigResource.class);
+    Jerseys.addResource(binder, KubernetesTaskRunnerPodTemplateResource.class);
 
     PolyBind.createChoiceWithDefault(
         binder,
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/execution/KubernetesTaskRunnerPodTemplateResource.java
 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/execution/KubernetesTaskRunnerPodTemplateResource.java
new file mode 100644
index 00000000000..d34413f58a5
--- /dev/null
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/execution/KubernetesTaskRunnerPodTemplateResource.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.k8s.overlord.execution;
+
+import com.sun.jersey.spi.container.ResourceFilters;
+import org.apache.druid.error.DruidException;
+import org.apache.druid.k8s.overlord.taskadapter.PodTemplateTaskAdapter;
+import org.apache.druid.k8s.overlord.taskadapter.TaskAdapter;
+import org.apache.druid.server.http.ServletResourceUtils;
+import org.apache.druid.server.http.security.ConfigResourceFilter;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Resource that exposes the names of the pod templates currently configured 
for running peons in
+ * Kubernetes.
+ *
+ * <p>Pod templates only exist for the pod template adapter 
("customTemplateAdapter"). For any other
+ * adapter this endpoint returns a 404.</p>
+ */
+@Path("/druid/indexer/v1/k8s/taskrunner/podTemplates")
+public class KubernetesTaskRunnerPodTemplateResource
+{
+  private final TaskAdapter taskAdapter;
+
+  @Inject
+  public KubernetesTaskRunnerPodTemplateResource(final TaskAdapter taskAdapter)
+  {
+    this.taskAdapter = taskAdapter;
+  }
+
+  /**
+   * Retrieves the names of the currently configured peon pod templates.
+   *
+   * @return a Response with the configured template names (200), or 404 when 
the configured adapter
+   *         has no pod templates.
+   */
+  @GET
+  @Produces(MediaType.APPLICATION_JSON)
+  @ResourceFilters(ConfigResourceFilter.class)
+  public Response getPodTemplateNames()
+  {
+    if (!(taskAdapter instanceof PodTemplateTaskAdapter)) {
+      return ServletResourceUtils.buildErrorResponseFrom(
+          DruidException.forPersona(DruidException.Persona.OPERATOR)
+                        .ofCategory(DruidException.Category.NOT_FOUND)
+                        .build(
+                            "Pod templates are only available when the k8s 
task adapter type is [%s]",
+                            PodTemplateTaskAdapter.TYPE
+                        )
+      );
+    }
+    return Response.ok(((PodTemplateTaskAdapter) 
taskAdapter).getPodTemplateSelector().getPodTemplateNames()).build();
+  }
+}
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelector.java
 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelector.java
index 735eaf1dc5d..3ee10ae260b 100644
--- 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelector.java
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelector.java
@@ -32,8 +32,11 @@ import 
org.apache.druid.k8s.overlord.common.DruidK8sConstants;
 
 import java.io.File;
 import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Properties;
 import java.util.Set;
 
@@ -144,4 +147,12 @@ public class DynamicConfigPodTemplateSelector implements 
PodTemplateSelector
 
     return 
Optional.of(effectiveConfig.getPodTemplateSelectStrategy().getPodTemplateForTask(task,
 podTemplates));
   }
+
+  @Override
+  public List<String> getPodTemplateNames()
+  {
+    List<String> names = new ArrayList<>(podTemplates.keySet());
+    Collections.sort(names);
+    return names;
+  }
 }
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateSelector.java
 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateSelector.java
index 7795fe1eed4..e7f1a29ad26 100644
--- 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateSelector.java
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateSelector.java
@@ -22,6 +22,8 @@ package org.apache.druid.k8s.overlord.taskadapter;
 import com.google.common.base.Optional;
 import org.apache.druid.indexing.common.task.Task;
 
+import java.util.List;
+
 /**
  * Interface for selecting a Pod template based on a given task.
  * Implementations of this interface are responsible for determining the 
appropriate
@@ -37,4 +39,10 @@ public interface PodTemplateSelector
    *         is available for the given task.
    */
   Optional<PodTemplateWithName> getPodTemplateForTask(Task task);
+
+  /**
+   * Returns the names of all currently configured pod templates.
+   * @return the configured template names.
+   */
+  List<String> getPodTemplateNames();
 }
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateTaskAdapter.java
 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateTaskAdapter.java
index 0ad3385ca21..b7976e1dab3 100644
--- 
a/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateTaskAdapter.java
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/main/java/org/apache/druid/k8s/overlord/taskadapter/PodTemplateTaskAdapter.java
@@ -103,6 +103,11 @@ public class PodTemplateTaskAdapter implements TaskAdapter
     return TYPE;
   }
 
+  public PodTemplateSelector getPodTemplateSelector()
+  {
+    return podTemplateSelector;
+  }
+
   /**
    * Create a {@link Job} from a {@link Task}
    *
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/execution/KubernetesTaskRunnerPodTemplateResourceTest.java
 
b/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/execution/KubernetesTaskRunnerPodTemplateResourceTest.java
new file mode 100644
index 00000000000..b24cadfcaaf
--- /dev/null
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/execution/KubernetesTaskRunnerPodTemplateResourceTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.k8s.overlord.execution;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.druid.k8s.overlord.taskadapter.PodTemplateSelector;
+import org.apache.druid.k8s.overlord.taskadapter.PodTemplateTaskAdapter;
+import org.apache.druid.k8s.overlord.taskadapter.TaskAdapter;
+import org.easymock.EasyMock;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+public class KubernetesTaskRunnerPodTemplateResourceTest
+{
+  @Test
+  public void test_getPodTemplateNames_returnsConfiguredTemplateNames()
+  {
+    List<String> names = ImmutableList.of("base", "index_kafka");
+
+    PodTemplateSelector selector = 
EasyMock.createMock(PodTemplateSelector.class);
+    EasyMock.expect(selector.getPodTemplateNames()).andReturn(names);
+    PodTemplateTaskAdapter adapter = 
EasyMock.createMock(PodTemplateTaskAdapter.class);
+    EasyMock.expect(adapter.getPodTemplateSelector()).andReturn(selector);
+    EasyMock.replay(selector, adapter);
+
+    Response result = new 
KubernetesTaskRunnerPodTemplateResource(adapter).getPodTemplateNames();
+
+    Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
result.getStatus());
+    Assertions.assertEquals(names, result.getEntity());
+  }
+
+  @Test
+  public void 
test_getPodTemplateNames_whenAdapterIsNotPodTemplateAdapter_returnsNotFound()
+  {
+    TaskAdapter adapter = EasyMock.createMock(TaskAdapter.class);
+    EasyMock.replay(adapter);
+
+    Response result = new 
KubernetesTaskRunnerPodTemplateResource(adapter).getPodTemplateNames();
+
+    Assertions.assertEquals(Response.Status.NOT_FOUND.getStatusCode(), 
result.getStatus());
+  }
+}
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelectorTest.java
 
b/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelectorTest.java
index fbd0691efda..3c80f414516 100644
--- 
a/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelectorTest.java
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/DynamicConfigPodTemplateSelectorTest.java
@@ -49,6 +49,8 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Properties;
 
 public class DynamicConfigPodTemplateSelectorTest
@@ -186,6 +188,25 @@ public class DynamicConfigPodTemplateSelectorTest
     Assertions.assertEquals("base", podTemplateWithName.get().getName());
   }
 
+  @Test
+  public void test_getPodTemplateNames() throws IOException
+  {
+    Path baseTemplatePath = Files.createFile(tempDir.resolve("base.yaml"));
+    mapper.writeValue(baseTemplatePath.toFile(), podTemplateSpec);
+
+    Path kafkaTemplatePath = Files.createFile(tempDir.resolve("kafka.yaml"));
+    mapper.writeValue(kafkaTemplatePath.toFile(), podTemplateSpec);
+
+    Properties props = new Properties();
+    props.setProperty("druid.indexer.runner.k8s.podTemplate.base", 
baseTemplatePath.toString());
+    props.setProperty("druid.indexer.runner.k8s.podTemplate.index_kafka", 
kafkaTemplatePath.toString());
+
+    DynamicConfigPodTemplateSelector selector = new 
DynamicConfigPodTemplateSelector(props, effectiveConfig);
+
+    List<String> names = selector.getPodTemplateNames();
+    Assertions.assertEquals(Sets.newSet("base", "index_kafka"), new 
HashSet<>(names));
+  }
+
   @Test
   public void 
test_fromTask_withNoopPodTemplateInRuntimeProperties_withEmptyFile_raisesIAE() 
throws IOException
   {
diff --git 
a/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/TestPodTemplateSelector.java
 
b/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/TestPodTemplateSelector.java
index 4c12c16f32b..02fd05b0b0b 100644
--- 
a/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/TestPodTemplateSelector.java
+++ 
b/extensions-core/kubernetes-overlord-extensions/src/test/java/org/apache/druid/k8s/overlord/taskadapter/TestPodTemplateSelector.java
@@ -23,6 +23,9 @@ import com.google.common.base.Optional;
 import io.fabric8.kubernetes.api.model.PodTemplate;
 import org.apache.druid.indexing.common.task.Task;
 
+import java.util.Collections;
+import java.util.List;
+
 public class TestPodTemplateSelector implements PodTemplateSelector
 {
 
@@ -38,4 +41,10 @@ public class TestPodTemplateSelector implements 
PodTemplateSelector
   {
     return Optional.of(new PodTemplateWithName("base", basePodTemplate));
   }
+
+  @Override
+  public List<String> getPodTemplateNames()
+  {
+    return Collections.singletonList("base");
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to