Skip to content

Commit e4d57bf

Browse files
committed
Added workflow/pipeline support for pooled ports.
1 parent 7c1ec95 commit e4d57bf

File tree

9 files changed

+185
-96
lines changed

9 files changed

+185
-96
lines changed

pom.xml

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>org.jenkins-ci.plugins</groupId>
55
<artifactId>plugin</artifactId>
6-
<version>1.424</version>
6+
<version>1.609.1</version>
77
</parent>
88

99
<artifactId>port-allocator</artifactId>
@@ -29,8 +29,15 @@
2929
<id>pepov</id>
3030
<name>Peter Wilcsinszky</name>
3131
</developer>
32+
<developer>
33+
<name>Jens Mittag</name>
34+
</developer>
3235
</developers>
3336

37+
<properties>
38+
<workflow.version>1.8</workflow.version>
39+
</properties>
40+
3441
<scm>
3542
<connection>scm:git:git://github.com/jenkinsci/port-allocator-plugin.git</connection>
3643
<developerConnection>scm:git:ssh://[email protected]/jenkinsci/port-allocator-plugin.git</developerConnection>
@@ -59,6 +66,57 @@
5966
</pluginRepositories>
6067

6168
<dependencies>
69+
<dependency>
70+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
71+
<artifactId>workflow-job</artifactId>
72+
<version>${workflow.version}</version>
73+
<scope>test</scope>
74+
</dependency>
75+
<dependency>
76+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
77+
<artifactId>workflow-basic-steps</artifactId>
78+
<version>${workflow.version}</version>
79+
<scope>test</scope>
80+
</dependency>
81+
<dependency>
82+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
83+
<artifactId>workflow-cps</artifactId>
84+
<version>${workflow.version}</version>
85+
<scope>test</scope>
86+
</dependency>
87+
<dependency>
88+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
89+
<artifactId>workflow-durable-task-step</artifactId>
90+
<version>${workflow.version}</version>
91+
<scope>test</scope>
92+
</dependency>
93+
<dependency> <!-- StepConfigTester -->
94+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
95+
<artifactId>workflow-step-api</artifactId>
96+
<version>${workflow.version}</version>
97+
<classifier>tests</classifier>
98+
<scope>test</scope>
99+
</dependency>
100+
<dependency> <!-- JenkinsRuleExt -->
101+
<groupId>org.jenkins-ci.plugins.workflow</groupId>
102+
<artifactId>workflow-aggregator</artifactId>
103+
<version>${workflow.version}</version>
104+
<classifier>tests</classifier>
105+
<scope>test</scope>
106+
</dependency>
107+
<dependency>
108+
<groupId>org.jenkins-ci.modules</groupId>
109+
<artifactId>sshd</artifactId>
110+
<version>1.6</version>
111+
<scope>test</scope>
112+
</dependency>
113+
<dependency>
114+
<groupId>org.mockito</groupId>
115+
<artifactId>mockito-all</artifactId>
116+
<version>1.9.0-rc1</version>
117+
<type>jar</type>
118+
<scope>test</scope>
119+
</dependency>
62120
<dependency>
63121
<groupId>org.mockito</groupId>
64122
<artifactId>mockito-all</artifactId>
@@ -67,4 +125,4 @@
67125
<scope>test</scope>
68126
</dependency>
69127
</dependencies>
70-
</project>
128+
</project>

src/main/java/org/jvnet/hudson/plugins/port_allocator/DefaultPortType.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package org.jvnet.hudson.plugins.port_allocator;
22

3-
import hudson.model.AbstractBuild;
43
import hudson.model.BuildListener;
54
import hudson.Launcher;
5+
import hudson.model.Run;
6+
import hudson.model.TaskListener;
67
import net.sf.json.JSONObject;
78
import org.kohsuke.stapler.DataBoundConstructor;
89
import org.kohsuke.stapler.StaplerRequest;
@@ -22,13 +23,15 @@ public DefaultPortType(String name) {
2223
}
2324

2425
@Override
25-
public Port allocate(AbstractBuild<?, ?> build, final PortAllocationManager manager, int prefPort, Launcher launcher, BuildListener buildListener) throws IOException, InterruptedException {
26+
public Port allocate(Run<?, ?> run, final PortAllocationManager manager, int prefPort, Launcher launcher, TaskListener taskListener)
27+
throws IOException, InterruptedException
28+
{
2629
final int n;
2730
if(isFixedPort())
28-
n = manager.allocate(build, getFixedPort());
31+
n = manager.allocate(run, getFixedPort());
2932
else
30-
n = manager.allocateRandom(build, prefPort);
31-
33+
n = manager.allocateRandom(run, prefPort);
34+
3235
return new Port(this) {
3336
public int get() {
3437
return n;

src/main/java/org/jvnet/hudson/plugins/port_allocator/GlassFishJmxPortType.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package org.jvnet.hudson.plugins.port_allocator;
22

33
import hudson.Launcher;
4-
import hudson.model.AbstractBuild;
5-
import hudson.model.BuildListener;
4+
import hudson.model.Run;
5+
import hudson.model.TaskListener;
66
import hudson.remoting.Callable;
77
import net.sf.json.JSONObject;
8+
import org.jenkinsci.remoting.RoleChecker;
89
import org.kohsuke.stapler.DataBoundConstructor;
910
import org.kohsuke.stapler.StaplerRequest;
1011

@@ -27,7 +28,7 @@
2728

2829
/**
2930
* GlassFish JMX port so that runaway GF instance can be terminated.
30-
*
31+
*
3132
* @author Kohsuke Kawaguchi
3233
*/
3334
public class GlassFishJmxPortType extends PortType {
@@ -48,21 +49,23 @@ public GlassFishJmxPortType(String name, String userName, String password) {
4849
}
4950

5051
@Override
51-
public Port allocate(AbstractBuild<?, ?> build, final PortAllocationManager manager, int prefPort, final Launcher launcher, final BuildListener buildListener) throws IOException, InterruptedException {
52+
public Port allocate(Run<?, ?> run, final PortAllocationManager manager, int prefPort, final Launcher launcher, final TaskListener taskListener)
53+
throws IOException, InterruptedException
54+
{
5255
final int n;
5356
if(isFixedPort())
54-
n = manager.allocate(build, getFixedPort());
57+
n = manager.allocate(run, getFixedPort());
5558
else
56-
n = manager.allocateRandom(build, prefPort);
59+
n = manager.allocateRandom(run, prefPort);
5760

5861
/**
5962
* Cleans up GlassFish instance.
6063
*/
6164
final class GlassFishCleanUpTask implements Callable<Void,IOException>, Serializable {
62-
private final BuildListener buildListener;
65+
private final TaskListener taskListener;
6366

64-
public GlassFishCleanUpTask(BuildListener buildListener) {
65-
this.buildListener = buildListener;
67+
public GlassFishCleanUpTask(TaskListener taskListener) {
68+
this.taskListener = taskListener;
6669
}
6770

6871
public Void call() throws IOException {
@@ -87,23 +90,27 @@ public Void call() throws IOException {
8790
} catch (UnmarshalException e) {
8891
if(e.getCause() instanceof SocketException || e.getCause() instanceof IOException) {
8992
// to be expected, as the above would shut down the server.
90-
buildListener.getLogger().println("GlassFish was shut down");
93+
taskListener.getLogger().println("GlassFish was shut down");
9194
} else {
9295
throw e;
9396
}
9497
} catch (MalformedObjectNameException e) {
9598
throw new AssertionError(e); // impossible
9699
} catch (InstanceNotFoundException e) {
97-
e.printStackTrace(buildListener.error("Unable to find J2EEServer mbean"));
100+
e.printStackTrace(taskListener.error("Unable to find J2EEServer mbean"));
98101
} catch (ReflectionException e) {
99-
e.printStackTrace(buildListener.error("Unable to access J2EEServer mbean"));
102+
e.printStackTrace(taskListener.error("Unable to access J2EEServer mbean"));
100103
} catch (MBeanException e) {
101-
e.printStackTrace(buildListener.error("Unable to call J2EEServer mbean"));
104+
e.printStackTrace(taskListener.error("Unable to call J2EEServer mbean"));
102105
}
103106
return null;
104107
}
105108

106109
private static final long serialVersionUID = 1L;
110+
111+
@Override
112+
public void checkRoles(RoleChecker roleChecker) throws SecurityException {
113+
}
107114
}
108115

109116
return new Port(this) {
@@ -113,7 +120,7 @@ public int get() {
113120

114121
public void cleanUp() throws IOException, InterruptedException {
115122
manager.free(n);
116-
launcher.getChannel().call(new GlassFishCleanUpTask(buildListener));
123+
launcher.getChannel().call(new GlassFishCleanUpTask(taskListener));
117124
}
118125
};
119126
}

src/main/java/org/jvnet/hudson/plugins/port_allocator/PooledPortType.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
import hudson.Extension;
44
import hudson.Launcher;
5-
import hudson.model.AbstractBuild;
65
import hudson.model.BuildListener;
6+
import hudson.model.Run;
7+
import hudson.model.TaskListener;
78
import hudson.util.ListBoxModel;
89
import net.sf.json.JSONObject;
910
import org.kohsuke.stapler.DataBoundConstructor;
@@ -30,23 +31,14 @@ public PooledPortType(String name) {
3031
* Wait for a short period if no free port is available, then try again.
3132
*/
3233
@Override
33-
public Port allocate(
34-
AbstractBuild<?, ?> build,
35-
final PortAllocationManager manager,
36-
int prefPort,
37-
Launcher launcher,
38-
BuildListener buildListener
39-
) throws IOException, InterruptedException {
40-
34+
public Port allocate(Run<?, ?> run, PortAllocationManager manager, int prefPort, Launcher launcher, TaskListener taskListener) throws IOException, InterruptedException {
4135
try {
4236
while (true) {
43-
4437
Pool pool = PortAllocator.DESCRIPTOR.getPoolByName(name);
45-
4638
synchronized (pool) {
4739
for (int port : pool.getPortsAsInt()) {
4840
if (manager.isFree(port)) {
49-
manager.allocate(build, port);
41+
manager.allocate(run, port);
5042
return new PooledPort(this, port, manager);
5143
}
5244
}

src/main/java/org/jvnet/hudson/plugins/port_allocator/Port.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package org.jvnet.hudson.plugins.port_allocator;
22

33
import java.io.IOException;
4+
import java.io.Serializable;
45

56
/**
67
* Represents an assigned TCP port and encapsulates how it should be cleaned up.
78
*
89
* @author Kohsuke Kawaguchi
910
*/
10-
public abstract class Port {
11+
public abstract class Port implements Serializable {
1112
/**
1213
* {@link PortType} that created this port.
1314
*/

src/main/java/org/jvnet/hudson/plugins/port_allocator/PortAllocationManager.java

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package org.jvnet.hudson.plugins.port_allocator;
22

3-
import hudson.model.AbstractBuild;
3+
import hudson.Extension;
44
import hudson.model.Computer;
5+
import hudson.model.Run;
56
import hudson.remoting.Callable;
7+
import org.jenkinsci.remoting.RoleChecker;
68

79
import java.io.IOException;
10+
import java.io.Serializable;
811
import java.lang.ref.WeakReference;
912
import java.net.ServerSocket;
1013
import java.util.HashMap;
@@ -19,7 +22,8 @@
1922
* @author Rama Pulavarthi
2023
* @author Kohsuke Kawaguchi
2124
*/
22-
public final class PortAllocationManager {
25+
26+
public final class PortAllocationManager implements Serializable {
2327
private final Computer node;
2428

2529
/** Maximum number of tries to allocate a specific port range. */
@@ -28,7 +32,7 @@ public final class PortAllocationManager {
2832
/**
2933
* Ports currently in use, to the build that uses it.
3034
*/
31-
private final Map<Integer,AbstractBuild> ports = new HashMap<Integer,AbstractBuild>();
35+
private final Map<Integer, String> ports = new HashMap<Integer, String>();
3236

3337
private static final Map<Computer, WeakReference<PortAllocationManager>> INSTANCES =
3438
new WeakHashMap<Computer, WeakReference<PortAllocationManager>>();
@@ -47,7 +51,7 @@ private PortAllocationManager(Computer node) {
4751
* Preffered port. This method trys to assign this port, and upon failing, fall back to
4852
* assigning a random port.
4953
*/
50-
public synchronized int allocateRandom(AbstractBuild owner, int prefPort) throws InterruptedException, IOException {
54+
public synchronized int allocateRandom(Run<?, ?> run, int prefPort) throws InterruptedException, IOException {
5155
int i;
5256
try {
5357
// try to allocate preferential port,
@@ -56,16 +60,15 @@ public synchronized int allocateRandom(AbstractBuild owner, int prefPort) throws
5660
// if not available, assign a random port
5761
i = allocatePort(0);
5862
}
59-
ports.put(i,owner);
63+
ports.put(i,run.getId());
6064
return i;
6165
}
6266

6367
/**
6468
* Allocate a continuous range of ports within specified limits.
6569
* The caller is responsible for freeing the individual ports within
6670
* the allocated range.
67-
* @param portAllocator
68-
* @param build the current build
71+
* @param run the current build
6972
* @param start the first in the range of allowable ports
7073
* @param end the last entry in the range of allowable ports
7174
* @param count the number of ports to allocate
@@ -75,7 +78,7 @@ public synchronized int allocateRandom(AbstractBuild owner, int prefPort) throws
7578
* @throws IOException if the allocation failed
7679
*/
7780
public int[] allocatePortRange(
78-
final AbstractBuild owner,
81+
final Run<?, ?> run,
7982
int start, int end, int count, boolean isConsecutive)
8083
throws InterruptedException, IOException {
8184
int[] allocated = new int[count];
@@ -100,7 +103,7 @@ public int[] allocatePortRange(
100103
final int i;
101104
synchronized (this) {
102105
i = allocatePort(requestedPort);
103-
ports.put(i, owner);
106+
ports.put(i, run.getId());
104107
}
105108
allocated[offset] = i;
106109
} catch (PortUnavailableException ex) {
@@ -126,8 +129,8 @@ public int[] allocatePortRange(
126129
*
127130
* This method blocks until the port becomes available.
128131
*/
129-
public synchronized int allocate(AbstractBuild owner, int port) throws InterruptedException, IOException {
130-
while(ports.get(port)!=null)
132+
public synchronized int allocate(Run<?, ?> run, int port) throws InterruptedException, IOException {
133+
while (ports.get(port) != null)
131134
wait();
132135

133136
/*
@@ -160,13 +163,12 @@ the port actually becomes available (not only in our book-keeping but also at OS
160163
// wait(10000);
161164
// }
162165
// }
163-
ports.put(port,owner);
166+
ports.put(port,run.getId());
164167
return port;
165168
}
166169

167170
public synchronized boolean isFree(int port) {
168-
AbstractBuild owner = ports.get(port);
169-
if (owner == null) {
171+
if (ports.get(port) == null) {
170172
return true;
171173
}
172174
return false;
@@ -211,9 +213,9 @@ public synchronized void free(int n) {
211213
* If the specified port is not available
212214
*/
213215
private int allocatePort(final int port) throws InterruptedException, IOException {
214-
AbstractBuild owner = ports.get(port);
215-
if(owner!=null)
216-
throw new PortUnavailableException("Owned by "+owner);
216+
String id = ports.get(port);
217+
if (id != null)
218+
throw new PortUnavailableException("Owned by run " + id);
217219

218220
return node.getChannel().call(new AllocateTask(port));
219221
}
@@ -254,5 +256,9 @@ public Integer call() throws IOException {
254256
}
255257

256258
private static final long serialVersionUID = 1L;
259+
260+
@Override
261+
public void checkRoles(RoleChecker roleChecker) throws SecurityException {
262+
}
257263
}
258264
}

0 commit comments

Comments
 (0)