feat:(unify): 完成发布配置 新增列表查询

This commit is contained in:
opensnail 2024-12-29 23:32:43 +08:00
parent 1cdd8b4b6d
commit 1efe432403
14 changed files with 231 additions and 27 deletions

View File

@ -541,17 +541,17 @@ CREATE TABLE `sj_publish_config`
`exposed_ports` varchar(512) NOT NULL DEFAULT '' COMMENT '端口',
`auto_remove` tinyint(4) NOT NULL DEFAULT 0 COMMENT '容器退出后是否自动删除容器',
`network` varchar(512) NOT NULL DEFAULT '' COMMENT '端口',
`open_stdin` tinyint(4) NOT NULL DEFAULT '' COMMENT '是否标准输入',
`restart_policy` tinyint(4) NOT NULL DEFAULT '' COMMENT '重启规则',
`cpu_shares` int(11) NOT NULL DEFAULT '' COMMENT 'CPU权重',
`nano_cpus` int(11) NOT NULL DEFAULT '' COMMENT 'CPU限制',
`memory` int(11) NOT NULL DEFAULT '' COMMENT '内存限制',
`restart_policy` tinyint(4) NOT NULL DEFAULT 0 COMMENT '重启规则',
`cpu_shares` int(11) NOT NULL DEFAULT 0 COMMENT 'CPU权重',
`nano_cpus` int(11) NOT NULL DEFAULT 0 COMMENT 'CPU限制',
`memory` int(11) NOT NULL DEFAULT 0 COMMENT '内存限制',
`env` varchar(256) NOT NULL DEFAULT '' COMMENT '环境变量',
`labels` varchar(256) NOT NULL DEFAULT '' COMMENT '标签',
`create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `idx_namespace_id_group_name_config_name` (`namespace_id`, `group_name`, config_name),
KEY `idx_namespace_id_group_name_config_name` (`namespace_id`, `group_name`, config_name)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8mb4 COMMENT ='发布配置';
DEFAULT CHARSET = utf8mb4 COMMENT ='发布配置';

View File

@ -17,7 +17,7 @@ import lombok.Setter;
*/
@Getter
@Setter
@TableName("sj_notify_recipient")
@TableName("sj_publish_config")
public class PublishConfig extends CreateUpdateDt {
@TableId(value = "id", type = IdType.AUTO)
@ -48,15 +48,13 @@ public class PublishConfig extends CreateUpdateDt {
private String network;
private Integer openStdin;
private Integer restartPolicy;
private Integer cpuShares;
private Integer nanoCpus;
private Integer memory;
private Long memory;
private String env;

View File

@ -1,5 +1,6 @@
package com.aizuda.snailjob.server.web.controller;
import com.aizuda.snailjob.server.web.annotation.LoginRequired;
import com.aizuda.snailjob.server.web.model.base.PageResult;
import com.aizuda.snailjob.server.web.model.request.BuildImageRequestVO;
import com.aizuda.snailjob.server.web.model.request.ContainerQueryVO;
@ -15,6 +16,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
@RestController
@RequestMapping("/docker")
@ -28,37 +30,50 @@ public class DockerController {
}
@GetMapping("/container/page/list")
@LoginRequired
public PageResult<List<ContainerResponseVO>> getContainerList(ContainerQueryVO containerQueryVO) {
return dockerService.getContainerList(containerQueryVO);
}
@GetMapping("/container/{id}")
@LoginRequired
public InspectContainerResponse getContainerById(@PathVariable("id") String id) {
return dockerService.getContainerById(id);
}
@GetMapping("/container/log/{id}")
@LoginRequired
public ResultCallback<Frame> getContainerLogById(@PathVariable("id") String id) throws InterruptedException {
return dockerService.getContainerLogById(id);
}
@PostMapping("/create/container")
@LoginRequired
public boolean createContainer(@RequestBody CreateContainerRequestVO requestVO) {
return dockerService.createContainer(requestVO);
}
@GetMapping("/image/page/list")
@LoginRequired
public PageResult<List<ImageResponseVO>> getImageList(ImageQueryVO imageQueryVO) {
return dockerService.getImageList(imageQueryVO);
}
@PostMapping("/build/image")
@LoginRequired
public String buildImage(@RequestBody BuildImageRequestVO requestVO) {
return dockerService.buildImage(requestVO);
}
@PostMapping("/quick/publish")
@LoginRequired
public boolean quickPublish(@RequestBody CreateContainerRequestVO requestVO) {
return dockerService.quickPublish(requestVO);
}
@GetMapping("/network/list")
@LoginRequired
public Set<String> getNetworkList() {
return dockerService.getNetworkList();
}
}

View File

@ -1,5 +1,6 @@
package com.aizuda.snailjob.server.web.controller;
import com.aizuda.snailjob.server.web.annotation.LoginRequired;
import com.aizuda.snailjob.server.web.model.base.PageResult;
import com.aizuda.snailjob.server.web.model.request.PublishConfigQueryVO;
import com.aizuda.snailjob.server.web.model.request.PublishConfigRequestVO;
@ -7,6 +8,7 @@ import com.aizuda.snailjob.server.web.model.response.PublishConfigResponseVO;
import com.aizuda.snailjob.server.web.service.PublishConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ -27,22 +29,33 @@ public class PublishConfigController {
private final PublishConfigService publishConfigService;
@PostMapping
public boolean save(@RequestBody PublishConfigRequestVO requestVO) {
@LoginRequired
public boolean save(@RequestBody @Validated PublishConfigRequestVO requestVO) {
return publishConfigService.save(requestVO);
}
@PutMapping
public boolean update(@RequestBody PublishConfigRequestVO requestVO) {
@LoginRequired
public boolean update(@RequestBody @Validated PublishConfigRequestVO requestVO) {
return publishConfigService.update(requestVO);
}
@GetMapping("/{id}")
@LoginRequired
public PublishConfigResponseVO getDetail(@PathVariable("id") Long id) {
return publishConfigService.getById(id);
}
@GetMapping("/page/list")
@LoginRequired
public PageResult<List<PublishConfigResponseVO>> getPageList(PublishConfigQueryVO queryVO) {
return publishConfigService.getPageList(queryVO);
}
@GetMapping("/list")
@LoginRequired
public List<PublishConfigResponseVO> getConfigNameList(@RequestParam("groupName") String groupName) {
return publishConfigService.getConfigNameList(groupName);
}
}

View File

@ -7,5 +7,5 @@ public class BuildImageRequestVO {
private String groupName;
private String namespaceId;
private Long publishConfigId;
}

View File

@ -7,7 +7,7 @@ public class CreateContainerRequestVO {
private String groupName;
private String namespaceId;
private Long publishConfigId;
private String imageName;
}

View File

@ -1,5 +1,7 @@
package com.aizuda.snailjob.server.web.model.request;
import com.aizuda.snailjob.server.web.model.base.BaseQueryVO;
/**
* <p>
*
@ -8,5 +10,5 @@ package com.aizuda.snailjob.server.web.model.request;
* @author opensnail
* @date 2024-12-22
*/
public class PublishConfigQueryVO {
public class PublishConfigQueryVO extends BaseQueryVO {
}

View File

@ -1,5 +1,9 @@
package com.aizuda.snailjob.server.web.model.request;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
/**
* <p>
*
@ -8,5 +12,43 @@ package com.aizuda.snailjob.server.web.model.request;
* @author opensnail
* @date 2024-12-22
*/
@Data
public class PublishConfigRequestVO {
/**
* 组名称
*/
@NotBlank(message = "组名称不能为空")
@Pattern(regexp = "^[A-Za-z0-9_-]{1,64}$", message = "仅支持长度为1~64字符且类型为数字、字母、下划线和短横线")
private String groupName;
/**
* 配置名称
*/
@NotBlank(message = "配置名称不能为空")
private String configName;
private String ipv4;
private String ipv6;
private String exposedPorts;
private Integer autoRemove;
private String network;
// private Integer openStdin;
private Integer restartPolicy;
private Integer cpuShares;
private Integer nanoCpus;
private Integer memory;
private String env;
private String labels;
}

View File

@ -1,5 +1,7 @@
package com.aizuda.snailjob.server.web.model.response;
import lombok.Data;
/**
* <p>
*
@ -8,5 +10,45 @@ package com.aizuda.snailjob.server.web.model.response;
* @author opensnail
* @date 2024-12-22
*/
@Data
public class PublishConfigResponseVO {
private Long id;
/**
* 命名空间id
*/
private String namespaceId;
/**
* 组名称
*/
private String groupName;
/**
* 配置名称
*/
private String configName;
private String ipv4;
private String ipv6;
private String exposedPorts;
private Integer autoRemove;
private String network;
private Integer restartPolicy;
private Integer cpuShares;
private Integer nanoCpus;
private Integer memory;
private String env;
private String labels;
}

View File

@ -12,6 +12,7 @@ import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.model.Frame;
import java.util.List;
import java.util.Set;
public interface DockerService {
@ -30,4 +31,7 @@ public interface DockerService {
PageResult<List<ImageResponseVO>> getImageList(ImageQueryVO imageQueryVO);
boolean dockerStatus();
Set<String> getNetworkList();
}

View File

@ -24,4 +24,7 @@ public interface PublishConfigService {
PublishConfigResponseVO getById(Long id);
PageResult<List<PublishConfigResponseVO>> getPageList(PublishConfigQueryVO queryVO);
List<PublishConfigResponseVO> getConfigNameList(String groupName);
}

View File

@ -0,0 +1,28 @@
package com.aizuda.snailjob.server.web.service.convert;
import com.aizuda.snailjob.server.web.model.request.PublishConfigRequestVO;
import com.aizuda.snailjob.server.web.model.response.PublishConfigResponseVO;
import com.aizuda.snailjob.template.datasource.persistence.po.PublishConfig;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* <p>
*
* </p>
*
* @author opensnail
* @date 2024-12-29
*/
@Mapper
public interface PublishConfigConverter {
PublishConfigConverter INSTANCE = Mappers.getMapper(PublishConfigConverter.class);
PublishConfig toPublishConfig(PublishConfigRequestVO requestVO);
List<PublishConfigResponseVO> toPublishConfigList(List<PublishConfig> publishConfigList);
PublishConfigResponseVO toPublishConfigVO(PublishConfig publishConfig);
}

View File

@ -2,6 +2,7 @@ package com.aizuda.snailjob.server.web.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import com.aizuda.snailjob.common.core.util.JsonUtil;
import com.aizuda.snailjob.common.core.util.StreamUtils;
import com.aizuda.snailjob.server.common.exception.SnailJobServerException;
import com.aizuda.snailjob.server.common.util.DateUtils;
@ -16,11 +17,15 @@ import com.aizuda.snailjob.server.web.model.response.ContainerResponseVO;
import com.aizuda.snailjob.server.web.model.response.ImageResponseVO;
import com.aizuda.snailjob.server.web.service.DockerService;
import com.aizuda.snailjob.server.web.service.handler.DockerHandler;
import com.aizuda.snailjob.server.web.util.UserSessionUtils;
import com.aizuda.snailjob.template.datasource.persistence.mapper.PublishConfigMapper;
import com.aizuda.snailjob.template.datasource.persistence.po.PublishConfig;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.async.ResultCallbackTemplate;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.model.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sun.jna.LastErrorException;
@ -29,10 +34,9 @@ import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.aizuda.snailjob.server.common.util.DateUtils.PURE_DATETIME_MS_PATTERN;
@ -40,6 +44,7 @@ import static com.aizuda.snailjob.server.common.util.DateUtils.PURE_DATETIME_MS_
@RequiredArgsConstructor
public class DockerServiceImpl implements DockerService {
private final DockerHandler dockerHandler;
private final PublishConfigMapper publishConfigMapper;
private static final String workdir = WebConstants.WORKDIR;
@ -60,6 +65,7 @@ public class DockerServiceImpl implements DockerService {
try {
BuildImageCmd imageCmd = dockerClient
.buildImageCmd(file)
.withRemove(true)
.withTags(Sets.newHashSet(imageName));
imageCmd.exec(new SjBuildImageResultCallback()).awaitImageId();
} catch (Exception e) {
@ -78,17 +84,35 @@ public class DockerServiceImpl implements DockerService {
Map<String, String> labels = Maps.newHashMap();
labels.put("groupName", requestVO.getGroupName());
labels.put("namespaceId", requestVO.getNamespaceId());
labels.put("namespaceId", UserSessionUtils.currentUserSession().getNamespaceId());
PublishConfig publishConfig = publishConfigMapper.selectById(requestVO.getPublishConfigId());
HostConfig cfg = new HostConfig();
cfg.withMemory(publishConfig.getMemory());
cfg.withAutoRemove(publishConfig.getAutoRemove() == 1);
// [{key:value}]
String env = publishConfig.getEnv();
List<String> envs = Lists.newArrayList();
Map<String, String> envMap = JsonUtil.parseHashMap(env);
envMap.forEach((key, value) -> {
envs.add(String.format("%s=%s", key, value));
});
// [{key:value}]
String dbLabels = publishConfig.getLabels();
Map<String, String> map = JsonUtil.parseHashMap(dbLabels);
labels.putAll(map);
// Create a container
CreateContainerResponse container = dockerClient
.createContainerCmd(image)
.withName(containerName)
.withEnv()
.withEnv(envs)
.withExposedPorts()
.withHealthcheck(new HealthCheck())
// .withHostName(HostConfig)
.withHostConfig(cfg)
.withLabels(labels)
.exec();
@ -170,7 +194,8 @@ public class DockerServiceImpl implements DockerService {
public boolean quickPublish(CreateContainerRequestVO requestVO) {
BuildImageRequestVO buildImageRequestVO = new BuildImageRequestVO();
buildImageRequestVO.setGroupName(requestVO.getGroupName());
buildImageRequestVO.setNamespaceId(requestVO.getNamespaceId());
buildImageRequestVO.setPublishConfigId(requestVO.getPublishConfigId());
requestVO.setImageName(buildImage(buildImageRequestVO));
createContainer(requestVO);
return false;
@ -221,4 +246,11 @@ public class DockerServiceImpl implements DockerService {
return false;
}
}
@Override
public Set<String> getNetworkList() {
DockerClient dockerClient = dockerHandler.getDockerClient();
List<Network> exec = dockerClient.listNetworksCmd().exec();
return exec.stream().map(Network::getName).collect(Collectors.toSet());
}
}

View File

@ -3,10 +3,15 @@ package com.aizuda.snailjob.server.web.service.impl;
import com.aizuda.snailjob.server.web.model.base.PageResult;
import com.aizuda.snailjob.server.web.model.request.PublishConfigQueryVO;
import com.aizuda.snailjob.server.web.model.request.PublishConfigRequestVO;
import com.aizuda.snailjob.server.web.model.request.UserSessionVO;
import com.aizuda.snailjob.server.web.model.response.PublishConfigResponseVO;
import com.aizuda.snailjob.server.web.service.PublishConfigService;
import com.aizuda.snailjob.server.web.service.convert.PublishConfigConverter;
import com.aizuda.snailjob.server.web.util.UserSessionUtils;
import com.aizuda.snailjob.template.datasource.persistence.mapper.PublishConfigMapper;
import com.aizuda.snailjob.template.datasource.persistence.po.PublishConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -27,7 +32,9 @@ public class PublishConfigServiceImpl implements PublishConfigService {
@Override
public boolean save(PublishConfigRequestVO requestVO) {
return 1 == publishConfigMapper.insert(new PublishConfig());
PublishConfig publishConfig = PublishConfigConverter.INSTANCE.toPublishConfig(requestVO);
publishConfig.setNamespaceId(UserSessionUtils.currentUserSession().getNamespaceId());
return 1 == publishConfigMapper.insert(publishConfig);
}
@Override
@ -37,11 +44,29 @@ public class PublishConfigServiceImpl implements PublishConfigService {
@Override
public PublishConfigResponseVO getById(Long id) {
return null;
PublishConfig publishConfig = publishConfigMapper.selectById(id);
return PublishConfigConverter.INSTANCE.toPublishConfigVO(publishConfig);
}
@Override
public PageResult<List<PublishConfigResponseVO>> getPageList(PublishConfigQueryVO queryVO) {
return new PageResult<>();
PageDTO<PublishConfig> pageDTO = new PageDTO<>(queryVO.getPage(), queryVO.getSize());
UserSessionVO userSessionVO = UserSessionUtils.currentUserSession();
PageDTO<PublishConfig> publishConfigPageDTO =
publishConfigMapper.selectPage(pageDTO,
new LambdaQueryWrapper<PublishConfig>()
.eq(PublishConfig::getNamespaceId, userSessionVO.getNamespaceId())
);
return new PageResult<>(publishConfigPageDTO, PublishConfigConverter.INSTANCE.toPublishConfigList(pageDTO.getRecords()));
}
@Override
public List<PublishConfigResponseVO> getConfigNameList(String groupName) {
List<PublishConfig> publishConfigs = publishConfigMapper.selectList(new LambdaQueryWrapper<PublishConfig>()
.select(PublishConfig::getConfigName, PublishConfig::getId)
.eq(PublishConfig::getGroupName, groupName)
);
return PublishConfigConverter.INSTANCE.toPublishConfigList(publishConfigs);
}
}