首页接口重构
This commit is contained in:
@@ -5,93 +5,32 @@ import com.jeesite.modules.apps.Module.ContainerInfo;
|
||||
import com.jeesite.modules.apps.Module.DockerResult;
|
||||
import com.jeesite.modules.biz.entity.MySftpAccounts;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Docker 容器管理工具
|
||||
* <p>
|
||||
* 通过 SSH 连接主机,基于 MySftpAccounts 凭证执行 docker 命令。
|
||||
* 支持密码认证和私钥认证。
|
||||
*/
|
||||
public class DockerUtil {
|
||||
|
||||
private static final int SSH_TIMEOUT = 30000;
|
||||
|
||||
public static DockerResult start(MySftpAccounts accounts, String containerId) {
|
||||
return exec(accounts, "docker start " + containerId);
|
||||
}
|
||||
|
||||
public static DockerResult stop(MySftpAccounts accounts, String containerId) {
|
||||
return exec(accounts, "docker stop " + containerId);
|
||||
}
|
||||
|
||||
public static DockerResult restart(MySftpAccounts accounts, String containerId) {
|
||||
return exec(accounts, "docker restart " + containerId);
|
||||
}
|
||||
|
||||
public static DockerResult getLogs(MySftpAccounts accounts, String containerId,
|
||||
int tail, boolean timestamps) {
|
||||
String cmd = "docker logs" + (timestamps ? " -t" : "")
|
||||
+ " --tail " + tail + " " + containerId;
|
||||
return exec(accounts, cmd);
|
||||
}
|
||||
|
||||
public static DockerResult list(MySftpAccounts accounts, boolean all) {
|
||||
return exec(accounts, all ? "docker ps -a" : "docker ps");
|
||||
}
|
||||
|
||||
public static DockerResult inspect(MySftpAccounts accounts, String containerId) {
|
||||
return exec(accounts, "docker inspect " + containerId);
|
||||
}
|
||||
|
||||
public static List<ContainerInfo> listContainers(MySftpAccounts accounts, boolean all) {
|
||||
List<ContainerInfo> list = new ArrayList<>();
|
||||
String cmd = (all ? "docker ps -a" : "docker ps")
|
||||
+ " --format \"{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}\"";
|
||||
DockerResult r = exec(accounts, cmd);
|
||||
if (!r.isSuccess()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
for (String line : r.getOutput().split("\n")) {
|
||||
if (line.trim().isEmpty()) continue;
|
||||
String[] p = line.split("\\|");
|
||||
if (p.length < 2) continue;
|
||||
ContainerInfo info = new ContainerInfo();
|
||||
info.setContainerId(p[0].trim());
|
||||
info.setImage(p[1].trim());
|
||||
info.setCommand(p.length > 2 ? p[2].trim() : "");
|
||||
info.setCreated(p.length > 3 ? p[3].trim() : "");
|
||||
info.setStatus(p.length > 4 ? p[4].trim() : "");
|
||||
info.setPorts(p.length > 5 ? p[5].trim() : "");
|
||||
info.setNames(p.length > 6 ? p[6].trim() : "");
|
||||
info.setAccountId(accounts.getAccountId());
|
||||
list.add(info);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static DockerResult exec(MySftpAccounts accounts, String command) {
|
||||
private static String runCommand(MySftpAccounts account, String cmd) {
|
||||
JSch jsch = new JSch();
|
||||
Session session = null;
|
||||
ChannelExec channel = null;
|
||||
|
||||
try {
|
||||
int port = accounts.getHostPort() != null ? accounts.getHostPort() : 22;
|
||||
session = jsch.getSession(accounts.getUsername(), accounts.getHostIp(), port);
|
||||
int port = account.getHostPort() == null ? 22 : account.getHostPort();
|
||||
session = jsch.getSession(account.getUsername(), account.getHostIp(), port);
|
||||
session.setTimeout(SSH_TIMEOUT);
|
||||
|
||||
if ("key".equalsIgnoreCase(accounts.getAuthType())
|
||||
&& accounts.getPrivateKey() != null && !accounts.getPrivateKey().isEmpty()) {
|
||||
jsch.addIdentity("temp",
|
||||
accounts.getPrivateKey().getBytes(StandardCharsets.UTF_8),
|
||||
null, null);
|
||||
} else if (accounts.getPassword() != null && !accounts.getPassword().isEmpty()) {
|
||||
session.setPassword(accounts.getPassword());
|
||||
// 认证
|
||||
if ("key".equalsIgnoreCase(account.getAuthType()) && account.getPrivateKey() != null) {
|
||||
jsch.addIdentity("temp", account.getPrivateKey().getBytes(StandardCharsets.UTF_8), null, null);
|
||||
} else {
|
||||
return DockerResult.fail("SSH 认证信息不完整:缺少密码或私钥");
|
||||
session.setPassword(account.getPassword());
|
||||
}
|
||||
|
||||
Hashtable<String, String> config = new Hashtable<>();
|
||||
@@ -99,46 +38,85 @@ public class DockerUtil {
|
||||
session.setConfig(config);
|
||||
session.connect(SSH_TIMEOUT);
|
||||
|
||||
// 执行命令
|
||||
channel = (ChannelExec) session.openChannel("exec");
|
||||
String finalCmd = (accounts.getRootPath() != null && !accounts.getRootPath().isEmpty())
|
||||
? "cd " + accounts.getRootPath() + " && " + command
|
||||
: command;
|
||||
channel.setCommand(finalCmd);
|
||||
channel.setInputStream(null);
|
||||
String command = account.getRootPath() != null && !account.getRootPath().isEmpty()
|
||||
? "cd " + account.getRootPath() + " && " + cmd
|
||||
: cmd;
|
||||
|
||||
channel.setCommand(command);
|
||||
InputStream in = channel.getInputStream();
|
||||
ByteArrayOutputStream errOut = new ByteArrayOutputStream();
|
||||
channel.setExtOutputStream(errOut);
|
||||
|
||||
channel.connect();
|
||||
|
||||
StringBuilder outBuilder = new StringBuilder();
|
||||
if (in != null) {
|
||||
byte[] buf = new byte[4096];
|
||||
int n;
|
||||
while ((n = in.read(buf)) != -1) {
|
||||
outBuilder.append(new String(buf, 0, n, StandardCharsets.UTF_8));
|
||||
}
|
||||
// 读取输出
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
|
||||
String stdout = outBuilder.toString().trim();
|
||||
String stderr = errOut.toString(StandardCharsets.UTF_8).trim();
|
||||
int exitCode = channel.getExitStatus();
|
||||
return out.toString(StandardCharsets.UTF_8).trim();
|
||||
|
||||
if (exitCode == 0) {
|
||||
return DockerResult.ok(stdout);
|
||||
} else {
|
||||
return DockerResult.fail("命令执行失败,退出码: " + exitCode,
|
||||
stderr.isEmpty() ? stdout : stderr);
|
||||
}
|
||||
|
||||
} catch (JSchException e) {
|
||||
return DockerResult.fail("SSH 连接失败: " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
return DockerResult.fail("IO 异常: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
if (channel != null && channel.isConnected()) channel.disconnect();
|
||||
if (session != null && session.isConnected()) session.disconnect();
|
||||
if (channel != null) channel.disconnect();
|
||||
if (session != null) session.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ContainerInfo> listContainers(MySftpAccounts accounts, boolean all) {
|
||||
List<ContainerInfo> list = new ArrayList<>();
|
||||
String cmd = (all ? "docker ps -a" : "docker ps")
|
||||
+ " --format \"{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}\"";
|
||||
|
||||
String output = runCommand(accounts, cmd);
|
||||
if (output == null || output.isBlank()) return list;
|
||||
for (String line : output.split("\\R")) {
|
||||
if (line.isBlank()) continue;
|
||||
String[] arr = line.split("\\|");
|
||||
ContainerInfo info = new ContainerInfo();
|
||||
info.setContainerId(arr.length > 0 ? arr[0].trim() : "");
|
||||
info.setImage(arr.length > 1 ? arr[1].trim() : "");
|
||||
info.setCommand(arr.length > 2 ? arr[2].trim() : "");
|
||||
info.setCreated(arr.length > 3 ? arr[3].trim() : "");
|
||||
info.setStatus(arr.length > 4 ? arr[4].trim() : "");
|
||||
info.setPorts(arr.length > 5 ? arr[5].trim() : "");
|
||||
info.setNames(arr.length > 6 ? arr[6].trim() : "");
|
||||
info.setAccountId(accounts.getAccountId());
|
||||
list.add(info);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
public static DockerResult start(MySftpAccounts accounts, String containerId) {
|
||||
String res = runCommand(accounts, "docker start " + containerId);
|
||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("执行失败");
|
||||
}
|
||||
|
||||
public static DockerResult stop(MySftpAccounts accounts, String containerId) {
|
||||
String res = runCommand(accounts, "docker stop " + containerId);
|
||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("执行失败");
|
||||
}
|
||||
|
||||
public static DockerResult restart(MySftpAccounts accounts, String containerId) {
|
||||
String res = runCommand(accounts, "docker restart " + containerId);
|
||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("执行失败");
|
||||
}
|
||||
|
||||
public static DockerResult getLogs(MySftpAccounts accounts, String containerId, int tail, boolean timestamps) {
|
||||
String cmd = "docker logs " + (timestamps ? "-t " : "") + "--tail " + tail + " " + containerId;
|
||||
String res = runCommand(accounts, cmd);
|
||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("获取日志失败");
|
||||
}
|
||||
|
||||
public static DockerResult list(MySftpAccounts accounts, boolean all) {
|
||||
String res = runCommand(accounts, all ? "docker ps -a" : "docker ps");
|
||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("获取列表失败");
|
||||
}
|
||||
|
||||
public static DockerResult inspect(MySftpAccounts accounts, String containerId) {
|
||||
String res = runCommand(accounts, "docker inspect " + containerId);
|
||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("查询详情失败");
|
||||
}
|
||||
}
|
||||
@@ -36,12 +36,12 @@ server:
|
||||
#========= Database settings ==========#
|
||||
#======================================#
|
||||
|
||||
jdbc:
|
||||
jdbc:
|
||||
type: mysql
|
||||
driver: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.31.182:13306/system?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||
username: dream
|
||||
password: info_dream
|
||||
url: jdbc:mysql://127.0.0.1:13306/my_app?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: root_dream
|
||||
testSql: SELECT 1
|
||||
encrypt:
|
||||
username: false
|
||||
@@ -156,7 +156,7 @@ web:
|
||||
addPathPatterns: >
|
||||
${frontPath}/**
|
||||
excludePathPatterns: ~
|
||||
core:
|
||||
core:
|
||||
enabled: true
|
||||
|
||||
# 在线API文档
|
||||
|
||||
Reference in New Issue
Block a user