mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-12-02 20:08:40 +08:00
feat(add) 新增 docker swarm 集群管理
This commit is contained in:
parent
273011c210
commit
2e1e4aaaf4
@ -7,6 +7,8 @@
|
|||||||
1. nginx 删除操作新增还原配置
|
1. nginx 删除操作新增还原配置
|
||||||
2. 【server】新增用户登录日志记录
|
2. 【server】新增用户登录日志记录
|
||||||
3. 【server】log view 新增正则参考
|
3. 【server】log view 新增正则参考
|
||||||
|
4. 【server】docker 控制台新增 docker 信息查看
|
||||||
|
5. 【server】新增 docker swarm 集群管理
|
||||||
|
|
||||||
### 🐞 解决BUG、优化功能
|
### 🐞 解决BUG、优化功能
|
||||||
|
|
||||||
|
@ -275,11 +275,7 @@ public class DockerInfoController extends BaseServerController {
|
|||||||
parameter.put("force", true);
|
parameter.put("force", true);
|
||||||
plugin.execute("leaveSwarm", parameter, JSONObject.class);
|
plugin.execute("leaveSwarm", parameter, JSONObject.class);
|
||||||
//
|
//
|
||||||
DockerInfoModel update = new DockerInfoModel();
|
dockerInfoService.unbind(id);
|
||||||
update.setId(id);
|
|
||||||
update.setSwarmId(StrUtil.EMPTY);
|
|
||||||
update.setSwarmNodeId(StrUtil.EMPTY);
|
|
||||||
dockerInfoService.update(update);
|
|
||||||
return new JsonMessage<>(200, "强制解绑成功");
|
return new JsonMessage<>(200, "强制解绑成功");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package io.jpom.controller.docker;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.db.Entity;
|
import cn.hutool.db.Entity;
|
||||||
import cn.jiangzeyin.common.JsonMessage;
|
import cn.jiangzeyin.common.JsonMessage;
|
||||||
@ -25,7 +24,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.*;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +106,7 @@ public class DockerSwarmInfoController extends BaseServerController {
|
|||||||
DockerSwarmInfoMode dockerSwarmInfoMode = infoModeBuilder.build();
|
DockerSwarmInfoMode dockerSwarmInfoMode = infoModeBuilder.build();
|
||||||
consumer.accept(dockerSwarmInfoMode);
|
consumer.accept(dockerSwarmInfoMode);
|
||||||
// 更新 docker id
|
// 更新 docker id
|
||||||
this.bindDockerSwarm(dockerInfoModel1, tag, null, id);
|
dockerInfoService.bindDockerSwarm(dockerInfoModel1, tag, null, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void check(String id, String swarmId) {
|
private void check(String id, String swarmId) {
|
||||||
@ -144,26 +146,6 @@ public class DockerSwarmInfoController extends BaseServerController {
|
|||||||
return JsonMessage.getString(200, "修改成功");
|
return JsonMessage.getString(200, "修改成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindDockerSwarm(DockerInfoModel joinSwarmDocker, String tag, JSONObject swarm, String swarmId) {
|
|
||||||
DockerInfoModel dockerInfoModel = new DockerInfoModel();
|
|
||||||
dockerInfoModel.setSwarmId(swarmId);
|
|
||||||
//
|
|
||||||
if (swarm != null) {
|
|
||||||
String swarmNodeId = swarm.getString("nodeID");
|
|
||||||
dockerInfoModel.setSwarmNodeId(swarmNodeId);
|
|
||||||
}
|
|
||||||
dockerInfoModel.setId(joinSwarmDocker.getId());
|
|
||||||
String tags = joinSwarmDocker.getTags();
|
|
||||||
// 处理标签
|
|
||||||
List<String> allTag = StrUtil.splitTrim(tags, StrUtil.COMMA);
|
|
||||||
allTag = ObjectUtil.defaultIfNull(allTag, new ArrayList<>());
|
|
||||||
if (!allTag.contains(tag)) {
|
|
||||||
allTag.add(tag);
|
|
||||||
}
|
|
||||||
dockerInfoModel.setTags(CollUtil.join(allTag, StrUtil.COMMA));
|
|
||||||
dockerInfoService.update(dockerInfoModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加入集群
|
* 加入集群
|
||||||
*
|
*
|
||||||
@ -210,7 +192,7 @@ public class DockerSwarmInfoController extends BaseServerController {
|
|||||||
Assert.state(optional.isPresent(), "当前 docker 已经加入到其他集群啦");
|
Assert.state(optional.isPresent(), "当前 docker 已经加入到其他集群啦");
|
||||||
// 绑定数据
|
// 绑定数据
|
||||||
String managerId = managerSwarmInfo.getString("id");
|
String managerId = managerSwarmInfo.getString("id");
|
||||||
this.bindDockerSwarm(joinSwarmDocker, swarmInfoMode1.getTag(), swarm, managerId);
|
dockerInfoService.bindDockerSwarm(joinSwarmDocker, swarmInfoMode1.getTag(), swarm, managerId);
|
||||||
return JsonMessage.getString(200, "集群绑定成功");
|
return JsonMessage.getString(200, "集群绑定成功");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,7 +213,7 @@ public class DockerSwarmInfoController extends BaseServerController {
|
|||||||
JSONObject swarm = info.getJSONObject("swarm");
|
JSONObject swarm = info.getJSONObject("swarm");
|
||||||
Assert.notNull(swarm, "获取 docker 集群信息失败:-1");
|
Assert.notNull(swarm, "获取 docker 集群信息失败:-1");
|
||||||
String managerId = managerSwarmInfo.getString("id");
|
String managerId = managerSwarmInfo.getString("id");
|
||||||
this.bindDockerSwarm(joinSwarmDocker, swarmInfoMode1.getTag(), swarm, managerId);
|
dockerInfoService.bindDockerSwarm(joinSwarmDocker, swarmInfoMode1.getTag(), swarm, managerId);
|
||||||
return JsonMessage.getString(200, "集群创建成功");
|
return JsonMessage.getString(200, "集群创建成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,14 +247,9 @@ public class DockerSwarmInfoController extends BaseServerController {
|
|||||||
public JsonMessage<List<JSONObject>> nodeList(
|
public JsonMessage<List<JSONObject>> nodeList(
|
||||||
@ValidatorItem String id,
|
@ValidatorItem String id,
|
||||||
String nodeId, String nodeName, String nodeRole) throws Exception {
|
String nodeId, String nodeName, String nodeRole) throws Exception {
|
||||||
HttpServletRequest request = getRequest();
|
|
||||||
DockerSwarmInfoMode swarmInfoMode1 = dockerSwarmInfoService.getByKey(id, request);
|
|
||||||
Assert.notNull(swarmInfoMode1, "没有对应的集群");
|
|
||||||
DockerInfoModel managerSwarmDocker = dockerInfoService.getByKey(swarmInfoMode1.getDockerId(), request);
|
|
||||||
Assert.notNull(managerSwarmDocker, "对应的 docker 不存在");
|
|
||||||
//
|
//
|
||||||
IPlugin plugin = PluginFactory.getPlugin(DockerSwarmInfoService.DOCKER_PLUGIN_NAME);
|
IPlugin plugin = PluginFactory.getPlugin(DockerSwarmInfoService.DOCKER_PLUGIN_NAME);
|
||||||
Map<String, Object> map = managerSwarmDocker.toParameter();
|
Map<String, Object> map = this.getPluginMap(id);
|
||||||
map.put("id", nodeId);
|
map.put("id", nodeId);
|
||||||
map.put("name", nodeName);
|
map.put("name", nodeName);
|
||||||
map.put("role", nodeRole);
|
map.put("role", nodeRole);
|
||||||
@ -280,19 +257,65 @@ public class DockerSwarmInfoController extends BaseServerController {
|
|||||||
return new JsonMessage<>(200, "", listSwarmNodes);
|
return new JsonMessage<>(200, "", listSwarmNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getPluginMap(String id) {
|
||||||
|
HttpServletRequest request = getRequest();
|
||||||
|
DockerSwarmInfoMode swarmInfoMode1 = dockerSwarmInfoService.getByKey(id, request);
|
||||||
|
Assert.notNull(swarmInfoMode1, "没有对应的集群");
|
||||||
|
//
|
||||||
|
DockerInfoModel managerSwarmDocker = dockerInfoService.getByKey(swarmInfoMode1.getDockerId(), request);
|
||||||
|
Assert.notNull(managerSwarmDocker, "对应的 docker 不存在");
|
||||||
|
return managerSwarmDocker.toParameter();
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * 退出集群
|
* 修改节点信息
|
||||||
// *
|
*
|
||||||
// * @param id 集群ID
|
* @param id 集群ID
|
||||||
// * @return json
|
* @return json
|
||||||
// */
|
*/
|
||||||
// @GetMapping(value = "leave", produces = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(value = "update", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
// @Feature(method = MethodFeature.DEL)
|
@Feature(method = MethodFeature.EXECUTE)
|
||||||
// public JsonMessage<String> leave(@ValidatorItem String id) {
|
public JsonMessage<String> update(@ValidatorItem String id, @ValidatorItem String nodeId, @ValidatorItem String availability, @ValidatorItem String role) throws Exception {
|
||||||
// HttpServletRequest request = getRequest();
|
//
|
||||||
// DockerSwarmInfoMode swarmInfoMode1 = dockerSwarmInfoService.getByKey(id, request);
|
IPlugin plugin = PluginFactory.getPlugin(DockerSwarmInfoService.DOCKER_PLUGIN_NAME);
|
||||||
// Assert.notNull(swarmInfoMode1, "没有对应的集群");
|
Map<String, Object> map = this.getPluginMap(id);
|
||||||
// return new JsonMessage<>(200, "解绑成功");
|
map.put("nodeId", nodeId);
|
||||||
// }
|
map.put("availability", availability);
|
||||||
|
map.put("role", role);
|
||||||
|
plugin.execute("updateSwarmNode", map);
|
||||||
|
return new JsonMessage<>(200, "解绑成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出集群
|
||||||
|
*
|
||||||
|
* @param id 集群ID
|
||||||
|
* @return json
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "leave", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
@Feature(method = MethodFeature.DEL)
|
||||||
|
public JsonMessage<String> leave(@ValidatorItem String id, @ValidatorItem String nodeId) throws Exception {
|
||||||
|
//
|
||||||
|
IPlugin plugin = PluginFactory.getPlugin(DockerSwarmInfoService.DOCKER_PLUGIN_NAME);
|
||||||
|
// 查询节点信息
|
||||||
|
DockerInfoModel dockerInfoModel = new DockerInfoModel();
|
||||||
|
dockerInfoModel.setSwarmNodeId(nodeId);
|
||||||
|
List<DockerInfoModel> dockerInfoModels = dockerInfoService.queryList(dockerInfoModel, 2);
|
||||||
|
Assert.state(CollUtil.size(dockerInfoModels) == 1, "当前节点未在系统中绑定或者绑定信息异常,不能操作");
|
||||||
|
//
|
||||||
|
{
|
||||||
|
DockerInfoModel dockerInfoModel1 = CollUtil.getFirst(dockerInfoModels);
|
||||||
|
Map<String, Object> parameter = dockerInfoModel1.toParameter();
|
||||||
|
parameter.put("force", true);
|
||||||
|
plugin.execute("leaveSwarm", parameter, JSONObject.class);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Map<String, Object> map = this.getPluginMap(id);
|
||||||
|
map.put("nodeId", nodeId);
|
||||||
|
plugin.execute("removeSwarmNode", map);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
dockerInfoService.unbind(id);
|
||||||
|
return new JsonMessage<>(200, "剔除成功");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ package io.jpom.service.docker;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.date.SystemClock;
|
import cn.hutool.core.date.SystemClock;
|
||||||
import cn.hutool.core.thread.ThreadUtil;
|
import cn.hutool.core.thread.ThreadUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.cron.task.Task;
|
import cn.hutool.cron.task.Task;
|
||||||
import cn.hutool.db.Entity;
|
import cn.hutool.db.Entity;
|
||||||
@ -40,6 +41,7 @@ import io.jpom.service.h2db.BaseWorkspaceService;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -181,4 +183,45 @@ public class DockerInfoService extends BaseWorkspaceService<DockerInfoModel> imp
|
|||||||
String sql = StrUtil.format("SELECT * FROM {} where workspaceId=? and instr(tags,?)", super.getTableName());
|
String sql = StrUtil.format("SELECT * FROM {} where workspaceId=? and instr(tags,?)", super.getTableName());
|
||||||
return (int) super.count(sql, workspaceId, tag);
|
return (int) super.count(sql, workspaceId, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* docker 绑定集群
|
||||||
|
*
|
||||||
|
* @param joinSwarmDocker docker
|
||||||
|
* @param tag 标签
|
||||||
|
* @param swarm 集群信息
|
||||||
|
* @param swarmId 集群ID
|
||||||
|
*/
|
||||||
|
public void bindDockerSwarm(DockerInfoModel joinSwarmDocker, String tag, JSONObject swarm, String swarmId) {
|
||||||
|
DockerInfoModel dockerInfoModel = new DockerInfoModel();
|
||||||
|
dockerInfoModel.setSwarmId(swarmId);
|
||||||
|
//
|
||||||
|
if (swarm != null) {
|
||||||
|
String swarmNodeId = swarm.getString("nodeID");
|
||||||
|
dockerInfoModel.setSwarmNodeId(swarmNodeId);
|
||||||
|
}
|
||||||
|
dockerInfoModel.setId(joinSwarmDocker.getId());
|
||||||
|
String tags = joinSwarmDocker.getTags();
|
||||||
|
// 处理标签
|
||||||
|
List<String> allTag = StrUtil.splitTrim(tags, StrUtil.COMMA);
|
||||||
|
allTag = ObjectUtil.defaultIfNull(allTag, new ArrayList<>());
|
||||||
|
if (!allTag.contains(tag)) {
|
||||||
|
allTag.add(tag);
|
||||||
|
}
|
||||||
|
dockerInfoModel.setTags(CollUtil.join(allTag, StrUtil.COMMA));
|
||||||
|
this.update(dockerInfoModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解绑集群信息
|
||||||
|
*
|
||||||
|
* @param id docker id
|
||||||
|
*/
|
||||||
|
public void unbind(String id) {
|
||||||
|
DockerInfoModel update = new DockerInfoModel();
|
||||||
|
update.setId(id);
|
||||||
|
update.setSwarmId(StrUtil.EMPTY);
|
||||||
|
update.setSwarmNodeId(StrUtil.EMPTY);
|
||||||
|
this.update(update);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,20 +22,21 @@
|
|||||||
*/
|
*/
|
||||||
package io.jpom;
|
package io.jpom;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import cn.hutool.core.util.EnumUtil;
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.github.dockerjava.api.DockerClient;
|
import com.github.dockerjava.api.DockerClient;
|
||||||
import com.github.dockerjava.api.command.JoinSwarmCmd;
|
import com.github.dockerjava.api.command.*;
|
||||||
import com.github.dockerjava.api.command.LeaveSwarmCmd;
|
import com.github.dockerjava.api.model.*;
|
||||||
import com.github.dockerjava.api.command.ListSwarmNodesCmd;
|
import com.github.dockerjava.core.command.RemoveSwarmNodeCmdImpl;
|
||||||
import com.github.dockerjava.api.model.Swarm;
|
|
||||||
import com.github.dockerjava.api.model.SwarmNode;
|
|
||||||
import com.github.dockerjava.api.model.SwarmSpec;
|
|
||||||
import io.jpom.plugin.IDefaultPlugin;
|
import io.jpom.plugin.IDefaultPlugin;
|
||||||
import io.jpom.plugin.PluginConfig;
|
import io.jpom.plugin.PluginConfig;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -67,12 +68,62 @@ public class DefaultDockerSwarmPluginImpl implements IDefaultPlugin {
|
|||||||
case "leaveSwarm":
|
case "leaveSwarm":
|
||||||
this.leaveSwarmCmd(parameter);
|
this.leaveSwarmCmd(parameter);
|
||||||
return null;
|
return null;
|
||||||
|
case "updateSwarmNode":
|
||||||
|
this.updateSwarmNodeCmd(parameter);
|
||||||
|
return null;
|
||||||
|
case "removeSwarmNode":
|
||||||
|
this.removeSwarmNodeCmd(parameter);
|
||||||
|
return null;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeSwarmNodeCmd(Map<String, Object> parameter) {
|
||||||
|
DockerClient dockerClient = DockerUtil.build(parameter);
|
||||||
|
try {
|
||||||
|
DockerCmdExecFactory dockerCmdExecFactory = (DockerCmdExecFactory) ReflectUtil.getFieldValue(dockerClient, "dockerCmdExecFactory");
|
||||||
|
Assert.notNull(dockerCmdExecFactory, "当前方法不被支持,暂时不能使用");
|
||||||
|
String nodeId = (String) parameter.get("nodeId");
|
||||||
|
RemoveSwarmNodeCmdImpl removeSwarmNodeCmd = new RemoveSwarmNodeCmdImpl(
|
||||||
|
dockerCmdExecFactory.removeSwarmNodeCmdExec(), nodeId);
|
||||||
|
removeSwarmNodeCmd.withForce(true);
|
||||||
|
removeSwarmNodeCmd.exec();
|
||||||
|
} finally {
|
||||||
|
IoUtil.close(dockerClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSwarmNodeCmd(Map<String, Object> parameter) {
|
||||||
|
DockerClient dockerClient = DockerUtil.build(parameter);
|
||||||
|
try {
|
||||||
|
String nodeId = (String) parameter.get("nodeId");
|
||||||
|
List<SwarmNode> nodes = dockerClient.listSwarmNodesCmd()
|
||||||
|
.withIdFilter(CollUtil.newArrayList(nodeId)).exec();
|
||||||
|
SwarmNode swarmNode = CollUtil.getFirst(nodes);
|
||||||
|
Assert.notNull(swarmNode, "没有对应的节点");
|
||||||
|
ObjectVersion version = swarmNode.getVersion();
|
||||||
|
Assert.notNull(version, "对应的节点信息不完整不能继续");
|
||||||
|
//
|
||||||
|
String availabilityStr = (String) parameter.get("availability");
|
||||||
|
String roleStr = (String) parameter.get("role");
|
||||||
|
//
|
||||||
|
SwarmNodeAvailability availability = EnumUtil.fromString(SwarmNodeAvailability.class, availabilityStr);
|
||||||
|
SwarmNodeRole role = EnumUtil.fromString(SwarmNodeRole.class, roleStr);
|
||||||
|
UpdateSwarmNodeCmd swarmNodeCmd = dockerClient.updateSwarmNodeCmd();
|
||||||
|
swarmNodeCmd.withSwarmNodeId(nodeId);
|
||||||
|
SwarmNodeSpec swarmNodeSpec = new SwarmNodeSpec();
|
||||||
|
swarmNodeSpec.withAvailability(availability);
|
||||||
|
swarmNodeSpec.withRole(role);
|
||||||
|
swarmNodeCmd.withSwarmNodeSpec(swarmNodeSpec);
|
||||||
|
swarmNodeCmd.withVersion(version.getIndex());
|
||||||
|
swarmNodeCmd.exec();
|
||||||
|
} finally {
|
||||||
|
IoUtil.close(dockerClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void leaveSwarmCmd(Map<String, Object> parameter) {
|
private void leaveSwarmCmd(Map<String, Object> parameter) {
|
||||||
DockerClient dockerClient = DockerUtil.build(parameter);
|
DockerClient dockerClient = DockerUtil.build(parameter);
|
||||||
|
@ -32,10 +32,7 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
import com.github.dockerjava.api.DockerClient;
|
import com.github.dockerjava.api.DockerClient;
|
||||||
import com.github.dockerjava.api.command.*;
|
import com.github.dockerjava.api.command.*;
|
||||||
import com.github.dockerjava.api.model.Info;
|
import com.github.dockerjava.api.model.*;
|
||||||
import com.github.dockerjava.api.model.Swarm;
|
|
||||||
import com.github.dockerjava.api.model.SwarmNode;
|
|
||||||
import com.github.dockerjava.api.model.SwarmSpec;
|
|
||||||
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
||||||
import com.github.dockerjava.core.DockerClientConfig;
|
import com.github.dockerjava.core.DockerClientConfig;
|
||||||
import com.github.dockerjava.core.DockerClientImpl;
|
import com.github.dockerjava.core.DockerClientImpl;
|
||||||
@ -177,6 +174,28 @@ public class TestSwarm {
|
|||||||
removeSwarmNodeCmd.exec();
|
removeSwarmNodeCmd.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void update() {
|
||||||
|
DockerClient client = this.client(node1);
|
||||||
|
|
||||||
|
|
||||||
|
String nodeId = "rk2gxpql2449t0s1ymtivtyoy";
|
||||||
|
List<SwarmNode> nodes = client.listSwarmNodesCmd().withIdFilter(CollUtil.newArrayList(nodeId)).exec();
|
||||||
|
System.out.println(nodes);
|
||||||
|
SwarmNode swarmNode = CollUtil.getFirst(nodes);
|
||||||
|
UpdateSwarmNodeCmd swarmNodeCmd = client.updateSwarmNodeCmd();
|
||||||
|
|
||||||
|
swarmNodeCmd.withSwarmNodeId(nodeId);
|
||||||
|
SwarmNodeSpec swarmNodeSpec = new SwarmNodeSpec();
|
||||||
|
swarmNodeSpec.withAvailability(SwarmNodeAvailability.PAUSE);
|
||||||
|
swarmNodeSpec.withRole(SwarmNodeRole.WORKER);
|
||||||
|
swarmNodeCmd.withSwarmNodeSpec(swarmNodeSpec);
|
||||||
|
|
||||||
|
swarmNodeCmd.withVersion(swarmNode.getVersion().getIndex());
|
||||||
|
|
||||||
|
swarmNodeCmd.exec();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testJoin() {
|
public void testJoin() {
|
||||||
|
|
||||||
|
@ -69,3 +69,27 @@ export function dockerSwarmNodeList(params) {
|
|||||||
data: params,
|
data: params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 容器集群节点修改
|
||||||
|
* @param {JSON} params
|
||||||
|
*/
|
||||||
|
export function dockerSwarmNodeUpdate(params) {
|
||||||
|
return axios({
|
||||||
|
url: "/docker-swarm/update",
|
||||||
|
method: "post",
|
||||||
|
data: params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 容器集群节点剔除
|
||||||
|
* @param {JSON} params
|
||||||
|
*/
|
||||||
|
export function dockerSwarmNodeLeave(params) {
|
||||||
|
return axios({
|
||||||
|
url: "/docker-swarm/leave",
|
||||||
|
method: "get",
|
||||||
|
params: params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<a-tooltip :title="`${parseInt(record.status) !== 1 ? '已经离线' : '已经创建过集群啦'}`">
|
<a-tooltip :title="`${parseInt(record.status) !== 1 ? '已经离线' : '已经在集群啦'}`">
|
||||||
<a-button size="small" disabled type="primary">集群</a-button>
|
<a-button size="small" disabled type="primary">集群</a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
@ -140,7 +140,7 @@
|
|||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 创建集群 -->
|
<!-- 创建集群 -->
|
||||||
<a-modal v-model="initSwarmVisible" title="创建 Docker 集群" @ok="handleSwarm" :maskClosable="false">
|
<a-modal v-model="initSwarmVisible" title="创建 Docker 集群" @ok="handleSwarm" :maskClosable="false">
|
||||||
<a-form-model ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form-model ref="initForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-model-item label="集群名称" prop="name">
|
<a-form-model-item label="集群名称" prop="name">
|
||||||
<a-input v-model="temp.name" placeholder="容器名称" />
|
<a-input v-model="temp.name" placeholder="容器名称" />
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
@ -150,7 +150,7 @@
|
|||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 加入集群 -->
|
<!-- 加入集群 -->
|
||||||
<a-modal v-model="joinSwarmVisible" title="加入 Docker 集群" @ok="handleSwarmJoin" :maskClosable="false">
|
<a-modal v-model="joinSwarmVisible" title="加入 Docker 集群" @ok="handleSwarmJoin" :maskClosable="false">
|
||||||
<a-form-model ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
<a-form-model ref="joinForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
<a-form-model-item label="选择集群" prop="swarmId">
|
<a-form-model-item label="选择集群" prop="swarmId">
|
||||||
<a-select
|
<a-select
|
||||||
show-search
|
show-search
|
||||||
@ -416,7 +416,13 @@ export default {
|
|||||||
},
|
},
|
||||||
// 强制解绑
|
// 强制解绑
|
||||||
handleLeaveForce(record) {
|
handleLeaveForce(record) {
|
||||||
const html = "<h1 style='color:red;'>真的要强制退出集群吗?</h1><ul style='color:red;'>" + "<li>请提前备份数据再操作奥</li>" + "<li>操作不能撤回奥</li>" + " </ul>";
|
const html =
|
||||||
|
"<h1 style='color:red;'>真的要强制退出集群吗?</h1> " +
|
||||||
|
"<h3 style='color:red;'>如果当前集群还存在可能出现数据不一致问题奥</h3> " +
|
||||||
|
"<ul style='color:red;'>" +
|
||||||
|
"<li>请提前备份数据再操作奥</li>" +
|
||||||
|
"<li>操作不能撤回奥</li>" +
|
||||||
|
" </ul>";
|
||||||
const h = this.$createElement;
|
const h = this.$createElement;
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: "系统提示",
|
title: "系统提示",
|
||||||
@ -480,7 +486,7 @@ export default {
|
|||||||
dockerId: record.id,
|
dockerId: record.id,
|
||||||
};
|
};
|
||||||
this.initSwarmVisible = true;
|
this.initSwarmVisible = true;
|
||||||
this.$refs["editForm"]?.resetFields();
|
this.$refs["initForm"]?.resetFields();
|
||||||
},
|
},
|
||||||
// 加入集群
|
// 加入集群
|
||||||
joinSwarm(record) {
|
joinSwarm(record) {
|
||||||
@ -490,11 +496,11 @@ export default {
|
|||||||
dockerId: record.id,
|
dockerId: record.id,
|
||||||
};
|
};
|
||||||
this.joinSwarmVisible = true;
|
this.joinSwarmVisible = true;
|
||||||
this.$refs["editForm"]?.resetFields();
|
this.$refs["joinForm"]?.resetFields();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSwarm() {
|
handleSwarm() {
|
||||||
this.$refs["editForm"].validate((valid) => {
|
this.$refs["initForm"].validate((valid) => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -512,7 +518,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 处理加入集群
|
// 处理加入集群
|
||||||
handleSwarmJoin() {
|
handleSwarmJoin() {
|
||||||
this.$refs["editForm"].validate((valid) => {
|
this.$refs["joinForm"].validate((valid) => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
</a-modal>
|
</a-modal>
|
||||||
<!-- 节点信息 -->
|
<!-- 节点信息 -->
|
||||||
<a-modal v-model="nodeVisible" width="90vw" title="集群节点" :footer="null" :maskClosable="false">
|
<a-modal v-model="nodeVisible" width="90vw" title="集群节点" :footer="null" :maskClosable="false">
|
||||||
<swarm-node :id="this.temp.id" />
|
<swarm-node ref="swarmNode" :id="this.temp.id" />
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -158,6 +158,9 @@ export default {
|
|||||||
handleNode(record) {
|
handleNode(record) {
|
||||||
this.temp = record;
|
this.temp = record;
|
||||||
this.nodeVisible = true;
|
this.nodeVisible = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.swarmNode.refreshData();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
// 提交 数据
|
// 提交 数据
|
||||||
handleEditOk() {
|
handleEditOk() {
|
||||||
@ -183,7 +186,7 @@ export default {
|
|||||||
handleUnbind(record) {
|
handleUnbind(record) {
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: "系统提示",
|
title: "系统提示",
|
||||||
content: "真的要解绑该集群么?解绑至少删除在本系统的关联数据,不会删除容器里面数据",
|
content: "真的要解绑该集群么?解绑只删除在本系统的关联数据,不会删除容器里面数据",
|
||||||
okText: "确认",
|
okText: "确认",
|
||||||
cancelText: "取消",
|
cancelText: "取消",
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
|
@ -9,30 +9,59 @@
|
|||||||
<a-select-option key="worker">工作节点</a-select-option>
|
<a-select-option key="worker">工作节点</a-select-option>
|
||||||
<a-select-option key="manager">管理节点</a-select-option>
|
<a-select-option key="manager">管理节点</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
<a-tooltip title="按住 Ctr 或者 Alt 键点击按钮快速回到第一页">
|
|
||||||
<a-button type="primary" @click="loadData" :loading="loading">搜索</a-button>
|
<a-button type="primary" @click="loadData" :loading="loading">搜索</a-button>
|
||||||
</a-tooltip>
|
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-tooltip slot="tooltip" slot-scope="text" placement="topLeft" :title="text">
|
<a-tooltip slot="tooltip" slot-scope="text" placement="topLeft" :title="text">
|
||||||
<span>{{ text }}</span>
|
<span>{{ text }}</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
|
||||||
<a-tooltip slot="status" slot-scope="text, item" placement="topLeft" :title="text">
|
<a-tooltip slot="status" slot-scope="text, item" placement="topLeft" :title="`节点状态:${text} 节点可用性:${item.spec ? item.spec.availability || '' : ''}`">
|
||||||
<a-tag :color="text === 'READY' ? 'green' : text === 'DOWN' ? 'red' : ''">
|
<a-tag :color="(item.spec && item.spec.availability) === 'ACTIVE' ? 'green' : 'red'">
|
||||||
{{ text }}-<template v-if="item.spec">{{ item.spec.role }}</template>
|
{{ text }}
|
||||||
|
<template v-if="item.spec">{{ item.spec.availability }}</template>
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
<!-- 角色显示 -->
|
||||||
|
<a-tooltip
|
||||||
|
slot="role"
|
||||||
|
slot-scope="text, item"
|
||||||
|
placement="topLeft"
|
||||||
|
:title="`角色:${text} ${item.managerStatus && item.managerStatus.reachability === 'REACHABLE' ? '管理状态:' + item.managerStatus.reachability : ''}`"
|
||||||
|
>
|
||||||
|
<a-tag :color="`${item.managerStatus && item.managerStatus.reachability === 'REACHABLE' ? 'green' : ''}`">
|
||||||
|
{{ text }}
|
||||||
|
</a-tag>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-tooltip slot="address" slot-scope="text, item" placement="topLeft" :title="text">
|
||||||
|
<a-icon v-if="item.managerStatus && item.managerStatus.leader" type="cloud-server" />
|
||||||
|
{{ text }}
|
||||||
|
</a-tooltip>
|
||||||
|
|
||||||
<a-tooltip slot="os" slot-scope="text, item" placement="topLeft" :title="text">
|
<a-tooltip slot="os" slot-scope="text, item" placement="topLeft" :title="text">
|
||||||
<span>
|
<span>
|
||||||
<a-tag>{{ text }}-{{ item.description && item.description.platform && item.description.platform.architecture }}</a-tag>
|
<a-tag>{{ text }}-{{ item.description && item.description.platform && item.description.platform.architecture }}</a-tag>
|
||||||
</span>
|
</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
<a-tooltip slot="updatedAt" slot-scope="text, item" placement="topLeft" :title="`修改时间:${text} 创建时间:${item.createdAt}`">
|
||||||
|
<span>
|
||||||
|
<a-tag>{{ text }}</a-tag>
|
||||||
|
</span>
|
||||||
|
</a-tooltip>
|
||||||
|
|
||||||
<template slot="operation" slot-scope="text, record">
|
<template slot="operation" slot-scope="text, record">
|
||||||
<a-space>
|
<a-space>
|
||||||
<a-button size="small" type="primary" @click="handleEdit(record)">编辑</a-button>
|
<template v-if="record.managerStatus && record.managerStatus.leader"> - </template>
|
||||||
<a-dropdown>
|
<template v-else>
|
||||||
|
<a-button size="small" type="primary" @click="handleEdit(record)">修改</a-button>
|
||||||
|
<a-button size="small" type="danger" @click="handleLeava(record)">剔除</a-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- <template v-else>
|
||||||
|
<a-button size="small" type="danger" v-if="!item.managerStatus.leader" @click="handleLeava(record)">剔除</a-button>
|
||||||
|
</template> -->
|
||||||
|
<!-- <a-dropdown>
|
||||||
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()"> 更多 <a-icon type="down" /> </a>
|
<a class="ant-dropdown-link" @click="(e) => e.preventDefault()"> 更多 <a-icon type="down" /> </a>
|
||||||
<a-menu slot="overlay">
|
<a-menu slot="overlay">
|
||||||
<a-menu-item> </a-menu-item>
|
<a-menu-item> </a-menu-item>
|
||||||
@ -40,15 +69,33 @@
|
|||||||
<a-button size="small" type="danger" @click="handleUnbind(record)">解绑</a-button>
|
<a-button size="small" type="danger" @click="handleUnbind(record)">解绑</a-button>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-menu></a-dropdown
|
</a-menu></a-dropdown
|
||||||
>
|
> -->
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
|
<!-- 编辑节点 -->
|
||||||
|
<a-modal v-model="editVisible" title="编辑节点" @ok="handleEditOk" :maskClosable="false">
|
||||||
|
<a-form-model ref="editForm" :rules="rules" :model="temp" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
|
||||||
|
<a-form-model-item label="角色" prop="role">
|
||||||
|
<a-radio-group name="role" v-model="temp.role">
|
||||||
|
<a-radio value="WORKER"> 工作节点</a-radio>
|
||||||
|
<a-radio value="MANAGER"> 管理节点 </a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="状态" prop="availability">
|
||||||
|
<a-radio-group name="availability" v-model="temp.availability">
|
||||||
|
<a-radio value="ACTIVE"> 活跃</a-radio>
|
||||||
|
<a-radio value="PAUSE"> 暂停 </a-radio>
|
||||||
|
<a-radio value="DRAIN"> 排空 </a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { editDockerSwarm, dockerSwarmNodeList, unbindSwarm } from "@/api/docker-swarm";
|
import { dockerSwarmNodeList, dockerSwarmNodeLeave, dockerSwarmNodeUpdate } from "@/api/docker-swarm";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
components: {},
|
||||||
@ -65,42 +112,51 @@ export default {
|
|||||||
temp: {},
|
temp: {},
|
||||||
editVisible: false,
|
editVisible: false,
|
||||||
initSwarmVisible: false,
|
initSwarmVisible: false,
|
||||||
|
rules: {
|
||||||
|
role: [{ required: true, message: "请选择节点角色", trigger: "blur" }],
|
||||||
|
availability: [{ required: true, message: "请选择节点状态", trigger: "blur" }],
|
||||||
|
},
|
||||||
columns: [
|
columns: [
|
||||||
{ title: "节点Id", dataIndex: "id", ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
{ title: "节点Id", dataIndex: "id", ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
||||||
{ title: "节点地址", dataIndex: "status.address", ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
|
||||||
{ title: "状态", width: 160, align: "center", dataIndex: "status.state", ellipsis: true, scopedSlots: { customRender: "status" } },
|
|
||||||
{ title: "主机名", dataIndex: "description.hostname", ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
{ title: "主机名", dataIndex: "description.hostname", ellipsis: true, scopedSlots: { customRender: "tooltip" } },
|
||||||
{ title: "系统类型", width: 140, align: "center", dataIndex: "description.platform.os", ellipsis: true, scopedSlots: { customRender: "os" } },
|
{ title: "节点地址", width: 150, dataIndex: "status.address", ellipsis: true, scopedSlots: { customRender: "address" } },
|
||||||
{
|
{ title: "状态", width: 140, dataIndex: "status.state", ellipsis: true, scopedSlots: { customRender: "status" } },
|
||||||
title: "创建时间",
|
{ title: "角色", width: 110, dataIndex: "spec.role", ellipsis: true, scopedSlots: { customRender: "role" } },
|
||||||
dataIndex: "createdAt",
|
|
||||||
|
|
||||||
ellipsis: true,
|
{ title: "系统类型", width: 140, align: "center", dataIndex: "description.platform.os", ellipsis: true, scopedSlots: { customRender: "os" } },
|
||||||
scopedSlots: { customRender: "tooltip" },
|
// {
|
||||||
width: 170,
|
// title: "创建时间",
|
||||||
},
|
// dataIndex: "createdAt",
|
||||||
|
|
||||||
|
// ellipsis: true,
|
||||||
|
// scopedSlots: { customRender: "tooltip" },
|
||||||
|
// width: 170,
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
title: "修改时间",
|
title: "修改时间",
|
||||||
dataIndex: "updatedAt",
|
dataIndex: "updatedAt",
|
||||||
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
scopedSlots: { customRender: "tooltip" },
|
scopedSlots: { customRender: "updatedAt" },
|
||||||
width: 170,
|
width: 170,
|
||||||
},
|
},
|
||||||
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, align: "center", width: 140 },
|
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, align: "center", width: 120 },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.list = [];
|
// this.loadData();
|
||||||
this.loadData();
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
refreshData() {
|
||||||
|
this.list = [];
|
||||||
|
this.loadData();
|
||||||
|
},
|
||||||
// 加载数据
|
// 加载数据
|
||||||
loadData(pointerEvent) {
|
loadData() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.listQuery.page = pointerEvent?.altKey || pointerEvent?.ctrlKey ? 1 : this.listQuery.page;
|
|
||||||
this.listQuery.id = this.id;
|
this.listQuery.id = this.id;
|
||||||
dockerSwarmNodeList(this.listQuery).then((res) => {
|
dockerSwarmNodeList(this.listQuery).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
@ -109,22 +165,21 @@ export default {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 修改
|
|
||||||
handleEdit(record) {
|
handleEdit(record) {
|
||||||
this.temp = record;
|
|
||||||
this.editVisible = true;
|
this.editVisible = true;
|
||||||
|
this.temp = {
|
||||||
this.$refs["editForm"]?.resetFields();
|
nodeId: record.id,
|
||||||
|
role: record.spec.role,
|
||||||
|
availability: record.spec.availability,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
// 提交 数据
|
|
||||||
handleEditOk() {
|
handleEditOk() {
|
||||||
// 检验表单
|
|
||||||
this.$refs["editForm"].validate((valid) => {
|
this.$refs["editForm"].validate((valid) => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
this.temp.id = this.id;
|
||||||
editDockerSwarm(this.temp).then((res) => {
|
dockerSwarmNodeUpdate(this.temp).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
// 成功
|
// 成功
|
||||||
this.$notification.success({
|
this.$notification.success({
|
||||||
@ -137,18 +192,19 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 解绑
|
// 解绑
|
||||||
handleUnbind(record) {
|
handleLeava(record) {
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: "系统提示",
|
title: "系统提示",
|
||||||
content: "真的要解绑该集群么?解绑至少删除在本系统的关联数据,不会删除容器里面数据",
|
content: "真的要在该集群剔除此节点么?",
|
||||||
okText: "确认",
|
okText: "确认",
|
||||||
cancelText: "取消",
|
cancelText: "取消",
|
||||||
onOk: () => {
|
onOk: () => {
|
||||||
// 组装参数
|
// 组装参数
|
||||||
const params = {
|
const params = {
|
||||||
id: record.id,
|
nodeId: record.id,
|
||||||
|
id: this.id,
|
||||||
};
|
};
|
||||||
unbindSwarm(params).then((res) => {
|
dockerSwarmNodeLeave(params).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
this.$notification.success({
|
this.$notification.success({
|
||||||
message: res.msg,
|
message: res.msg,
|
||||||
|
Loading…
Reference in New Issue
Block a user