diff --git a/pom.xml b/pom.xml
index 5665c6e..29b78ea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,6 +62,11 @@
3.0.1
provided
+
+ org.jenkins-ci.plugins
+ credentials
+ 2.1.16
+
diff --git a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/AbstractDockerLauncher.java b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/AbstractDockerLauncher.java
index a09bb78..74b620d 100644
--- a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/AbstractDockerLauncher.java
+++ b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/AbstractDockerLauncher.java
@@ -26,6 +26,7 @@
import com.gpuopenanalytics.jenkins.remotedocker.job.DockerConfiguration;
import hudson.EnvVars;
+import hudson.FilePath;
import hudson.Launcher;
import hudson.Proc;
import hudson.util.ArgumentListBuilder;
@@ -45,6 +46,7 @@ public abstract class AbstractDockerLauncher extends Launcher.DecoratedLauncher
private DockerState dockerState;
private DockerVersion version;
+ private FilePath loginTempDir;
protected AbstractDockerLauncher(@Nonnull Launcher launcher) {
super(launcher);
@@ -167,6 +169,9 @@ public Launcher.ProcStarter executeCommand(ArgumentListBuilder args) {
if (!"docker".equals(args.toList().get(0))) {
args.prepend("docker");
}
+ if (loginTempDir != null) {
+ args.prepend("env", "HOME=" + loginTempDir.getRemote());
+ }
return getInner().launch()
//TODO I think we should pass something here
//.envs()
@@ -223,6 +228,7 @@ private DockerVersion parseVersion() throws IOException, InterruptedException {
*/
void configure(DockerState dockerState) {
this.dockerState = dockerState;
+ configureTempDir(dockerState.getLoginTempDir());
}
/**
@@ -233,4 +239,8 @@ void configure(DockerState dockerState) {
protected DockerState getDockerState() {
return dockerState;
}
+
+ public void configureTempDir(FilePath loginTempDir) {
+ this.loginTempDir = loginTempDir;
+ }
}
diff --git a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/DockerState.java b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/DockerState.java
index fd82da2..9051c86 100644
--- a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/DockerState.java
+++ b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/DockerState.java
@@ -24,6 +24,7 @@
package com.gpuopenanalytics.jenkins.remotedocker;
+import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
import com.google.common.collect.ImmutableList;
import com.gpuopenanalytics.jenkins.remotedocker.job.DockerConfiguration;
import com.gpuopenanalytics.jenkins.remotedocker.job.SideDockerConfiguration;
@@ -34,6 +35,7 @@
import hudson.slaves.WorkspaceList;
import hudson.util.ArgumentListBuilder;
import jenkins.model.Jenkins;
+import org.apache.commons.lang.StringUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -58,17 +60,20 @@ public class DockerState implements Serializable {
private ImmutableList containerIds;
private String networkId;
private boolean removeContainers;
+ private FilePath loginTempDir;
public DockerState(boolean debug,
String mainContainerId,
Collection containerIds,
Optional network,
- boolean removeContainers) {
+ boolean removeContainers,
+ FilePath loginTempDir) {
this.debug = debug;
this.mainContainerId = mainContainerId;
this.containerIds = ImmutableList.copyOf(containerIds);
this.networkId = network.map(DockerNetwork::getId).orElse(null);
this.removeContainers = removeContainers;
+ this.loginTempDir = loginTempDir;
}
private int execute(Launcher launcher,
@@ -84,13 +89,13 @@ private int execute(Launcher launcher,
return status;
}
- public void tearDown(Launcher launcher) throws IOException, InterruptedException {
+ public void tearDown(AbstractDockerLauncher launcher) throws IOException, InterruptedException {
if (removeContainers) {
TaskListener listener = launcher.getListener();
for (String containerId : containerIds) {
ArgumentListBuilder args = new ArgumentListBuilder()
.add("docker", "rm", "-f", containerId);
- int status = execute(launcher, args);
+ int status = execute(launcher.getInner(), args);
if (status != 0) {
listener.error("Failed to remove container %s",
containerId);
@@ -99,12 +104,69 @@ public void tearDown(Launcher launcher) throws IOException, InterruptedException
if (networkId != null) {
ArgumentListBuilder args = new ArgumentListBuilder()
.add("docker", "network", "rm", networkId);
- int status = execute(launcher, args);
+ int status = execute(launcher.getInner(), args);
if (status != 0) {
listener.error("Failed to remove network %s", networkId);
}
}
}
+ logout(launcher.getInner());
+ }
+
+ private void logout(Launcher launcher) throws IOException, InterruptedException {
+ if (loginTempDir != null) {
+ ArgumentListBuilder args = new ArgumentListBuilder("env",
+ "HOME=" + loginTempDir
+ .getRemote(),
+ "docker",
+ "logout");
+ int status = execute(launcher, args);
+ if (status != 0) {
+ launcher.getListener().error("Failed to docker logout");
+ }
+ }
+ }
+
+ /**
+ * Attempt to docker login. Returns the temporary directory to
+ * use for HOME to store docker credentials.
+ *
+ * @param buildWrapper
+ * @param launcher
+ * @param workspace
+ * @return
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ private static FilePath login(RemoteDockerBuildWrapper buildWrapper,
+ AbstractDockerLauncher launcher,
+ FilePath workspace) throws IOException, InterruptedException {
+ if (buildWrapper.getCredentialsId() != null) {
+ UsernamePasswordCredentials creds = buildWrapper.getCredentials();
+ FilePath tempDir = WorkspaceList.tempDir(workspace);
+ launcher.configureTempDir(tempDir);
+ ArgumentListBuilder args = new ArgumentListBuilder("docker",
+ "login");
+ args.add("-u", creds.getUsername());
+ args.add("-p");
+ args.addMasked(creds.getPassword());
+ if (!StringUtils.isEmpty(buildWrapper.getDockerRegistryUrl())) {
+ args.add(buildWrapper.getDockerRegistryUrl());
+ }
+ Launcher.ProcStarter cmd = launcher.executeCommand(args);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ cmd.stdout(launcher.getListener());
+ cmd.stderr(baos);
+ int status = cmd.join();
+ if (status != 0) {
+ launcher.getListener().error("Failed to docker login");
+ launcher.getListener().error(baos.toString());
+ throw new RuntimeException(
+ "Could not docker login. Are your credentials correct?");
+ }
+ return tempDir;
+ }
+ return null;
}
/**
@@ -116,6 +178,8 @@ public void tearDown(Launcher launcher) throws IOException, InterruptedException
public static DockerState launchContainers(RemoteDockerBuildWrapper buildWrapper,
AbstractDockerLauncher launcher,
FilePath workspace) throws IOException, InterruptedException {
+ FilePath loginTempDir = login(buildWrapper, launcher, workspace);
+
Optional network = Optional.empty();
if (!buildWrapper.getSideDockerConfigurations().isEmpty()) {
//There are side container, so create a network
@@ -124,14 +188,16 @@ public static DockerState launchContainers(RemoteDockerBuildWrapper buildWrapper
List containerIds = new ArrayList<>();
//Launch side containers first
for (SideDockerConfiguration side : buildWrapper.getSideDockerConfigurations()) {
- String id = launchContainer(buildWrapper, side, false, launcher, workspace,
+ String id = launchContainer(buildWrapper, side, false, launcher,
+ workspace,
network);
containerIds.add(id);
}
//Launch main container
DockerConfiguration main = buildWrapper.getDockerConfiguration();
- String mainId = launchContainer(buildWrapper, main, true, launcher, workspace,
+ String mainId = launchContainer(buildWrapper, main, true, launcher,
+ workspace,
network);
containerIds.add(mainId);
Collections.reverse(containerIds);
@@ -139,7 +205,8 @@ public static DockerState launchContainers(RemoteDockerBuildWrapper buildWrapper
DockerState dockerState = new DockerState(buildWrapper.isDebug(),
mainId, containerIds,
network,
- buildWrapper.isRemoveContainers());
+ buildWrapper.isRemoveContainers(),
+ loginTempDir);
launcher.configure(dockerState);
return dockerState;
}
@@ -159,8 +226,8 @@ private static ArgumentListBuilder getlaunchArgs(RemoteDockerBuildWrapper buildW
Optional network) throws IOException, InterruptedException {
String workspacePath = workspace.getRemote();
String workspaceTarget = Optional.ofNullable(
- buildWrapper.getWorkspaceOverride())
- .orElse(workspacePath);
+ buildWrapper.getWorkspaceOverride())
+ .orElse(workspacePath);
//Fully resolve the source workspace
String workspaceSrc = Paths.get(workspacePath)
.toAbsolutePath()
@@ -212,7 +279,8 @@ private static String launchContainer(RemoteDockerBuildWrapper buildWrapper,
AbstractDockerLauncher launcher,
FilePath workspace,
Optional network) throws IOException, InterruptedException {
- ArgumentListBuilder args = getlaunchArgs(buildWrapper, config, isMain, launcher,
+ ArgumentListBuilder args = getlaunchArgs(buildWrapper, config, isMain,
+ launcher,
workspace, network);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int status = launcher.executeCommand(args)
@@ -231,7 +299,8 @@ private static String launchContainer(RemoteDockerBuildWrapper buildWrapper,
containerId,
ImmutableList.of(containerId),
Optional.empty(),
- false);
+ false,
+ null);
launcher.configure(tempState);
config.postCreate(launcher);
return containerId;
@@ -258,4 +327,7 @@ public Optional getNetworkId() {
return Optional.ofNullable(networkId);
}
+ public FilePath getLoginTempDir() {
+ return loginTempDir;
+ }
}
diff --git a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper.java b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper.java
index e94f950..39218ac 100644
--- a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper.java
+++ b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper.java
@@ -24,6 +24,12 @@
package com.gpuopenanalytics.jenkins.remotedocker;
+import com.cloudbees.plugins.credentials.CredentialsMatchers;
+import com.cloudbees.plugins.credentials.CredentialsProvider;
+import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
+import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
+import com.cloudbees.plugins.credentials.domains.DomainRequirement;
+import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
import com.gpuopenanalytics.jenkins.remotedocker.job.AbstractDockerConfiguration;
import com.gpuopenanalytics.jenkins.remotedocker.job.AbstractDockerConfigurationDescriptor;
import com.gpuopenanalytics.jenkins.remotedocker.job.DockerImageConfiguration;
@@ -34,17 +40,23 @@
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
+import hudson.model.Item;
import hudson.model.Run;
+import hudson.security.ACL;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
+import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
+import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
+import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -59,6 +71,9 @@ public class RemoteDockerBuildWrapper extends BuildWrapper {
private static final String WORKSPACE_OVERRIDE_FIELD = "workspaceOverride";
private static final String WORKSPACE_OVERRIDE_OPTIONAL_FIELD = "workspaceOverrideOptional";
+ private static final String DOCKER_REGISTRY_URL_FIELD = "dockerRegistryUrl";
+ private static final String CREDENTIALS_ID_FIELD = "credentialsId";
+ private static final String DOCKER_LOGIN_OPTIONAL_FIELD = "dockerLoginOptional";
private boolean debug;
private String workspaceOverride;
@@ -66,11 +81,16 @@ public class RemoteDockerBuildWrapper extends BuildWrapper {
private AbstractDockerConfiguration dockerConfiguration;
private List sideDockerConfigurations;
+ private String dockerRegistryUrl;
+ private String credentialsId;
+
@DataBoundConstructor
public RemoteDockerBuildWrapper(boolean debug,
String workspaceOverride,
AbstractDockerConfiguration dockerConfiguration,
- List sideDockerConfigurations) {
+ List sideDockerConfigurations,
+ String dockerRegistryUrl,
+ String credentialsId) {
this.debug = debug;
this.workspaceOverride = StringUtils.isNotEmpty(
workspaceOverride) ? workspaceOverride : null;
@@ -78,6 +98,8 @@ public RemoteDockerBuildWrapper(boolean debug,
this.sideDockerConfigurations = Optional.ofNullable(
sideDockerConfigurations)
.orElse(Collections.emptyList());
+ this.dockerRegistryUrl = dockerRegistryUrl;
+ this.credentialsId = credentialsId;
}
public boolean isDebug() {
@@ -105,6 +127,27 @@ public List getSideDockerConfigurations() {
return sideDockerConfigurations;
}
+ public UsernamePasswordCredentials getCredentials() {
+ List allCredentials = CredentialsProvider
+ .lookupCredentials(UsernamePasswordCredentials.class,
+ Jenkins.get(),
+ ACL.SYSTEM, Collections.emptyList());
+ UsernamePasswordCredentials credentials = CredentialsMatchers.firstOrNull(
+ allCredentials,
+ CredentialsMatchers.allOf(
+ CredentialsMatchers
+ .withId(credentialsId)));
+ return credentials;
+ }
+
+ public String getDockerRegistryUrl() {
+ return dockerRegistryUrl;
+ }
+
+ public String getCredentialsId() {
+ return credentialsId;
+ }
+
private void validate() throws Descriptor.FormException {
if (StringUtils.isNotEmpty(workspaceOverride)
&& !workspaceOverride.startsWith("/")) {
@@ -152,7 +195,7 @@ public DockerEnvironment(DockerLauncher launcher,
@Override
public boolean tearDown(AbstractBuild build,
BuildListener listener) throws IOException, InterruptedException {
- dockerState.tearDown(launcher.getInner());
+ dockerState.tearDown(launcher);
return true;
}
}
@@ -180,6 +223,11 @@ public BuildWrapper newInstance(StaplerRequest req,
//If the box is unchecked, override whatever value might have been entered
formData.remove(WORKSPACE_OVERRIDE_FIELD);
}
+ if (!formData.getBoolean(DOCKER_LOGIN_OPTIONAL_FIELD)) {
+ //If the box is unchecked, delete registry & credentials
+ formData.remove(DOCKER_REGISTRY_URL_FIELD);
+ formData.remove(CREDENTIALS_ID_FIELD);
+ }
RemoteDockerBuildWrapper wrapper = (RemoteDockerBuildWrapper) super.newInstance(
req, formData);
wrapper.validate();
@@ -198,6 +246,21 @@ public Descriptor getDefaultDockerConfigurationDescriptor() {
return Jenkins.get().getDescriptorOrDie(
DockerImageConfiguration.class);
}
+
+ public ListBoxModel doFillCredentialsIdItems(
+ @AncestorInPath Jenkins context,
+ @QueryParameter String credentialsId) {
+ if (context == null || !context.hasPermission(Item.CONFIGURE)) {
+ return new StandardListBoxModel();
+ }
+
+ List domainRequirements = new ArrayList<>();
+ return new StandardListBoxModel()
+ .includeEmptyValue()
+ .includeAs(ACL.SYSTEM, Jenkins.get(),
+ UsernamePasswordCredentialsImpl.class)
+ .includeCurrentValue(credentialsId);
+ }
}
}
diff --git a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/DockerLauncherDecorator.java b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/DockerLauncherDecorator.java
index 8566ee8..4cf2a1b 100644
--- a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/DockerLauncherDecorator.java
+++ b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/DockerLauncherDecorator.java
@@ -24,6 +24,7 @@
package com.gpuopenanalytics.jenkins.remotedocker.pipeline;
+import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
import com.gpuopenanalytics.jenkins.remotedocker.AbstractDockerLauncher;
import com.gpuopenanalytics.jenkins.remotedocker.DockerState;
import com.gpuopenanalytics.jenkins.remotedocker.job.DockerConfiguration;
@@ -34,6 +35,7 @@
import hudson.model.Node;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import java.io.IOException;
import java.io.Serializable;
@@ -47,17 +49,20 @@ public class DockerLauncherDecorator extends LauncherDecorator implements Serial
private DockerConfiguration dockerConfiguration;
private EnvVars environment;
private String workspaceOverride;
+ private UsernamePasswordCredentials credentials;
public DockerLauncherDecorator(boolean debug,
DockerState dockerState,
DockerConfiguration dockerConfiguration,
EnvVars environment,
- String workspaceOverride) {
+ String workspaceOverride,
+ @Nullable UsernamePasswordCredentials credentials) {
this.debug = debug;
this.dockerState = dockerState;
this.dockerConfiguration = dockerConfiguration;
this.environment = environment;
this.workspaceOverride = workspaceOverride;
+ this.credentials=credentials;
}
@Nonnull
diff --git a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStep.java b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStep.java
index d579b93..4d9dde4 100644
--- a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStep.java
+++ b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStep.java
@@ -57,12 +57,16 @@ public class RemoteDockerStep extends Step {
private List sideContainers;
private String workspaceOverride;
private Boolean removeContainers = true;
+ private String registryUrl;
+ private String credentialsId;
@DataBoundConstructor
public RemoteDockerStep(boolean debug,
AbstractDockerConfiguration main,
List sideContainers,
- String workspaceOverride) {
+ String workspaceOverride,
+ String registryUrl,
+ String credentialsId) {
this.debug = debug;
this.main = main;
this.sideContainers = ImmutableList.copyOf(
@@ -70,6 +74,8 @@ public RemoteDockerStep(boolean debug,
.orElse(Collections.emptyList()));
this.workspaceOverride = StringUtils.isNotEmpty(
workspaceOverride) ? workspaceOverride : null;
+ this.registryUrl = registryUrl;
+ this.credentialsId = credentialsId;
}
@Override
@@ -102,6 +108,14 @@ public String getWorkspaceOverride() {
return workspaceOverride;
}
+ public String getRegistryUrl() {
+ return registryUrl;
+ }
+
+ public String getCredentialsId() {
+ return credentialsId;
+ }
+
@Extension
public static final class DescriptorImpl extends StepDescriptor {
diff --git a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStepExecution.java b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStepExecution.java
index cc2dd56..754d6b5 100644
--- a/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStepExecution.java
+++ b/src/main/java/com/gpuopenanalytics/jenkins/remotedocker/pipeline/RemoteDockerStepExecution.java
@@ -24,6 +24,8 @@
package com.gpuopenanalytics.jenkins.remotedocker.pipeline;
+import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
+import com.gpuopenanalytics.jenkins.remotedocker.AbstractDockerLauncher;
import com.gpuopenanalytics.jenkins.remotedocker.DockerState;
import com.gpuopenanalytics.jenkins.remotedocker.RemoteDockerBuildWrapper;
import com.gpuopenanalytics.jenkins.remotedocker.SimpleDockerLauncher;
@@ -32,6 +34,7 @@
import hudson.FilePath;
import hudson.Launcher;
import hudson.LauncherDecorator;
+import hudson.Proc;
import org.jenkinsci.plugins.workflow.steps.BodyExecution;
import org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback;
import org.jenkinsci.plugins.workflow.steps.BodyInvoker;
@@ -68,12 +71,16 @@ public boolean start() throws Exception {
remoteDockerStep.isDebug(),
remoteDockerStep.getWorkspaceOverride(),
remoteDockerStep.getMain(),
- remoteDockerStep.getSideContainers());
+ remoteDockerStep.getSideContainers(),
+ remoteDockerStep.getRegistryUrl(),
+ remoteDockerStep.getCredentialsId());
buildWrapper.setRemoveContainers(remoteDockerStep.isRemoveContainers());
Launcher launcher = getContext().get(Launcher.class);
FilePath workspace = getContext().get(FilePath.class);
EnvVars environment = getContext().get(EnvVars.class);
+ UsernamePasswordCredentials credentials = getContext().get(
+ UsernamePasswordCredentials.class);
SimpleDockerLauncher simpleDockerLauncher = new SimpleDockerLauncher(
launcher, buildWrapper.isDebug(), environment, buildWrapper);
@@ -87,7 +94,8 @@ public boolean start() throws Exception {
dockerState,
remoteDockerStep.getMain(),
environment,
- remoteDockerStep.getWorkspaceOverride());
+ remoteDockerStep.getWorkspaceOverride(),
+ credentials);
LauncherDecorator launcherDecorator = BodyInvoker.mergeLauncherDecorators(
getContext().get(LauncherDecorator.class),
@@ -108,7 +116,7 @@ public void stop(@Nonnull Throwable cause) throws Exception {
}
if (dockerState != null) {
Launcher launcher = getContext().get(Launcher.class);
- dockerState.tearDown(launcher);
+ dockerState.tearDown(createLauncher(launcher, dockerState));
}
}
@@ -124,6 +132,27 @@ public String getStatus() {
return null;
}
+ private static AbstractDockerLauncher createLauncher(Launcher launcher,
+ DockerState dockerState) {
+ return new AbstractDockerLauncher(launcher, dockerState) {
+ @Override
+ public Proc dockerExec(ProcStarter starter,
+ boolean addRunArgs) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public EnvVars getEnvironment() {
+ return new EnvVars();
+ }
+
+ @Override
+ public boolean isDebug() {
+ return dockerState.isDebug();
+ }
+ };
+ }
+
/**
* Callback to execute at the end of the step's body. Basically, just
* shutdown the containers
@@ -140,7 +169,7 @@ public Callback(DockerState dockerState) {
public void onSuccess(StepContext context, Object result) {
try {
Launcher launcher = context.get(Launcher.class);
- dockerState.tearDown(launcher);
+ dockerState.tearDown(createLauncher(launcher, dockerState));
context.onSuccess(result);
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
@@ -151,7 +180,7 @@ public void onSuccess(StepContext context, Object result) {
public void onFailure(StepContext context, Throwable t) {
try {
Launcher launcher = context.get(Launcher.class);
- dockerState.tearDown(launcher);
+ dockerState.tearDown(createLauncher(launcher, dockerState));
context.onFailure(t);
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
diff --git a/src/main/resources/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper/config.jelly b/src/main/resources/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper/config.jelly
index 7445953..e23e9c4 100644
--- a/src/main/resources/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper/config.jelly
+++ b/src/main/resources/com/gpuopenanalytics/jenkins/remotedocker/RemoteDockerBuildWrapper/config.jelly
@@ -24,7 +24,8 @@
-->
+ xmlns:f="/lib/form"
+ xmlns:c="/lib/credentials">
-
+
+
+
+
+
+
+
+
+