Skip to content

Commit 669a7bb

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

File tree

6 files changed

+98
-9
lines changed

6 files changed

+98
-9
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
<groupId>org.jenkins-ci.plugins</groupId>
8585
<artifactId>authentication-tokens</artifactId>
8686
</dependency>
87+
<dependency>
88+
<groupId>org.jenkins-ci.plugins</groupId>
89+
<artifactId>cloud-stats</artifactId>
90+
<version>302.v45b_647b_90608</version>
91+
</dependency>
8792

8893
<dependency>
8994
<!-- Requires Permission -->
@@ -140,6 +145,8 @@
140145
<groupId>org.jenkins-ci.plugins.workflow</groupId>
141146
<artifactId>workflow-durable-task-step</artifactId>
142147
</dependency>
148+
149+
<!-- for testing -->
143150
<dependency>
144151
<groupId>org.jenkins-ci.plugins.workflow</groupId>
145152
<artifactId>workflow-step-api</artifactId>

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 edu.umd.cs.findbugs.annotations.NonNull;
45
import hudson.model.Computer;
56
import hudson.model.Executor;
@@ -23,6 +24,8 @@
2324
import jenkins.model.Jenkins;
2425
import org.acegisecurity.Authentication;
2526
import org.apache.commons.lang.StringUtils;
27+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
28+
import org.jenkinsci.plugins.cloudstats.TrackedItem;
2629
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException;
2730
import org.kohsuke.stapler.QueryParameter;
2831
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;
@@ -203,4 +206,15 @@ public void setAcceptingTasks(boolean acceptingTasks) {
203206
launching = false;
204207
}
205208
}
209+
210+
@CheckForNull
211+
@Override
212+
public ProvisioningActivity.Id getId() {
213+
KubernetesSlave slave = getNode();
214+
if (slave != null) {
215+
return slave.getId();
216+
}
217+
218+
return null;
219+
}
206220
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import org.apache.commons.lang.StringUtils;
5050
import org.apache.commons.lang.Validate;
5151
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention;
52+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
53+
import org.jenkinsci.plugins.cloudstats.TrackedItem;
5254
import org.jenkinsci.plugins.durabletask.executors.OnceRetentionStrategy;
5355
import org.jenkinsci.plugins.kubernetes.auth.KubernetesAuthException;
5456
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

@@ -85,6 +87,9 @@ public class KubernetesSlave extends AbstractCloudSlave {
8587
@CheckForNull
8688
private transient Pod pod;
8789

90+
@NonNull
91+
private final ProvisioningActivity.Id id;
92+
8893
@NonNull
8994
public PodTemplate getTemplate() throws IllegalStateException {
9095
// Look up updated pod template after a restart
@@ -210,6 +215,7 @@ protected KubernetesSlave(
210215
this.cloudName = cloudName;
211216
this.template = template;
212217
this.podTemplateId = template.getId();
218+
this.id = new ProvisioningActivity.Id(cloudName, template.getName(), name);
213219
}
214220

215221
public String getCloudName() {
@@ -450,6 +456,12 @@ private void deleteSlavePod(TaskListener listener, KubernetesClient client) thro
450456
listener.getLogger().println(msg);
451457
}
452458

459+
@CheckForNull
460+
@Override
461+
public ProvisioningActivity.Id getId() {
462+
return id;
463+
}
464+
453465
@Override
454466
public String toString() {
455467
return String.format("KubernetesSlave name: %s", name);
Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
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;
66
import java.io.IOException;
77
import java.util.concurrent.CompletableFuture;
8+
import org.jenkinsci.plugins.cloudstats.ProvisioningActivity;
9+
import org.jenkinsci.plugins.cloudstats.TrackedPlannedNode;
810

911
/**
1012
* The default {@link PlannedNodeBuilder} implementation, in case there is other registered.
@@ -14,20 +16,25 @@ public class StandardPlannedNodeBuilder extends PlannedNodeBuilder {
1416
public NodeProvisioner.PlannedNode build() {
1517
KubernetesCloud cloud = getCloud();
1618
PodTemplate t = getTemplate();
17-
CompletableFuture f;
18-
String displayName;
19+
CompletableFuture<Node> f;
20+
ProvisioningActivity.Id id = null;
1921
try {
2022
KubernetesSlave agent = KubernetesSlave.builder()
2123
.podTemplate(t.isUnwrapped() ? t : cloud.getUnwrappedTemplate(t))
2224
.cloud(cloud)
2325
.build();
24-
displayName = agent.getDisplayName();
26+
id = agent.getId(); // always use one sourced from the slave we are provisioning so the identity is
27+
// maintained
2528
f = CompletableFuture.completedFuture(agent);
2629
} catch (IOException | Descriptor.FormException e) {
27-
displayName = null;
28-
f = new CompletableFuture();
30+
f = new CompletableFuture<>();
2931
f.completeExceptionally(e);
3032
}
31-
return new NodeProvisioner.PlannedNode(Util.fixNull(displayName), f, getNumExecutors());
33+
34+
if (id == null) {
35+
id = new ProvisioningActivity.Id(cloud.name, t.getName());
36+
}
37+
38+
return new TrackedPlannedNode(id, getNumExecutors(), f);
3239
}
3340
}

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;
@@ -70,6 +71,18 @@ public void testGetSlaveName() {
7071
("jenkins-agent-[0-9a-z]{5}"));
7172
}
7273

74+
@Test
75+
public void testProvisioningActivityId() throws Descriptor.FormException, IOException {
76+
PodTemplate pt = new PodTemplate("x");
77+
pt.setName("Template");
78+
KubernetesSlave slave = new KubernetesSlave("Node", pt, "bar", "Cloud", "", null, null);
79+
ProvisioningActivity.Id id = slave.getId();
80+
assertNotNull(id);
81+
assertEquals(id.getCloudName(), "Cloud");
82+
assertEquals(id.getTemplateName(), "Template");
83+
assertEquals(id.getNodeName(), "Node");
84+
}
85+
7386
@Test
7487
public void testGetPodRetention() {
7588
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)