Skip to content

Commit b05d3a2

Browse files
committed
add container manager for ssh connection
1 parent cb4f1a4 commit b05d3a2

File tree

2 files changed

+112
-15
lines changed

2 files changed

+112
-15
lines changed

docker/src/main/java/com/flowci/docker/DockerSSHManager.java

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
import com.fasterxml.jackson.databind.ObjectMapper;
77
import com.flowci.docker.domain.DockerStartOption;
88
import com.flowci.docker.domain.SSHOption;
9+
import com.flowci.domain.ObjectWrapper;
910
import com.flowci.util.StringHelper;
1011
import com.github.dockerjava.api.command.InspectContainerResponse;
1112
import com.github.dockerjava.api.model.Container;
1213
import com.github.dockerjava.api.model.Frame;
14+
import com.github.dockerjava.api.model.StreamType;
1315
import com.jcraft.jsch.*;
1416
import lombok.AllArgsConstructor;
1517
import lombok.Getter;
@@ -24,8 +26,11 @@ public class DockerSSHManager implements DockerManager {
2426

2527
private static final int ChannelTimeout = 10 * 1000;
2628

29+
private static final String FormatAsJson = "--format \"{{json .}}\"";
30+
2731
private static final ObjectMapper mapper = new ObjectMapper();
2832

33+
2934
private Session session;
3035

3136
private final ContainerManager containerManager = new ContainerManagerImpl();
@@ -60,66 +65,127 @@ public ImageManager getImageManager() {
6065
}
6166

6267
private class ContainerManagerImpl implements ContainerManager {
68+
6369
@Override
6470
public List<Container> list(String statusFilter, String nameFilter) throws Exception {
6571
StringBuilder cmd = new StringBuilder();
6672
cmd.append("docker ps -a ");
67-
6873
if (StringHelper.hasValue(statusFilter)) {
6974
cmd.append(String.format("--filter \"status=%s\" ", statusFilter));
7075
}
71-
7276
if (StringHelper.hasValue(nameFilter)) {
7377
cmd.append(String.format("--filter \"name=%s\" ", nameFilter));
7478
}
75-
76-
cmd.append("--format \"{{json .}}\"");
79+
cmd.append(FormatAsJson);
7780

7881
List<Container> list = new LinkedList<>();
79-
8082
Output output = runCmd(cmd.toString(), (line) -> {
8183
try {
8284
list.add(mapper.readValue(line, Container.class));
8385
} catch (JsonProcessingException ignore) {
84-
ignore.printStackTrace();
8586
}
8687
});
8788

88-
if (output.getExit() != 0) {
89-
throw new Exception(output.getErr());
90-
}
91-
89+
throwExceptionIfError(output);
9290
return list;
9391
}
9492

9593
@Override
9694
public InspectContainerResponse inspect(String containerId) throws Exception {
97-
return null;
95+
String cmd = String.format("docker inspect %s %s", containerId, FormatAsJson);
96+
final ObjectWrapper<InspectContainerResponse> inspected = new ObjectWrapper<>();
97+
98+
Output output = runCmd(cmd, (line) -> {
99+
try {
100+
inspected.setValue(mapper.readValue(line, InspectContainerResponse.class));
101+
} catch (JsonProcessingException ignore) {
102+
}
103+
});
104+
throwExceptionIfError(output);
105+
106+
if (!inspected.hasValue()) {
107+
throw new Exception(String.format("Unable to inspect container %s result", containerId));
108+
}
109+
110+
return inspected.getValue();
98111
}
99112

100113
@Override
101114
public String start(DockerStartOption option) throws Exception {
102-
return null;
115+
StringBuilder cmd = new StringBuilder();
116+
cmd.append("docker run -d ");
117+
118+
if (option.hasName()) {
119+
cmd.append(String.format("--name %s ", option.getName()));
120+
}
121+
122+
List<String> entrypoint = option.getEntrypoint();
123+
if (!entrypoint.isEmpty()) {
124+
cmd.append(String.format("--entrypoint %s ", entrypoint.get(0)));
125+
}
126+
127+
option.getEnv().forEach((k, v) -> cmd.append(String.format("-e %s=%s ", k, v)));
128+
option.getBind().forEach((s, t) -> cmd.append(String.format("-v %s:%s ", s, t)));
129+
cmd.append(option.getImage());
130+
131+
if (!entrypoint.isEmpty() && entrypoint.size() > 1) {
132+
cmd.append(" ");
133+
for (int i = 1; i < entrypoint.size(); i++) {
134+
cmd.append(entrypoint.get(i)).append(" ");
135+
}
136+
}
137+
138+
ObjectWrapper<String> cid = new ObjectWrapper<>();
139+
Output output = runCmd(cmd.toString(), cid::setValue);
140+
throwExceptionIfError(output);
141+
142+
if (!cid.hasValue()) {
143+
throw new Exception("Unable to get container line from output");
144+
}
145+
146+
return cid.getValue();
103147
}
104148

105149
@Override
106150
public void wait(String containerId, int timeoutInSeconds, Consumer<Frame> onLog) throws Exception {
107-
151+
String cmd = String.format("docker logs -f %s", containerId);
152+
Output output = runCmd(cmd, (log) -> {
153+
if (onLog != null) {
154+
onLog.accept(new Frame(StreamType.RAW, log.getBytes()));
155+
}
156+
});
157+
throwExceptionIfError(output);
108158
}
109159

110160
@Override
111161
public void stop(String containerId) throws Exception {
112-
162+
InspectContainerResponse.ContainerState state = inspect(containerId).getState();
163+
Boolean running = state.getRunning();
164+
if (running != null && running) {
165+
String cmd = String.format("docker stop %s", containerId);
166+
Output output = runCmd(cmd, null);
167+
throwExceptionIfError(output);
168+
}
113169
}
114170

115171
@Override
116172
public void resume(String containerId) throws Exception {
117-
173+
String cmd = String.format("docker start %s", containerId);
174+
Output output = runCmd(cmd, null);
175+
throwExceptionIfError(output);
118176
}
119177

120178
@Override
121179
public void delete(String containerId) throws Exception {
180+
String cmd = String.format("docker rm -f %s", containerId);
181+
Output output = runCmd(cmd, null);
182+
throwExceptionIfError(output);
183+
}
184+
}
122185

186+
private void throwExceptionIfError(Output output) throws Exception {
187+
if (output.getExit() != 0) {
188+
throw new Exception(output.getErr());
123189
}
124190
}
125191

docker/src/test/java/com/flowci/docker/test/DockerSSHManagerTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.flowci.docker.test;
22

3+
import com.flowci.docker.ContainerManager;
34
import com.flowci.docker.DockerManager;
45
import com.flowci.docker.DockerSSHManager;
6+
import com.flowci.docker.domain.DockerStartOption;
57
import com.flowci.docker.domain.SSHOption;
68
import com.flowci.util.StringHelper;
9+
import com.github.dockerjava.api.command.InspectContainerResponse;
710
import com.github.dockerjava.api.model.Container;
811
import org.junit.Assert;
912
import org.junit.Before;
@@ -29,6 +32,34 @@ public void should_list_containers() throws Exception {
2932
Assert.assertNotNull(list);
3033
}
3134

35+
@Test
36+
public void should_create_start_and_delete_container() throws Exception {
37+
DockerStartOption option = new DockerStartOption();
38+
option.setImage("ubuntu:18.04");
39+
option.addEnv("FLOW_TEST", "hello.world");
40+
41+
option.addEntryPoint("/bin/bash");
42+
option.addEntryPoint("-c");
43+
option.addEntryPoint("\"echo helloworld\nsleep 10\necho end\necho helloworld\"");
44+
45+
ContainerManager cm = manager.getContainerManager();
46+
String cid = cm.start(option);
47+
Assert.assertNotNull(cid);
48+
49+
cm.wait(cid, 60, (frame -> {
50+
System.out.println(new String(frame.getPayload()));
51+
}));
52+
53+
cm.stop(cid);
54+
cm.delete(cid);
55+
}
56+
57+
@Test
58+
public void should_inspect_container() throws Exception {
59+
InspectContainerResponse inspect = manager.getContainerManager().inspect("a86fc2720b11");
60+
Assert.assertNotNull(inspect);
61+
}
62+
3263
protected InputStream load(String resource) {
3364
return getClass().getClassLoader().getResourceAsStream(resource);
3465
}

0 commit comments

Comments
 (0)