diff --git a/pom.xml b/pom.xml
index 506cb01872..c1450b06b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,6 +84,11 @@
org.jenkins-ci.plugins
authentication-tokens
+
+ org.jenkins-ci.plugins
+ cloud-stats
+ 302.v45b_647b_90608
+
@@ -140,6 +145,8 @@
org.jenkins-ci.plugins.workflow
workflow-durable-task-step
+
+
org.jenkins-ci.plugins.workflow
workflow-step-api
diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesComputer.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesComputer.java
index 2355dbc225..c84e2e81e4 100644
--- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesComputer.java
+++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesComputer.java
@@ -1,5 +1,6 @@
package org.csanchez.jenkins.plugins.kubernetes;
+import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.Computer;
import hudson.model.Executor;
@@ -23,6 +24,8 @@
import jenkins.model.Jenkins;
import org.acegisecurity.Authentication;
import org.apache.commons.lang.StringUtils;
+import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
+import org.jenkinsci.plugins.cloudstats.TrackedItem;
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
@@ -34,7 +37,7 @@
/**
* @author Carlos Sanchez carlos@apache.org
*/
-public class KubernetesComputer extends AbstractCloudComputer {
+public class KubernetesComputer extends AbstractCloudComputer implements TrackedItem {
private static final Logger LOGGER = Logger.getLogger(KubernetesComputer.class.getName());
private boolean launching;
@@ -203,4 +206,15 @@ public void setAcceptingTasks(boolean acceptingTasks) {
launching = false;
}
}
+
+ @CheckForNull
+ @Override
+ public ProvisioningActivity.Id getId() {
+ KubernetesSlave slave = getNode();
+ if (slave != null) {
+ return slave.getId();
+ }
+
+ return null;
+ }
}
diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java
index cf59602b5d..0cc5b5b627 100644
--- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java
+++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java
@@ -49,6 +49,8 @@
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention;
+import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
+import org.jenkinsci.plugins.cloudstats.TrackedItem;
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException;
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
@@ -58,7 +60,7 @@
/**
* @author Carlos Sanchez carlos@apache.org
*/
-public class KubernetesSlave extends AbstractCloudSlave {
+public class KubernetesSlave extends AbstractCloudSlave implements TrackedItem {
private static final Logger LOGGER = Logger.getLogger(KubernetesSlave.class.getName());
@@ -85,6 +87,9 @@ public class KubernetesSlave extends AbstractCloudSlave {
@CheckForNull
private transient Pod pod;
+ @NonNull
+ private final ProvisioningActivity.Id id;
+
@NonNull
public PodTemplate getTemplate() throws IllegalStateException {
// Look up updated pod template after a restart
@@ -210,6 +215,7 @@ protected KubernetesSlave(
this.cloudName = cloudName;
this.template = template;
this.podTemplateId = template.getId();
+ this.id = new ProvisioningActivity.Id(cloudName, template.getName(), name);
}
public String getCloudName() {
@@ -450,6 +456,12 @@ private void deleteSlavePod(TaskListener listener, KubernetesClient client) thro
listener.getLogger().println(msg);
}
+ @CheckForNull
+ @Override
+ public ProvisioningActivity.Id getId() {
+ return id;
+ }
+
@Override
public String toString() {
return String.format("KubernetesSlave name: %s", name);
diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/StandardPlannedNodeBuilder.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/StandardPlannedNodeBuilder.java
index f279521532..95cba818ea 100644
--- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/StandardPlannedNodeBuilder.java
+++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/StandardPlannedNodeBuilder.java
@@ -1,10 +1,12 @@
package org.csanchez.jenkins.plugins.kubernetes;
-import hudson.Util;
import hudson.model.Descriptor;
+import hudson.model.Node;
import hudson.slaves.NodeProvisioner;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
+import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
+import org.jenkinsci.plugins.cloudstats.TrackedPlannedNode;
/**
* The default {@link PlannedNodeBuilder} implementation, in case there is other registered.
@@ -14,20 +16,25 @@ public class StandardPlannedNodeBuilder extends PlannedNodeBuilder {
public NodeProvisioner.PlannedNode build() {
KubernetesCloud cloud = getCloud();
PodTemplate t = getTemplate();
- CompletableFuture f;
- String displayName;
+ CompletableFuture f;
+ ProvisioningActivity.Id id = null;
try {
KubernetesSlave agent = KubernetesSlave.builder()
.podTemplate(t.isUnwrapped() ? t : cloud.getUnwrappedTemplate(t))
.cloud(cloud)
.build();
- displayName = agent.getDisplayName();
+ id = agent.getId(); // always use one sourced from the slave we are provisioning so the identity is
+ // maintained
f = CompletableFuture.completedFuture(agent);
} catch (IOException | Descriptor.FormException e) {
- displayName = null;
- f = new CompletableFuture();
+ f = new CompletableFuture<>();
f.completeExceptionally(e);
}
- return new NodeProvisioner.PlannedNode(Util.fixNull(displayName), f, getNumExecutors());
+
+ if (id == null) {
+ id = new ProvisioningActivity.Id(cloud.name, t.getName());
+ }
+
+ return new TrackedPlannedNode(id, getNumExecutors(), f);
}
}
diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlaveTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlaveTest.java
index 3655b7d4c9..87dc773220 100644
--- a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlaveTest.java
+++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlaveTest.java
@@ -38,6 +38,7 @@
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.OnFailure;
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention;
import org.csanchez.jenkins.plugins.kubernetes.volumes.PodVolume;
+import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
@@ -70,6 +71,18 @@ public void testGetSlaveName() {
("jenkins-agent-[0-9a-z]{5}"));
}
+ @Test
+ public void testProvisioningActivityId() throws Descriptor.FormException, IOException {
+ PodTemplate pt = new PodTemplate("x");
+ pt.setName("Template");
+ KubernetesSlave slave = new KubernetesSlave("Node", pt, "bar", "Cloud", "", null, null);
+ ProvisioningActivity.Id id = slave.getId();
+ assertNotNull(id);
+ assertEquals(id.getCloudName(), "Cloud");
+ assertEquals(id.getTemplateName(), "Template");
+ assertEquals(id.getNodeName(), "Node");
+ }
+
@Test
public void testGetPodRetention() {
try {
diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/StandardPlannedNodeBuilderTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/StandardPlannedNodeBuilderTest.java
new file mode 100644
index 0000000000..4e2a8bdb27
--- /dev/null
+++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/StandardPlannedNodeBuilderTest.java
@@ -0,0 +1,36 @@
+package org.csanchez.jenkins.plugins.kubernetes;
+
+import static org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil.assertRegex;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import hudson.slaves.NodeProvisioner;
+import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
+import org.jenkinsci.plugins.cloudstats.TrackedPlannedNode;
+import org.junit.Rule;
+import org.junit.Test;
+import org.jvnet.hudson.test.JenkinsRule;
+
+public class StandardPlannedNodeBuilderTest {
+
+ @Rule
+ public JenkinsRule r = new JenkinsRule();
+
+ @Test
+ public void testBuild() {
+ KubernetesCloud cloud = new KubernetesCloud("Cloud");
+ PodTemplate template = new PodTemplate("t");
+ template.setName("Template");
+ StandardPlannedNodeBuilder builder = new StandardPlannedNodeBuilder();
+ builder.cloud(cloud);
+ builder.template(template);
+ builder.numExecutors(1);
+
+ NodeProvisioner.PlannedNode plannedNode = builder.build();
+ assertTrue(plannedNode instanceof TrackedPlannedNode);
+ ProvisioningActivity.Id id = ((TrackedPlannedNode) plannedNode).getId();
+ assertEquals(id.getCloudName(), "Cloud");
+ assertEquals(id.getTemplateName(), "Template");
+ assertRegex(id.getNodeName(), "template-\\w{5}");
+ }
+}