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

Commit 4972482

Browse files
authored
Merge pull request #41 from raydouglass/docker-login
Add support for docker login
2 parents 36b0eb9 + 67b181b commit 4972482

File tree

8 files changed

+231
-22
lines changed

8 files changed

+231
-22
lines changed

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@
6262
<version>3.0.1</version>
6363
<scope>provided</scope>
6464
</dependency>
65+
<dependency>
66+
<groupId>org.jenkins-ci.plugins</groupId>
67+
<artifactId>credentials</artifactId>
68+
<version>2.1.16</version>
69+
</dependency>
6570
</dependencies>
6671

6772
<repositories>

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import com.gpuopenanalytics.jenkins.remotedocker.job.DockerConfiguration;
2828
import hudson.EnvVars;
29+
import hudson.FilePath;
2930
import hudson.Launcher;
3031
import hudson.Proc;
3132
import hudson.util.ArgumentListBuilder;
@@ -45,6 +46,7 @@ public abstract class AbstractDockerLauncher extends Launcher.DecoratedLauncher
4546

4647
private DockerState dockerState;
4748
private DockerVersion version;
49+
private FilePath loginTempDir;
4850

4951
protected AbstractDockerLauncher(@Nonnull Launcher launcher) {
5052
super(launcher);
@@ -167,6 +169,9 @@ public Launcher.ProcStarter executeCommand(ArgumentListBuilder args) {
167169
if (!"docker".equals(args.toList().get(0))) {
168170
args.prepend("docker");
169171
}
172+
if (loginTempDir != null) {
173+
args.prepend("env", "HOME=" + loginTempDir.getRemote());
174+
}
170175
return getInner().launch()
171176
//TODO I think we should pass something here
172177
//.envs()
@@ -223,6 +228,7 @@ private DockerVersion parseVersion() throws IOException, InterruptedException {
223228
*/
224229
void configure(DockerState dockerState) {
225230
this.dockerState = dockerState;
231+
configureTempDir(dockerState.getLoginTempDir());
226232
}
227233

228234
/**
@@ -233,4 +239,8 @@ void configure(DockerState dockerState) {
233239
protected DockerState getDockerState() {
234240
return dockerState;
235241
}
242+
243+
public void configureTempDir(FilePath loginTempDir) {
244+
this.loginTempDir = loginTempDir;
245+
}
236246
}

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

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
package com.gpuopenanalytics.jenkins.remotedocker;
2626

27+
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
2728
import com.google.common.collect.ImmutableList;
2829
import com.gpuopenanalytics.jenkins.remotedocker.job.DockerConfiguration;
2930
import com.gpuopenanalytics.jenkins.remotedocker.job.SideDockerConfiguration;
@@ -34,6 +35,7 @@
3435
import hudson.slaves.WorkspaceList;
3536
import hudson.util.ArgumentListBuilder;
3637
import jenkins.model.Jenkins;
38+
import org.apache.commons.lang.StringUtils;
3739

3840
import java.io.ByteArrayOutputStream;
3941
import java.io.IOException;
@@ -58,17 +60,20 @@ public class DockerState implements Serializable {
5860
private ImmutableList<String> containerIds;
5961
private String networkId;
6062
private boolean removeContainers;
63+
private FilePath loginTempDir;
6164

6265
public DockerState(boolean debug,
6366
String mainContainerId,
6467
Collection<String> containerIds,
6568
Optional<DockerNetwork> network,
66-
boolean removeContainers) {
69+
boolean removeContainers,
70+
FilePath loginTempDir) {
6771
this.debug = debug;
6872
this.mainContainerId = mainContainerId;
6973
this.containerIds = ImmutableList.copyOf(containerIds);
7074
this.networkId = network.map(DockerNetwork::getId).orElse(null);
7175
this.removeContainers = removeContainers;
76+
this.loginTempDir = loginTempDir;
7277
}
7378

7479
private int execute(Launcher launcher,
@@ -84,13 +89,13 @@ private int execute(Launcher launcher,
8489
return status;
8590
}
8691

87-
public void tearDown(Launcher launcher) throws IOException, InterruptedException {
92+
public void tearDown(AbstractDockerLauncher launcher) throws IOException, InterruptedException {
8893
if (removeContainers) {
8994
TaskListener listener = launcher.getListener();
9095
for (String containerId : containerIds) {
9196
ArgumentListBuilder args = new ArgumentListBuilder()
9297
.add("docker", "rm", "-f", containerId);
93-
int status = execute(launcher, args);
98+
int status = execute(launcher.getInner(), args);
9499
if (status != 0) {
95100
listener.error("Failed to remove container %s",
96101
containerId);
@@ -99,12 +104,69 @@ public void tearDown(Launcher launcher) throws IOException, InterruptedException
99104
if (networkId != null) {
100105
ArgumentListBuilder args = new ArgumentListBuilder()
101106
.add("docker", "network", "rm", networkId);
102-
int status = execute(launcher, args);
107+
int status = execute(launcher.getInner(), args);
103108
if (status != 0) {
104109
listener.error("Failed to remove network %s", networkId);
105110
}
106111
}
107112
}
113+
logout(launcher.getInner());
114+
}
115+
116+
private void logout(Launcher launcher) throws IOException, InterruptedException {
117+
if (loginTempDir != null) {
118+
ArgumentListBuilder args = new ArgumentListBuilder("env",
119+
"HOME=" + loginTempDir
120+
.getRemote(),
121+
"docker",
122+
"logout");
123+
int status = execute(launcher, args);
124+
if (status != 0) {
125+
launcher.getListener().error("Failed to docker logout");
126+
}
127+
}
128+
}
129+
130+
/**
131+
* Attempt to <code>docker login</code>. Returns the temporary directory to
132+
* use for <code>HOME</code> to store docker credentials.
133+
*
134+
* @param buildWrapper
135+
* @param launcher
136+
* @param workspace
137+
* @return
138+
* @throws IOException
139+
* @throws InterruptedException
140+
*/
141+
private static FilePath login(RemoteDockerBuildWrapper buildWrapper,
142+
AbstractDockerLauncher launcher,
143+
FilePath workspace) throws IOException, InterruptedException {
144+
if (buildWrapper.getCredentialsId() != null) {
145+
UsernamePasswordCredentials creds = buildWrapper.getCredentials();
146+
FilePath tempDir = WorkspaceList.tempDir(workspace);
147+
launcher.configureTempDir(tempDir);
148+
ArgumentListBuilder args = new ArgumentListBuilder("docker",
149+
"login");
150+
args.add("-u", creds.getUsername());
151+
args.add("-p");
152+
args.addMasked(creds.getPassword());
153+
if (!StringUtils.isEmpty(buildWrapper.getDockerRegistryUrl())) {
154+
args.add(buildWrapper.getDockerRegistryUrl());
155+
}
156+
Launcher.ProcStarter cmd = launcher.executeCommand(args);
157+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
158+
cmd.stdout(launcher.getListener());
159+
cmd.stderr(baos);
160+
int status = cmd.join();
161+
if (status != 0) {
162+
launcher.getListener().error("Failed to docker login");
163+
launcher.getListener().error(baos.toString());
164+
throw new RuntimeException(
165+
"Could not docker login. Are your credentials correct?");
166+
}
167+
return tempDir;
168+
}
169+
return null;
108170
}
109171

110172
/**
@@ -116,6 +178,8 @@ public void tearDown(Launcher launcher) throws IOException, InterruptedException
116178
public static DockerState launchContainers(RemoteDockerBuildWrapper buildWrapper,
117179
AbstractDockerLauncher launcher,
118180
FilePath workspace) throws IOException, InterruptedException {
181+
FilePath loginTempDir = login(buildWrapper, launcher, workspace);
182+
119183
Optional<DockerNetwork> network = Optional.empty();
120184
if (!buildWrapper.getSideDockerConfigurations().isEmpty()) {
121185
//There are side container, so create a network
@@ -124,22 +188,25 @@ public static DockerState launchContainers(RemoteDockerBuildWrapper buildWrapper
124188
List<String> containerIds = new ArrayList<>();
125189
//Launch side containers first
126190
for (SideDockerConfiguration side : buildWrapper.getSideDockerConfigurations()) {
127-
String id = launchContainer(buildWrapper, side, false, launcher, workspace,
191+
String id = launchContainer(buildWrapper, side, false, launcher,
192+
workspace,
128193
network);
129194
containerIds.add(id);
130195
}
131196

132197
//Launch main container
133198
DockerConfiguration main = buildWrapper.getDockerConfiguration();
134-
String mainId = launchContainer(buildWrapper, main, true, launcher, workspace,
199+
String mainId = launchContainer(buildWrapper, main, true, launcher,
200+
workspace,
135201
network);
136202
containerIds.add(mainId);
137203
Collections.reverse(containerIds);
138204

139205
DockerState dockerState = new DockerState(buildWrapper.isDebug(),
140206
mainId, containerIds,
141207
network,
142-
buildWrapper.isRemoveContainers());
208+
buildWrapper.isRemoveContainers(),
209+
loginTempDir);
143210
launcher.configure(dockerState);
144211
return dockerState;
145212
}
@@ -159,8 +226,8 @@ private static ArgumentListBuilder getlaunchArgs(RemoteDockerBuildWrapper buildW
159226
Optional<DockerNetwork> network) throws IOException, InterruptedException {
160227
String workspacePath = workspace.getRemote();
161228
String workspaceTarget = Optional.ofNullable(
162-
buildWrapper.getWorkspaceOverride())
163-
.orElse(workspacePath);
229+
buildWrapper.getWorkspaceOverride())
230+
.orElse(workspacePath);
164231
//Fully resolve the source workspace
165232
String workspaceSrc = Paths.get(workspacePath)
166233
.toAbsolutePath()
@@ -212,7 +279,8 @@ private static String launchContainer(RemoteDockerBuildWrapper buildWrapper,
212279
AbstractDockerLauncher launcher,
213280
FilePath workspace,
214281
Optional<DockerNetwork> network) throws IOException, InterruptedException {
215-
ArgumentListBuilder args = getlaunchArgs(buildWrapper, config, isMain, launcher,
282+
ArgumentListBuilder args = getlaunchArgs(buildWrapper, config, isMain,
283+
launcher,
216284
workspace, network);
217285
ByteArrayOutputStream baos = new ByteArrayOutputStream();
218286
int status = launcher.executeCommand(args)
@@ -231,7 +299,8 @@ private static String launchContainer(RemoteDockerBuildWrapper buildWrapper,
231299
containerId,
232300
ImmutableList.of(containerId),
233301
Optional.empty(),
234-
false);
302+
false,
303+
null);
235304
launcher.configure(tempState);
236305
config.postCreate(launcher);
237306
return containerId;
@@ -258,4 +327,7 @@ public Optional<String> getNetworkId() {
258327
return Optional.ofNullable(networkId);
259328
}
260329

330+
public FilePath getLoginTempDir() {
331+
return loginTempDir;
332+
}
261333
}

0 commit comments

Comments
 (0)