Skip to content

Commit 6ec3953

Browse files
committed
[JENKINS-67256] Integrate with Cloud Statistics plugin
Implement TrackedItem on KubernetesComputer and KubernetesSlave. StandardPlannedNodeBuilder now returns a TrackedPlannedNode.
1 parent cf86a59 commit 6ec3953

File tree

6 files changed

+95
-9
lines changed

6 files changed

+95
-9
lines changed

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@
137137
<groupId>org.jenkins-ci.plugins.workflow</groupId>
138138
<artifactId>workflow-durable-task-step</artifactId>
139139
</dependency>
140+
<dependency>
141+
<groupId>org.jenkins-ci.plugins</groupId>
142+
<artifactId>cloud-stats</artifactId>
143+
<version>302.v45b_647b_90608</version>
144+
</dependency>
140145

141146
<!-- for testing -->
142147
<dependency>

src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesComputer.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.csanchez.jenkins.plugins.kubernetes;
22

3+
import edu.umd.cs.findbugs.annotations.CheckForNull;
34
import hudson.model.Computer;
45
import hudson.model.Executor;
56
import hudson.model.Queue;
@@ -15,6 +16,8 @@
1516
import jenkins.model.Jenkins;
1617
import org.acegisecurity.Authentication;
1718
import org.apache.commons.lang.StringUtils;
19+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
20+
import org.jenkinsci.plugins.cloudstats.TrackedItem;
1821
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException;
1922
import org.kohsuke.stapler.QueryParameter;
2023
import org.kohsuke.stapler.StaplerRequest;
@@ -34,7 +37,7 @@
3437
/**
3538
* @author Carlos Sanchez [email protected]
3639
*/
37-
public class KubernetesComputer extends AbstractCloudComputer<KubernetesSlave> {
40+
public class KubernetesComputer extends AbstractCloudComputer<KubernetesSlave> implements TrackedItem {
3841
private static final Logger LOGGER = Logger.getLogger(KubernetesComputer.class.getName());
3942

4043
private boolean launching;
@@ -180,4 +183,15 @@ public void setAcceptingTasks(boolean acceptingTasks) {
180183
launching = false;
181184
}
182185
}
186+
187+
@CheckForNull
188+
@Override
189+
public ProvisioningActivity.Id getId() {
190+
KubernetesSlave slave = getNode();
191+
if (slave != null) {
192+
return slave.getId();
193+
}
194+
195+
return null;
196+
}
183197
}

src/main/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlave.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import org.apache.commons.lang.StringUtils;
2525
import org.apache.commons.lang.Validate;
2626
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention;
27+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
28+
import org.jenkinsci.plugins.cloudstats.TrackedItem;
2729
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
2830
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException;
2931
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
@@ -58,7 +60,7 @@
5860
/**
5961
* @author Carlos Sanchez [email protected]
6062
*/
61-
public class KubernetesSlave extends AbstractCloudSlave {
63+
public class KubernetesSlave extends AbstractCloudSlave implements TrackedItem {
6264

6365
private static final Logger LOGGER = Logger.getLogger(KubernetesSlave.class.getName());
6466

@@ -83,6 +85,9 @@ public class KubernetesSlave extends AbstractCloudSlave {
8385
@CheckForNull
8486
private transient Pod pod;
8587

88+
@NonNull
89+
private final ProvisioningActivity.Id id;
90+
8691
@NonNull
8792
public PodTemplate getTemplate() throws IllegalStateException {
8893
// Look up updated pod template after a restart
@@ -195,6 +200,7 @@ protected KubernetesSlave(String name, @NonNull PodTemplate template, String nod
195200
this.cloudName = cloudName;
196201
this.template = template;
197202
this.podTemplateId = template.getId();
203+
this.id = new ProvisioningActivity.Id(cloudName, template.getName(), name);
198204
}
199205

200206
public String getCloudName() {
@@ -409,6 +415,12 @@ private void deleteSlavePod(TaskListener listener, KubernetesClient client) thro
409415
listener.getLogger().println(msg);
410416
}
411417

418+
@CheckForNull
419+
@Override
420+
public ProvisioningActivity.Id getId() {
421+
return id;
422+
}
423+
412424
@Override
413425
public String toString() {
414426
return String.format("KubernetesSlave name: %s", name);
Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package org.csanchez.jenkins.plugins.kubernetes;
22

3-
import hudson.Util;
43
import hudson.model.Descriptor;
4+
import hudson.model.Node;
55
import hudson.slaves.NodeProvisioner;
6+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
7+
import org.jenkinsci.plugins.cloudstats.TrackedPlannedNode;
68

79
import java.io.IOException;
810
import java.util.concurrent.CompletableFuture;
@@ -15,21 +17,25 @@ public class StandardPlannedNodeBuilder extends PlannedNodeBuilder {
1517
public NodeProvisioner.PlannedNode build() {
1618
KubernetesCloud cloud = getCloud();
1719
PodTemplate t = getTemplate();
18-
CompletableFuture f;
19-
String displayName;
20+
CompletableFuture<Node> f;
21+
ProvisioningActivity.Id id = null;
2022
try {
2123
KubernetesSlave agent = KubernetesSlave
2224
.builder()
2325
.podTemplate(t.isUnwrapped() ? t : cloud.getUnwrappedTemplate(t))
2426
.cloud(cloud)
2527
.build();
26-
displayName = agent.getDisplayName();
28+
id = agent.getId(); // always use one sourced from the slave we are provisioning so the identity is maintained
2729
f = CompletableFuture.completedFuture(agent);
2830
} catch (IOException | Descriptor.FormException e) {
29-
displayName = null;
30-
f = new CompletableFuture();
31+
f = new CompletableFuture<>();
3132
f.completeExceptionally(e);
3233
}
33-
return new NodeProvisioner.PlannedNode(Util.fixNull(displayName), f, getNumExecutors());
34+
35+
if (id == null) {
36+
id = new ProvisioningActivity.Id(cloud.name, t.getName());
37+
}
38+
39+
return new TrackedPlannedNode(id, getNumExecutors(), f);
3440
}
3541
}

src/test/java/org/csanchez/jenkins/plugins/kubernetes/KubernetesSlaveTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.OnFailure;
3939
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention;
4040
import org.csanchez.jenkins.plugins.kubernetes.volumes.PodVolume;
41+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
4142
import org.junit.Rule;
4243
import org.junit.Test;
4344
import org.jvnet.hudson.test.JenkinsRule;
@@ -68,6 +69,18 @@ public void testGetSlaveName() {
6869
assertRegex(KubernetesSlave.getSlaveName(new PodTemplate("whatever...", volumes, containers)), ("jenkins-agent-[0-9a-z]{5}"));
6970
}
7071

72+
@Test
73+
public void testProvisioningActivityId() throws Descriptor.FormException, IOException {
74+
PodTemplate pt = new PodTemplate("x");
75+
pt.setName("Template");
76+
KubernetesSlave slave = new KubernetesSlave("Node", pt, "bar", "Cloud", "", null, null);
77+
ProvisioningActivity.Id id = slave.getId();
78+
assertNotNull(id);
79+
assertEquals(id.getCloudName(), "Cloud");
80+
assertEquals(id.getTemplateName(), "Template");
81+
assertEquals(id.getNodeName(), "Node");
82+
}
83+
7184
@Test
7285
public void testGetPodRetention() {
7386
try {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.csanchez.jenkins.plugins.kubernetes;
2+
3+
import static org.csanchez.jenkins.plugins.kubernetes.KubernetesTestUtil.assertRegex;
4+
import static org.junit.Assert.assertEquals;
5+
import static org.junit.Assert.assertTrue;
6+
7+
import hudson.slaves.NodeProvisioner;
8+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
9+
import org.jenkinsci.plugins.cloudstats.TrackedPlannedNode;
10+
import org.junit.Rule;
11+
import org.junit.Test;
12+
import org.jvnet.hudson.test.JenkinsRule;
13+
14+
public class StandardPlannedNodeBuilderTest {
15+
16+
@Rule
17+
public JenkinsRule r = new JenkinsRule();
18+
19+
@Test
20+
public void testBuild() {
21+
KubernetesCloud cloud = new KubernetesCloud("Cloud");
22+
PodTemplate template = new PodTemplate("t");
23+
template.setName("Template");
24+
StandardPlannedNodeBuilder builder = new StandardPlannedNodeBuilder();
25+
builder.cloud(cloud);
26+
builder.template(template);
27+
builder.numExecutors(1);
28+
29+
NodeProvisioner.PlannedNode plannedNode = builder.build();
30+
assertTrue(plannedNode instanceof TrackedPlannedNode);
31+
ProvisioningActivity.Id id = ((TrackedPlannedNode) plannedNode).getId();
32+
assertEquals(id.getCloudName(), "Cloud");
33+
assertEquals(id.getTemplateName(), "Template");
34+
assertRegex(id.getNodeName(), "template-\\w{5}");
35+
}
36+
}

0 commit comments

Comments
 (0)