diff --git a/web-api/src/main/java/com/jeesite/modules/apps/Module/DockerInfo.java b/web-api/src/main/java/com/jeesite/modules/apps/Module/DockerInfo.java new file mode 100644 index 0000000..29727c3 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/Module/DockerInfo.java @@ -0,0 +1,19 @@ +package com.jeesite.modules.apps.Module; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class DockerInfo implements Serializable { + + private String username; // 登录账号 + private String password; // 登录密码 + private String rootPath; // 初始目录 + private String authType; // 认证方式 + private String privateKey; // 密钥内容 + private String hostIp; // 主机域名 + private Integer hostPort; // 主机端口 + private String containerId; + public DockerInfo(){} +} diff --git a/web-api/src/main/java/com/jeesite/modules/apps/web/docker/DockerController.java b/web-api/src/main/java/com/jeesite/modules/apps/web/docker/DockerController.java index 8dc11f7..f1b7044 100644 --- a/web-api/src/main/java/com/jeesite/modules/apps/web/docker/DockerController.java +++ b/web-api/src/main/java/com/jeesite/modules/apps/web/docker/DockerController.java @@ -1,9 +1,98 @@ package com.jeesite.modules.apps.web.docker; +import com.jeesite.modules.apps.Module.ContainerInfo; +import com.jeesite.modules.apps.Module.DockerInfo; +import com.jeesite.modules.apps.Module.DockerResult; +import com.jeesite.modules.biz.dao.MySftpAccountsDao; +import com.jeesite.modules.biz.entity.MySftpAccounts; +import com.jeesite.modules.utils.DockerUtil; +import jakarta.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; @Controller -@RequestMapping(value = "${adminPath}/desktop/analysis") +@RequestMapping(value = "${adminPath}/docker/analysis") public class DockerController { + + @Resource + private MySftpAccountsDao mySftpAccountsDao; + + /** + * 启动容器 + */ + @RequestMapping(value = "start") + @ResponseBody + public DockerResult start(DockerInfo dockerInfo) { + return DockerUtil.start(dockerInfo); + } + + /** + * 停止容器 + */ + @RequestMapping(value = "stop") + @ResponseBody + public DockerResult stop(DockerInfo dockerInfo) { + return DockerUtil.stop(dockerInfo); + } + + /** + * 重启容器 + */ + @RequestMapping(value = "restart") + @ResponseBody + public DockerResult restart(DockerInfo dockerInfo) { + return DockerUtil.restart(dockerInfo); + } + + /** + * 获取容器详情 + */ + @RequestMapping(value = "inspect") + @ResponseBody + public DockerResult inspect(DockerInfo dockerInfo) { + return DockerUtil.inspect(dockerInfo); + } + + /** + * 获取容器日志 + */ + @RequestMapping(value = "logs") + @ResponseBody + public DockerResult logs(DockerInfo dockerInfo) { + return DockerUtil.getLogs(dockerInfo, 20000, true); + } + + /** + * 获取容器列表 + */ + @RequestMapping(value = "listAll") + @ResponseBody + public List listAll(DockerInfo dockerInfo) { + return DockerUtil.listContainers(dockerInfo, true); + } + + /** + * 获取服务列表 + */ + @RequestMapping(value = "listInfo") + @ResponseBody + public List listInfo() { + List accountsList = mySftpAccountsDao.findList(new MySftpAccounts()); + return accountsList.stream() + .map(account -> { + DockerInfo info = new DockerInfo(); + info.setHostIp(account.getHostIp()); + info.setHostPort(account.getHostPort()); + info.setUsername(account.getUsername()); + info.setPassword(account.getPassword()); + info.setRootPath(account.getRootPath()); + info.setAuthType(account.getAuthType()); + info.setPrivateKey(account.getPrivateKey()); + return info; + }) + .toList(); + } } diff --git a/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpAccounts.java b/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpAccounts.java index 9b850ad..b93a6ac 100644 --- a/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpAccounts.java +++ b/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpAccounts.java @@ -39,6 +39,14 @@ import java.io.Serial; @Column(name = "account_remark", attrName = "accountRemark", label = "账号备注"), @Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true), @Column(name = "ustatus", attrName = "ustatus", label = "状态"), +}, joinTable = { + @JoinTable(type = Type.LEFT_JOIN, entity = MySftpHosts.class, alias = "b", + on = "a.host_id = b.host_id", attrName = "this", + columns = { + @Column(name = "host_ip", attrName = "hostIp", label = "主机域名"), + @Column(name = "host_port", attrName = "hostPort", label = "主机端口"), + @Column(name = "host_name", attrName = "hostName", label = "主机名称"), + }), }, orderBy = "a.create_time DESC" ) @Data @@ -59,9 +67,9 @@ public class MySftpAccounts extends DataEntity implements Serial private Date updateTime; // 更新时间 private String ustatus; // 状态 - private String hostIp; // 主机域名 - private Integer hostPort; // 主机端口 - private String hostName; // 主机名称 + private String hostIp; // 主机域名 + private Integer hostPort; // 主机端口 + private String hostName; // 主机名称 public MySftpAccounts() { this(null); @@ -71,116 +79,6 @@ public class MySftpAccounts extends DataEntity implements Serial this.hostId = hostId; } - @JsonFormat(pattern = "yyyy-MM-dd HH:mm") - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - public String getAccountId() { - return accountId; - } - - public void setAccountId(String accountId) { - this.accountId = accountId; - } - - public MySftpHosts getHostId() { - return hostId; - } - - public void setHostId(MySftpHosts hostId) { - this.hostId = hostId; - } - - @NotBlank(message = "登录账号不能为空") - @Size(min = 0, max = 100, message = "登录账号长度不能超过 100 个字符") - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - @NotBlank(message = "登录密码不能为空") - @Size(min = 0, max = 255, message = "登录密码长度不能超过 255 个字符") - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - @NotBlank(message = "初始目录不能为空") - @Size(min = 0, max = 255, message = "初始目录长度不能超过 255 个字符") - public String getRootPath() { - return rootPath; - } - - public void setRootPath(String rootPath) { - this.rootPath = rootPath; - } - - @NotBlank(message = "认证方式不能为空") - @Size(min = 0, max = 12, message = "认证方式长度不能超过 12 个字符") - public String getAuthType() { - return authType; - } - - public void setAuthType(String authType) { - this.authType = authType; - } - - public String getPrivateKey() { - return privateKey; - } - - public void setPrivateKey(String privateKey) { - this.privateKey = privateKey; - } - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm") - public Date getExpireTime() { - return expireTime; - } - - public void setExpireTime(Date expireTime) { - this.expireTime = expireTime; - } - - @Size(min = 0, max = 255, message = "账号备注长度不能超过 255 个字符") - public String getAccountRemark() { - return accountRemark; - } - - public void setAccountRemark(String accountRemark) { - this.accountRemark = accountRemark; - } - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm") - public Date getUpdateTime() { - return updateTime; - } - - public void setUpdateTime(Date updateTime) { - this.updateTime = updateTime; - } - - @NotBlank(message = "状态不能为空") - @Size(min = 0, max = 12, message = "状态长度不能超过 12 个字符") - public String getUstatus() { - return ustatus; - } - - public void setUstatus(String ustatus) { - this.ustatus = ustatus; - } - public Date getCreateTime_gte() { return sqlMap.getWhere().getValue("create_time", QueryType.GTE); } diff --git a/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpHosts.java b/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpHosts.java index d22c710..64df2b0 100644 --- a/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpHosts.java +++ b/web-api/src/main/java/com/jeesite/modules/biz/entity/MySftpHosts.java @@ -22,6 +22,7 @@ import com.jeesite.common.utils.excel.annotation.ExcelField.Align; import com.jeesite.common.utils.excel.annotation.ExcelFields; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Setter; import java.io.Serial; @@ -75,87 +76,9 @@ public class MySftpHosts extends DataEntity implements Serializabl super(id); } - @JsonFormat(pattern = "yyyy-MM-dd HH:mm") - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - public String getHostId() { - return hostId; - } - - public void setHostId(String hostId) { - this.hostId = hostId; - } - - @NotBlank(message="主机域名不能为空") - @Size(min=0, max=64, message="主机域名长度不能超过 64 个字符") - public String getHostIp() { - return hostIp; - } - - public void setHostIp(String hostIp) { - this.hostIp = hostIp; - } - - @NotNull(message="主机端口不能为空") - public Integer getHostPort() { - return hostPort; - } - - public void setHostPort(Integer hostPort) { - this.hostPort = hostPort; - } - - @NotBlank(message="主机名称不能为空") - @Size(min=0, max=100, message="主机名称长度不能超过 100 个字符") - public String getHostName() { - return hostName; - } - - public void setHostName(String hostName) { - this.hostName = hostName; - } - - @Size(min=0, max=255, message="备注说明长度不能超过 255 个字符") - public String getHostRemark() { - return hostRemark; - } - - public void setHostRemark(String hostRemark) { - this.hostRemark = hostRemark; - } - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm") - public Date getUpdateTime() { - return updateTime; - } - - public void setUpdateTime(Date updateTime) { - this.updateTime = updateTime; - } - - @NotBlank(message="状态不能为空") - @Size(min=0, max=12, message="状态长度不能超过 12 个字符") - public String getUstatus() { - return ustatus; - } - - public void setUstatus(String ustatus) { - this.ustatus = ustatus; - } - @Valid public List getMySftpAccountsList() { return mySftpAccountsList; } - public void setMySftpAccountsList(List mySftpAccountsList) { - this.mySftpAccountsList = mySftpAccountsList; - } - } \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java b/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java index 27b59bf..72e81ae 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java @@ -2,8 +2,8 @@ package com.jeesite.modules.utils; import com.jcraft.jsch.*; import com.jeesite.modules.apps.Module.ContainerInfo; +import com.jeesite.modules.apps.Module.DockerInfo; import com.jeesite.modules.apps.Module.DockerResult; -import com.jeesite.modules.biz.entity.MySftpAccounts; import java.io.*; import java.nio.charset.StandardCharsets; @@ -20,65 +20,38 @@ public class DockerUtil { private static final int SSH_TIMEOUT = 30000; - public static DockerResult start(MySftpAccounts account, String image, String name, - String[] ports, String[] envs) { - StringBuilder cmd = new StringBuilder("docker run -d"); - if (name != null && !name.isEmpty()) { - cmd.append(" --name ").append(name); - } - if (ports != null) { - for (String p : ports) cmd.append(" -p ").append(p); - } - if (envs != null) { - for (String e : envs) cmd.append(" -e \"").append(e).append("\""); - } - cmd.append(" ").append(image); - return exec(account, cmd.toString()); + public static DockerResult start(DockerInfo dockerInfo) { + return exec(dockerInfo, "docker start " + dockerInfo.getContainerId()); } - public static DockerResult stop(MySftpAccounts account, String containerId) { - return exec(account, "docker stop " + containerId); + public static DockerResult stop(DockerInfo dockerInfo) { + return exec(dockerInfo, "docker stop " + dockerInfo.getContainerId()); } - public static DockerResult restart(MySftpAccounts account, String containerId) { - return exec(account, "docker restart " + containerId); + public static DockerResult restart(DockerInfo dockerInfo) { + return exec(dockerInfo, "docker restart " + dockerInfo.getContainerId()); } - public static DockerResult getLogs(MySftpAccounts account, String containerId, + public static DockerResult getLogs(DockerInfo dockerInfo, int tail, boolean timestamps) { String cmd = "docker logs" + (timestamps ? " -t" : "") - + " --tail " + tail + " " + containerId; - return exec(account, cmd); + + " --tail " + tail + " " + dockerInfo.getContainerId(); + return exec(dockerInfo, cmd); } - public static DockerResult list(MySftpAccounts account, boolean all) { - return exec(account, all ? "docker ps -a" : "docker ps"); + public static DockerResult list(DockerInfo dockerInfo, boolean all) { + return exec(dockerInfo, all ? "docker ps -a" : "docker ps"); } - public static DockerResult remove(MySftpAccounts account, String containerId, boolean force) { - String cmd = force - ? "docker stop " + containerId + " && docker rm " + containerId - : "docker rm " + containerId; - return exec(account, cmd); + public static DockerResult inspect(DockerInfo dockerInfo) { + return exec(dockerInfo, "docker inspect " + dockerInfo.getContainerId()); } - public static DockerResult inspect(MySftpAccounts account, String containerId) { - return exec(account, "docker inspect " + containerId); - } - - public static DockerResult pull(MySftpAccounts account, String image) { - return exec(account, "docker pull " + image); - } - - public static DockerResult version(MySftpAccounts account) { - return exec(account, "docker version --format '{{json .}}'"); - } - - public static List listContainers(MySftpAccounts account, boolean all) { + public static List listContainers(DockerInfo dockerInfo, boolean all) { List list = new ArrayList<>(); String cmd = (all ? "docker ps -a" : "docker ps") + " --format \"{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}\""; - DockerResult r = exec(account, cmd); + DockerResult r = exec(dockerInfo, cmd); if (!r.isSuccess()) { return new ArrayList<>(); } @@ -99,22 +72,22 @@ public class DockerUtil { return list; } - public static DockerResult exec(MySftpAccounts account, String command) { + public static DockerResult exec(DockerInfo dockerInfo, String command) { JSch jsch = new JSch(); Session session = null; ChannelExec channel = null; try { - int port = account.getHostPort() != null ? account.getHostPort() : 22; - session = jsch.getSession(account.getUsername(), account.getHostIp(), port); + int port = dockerInfo.getHostPort() != null ? dockerInfo.getHostPort() : 22; + session = jsch.getSession(dockerInfo.getUsername(), dockerInfo.getHostIp(), port); session.setTimeout(SSH_TIMEOUT); - if ("key".equalsIgnoreCase(account.getAuthType()) - && account.getPrivateKey() != null && !account.getPrivateKey().isEmpty()) { + if ("key".equalsIgnoreCase(dockerInfo.getAuthType()) + && dockerInfo.getPrivateKey() != null && !dockerInfo.getPrivateKey().isEmpty()) { jsch.addIdentity("temp", - account.getPrivateKey().getBytes(StandardCharsets.UTF_8), + dockerInfo.getPrivateKey().getBytes(StandardCharsets.UTF_8), null, null); - } else if (account.getPassword() != null && !account.getPassword().isEmpty()) { - session.setPassword(account.getPassword()); + } else if (dockerInfo.getPassword() != null && !dockerInfo.getPassword().isEmpty()) { + session.setPassword(dockerInfo.getPassword()); } else { return DockerResult.fail("SSH 认证信息不完整:缺少密码或私钥"); } @@ -125,8 +98,8 @@ public class DockerUtil { session.connect(SSH_TIMEOUT); channel = (ChannelExec) session.openChannel("exec"); - String finalCmd = (account.getRootPath() != null && !account.getRootPath().isEmpty()) - ? "cd " + account.getRootPath() + " && " + command + String finalCmd = (dockerInfo.getRootPath() != null && !dockerInfo.getRootPath().isEmpty()) + ? "cd " + dockerInfo.getRootPath() + " && " + command : command; channel.setCommand(finalCmd); channel.setInputStream(null);