Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.dromara.jpom.func.assets.controller.MachineDockerController Maven / Gradle / Ivy
/*
* Copyright (c) 2019 Of Him Code Technology Studio
* Jpom is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.jpom.func.assets.controller;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.db.Entity;
import cn.keepbx.jpom.IJsonMessage;
import cn.keepbx.jpom.model.JsonMessage;
import cn.keepbx.jpom.plugins.IPlugin;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.ServerConst;
import org.dromara.jpom.common.i18n.I18nMessageUtil;
import org.dromara.jpom.common.validator.ValidatorItem;
import org.dromara.jpom.func.BaseGroupNameController;
import org.dromara.jpom.func.assets.model.MachineDockerModel;
import org.dromara.jpom.func.assets.model.MachineSshModel;
import org.dromara.jpom.func.assets.server.MachineDockerServer;
import org.dromara.jpom.func.assets.server.MachineSshServer;
import org.dromara.jpom.func.cert.model.CertificateInfoModel;
import org.dromara.jpom.func.cert.service.CertificateInfoService;
import org.dromara.jpom.model.PageResultDto;
import org.dromara.jpom.model.data.WorkspaceModel;
import org.dromara.jpom.model.docker.DockerInfoModel;
import org.dromara.jpom.model.docker.DockerSwarmInfoMode;
import org.dromara.jpom.permission.ClassFeature;
import org.dromara.jpom.permission.Feature;
import org.dromara.jpom.permission.MethodFeature;
import org.dromara.jpom.permission.SystemPermission;
import org.dromara.jpom.plugin.PluginFactory;
import org.dromara.jpom.service.docker.DockerInfoService;
import org.dromara.jpom.service.docker.DockerSwarmInfoService;
import org.dromara.jpom.service.system.WorkspaceService;
import org.dromara.jpom.system.ServerConfig;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;
/**
* @author bwcx_jzy
* @since 2023/3/3
*/
@RestController
@RequestMapping(value = "/system/assets/docker")
@Feature(cls = ClassFeature.SYSTEM_ASSETS_MACHINE_DOCKER)
@SystemPermission
@Slf4j
public class MachineDockerController extends BaseGroupNameController {
private final MachineDockerServer machineDockerServer;
private final ServerConfig serverConfig;
private final MachineSshServer machineSshServer;
private final DockerInfoService dockerInfoService;
private final DockerSwarmInfoService dockerSwarmInfoService;
private final WorkspaceService workspaceService;
private final CertificateInfoService certificateInfoService;
public MachineDockerController(MachineSshServer machineSshServer,
MachineDockerServer machineDockerServer,
DockerInfoService dockerInfoService,
DockerSwarmInfoService dockerSwarmInfoService,
WorkspaceService workspaceService,
CertificateInfoService certificateInfoService,
ServerConfig serverConfig) {
super(machineDockerServer);
this.machineSshServer = machineSshServer;
this.machineDockerServer = machineDockerServer;
this.dockerInfoService = dockerInfoService;
this.dockerSwarmInfoService = dockerSwarmInfoService;
this.workspaceService = workspaceService;
this.certificateInfoService = certificateInfoService;
this.serverConfig = serverConfig;
}
@PostMapping(value = "list-data", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage> listJson(HttpServletRequest request) {
PageResultDto pageResultDto = machineDockerServer.listPage(request);
return JsonMessage.success("", pageResultDto);
}
@PostMapping(value = "edit", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage edit(String id) throws Exception {
MachineDockerModel dockerInfoModel = this.takeOverModel();
if (StrUtil.isEmpty(id)) {
// 创建
this.check(dockerInfoModel);
// 默认正常
dockerInfoModel.setStatus(1);
machineDockerServer.insert(dockerInfoModel);
} else {
this.check(dockerInfoModel);
machineDockerServer.updateById(dockerInfoModel);
}
//
return JsonMessage.success(I18nMessageUtil.get("i18n.operation_succeeded.3313"));
}
/**
* 接收前端参数
*
* @return model
* @throws Exception 异常
*/
private MachineDockerModel takeOverModel() throws Exception {
IPlugin plugin = PluginFactory.getPlugin(DockerInfoService.DOCKER_CHECK_PLUGIN_NAME);
String name = getParameter("name");
Assert.hasText(name, I18nMessageUtil.get("i18n.please_fill_in_name.52f3"));
String host = getParameter("host");
String id = getParameter("id");
String tlsVerifyStr = getParameter("tlsVerify");
String registryUrl = getParameter("registryUrl");
String registryUsername = getParameter("registryUsername");
String registryPassword = getParameter("registryPassword");
String registryEmail = getParameter("registryEmail");
int heartbeatTimeout = getParameterInt("heartbeatTimeout", -1);
String groupName = getParameter("groupName");
String certInfo = getParameter("certInfo");
String enableSshStr = getParameter("enableSsh");
boolean enableSsh = Convert.toBool(enableSshStr, false);
String machineSshId = getParameter("machineSshId");
if (enableSsh) {
MachineSshModel model = machineSshServer.getByKey(machineSshId);
host = "ssh://" + model.getHost() + ":" + (model.getPort() == null ? 22 : model.getPort());
}
boolean tlsVerify = Convert.toBool(tlsVerifyStr, false);
//
if (tlsVerify) {
File filePath = certificateInfoService.getFilePath(certInfo);
Assert.notNull(filePath, I18nMessageUtil.get("i18n.incorrect_certificate_info.aee1"));
// 验证证书文件是否正确
boolean ok = (boolean) plugin.execute("certPath", "certPath", filePath.getAbsolutePath());
Assert.state(ok, I18nMessageUtil.get("i18n.certificate_info_incorrect.a950"));
} else {
certInfo = StrUtil.emptyToDefault(certInfo, StrUtil.EMPTY);
}
boolean ok = (boolean) plugin.execute("host", "host", host);
Assert.state(ok, I18nMessageUtil.get("i18n.correct_host_required.8c49"));
// 验证重复
Entity entity = Entity.create();
entity.set("host", host);
if (StrUtil.isNotEmpty(id)) {
entity.set("id", StrUtil.format(" <> {}", id));
}
boolean exists = machineDockerServer.exists(entity);
Assert.state(!exists, I18nMessageUtil.get("i18n.docker_already_exists.d9a5"));
//
MachineDockerModel machineDockerModel = new MachineDockerModel();
machineDockerModel.setHeartbeatTimeout(heartbeatTimeout);
machineDockerModel.setHost(host);
machineDockerModel.setEnableSsh(enableSsh);
machineDockerModel.setMachineSshId(machineSshId);
// 保存是会验证证书一定存在
machineDockerModel.setCertExist(tlsVerify);
machineDockerModel.setName(name);
machineDockerModel.setCertInfo(certInfo);
machineDockerModel.setTlsVerify(tlsVerify);
machineDockerModel.setRegistryUrl(registryUrl);
machineDockerModel.setRegistryUsername(registryUsername);
machineDockerModel.setRegistryPassword(registryPassword);
machineDockerModel.setRegistryEmail(registryEmail);
machineDockerModel.setGroupName(groupName);
//
machineDockerModel.setId(id);
return machineDockerModel;
}
private void check(MachineDockerModel dockerInfoModel) throws Exception {
IPlugin plugin = PluginFactory.getPlugin(DockerInfoService.DOCKER_CHECK_PLUGIN_NAME);
Map parameter = machineDockerServer.toParameter(dockerInfoModel);
parameter.put("closeBefore", true);
String errorReason = (String) plugin.execute("ping", parameter);
Assert.isNull(errorReason, () -> I18nMessageUtil.get("i18n.unable_to_connect_to_docker.2bb3") + errorReason);
// 检查授权
String registryUrl = dockerInfoModel.getRegistryUrl();
if (StrUtil.isNotEmpty(registryUrl)) {
MachineDockerModel oldInfoModel = machineDockerServer.getByKey(dockerInfoModel.getId(), false);
String registryPassword = Optional.ofNullable(dockerInfoModel.getRegistryPassword()).orElseGet(() -> Optional.ofNullable(oldInfoModel).map(MachineDockerModel::getRegistryPassword).orElse(null));
Assert.hasText(registryPassword, I18nMessageUtil.get("i18n.repository_password_cannot_be_empty.20b3"));
parameter.put("closeBefore", true);
parameter.put("registryPassword", registryPassword);
try {
JSONObject jsonObject = (JSONObject) plugin.execute("testAuth", parameter);
log.info("{}", jsonObject);
} catch (Exception e) {
log.warn(I18nMessageUtil.get("i18n.repository_authorization_error.4f50"), e);
throw new IllegalArgumentException(I18nMessageUtil.get("i18n.incorrect_repository_credentials.f1c8") + e.getMessage());
}
}
// 修改状态为在线
dockerInfoModel.setStatus(1);
}
@GetMapping(value = "try-local-docker", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage tryLocalDocker(HttpServletRequest request) {
try {
IPlugin plugin = PluginFactory.getPlugin(DockerInfoService.DOCKER_CHECK_PLUGIN_NAME);
String dockerHost = (String) plugin.execute("testLocal", new HashMap<>(1));
Entity entity = Entity.create();
entity.set("host", dockerHost);
boolean exists = machineDockerServer.exists(entity);
if (exists) {
return new JsonMessage<>(405, I18nMessageUtil.get("i18n.local_docker_exists.ec31") + dockerHost);
}
MachineDockerModel dockerModel = new MachineDockerModel();
dockerModel.setHost(dockerHost);
dockerModel.setName("localhost");
dockerModel.setStatus(1);
machineDockerServer.insert(dockerModel);
return new JsonMessage<>(200, I18nMessageUtil.get("i18n.auto_detect_local_docker_and_add.af72") + dockerHost);
} catch (Throwable e) {
log.error(I18nMessageUtil.get("i18n.detect_local_docker_exception.ccfc"), e);
return new JsonMessage<>(500, I18nMessageUtil.get("i18n.detect_local_docker_exception_with_details.7cc9") + e.getMessage());
}
}
@GetMapping(value = "del", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.DEL)
public IJsonMessage del(@ValidatorItem String id) throws Exception {
//
{
DockerInfoModel dockerInfoModel = new DockerInfoModel();
dockerInfoModel.setMachineDockerId(id);
long count = dockerInfoService.count(dockerInfoModel);
Assert.state(count <= 0, StrUtil.format(I18nMessageUtil.get("i18n.docker_associated_workspaces_message.de78"), count));
}
MachineDockerModel infoModel = machineDockerServer.getByKey(id);
Optional.ofNullable(infoModel).ifPresent(machineDockerModel -> {
if (StrUtil.isNotEmpty(machineDockerModel.getSwarmId())) {
// 判断集群
DockerSwarmInfoMode dockerInfoModel = new DockerSwarmInfoMode();
dockerInfoModel.setSwarmId(machineDockerModel.getSwarmId());
long count = dockerSwarmInfoService.count(dockerInfoModel);
Assert.state(count <= 0, StrUtil.format(I18nMessageUtil.get("i18n.docker_cluster_associated_workspaces_message.5520"), count));
}
});
machineDockerServer.delByKey(id);
return JsonMessage.success(I18nMessageUtil.get("i18n.delete_success.0007"));
}
/**
* 将 docker 分配到指定工作空间
*
* @param ids docker id
* @param workspaceId 工作空间id
* @return json
*/
@PostMapping(value = "distribute", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.EDIT)
public IJsonMessage distribute(@ValidatorItem String ids, @ValidatorItem String workspaceId, String type) {
List list = StrUtil.splitTrim(ids, StrUtil.COMMA);
for (String id : list) {
MachineDockerModel machineDockerModel = machineDockerServer.getByKey(id);
Assert.notNull(machineDockerModel, I18nMessageUtil.get("i18n.no_corresponding_docker.733e"));
boolean exists = workspaceService.exists(new WorkspaceModel(workspaceId));
Assert.state(exists, I18nMessageUtil.get("i18n.workspace_not_exist.a6fd"));
if (StrUtil.equals(type, "docker")) {
DockerInfoModel dockerInfoModel = new DockerInfoModel();
dockerInfoModel.setMachineDockerId(id);
dockerInfoModel.setWorkspaceId(workspaceId);
//
exists = dockerInfoService.exists(dockerInfoModel);
if (!exists) {
//
dockerInfoModel.setName(machineDockerModel.getName());
dockerInfoService.insert(dockerInfoModel);
}
} else if (StrUtil.equals(type, "swarm")) {
Assert.hasText(machineDockerModel.getSwarmId(), () -> StrUtil.format(I18nMessageUtil.get("i18n.current_docker_not_in_cluster.f70c"), machineDockerModel.getName()));
DockerSwarmInfoMode dockerInfoModel = new DockerSwarmInfoMode();
dockerInfoModel.setSwarmId(machineDockerModel.getSwarmId());
dockerInfoModel.setWorkspaceId(workspaceId);
//
if (!dockerSwarmInfoService.exists(dockerInfoModel)) {
//
dockerInfoModel.setName(machineDockerModel.getName());
dockerSwarmInfoService.insert(dockerInfoModel);
}
} else {
throw new IllegalArgumentException(I18nMessageUtil.get("i18n.unknown_parameter.96dd"));
}
}
return JsonMessage.success(I18nMessageUtil.get("i18n.operation_succeeded.3313"));
}
@GetMapping(value = "list-workspace-docker", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage listWorkspaceSsh(@ValidatorItem String id) {
MachineDockerModel machineDockerModel = machineDockerServer.getByKey(id);
Assert.notNull(machineDockerModel, I18nMessageUtil.get("i18n.no_corresponding_docker.733e"));
JSONObject jsonObject = new JSONObject();
{
DockerInfoModel dockerInfoModel = new DockerInfoModel();
dockerInfoModel.setMachineDockerId(id);
List modelList = dockerInfoService.listByBean(dockerInfoModel);
modelList = Optional.ofNullable(modelList).orElseGet(ArrayList::new);
for (DockerInfoModel model : modelList) {
model.setWorkspace(workspaceService.getByKey(model.getWorkspaceId()));
}
jsonObject.put("dockerList", modelList);
}
{
String swarmId = machineDockerModel.getSwarmId();
if (StrUtil.isNotEmpty(swarmId)) {
DockerSwarmInfoMode dockerInfoModel = new DockerSwarmInfoMode();
dockerInfoModel.setSwarmId(swarmId);
List modelList = dockerSwarmInfoService.listByBean(dockerInfoModel);
modelList = Optional.ofNullable(modelList).orElseGet(ArrayList::new);
for (DockerSwarmInfoMode model : modelList) {
model.setWorkspace(workspaceService.getByKey(model.getWorkspaceId()));
}
jsonObject.put("swarmList", modelList);
}
}
return JsonMessage.success("", jsonObject);
}
/**
* 导入 docker tls
*
* @param file 文件
* @return model
* @throws Exception 异常
*/
@PostMapping(value = "import-tls", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.UPLOAD)
public IJsonMessage importTls(MultipartFile file) throws Exception {
Assert.notNull(file, I18nMessageUtil.get("i18n.no_uploaded_file.07ef"));
// 保存路径
File tempPath = FileUtil.file(serverConfig.getUserTempPath(), "docker", IdUtil.fastSimpleUUID());
try {
String originalFilename = file.getOriginalFilename();
String extName = FileUtil.extName(originalFilename);
Assert.state(StrUtil.containsIgnoreCase(extName, "zip"), I18nMessageUtil.get("i18n.invalid_file_type.7246"));
File saveFile = FileUtil.file(tempPath, originalFilename);
FileUtil.mkParentDirs(saveFile);
file.transferTo(saveFile);
// 解压
ZipUtil.unzip(saveFile, tempPath);
// 先判断文件
boolean checkCertPath = machineDockerServer.checkCertPath(tempPath.getAbsolutePath());
Assert.state(checkCertPath, I18nMessageUtil.get("i18n.certificate_info_incorrect.a950"));
CertificateInfoModel certificateInfoModel = certificateInfoService.resolveX509(tempPath, true);
certificateInfoModel.setWorkspaceId(ServerConst.WORKSPACE_GLOBAL);
certificateInfoService.insert(certificateInfoModel);
return JsonMessage.success(I18nMessageUtil.get("i18n.import_success.b6d1"));
} finally {
FileUtil.del(tempPath);
}
}
}