org.dromara.jpom.DefaultDockerSwarmPluginImpl Maven / Gradle / Ivy
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Code Technology Studio
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.dromara.jpom;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.unit.DataSize;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.keepbx.jpom.plugins.PluginConfig;
import com.alibaba.fastjson2.JSONObject;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.command.RemoveSwarmNodeCmdImpl;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.plugin.IDefaultPlugin;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* docker swarm
*
* @author bwcx_jzy
* @since 2022/2/13
*/
@PluginConfig(name = "docker-cli:swarm")
@Slf4j
public class DefaultDockerSwarmPluginImpl implements IDefaultPlugin {
@Override
public Object execute(Object main, Map parameter) {
String type = main.toString();
switch (type) {
case "inSpectSwarm":
return this.inSpectSwarmCmd(parameter);
case "tryInitializeSwarm":
return this.tryInitializeSwarmCmd(parameter);
case "joinSwarm":
this.joinSwarmCmd(parameter);
return null;
case "listSwarmNodes":
return this.listSwarmNodesCmd(parameter);
case "leaveSwarm":
this.leaveSwarmCmd(parameter);
return null;
case "updateSwarmNode":
this.updateSwarmNodeCmd(parameter);
return null;
case "removeSwarmNode":
this.removeSwarmNodeCmd(parameter);
return null;
case "listServices":
return this.listServicesCmd(parameter);
case "listTasks":
return this.listTasksCmd(parameter);
case "removeService":
this.removeServiceCmd(parameter);
return null;
case "updateService":
this.updateServiceCmd(parameter);
return null;
case "updateServiceImage":
this.updateServiceImage(parameter);
return null;
case "logService":
this.logServiceCmd(parameter);
return null;
case "logTask":
this.logTaskCmd(parameter);
return null;
default:
break;
}
return null;
}
private void logTaskCmd(Map parameter) {
this.logServiceCmd(parameter, (String) parameter.get("taskId"), "task");
}
private void logServiceCmd(Map parameter) {
this.logServiceCmd(parameter, (String) parameter.get("serviceId"), "service");
}
private void logServiceCmd(Map parameter, String id, String type) {
DockerClient dockerClient = DockerUtil.get(parameter);
Consumer consumer = (Consumer) parameter.get("consumer");
String uuid = (String) parameter.get("uuid");
try {
LogSwarmObjectCmd logSwarmObjectCmd = StrUtil.equalsIgnoreCase(type, "Service") ? dockerClient.logServiceCmd(id) : dockerClient.logTaskCmd(id);
Charset charset = (Charset) parameter.get("charset");
Integer tail = (Integer) parameter.get("tail");
// 获取日志
if (tail != null && tail > 0) {
logSwarmObjectCmd.withTail(tail);
}
//String since = (String) parameter.get("since");
// Opt.ofBlankAble(since).ifPresent(s -> logSwarmObjectCmd.withSince(s));
Boolean timestamps = Convert.toBool(parameter.get("timestamps"));
logSwarmObjectCmd.withTimestamps(timestamps);
ResultCallback.Adapter exec = logSwarmObjectCmd
.withDetails(true)
.withStderr(true)
.withFollow(true)
.withStdout(true)
.exec(new ResultCallback.Adapter() {
@Override
public void onNext(Frame object) {
byte[] payload = object.getPayload();
if (payload == null) {
return;
}
String s = new String(payload, charset);
consumer.accept(s);
}
});
// 添加到缓存中
DockerUtil.putClose(uuid, exec);
exec.awaitCompletion();
} catch (InterruptedException e) {
consumer.accept("获取容器日志被中断:" + e);
} finally {
DockerUtil.close(uuid);
}
}
private ServiceSpec intServiceSpec(DockerClient dockerClient, String serviceId) {
if (StrUtil.isEmpty(serviceId)) {
return new ServiceSpec();
}
// 读取之前的信息-保留之前的信息-否则会全部替换
InspectServiceCmd inspectServiceCmd = dockerClient.inspectServiceCmd(serviceId);
Service service = inspectServiceCmd.exec();
ServiceSpec spec = service.getSpec();
return ObjectUtil.defaultIfNull(spec, new ServiceSpec());
}
public void updateServiceImage(Map parameter) {
DockerClient dockerClient = DockerUtil.get(parameter);
String serviceId = (String) parameter.get("serviceId");
String image = (String) parameter.get("image");
//
InspectServiceCmd inspectServiceCmd = dockerClient.inspectServiceCmd(serviceId);
Service service = inspectServiceCmd.exec();
ServiceSpec spec = service.getSpec();
Assert.notNull(spec, "服务信息不完整不能操作");
TaskSpec taskTemplate = spec.getTaskTemplate();
Assert.notNull(taskTemplate, "服务信息不完整不能操作:-1");
ContainerSpec templateContainerSpec = taskTemplate.getContainerSpec();
Assert.notNull(templateContainerSpec, "服务信息不完整不能操作:-2");
templateContainerSpec.withImage(image);
//
UpdateServiceCmd updateServiceCmd = dockerClient.updateServiceCmd(serviceId, spec);
ResourceVersion version = service.getVersion();
Assert.notNull(version, "服务信息不完整不能操作:-3");
updateServiceCmd.withVersion(version.getIndex());
updateServiceCmd.exec();
}
/**
* 更新 服务,如果不存在 id 则创建。需要传人版本号
*
* @param parameter 测试
*/
public void updateServiceCmd(Map parameter) {
DockerClient dockerClient = DockerUtil.get(parameter);
String serviceId = (String) parameter.get("serviceId");
ServiceSpec serviceSpec = this.intServiceSpec(dockerClient, serviceId);
String name = (String) parameter.get("name");
serviceSpec.withName(name);
{
String mode = (String) parameter.get("mode");
ServiceMode serviceMode = EnumUtil.fromString(ServiceMode.class, mode);
ServiceModeConfig serviceModeConfig = new ServiceModeConfig();
if (serviceMode == ServiceMode.GLOBAL) {
serviceModeConfig.withGlobal(new ServiceGlobalModeOptions());
} else if (serviceMode == ServiceMode.REPLICATED) {
Object replicas = parameter.get("replicas");
ServiceReplicatedModeOptions serviceReplicatedModeOptions = new ServiceReplicatedModeOptions();
serviceReplicatedModeOptions.withReplicas(Convert.toInt(replicas, 1));
serviceModeConfig.withReplicated(serviceReplicatedModeOptions);
}
serviceSpec.withMode(serviceModeConfig);
}
{
TaskSpec taskSpec = ObjectUtil.defaultIfNull(serviceSpec.getTaskTemplate(), new TaskSpec());
//
ContainerSpec containerSpec = this.buildContainerSpec(parameter, taskSpec.getContainerSpec());
taskSpec.withContainerSpec(containerSpec);
//
Map> resources = (Map>) parameter.get("resources");
if (MapUtil.isNotEmpty(resources)) {
ResourceRequirements resourceRequirements = new ResourceRequirements();
ResourceSpecs limitsResourceSpecs = this.buildResourceSpecs(resources.get("limits"));
if (limitsResourceSpecs != null) {
resourceRequirements.withLimits(limitsResourceSpecs);
}
ResourceSpecs reservationsResourceSpecs = this.buildResourceSpecs(resources.get("reservations"));
if (reservationsResourceSpecs != null) {
resourceRequirements.withReservations(reservationsResourceSpecs);
}
if (ObjectUtil.isAllEmpty(resourceRequirements.getLimits(), resourceRequirements.getReservations())) {
taskSpec.withResources(null);
} else {
taskSpec.withResources(resourceRequirements);
}
}
serviceSpec.withTaskTemplate(taskSpec);
}
{
EndpointSpec endpointSpec = this.buildEndpointSpec(parameter);
serviceSpec.withEndpointSpec(endpointSpec);
}
{
Map update = (Map) parameter.get("update");
UpdateConfig updateConfig = this.buildUpdateConfig(update);
serviceSpec.withUpdateConfig(updateConfig);
Map rollback = (Map) parameter.get("rollback");
UpdateConfig rollbackConfig = this.buildUpdateConfig(rollback);
serviceSpec.withRollbackConfig(rollbackConfig);
}
if (StrUtil.isNotEmpty(serviceId)) {
Object version = parameter.get("version");
UpdateServiceCmd updateServiceCmd = dockerClient.updateServiceCmd(serviceId, serviceSpec);
updateServiceCmd.withVersion(Convert.toLong(version, 0L));
updateServiceCmd.exec();
} else {
CreateServiceCmd createServiceCmd = dockerClient.createServiceCmd(serviceSpec).withAuthConfig(dockerClient.authConfig());
createServiceCmd.exec();
}
}
private ResourceSpecs buildResourceSpecs(Map map) {
if (MapUtil.isNotEmpty(map)) {
ResourceSpecs resourceSpecs = new ResourceSpecs();
Object nanoCpus = map.get("nanoCPUs");
if (nanoCpus != null) {
String text = nanoCpus.toString();
if (StrUtil.isNotEmpty(text)) {
resourceSpecs.withNanoCPUs(Convert.toLong(nanoCpus, 1L));
}
}
Object memoryBytes = map.get("memoryBytes");
if (memoryBytes != null) {
String text = memoryBytes.toString();
if (StrUtil.isNotEmpty(text)) {
DataSize dataSize = DataSize.parse(text);
resourceSpecs.withMemoryBytes(dataSize.toBytes());
}
}
if (ObjectUtil.isAllEmpty(resourceSpecs.getNanoCPUs(), resourceSpecs.getMemoryBytes())) {
return null;
}
return resourceSpecs;
}
return null;
}
private EndpointSpec buildEndpointSpec(Map parameter) {
String endpointResolutionModeStr = (String) parameter.get("endpointResolutionMode");
EndpointResolutionMode endpointResolutionMode = EnumUtil.fromString(EndpointResolutionMode.class, endpointResolutionModeStr);
EndpointSpec endpointSpec = new EndpointSpec();
endpointSpec.withMode(endpointResolutionMode);
Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy