mirror of
https://gitee.com/dromara/Jpom.git
synced 2024-12-02 20:08:40 +08:00
feat(fix) swarm service update
This commit is contained in:
parent
3cccba88de
commit
62f7b35554
@ -25,6 +25,7 @@ package io.jpom;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.EnumUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
@ -164,70 +165,9 @@ public class DefaultDockerSwarmPluginImpl implements IDefaultPlugin {
|
||||
}
|
||||
serviceSpec.withMode(serviceModeConfig);
|
||||
}
|
||||
// {
|
||||
// UpdateConfig updateConfig = new UpdateConfig();
|
||||
//
|
||||
// serviceSpec.withUpdateConfig(updateConfig);
|
||||
// }
|
||||
{
|
||||
String image = (String) parameter.get("image");
|
||||
TaskSpec taskSpec = new TaskSpec();
|
||||
ContainerSpec containerSpec = new ContainerSpec();
|
||||
containerSpec.withImage(image);
|
||||
//
|
||||
Collection<Map<String, String>> args = (Collection) parameter.get("args");
|
||||
if (CollUtil.isNotEmpty(args)) {
|
||||
List<String> value = args.stream()
|
||||
.map(stringStringMap -> stringStringMap.get("value"))
|
||||
.filter(StrUtil::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withArgs(value);
|
||||
}
|
||||
Collection<Map<String, String>> envs = (Collection) parameter.get("envs");
|
||||
if (CollUtil.isNotEmpty(envs)) {
|
||||
List<String> value = envs.stream()
|
||||
.map(stringStringMap -> {
|
||||
String name1 = stringStringMap.get("name");
|
||||
String value1 = stringStringMap.get("value");
|
||||
if (StrUtil.isEmpty(name1)) {
|
||||
return null;
|
||||
}
|
||||
return StrUtil.format("{}={}", name1, value1);
|
||||
})
|
||||
.filter(StrUtil::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withEnv(value);
|
||||
}
|
||||
Collection<Map<String, String>> commands = (Collection) parameter.get("commands");
|
||||
if (CollUtil.isNotEmpty(commands)) {
|
||||
List<String> value = commands.stream()
|
||||
.map(stringStringMap -> stringStringMap.get("value"))
|
||||
.filter(StrUtil::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withCommand(value);
|
||||
}
|
||||
//
|
||||
Collection<Map<String, String>> volumes = (Collection<Map<String, String>>) parameter.get("volumes");
|
||||
if (CollUtil.isNotEmpty(volumes)) {
|
||||
List<Mount> value = volumes.stream()
|
||||
.map(stringStringMap -> {
|
||||
String source = stringStringMap.get("source");
|
||||
String target = stringStringMap.get("target");
|
||||
if (StrUtil.hasBlank(source, target)) {
|
||||
return null;
|
||||
}
|
||||
String type = stringStringMap.get("type");
|
||||
MountType mountType = EnumUtil.fromString(MountType.class, type);
|
||||
Mount mount = new Mount();
|
||||
mount.withSource(source);
|
||||
mount.withTarget(target);
|
||||
mount.withType(mountType);
|
||||
return mount;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withMounts(value);
|
||||
}
|
||||
ContainerSpec containerSpec = this.buildContainerSpec(parameter);
|
||||
taskSpec.withContainerSpec(containerSpec);
|
||||
//
|
||||
serviceSpec.withTaskTemplate(taskSpec);
|
||||
@ -263,6 +203,14 @@ public class DefaultDockerSwarmPluginImpl implements IDefaultPlugin {
|
||||
}
|
||||
serviceSpec.withEndpointSpec(endpointSpec);
|
||||
}
|
||||
{
|
||||
Map<String, Object> update = (Map<String, Object>) parameter.get("update");
|
||||
UpdateConfig updateConfig = this.buildUpdateConfig(update);
|
||||
serviceSpec.withUpdateConfig(updateConfig);
|
||||
Map<String, Object> rollback = (Map<String, Object>) parameter.get("rollback");
|
||||
UpdateConfig rollbackConfig = this.buildUpdateConfig(rollback);
|
||||
serviceSpec.withRollbackConfig(rollbackConfig);
|
||||
}
|
||||
String serviceId = (String) parameter.get("serviceId");
|
||||
String version = (String) parameter.get("version");
|
||||
if (StrUtil.isNotEmpty(serviceId)) {
|
||||
@ -278,6 +226,102 @@ public class DefaultDockerSwarmPluginImpl implements IDefaultPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private ContainerSpec buildContainerSpec(Map<String, Object> parameter) {
|
||||
String image = (String) parameter.get("image");
|
||||
ContainerSpec containerSpec = new ContainerSpec();
|
||||
containerSpec.withImage(image);
|
||||
//
|
||||
Collection<Map<String, String>> args = (Collection) parameter.get("args");
|
||||
if (CollUtil.isNotEmpty(args)) {
|
||||
List<String> value = args.stream()
|
||||
.map(stringStringMap -> stringStringMap.get("value"))
|
||||
.filter(StrUtil::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withArgs(value);
|
||||
}
|
||||
Collection<Map<String, String>> envs = (Collection) parameter.get("envs");
|
||||
if (CollUtil.isNotEmpty(envs)) {
|
||||
List<String> value = envs.stream()
|
||||
.map(stringStringMap -> {
|
||||
String name1 = stringStringMap.get("name");
|
||||
String value1 = stringStringMap.get("value");
|
||||
if (StrUtil.isEmpty(name1)) {
|
||||
return null;
|
||||
}
|
||||
return StrUtil.format("{}={}", name1, value1);
|
||||
})
|
||||
.filter(StrUtil::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withEnv(value);
|
||||
}
|
||||
Collection<Map<String, String>> commands = (Collection) parameter.get("commands");
|
||||
if (CollUtil.isNotEmpty(commands)) {
|
||||
List<String> value = commands.stream()
|
||||
.map(stringStringMap -> stringStringMap.get("value"))
|
||||
.filter(StrUtil::isNotEmpty)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withCommand(value);
|
||||
}
|
||||
//
|
||||
Collection<Map<String, String>> volumes = (Collection<Map<String, String>>) parameter.get("volumes");
|
||||
if (CollUtil.isNotEmpty(volumes)) {
|
||||
List<Mount> value = volumes.stream()
|
||||
.map(stringStringMap -> {
|
||||
String source = stringStringMap.get("source");
|
||||
String target = stringStringMap.get("target");
|
||||
if (StrUtil.hasBlank(source, target)) {
|
||||
return null;
|
||||
}
|
||||
String type = stringStringMap.get("type");
|
||||
MountType mountType = EnumUtil.fromString(MountType.class, type);
|
||||
Mount mount = new Mount();
|
||||
mount.withSource(source);
|
||||
mount.withTarget(target);
|
||||
mount.withType(mountType);
|
||||
return mount;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
containerSpec.withMounts(value);
|
||||
}
|
||||
return containerSpec;
|
||||
}
|
||||
|
||||
private UpdateConfig buildUpdateConfig(Map<String, Object> update) {
|
||||
if (MapUtil.isNotEmpty(update)) {
|
||||
UpdateConfig updateConfig = new UpdateConfig();
|
||||
String failureAction = (String) update.get("failureAction");
|
||||
if (StrUtil.isNotEmpty(failureAction)) {
|
||||
UpdateFailureAction updateFailureAction = EnumUtil.fromString(UpdateFailureAction.class, failureAction);
|
||||
updateConfig.withFailureAction(updateFailureAction);
|
||||
}
|
||||
String order = (String) update.get("order");
|
||||
if (StrUtil.isNotEmpty(order)) {
|
||||
UpdateOrder updateOrder = EnumUtil.fromString(UpdateOrder.class, order);
|
||||
updateConfig.withOrder(updateOrder);
|
||||
}
|
||||
Object parallelism = update.get("parallelism");
|
||||
if (parallelism != null) {
|
||||
updateConfig.withParallelism(Convert.toLong(parallelism));
|
||||
}
|
||||
Object delay = update.get("delay");
|
||||
if (delay != null) {
|
||||
updateConfig.withDelay(Convert.toLong(delay));
|
||||
}
|
||||
Object maxFailureRatio = update.get("maxFailureRatio");
|
||||
if (maxFailureRatio != null) {
|
||||
updateConfig.withMaxFailureRatio(Convert.toFloat(maxFailureRatio));
|
||||
}
|
||||
Object monitor = update.get("monitor");
|
||||
if (monitor != null) {
|
||||
updateConfig.withMonitor(Convert.toLong(monitor));
|
||||
}
|
||||
return updateConfig;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void removeServiceCmd(Map<String, Object> parameter) {
|
||||
DockerClient dockerClient = DockerUtil.build(parameter);
|
||||
try {
|
||||
|
@ -329,6 +329,7 @@ public class TestSwarm {
|
||||
taskSpec.withContainerSpec(containerSpec);
|
||||
serviceSpec.withTaskTemplate(taskSpec);
|
||||
}
|
||||
// serviceSpec.withRollbackConfig()
|
||||
serviceSpec.withEndpointSpec(new EndpointSpec());
|
||||
String serviceId = "tf2r29awevz2fcprybv6cvlm9";
|
||||
InspectServiceCmd inspectServiceCmd = client.inspectServiceCmd(serviceId);
|
||||
|
@ -50,7 +50,7 @@
|
||||
</span>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip slot="replicas" slot-scope="text, record" placement="topLeft" :title="text">
|
||||
<a-tooltip slot="replicas" slot-scope="text, record" placement="topLeft" :title="`点击数字查看运行中的任务,点击图标查看关联的所有任务`">
|
||||
<a-tag @click="handleTask(record, 'RUNNING')">{{ text }}</a-tag>
|
||||
|
||||
<a-icon type="read" @click="handleTask(record)" />
|
||||
@ -303,6 +303,60 @@
|
||||
</a-row>
|
||||
</a-form-model-item>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="update" tab="升级策略" v-if="temp.update">
|
||||
<a-form-model-item label="并行度" prop="parallelism">
|
||||
<a-input-number style="width: 80%" :min="0" v-model="temp.update.parallelism" placeholder="并行度" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="延迟" prop="delay">
|
||||
<a-input-number style="width: 80%" :min="1" v-model="temp.update.delay" placeholder="延迟" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="失败率" prop="maxFailureRatio">
|
||||
<a-input-number style="width: 80%" :min="0" v-model="temp.update.maxFailureRatio" placeholder="失败率" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="失败策略" prop="failureAction">
|
||||
<a-radio-group name="failureAction" v-model="temp.update.failureAction">
|
||||
<a-radio value="PAUSE">暂停</a-radio>
|
||||
<a-radio value="CONTINUE">继续</a-radio>
|
||||
<a-radio value="ROLLBACK">回滚</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="执行顺序" prop="order">
|
||||
<a-radio-group name="order" v-model="temp.update.order">
|
||||
<a-radio value="STOP_FIRST">先停止</a-radio>
|
||||
<a-radio value="START_FIRST">先启动</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="监控" prop="monitor">
|
||||
<a-input-number style="width: 80%" :min="1" v-model="temp.update.monitor" placeholder="延迟" />
|
||||
</a-form-model-item>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="rollback" tab="回滚策略" v-if="temp.rollback">
|
||||
<a-form-model-item label="并行度" prop="parallelism">
|
||||
<a-input-number style="width: 80%" :min="0" v-model="temp.rollback.parallelism" placeholder="并行度" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="延迟" prop="delay">
|
||||
<a-input-number style="width: 80%" :min="1" v-model="temp.rollback.delay" placeholder="延迟" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="失败率" prop="maxFailureRatio">
|
||||
<a-input-number style="width: 80%" :min="0" v-model="temp.rollback.maxFailureRatio" placeholder="失败率" />
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="失败策略" prop="failureAction">
|
||||
<a-radio-group name="failureAction" v-model="temp.rollback.failureAction">
|
||||
<a-radio value="PAUSE">暂停</a-radio>
|
||||
<a-radio value="CONTINUE">继续</a-radio>
|
||||
<a-radio value="ROLLBACK">回滚</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="执行顺序" prop="order">
|
||||
<a-radio-group name="order" v-model="temp.rollback.order">
|
||||
<a-radio value="STOP_FIRST">先停止</a-radio>
|
||||
<a-radio value="START_FIRST">先启动</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="监控" prop="monitor">
|
||||
<a-input-number style="width: 80%" :min="1" v-model="temp.rollback.monitor" placeholder="延迟" />
|
||||
</a-form-model-item>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
@ -338,7 +392,10 @@ export default {
|
||||
loading: false,
|
||||
listQuery: {},
|
||||
list: [],
|
||||
temp: {},
|
||||
temp: {
|
||||
update: {},
|
||||
rollback: {},
|
||||
},
|
||||
editVisible: false,
|
||||
initSwarmVisible: false,
|
||||
taskVisible: false,
|
||||
@ -427,6 +484,8 @@ export default {
|
||||
args: [{}],
|
||||
commands: [{}],
|
||||
envs: [{}],
|
||||
update: {},
|
||||
rollback: {},
|
||||
};
|
||||
},
|
||||
// 编辑
|
||||
@ -462,6 +521,8 @@ export default {
|
||||
args: [{}],
|
||||
commands: [{}],
|
||||
envs: [{}],
|
||||
update: {},
|
||||
rollback: {},
|
||||
};
|
||||
|
||||
const args = spec.taskTemplate?.containerSpec?.args;
|
||||
@ -469,7 +530,8 @@ export default {
|
||||
const command = spec.taskTemplate?.containerSpec?.command;
|
||||
const env = spec.taskTemplate?.containerSpec?.env;
|
||||
const ports = spec.endpointSpec?.ports;
|
||||
|
||||
const updateConfig = spec.updateConfig;
|
||||
const rollbackConfig = spec.rollbackConfig;
|
||||
if (args) {
|
||||
this.temp = {
|
||||
...this.temp,
|
||||
@ -507,6 +569,12 @@ export default {
|
||||
if (mounts) {
|
||||
this.temp = { ...this.temp, volumes: mounts };
|
||||
}
|
||||
if (updateConfig) {
|
||||
this.temp = { ...this.temp, update: updateConfig };
|
||||
}
|
||||
if (rollbackConfig) {
|
||||
this.temp = { ...this.temp, rollback: rollbackConfig };
|
||||
}
|
||||
},
|
||||
handleEditOk() {
|
||||
this.$refs["editForm"].validate((valid) => {
|
||||
|
@ -8,9 +8,11 @@
|
||||
<a-input v-model="listQuery['taskId']" @pressEnter="loadData" placeholder="任务id" class="search-input-item" />
|
||||
<a-input v-model="listQuery['taskNode']" @pressEnter="loadData" placeholder="节点id" class="search-input-item" />
|
||||
|
||||
<a-select show-search option-filter-prop="children" v-model="listQuery['taskState']" allowClear placeholder="状态" class="search-input-item">
|
||||
<a-select-option :key="key" v-for="(item, key) in TASK_STATE">{{ item }}- {{ key }}</a-select-option>
|
||||
</a-select>
|
||||
<a-tooltip :title="TASK_STATE[listQuery['taskState']]">
|
||||
<a-select show-search option-filter-prop="children" v-model="listQuery['taskState']" allowClear placeholder="状态" class="search-input-item">
|
||||
<a-select-option :key="key" v-for="(item, key) in TASK_STATE">{{ item }}- {{ key }}</a-select-option>
|
||||
</a-select>
|
||||
</a-tooltip>
|
||||
<a-button type="primary" @click="loadData" :loading="loading">搜索</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
Loading…
Reference in New Issue
Block a user