Skip to content
This repository was archived by the owner on Jan 17, 2024. It is now read-only.

Commit 0c41e87

Browse files
authored
Merge pull request #21 from raydouglass/workspace-override
[REVIEW] Workspace override
2 parents 943fde0 + 334b1c2 commit 0c41e87

File tree

5 files changed

+76
-7
lines changed

5 files changed

+76
-7
lines changed

src/main/java/com/gpuopenanalytics/jenkins/remotedocker/DockerLauncher.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ public void launchContainers() throws IOException, InterruptedException {
136136
private ArgumentListBuilder getlaunchArgs(DockerConfiguration config,
137137
boolean isMain) throws IOException, InterruptedException {
138138
String workspacePath = build.getWorkspace().getRemote();
139+
String workspaceTarget = Optional.ofNullable(
140+
buildWrapper.getWorkspaceOverride())
141+
.orElse(workspacePath);
139142
//Fully resolve the source workspace
140143
String workspaceSrc = Paths.get(workspacePath)
141144
.toAbsolutePath()
@@ -160,7 +163,6 @@ private ArgumentListBuilder getlaunchArgs(DockerConfiguration config,
160163
ArgumentListBuilder args = new ArgumentListBuilder()
161164
.add("run", "-t", "-d")
162165
.add("--name", Utils.resolveVariables(this, "$BUILD_TAG"))
163-
.add("--workdir", workspacePath)
164166
//Add bridge network for internet access
165167
.add("--network", "bridge");
166168
//Add inter-container network if needed
@@ -169,8 +171,9 @@ private ArgumentListBuilder getlaunchArgs(DockerConfiguration config,
169171
if (isMain) {
170172
//Start a shell to block the container, overriding the entrypoint in case the image already defines that
171173
args.add("--entrypoint", "/bin/sh")
172-
.add("-v", workspaceSrc + ":" + workspacePath)
173-
////Jenkins puts scripts here
174+
.add("--workdir", workspaceTarget)
175+
.add("-v", workspaceSrc + ":" + workspaceTarget)
176+
//Jenkins puts scripts here
174177
.add("-v", tmpSrc + ":" + tmpDest);
175178
}
176179
config.addCreateArgs(this, args, build);
@@ -252,7 +255,10 @@ public Proc dockerExec(Launcher.ProcStarter starter,
252255
ArgumentListBuilder args = new ArgumentListBuilder()
253256
.add("exec");
254257
if (starter.pwd() != null) {
255-
args.add("--workdir", starter.pwd().getRemote());
258+
String path = Optional.ofNullable(
259+
buildWrapper.getWorkspaceOverride())
260+
.orElse(starter.pwd().getRemote());
261+
args.add("--workdir", path);
256262
}
257263
if (addRunArgs) {
258264
buildWrapper.getDockerConfiguration().addRunArgs(this, args, build);
@@ -261,6 +267,10 @@ public Proc dockerExec(Launcher.ProcStarter starter,
261267
args.add(mainContainerId);
262268

263269
args.add("env").add(starter.envs());
270+
if (buildWrapper.getWorkspaceOverride() != null) {
271+
//Override $WORKSPACE inside the container
272+
args.add("WORKSPACE=" + buildWrapper.getWorkspaceOverride());
273+
}
264274

265275
List<String> originalCmds = starter.cmds();
266276
boolean[] originalMask = starter.masks();

src/main/java/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import hudson.tasks.BuildWrapperDescriptor;
4040
import jenkins.model.Jenkins;
4141
import net.sf.json.JSONObject;
42+
import org.apache.commons.lang.StringUtils;
4243
import org.kohsuke.stapler.DataBoundConstructor;
4344
import org.kohsuke.stapler.DataBoundSetter;
4445
import org.kohsuke.stapler.StaplerRequest;
@@ -56,16 +57,23 @@
5657
*/
5758
public class RemoteDockerBuildWrapper extends BuildWrapper {
5859

60+
private static final String WORKSPACE_OVERRIDE_FIELD = "workspaceOverride";
61+
private static final String WORKSPACE_OVERRIDE_OPTIONAL_FIELD = "workspaceOverrideOptional";
62+
5963
private boolean debug;
64+
private String workspaceOverride;
6065
private Boolean removeContainers = true;
6166
private AbstractDockerConfiguration dockerConfiguration;
6267
private List<SideDockerConfiguration> sideDockerConfigurations;
6368

6469
@DataBoundConstructor
6570
public RemoteDockerBuildWrapper(boolean debug,
71+
String workspaceOverride,
6672
AbstractDockerConfiguration dockerConfiguration,
6773
List<SideDockerConfiguration> sideDockerConfigurations) {
6874
this.debug = debug;
75+
this.workspaceOverride = StringUtils.isNotEmpty(
76+
workspaceOverride) ? workspaceOverride : null;
6977
this.dockerConfiguration = dockerConfiguration;
7078
this.sideDockerConfigurations = Optional.ofNullable(
7179
sideDockerConfigurations)
@@ -76,6 +84,10 @@ public boolean isDebug() {
7684
return debug;
7785
}
7886

87+
public String getWorkspaceOverride() {
88+
return workspaceOverride;
89+
}
90+
7991
@DataBoundSetter
8092
public void setRemoveContainers(Boolean removeContainers) {
8193
this.removeContainers = removeContainers;
@@ -93,6 +105,15 @@ public List<SideDockerConfiguration> getSideDockerConfigurations() {
93105
return sideDockerConfigurations;
94106
}
95107

108+
private void validate() throws Descriptor.FormException {
109+
if (StringUtils.isNotEmpty(workspaceOverride)
110+
&& !workspaceOverride.startsWith("/")) {
111+
throw new Descriptor.FormException(
112+
"Workspace override must be an absolute path",
113+
WORKSPACE_OVERRIDE_FIELD);
114+
}
115+
}
116+
96117
@Override
97118
public Launcher decorateLauncher(AbstractBuild build,
98119
Launcher launcher,
@@ -107,7 +128,8 @@ public Environment setUp(AbstractBuild build,
107128
build.addAction(new DockerAction());
108129
try {
109130
((DockerLauncher) launcher).launchContainers();
110-
return new DockerEnvironment((DockerLauncher) launcher, removeContainers);
131+
return new DockerEnvironment((DockerLauncher) launcher,
132+
removeContainers);
111133
} catch (IOException | InterruptedException e) {
112134
//Attempt tearDown in case we partially started some containers
113135
((DockerLauncher) launcher).tearDown(true);
@@ -123,9 +145,10 @@ private class DockerEnvironment extends BuildWrapper.Environment {
123145
private DockerLauncher launcher;
124146
private boolean removeContainers;
125147

126-
public DockerEnvironment(DockerLauncher launcher, boolean removeContainers) {
148+
public DockerEnvironment(DockerLauncher launcher,
149+
boolean removeContainers) {
127150
this.launcher = launcher;
128-
this.removeContainers=removeContainers;
151+
this.removeContainers = removeContainers;
129152
}
130153

131154
@Override
@@ -155,8 +178,13 @@ public BuildWrapper newInstance(StaplerRequest req,
155178
if (formData.isNullObject()) {
156179
return null;
157180
}
181+
if (!formData.getBoolean(WORKSPACE_OVERRIDE_OPTIONAL_FIELD)) {
182+
//If the box is unchecked, override whatever value might have been entered
183+
formData.remove(WORKSPACE_OVERRIDE_FIELD);
184+
}
158185
RemoteDockerBuildWrapper wrapper = (RemoteDockerBuildWrapper) super.newInstance(
159186
req, formData);
187+
wrapper.validate();
160188
wrapper.dockerConfiguration.validate();
161189
for (SideDockerConfiguration side : wrapper.sideDockerConfigurations) {
162190
side.validate();

src/main/resources/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper/config.jelly

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,10 @@
4343
<f:entry title="Debug" field="debug">
4444
<f:checkbox/>
4545
</f:entry>
46+
<f:optionalBlock name="workspaceOverrideOptional" title="Override workspace mount" inline="true" checked="${!empty(instance.workspaceOverride)}">
47+
<f:entry title="Workspace path" field="workspaceOverride">
48+
<f:textbox/>
49+
</f:entry>
50+
</f:optionalBlock>
4651

4752
</j:jelly>

src/main/resources/com/gpuopenanalytics/jenkins/remotedocker/job/AbstractDockerConfiguration/help-debug.html renamed to src/main/resources/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper/help-debug.html

File renamed without changes.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!--
2+
~ The MIT License
3+
~
4+
~ Copyright (c) 2019, NVIDIA CORPORATION.
5+
~
6+
~ Permission is hereby granted, free of charge, to any person obtaining a copy
7+
~ of this software and associated documentation files (the "Software"), to deal
8+
~ in the Software without restriction, including without limitation the rights
9+
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
~ copies of the Software, and to permit persons to whom the Software is
11+
~ furnished to do so, subject to the following conditions:
12+
~
13+
~ The above copyright notice and this permission notice shall be included in
14+
~ all copies or substantial portions of the Software.
15+
~
16+
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
~ THE SOFTWARE.
23+
-->
24+
<div>
25+
Change where the job's workspace is mounted inside of the container. By default, the path is the same as the Jenkins agent's workspace.
26+
</div>

0 commit comments

Comments
 (0)