Skip to content
This repository was archived by the owner on Jan 17, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials</artifactId>
<version>2.1.16</version>
</dependency>
</dependencies>

<repositories>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -223,6 +228,7 @@ private DockerVersion parseVersion() throws IOException, InterruptedException {
*/
void configure(DockerState dockerState) {
this.dockerState = dockerState;
configureTempDir(dockerState.getLoginTempDir());
}

/**
Expand All @@ -233,4 +239,8 @@ void configure(DockerState dockerState) {
protected DockerState getDockerState() {
return dockerState;
}

public void configureTempDir(FilePath loginTempDir) {
this.loginTempDir = loginTempDir;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -58,17 +60,20 @@ public class DockerState implements Serializable {
private ImmutableList<String> containerIds;
private String networkId;
private boolean removeContainers;
private FilePath loginTempDir;

public DockerState(boolean debug,
String mainContainerId,
Collection<String> containerIds,
Optional<DockerNetwork> 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,
Expand All @@ -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);
Expand All @@ -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 <code>docker login</code>. Returns the temporary directory to
* use for <code>HOME</code> 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;
}

/**
Expand All @@ -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<DockerNetwork> network = Optional.empty();
if (!buildWrapper.getSideDockerConfigurations().isEmpty()) {
//There are side container, so create a network
Expand All @@ -124,22 +188,25 @@ public static DockerState launchContainers(RemoteDockerBuildWrapper buildWrapper
List<String> 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);

DockerState dockerState = new DockerState(buildWrapper.isDebug(),
mainId, containerIds,
network,
buildWrapper.isRemoveContainers());
buildWrapper.isRemoveContainers(),
loginTempDir);
launcher.configure(dockerState);
return dockerState;
}
Expand All @@ -159,8 +226,8 @@ private static ArgumentListBuilder getlaunchArgs(RemoteDockerBuildWrapper buildW
Optional<DockerNetwork> 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()
Expand Down Expand Up @@ -212,7 +279,8 @@ private static String launchContainer(RemoteDockerBuildWrapper buildWrapper,
AbstractDockerLauncher launcher,
FilePath workspace,
Optional<DockerNetwork> 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)
Expand All @@ -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;
Expand All @@ -258,4 +327,7 @@ public Optional<String> getNetworkId() {
return Optional.ofNullable(networkId);
}

public FilePath getLoginTempDir() {
return loginTempDir;
}
}
Loading