diff --git a/react-ui/src/pages/Dataset/components/ResourceItem/index.less b/react-ui/src/pages/Dataset/components/ResourceItem/index.less deleted file mode 100644 index edd97f85..00000000 --- a/react-ui/src/pages/Dataset/components/ResourceItem/index.less +++ /dev/null @@ -1,61 +0,0 @@ -.resource-item { - position: relative; - width: calc(25% - 15px); - padding: 20px; - background: white; - border: 1px solid #eaeaea; - border-radius: 4px; - cursor: pointer; - - @media screen and (max-width: 1860px) { - & { - width: calc(33.33% - 13.33px); - } - } - - &__name { - position: relative; - display: inline-block; - height: 24px; - margin: 0 10px 0 0 !important; - color: @text-color; - font-size: 16px; - } - - &__description { - height: 44px; - margin-bottom: 20px; - color: @text-color-secondary; - font-size: 14px; - .multiLine(2); - } - &__time { - display: flex; - flex: 0 1 content; - align-items: center; - width: 100%; - color: #808080; - font-size: 13px; - } - - &:hover { - border-color: @primary-color; - box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); - - .resource-item__name { - color: @primary-color; - } - } -} - -.resource-item__name { - &::after { - position: absolute; - top: 14px; - left: 0; - width: 100%; - height: 6px; - background: linear-gradient(to right, rgba(22, 100, 255, 0.3) 0, rgba(22, 100, 255, 0) 100%); - content: ''; - } -} diff --git a/react-ui/src/pages/Dataset/components/ResourceItem/index.tsx b/react-ui/src/pages/Dataset/components/ResourceItem/index.tsx deleted file mode 100644 index 3b517184..00000000 --- a/react-ui/src/pages/Dataset/components/ResourceItem/index.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import clock from '@/assets/img/clock.png'; -import creatByImg from '@/assets/img/creatBy.png'; -import KFIcon from '@/components/KFIcon'; -import { formatDate } from '@/utils/date'; -import { Button, Flex, Typography } from 'antd'; -import { ResourceData } from '../../config'; -import styles from './index.less'; - -type ResourceItemProps = { - item: ResourceData; - isPublic: boolean; - onRemove: (item: ResourceData) => void; - onClick: (item: ResourceData) => void; -}; - -function ResourceItem({ item, isPublic, onClick, onRemove }: ResourceItemProps) { - return ( -
onClick(item)}> - - - {item.name} - - {!isPublic && ( - - )} - -
{item.description}
- -
- - {item.create_by} -
-
- - 最近更新: {formatDate(item.update_time, 'YYYY-MM-DD')} -
-
-
- ); -} - -export default ResourceItem; diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java index a64751aa..fc1aa78c 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java @@ -1,323 +1,344 @@ package com.ruoyi.system.api.domain; -import java.util.Date; -import java.util.List; -import javax.validation.constraints.*; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; import com.ruoyi.common.core.annotation.Excel; import com.ruoyi.common.core.annotation.Excel.ColumnType; import com.ruoyi.common.core.annotation.Excel.Type; import com.ruoyi.common.core.annotation.Excels; import com.ruoyi.common.core.web.domain.BaseEntity; import com.ruoyi.common.core.xss.Xss; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.util.Date; +import java.util.List; /** * 用户对象 sys_user - * + * * @author ruoyi */ -public class SysUser extends BaseEntity -{ +public class SysUser extends BaseEntity { private static final long serialVersionUID = 1L; - /** 用户ID */ + /** + * 用户ID + */ @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") private Long userId; - /** 部门ID */ + /** + * 部门ID + */ @Excel(name = "部门编号", type = Type.IMPORT) private Long deptId; - /** 用户账号 */ + /** + * 用户账号 + */ @Excel(name = "登录名称") private String userName; - /** 用户昵称 */ + /** + * 用户昵称 + */ @Excel(name = "用户名称") private String nickName; - /** 用户邮箱 */ + /** + * 用户邮箱 + */ @Excel(name = "用户邮箱") private String email; - /** 手机号码 */ + /** + * 手机号码 + */ @Excel(name = "手机号码") private String phonenumber; - /** 用户性别 */ + /** + * 用户性别 + */ @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") private String sex; - /** 用户头像 */ + /** + * 用户头像 + */ private String avatar; - /** 密码 */ + /** + * 密码 + */ private String password; - /** 帐号状态(0正常 1停用) */ + /** + * 帐号状态(0正常 1停用) + */ @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") private String status; - /** 删除标志(0代表存在 2代表删除) */ + /** + * 删除标志(0代表存在 2代表删除) + */ private String delFlag; - /** 最后登录IP */ + /** + * 最后登录IP + */ @Excel(name = "最后登录IP", type = Type.EXPORT) private String loginIp; - /** 最后登录时间 */ + /** + * 最后登录时间 + */ @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) private Date loginDate; - /** 部门对象 */ + /** + * 部门对象 + */ @Excels({ - @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), - @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) + @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), + @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) }) private SysDept dept; - /** 角色对象 */ + /** + * 角色对象 + */ private List roles; - /** 角色组 */ + /** + * 角色组 + */ private Long[] roleIds; - /** 岗位组 */ + /** + * 岗位组 + */ private Long[] postIds; - /** 角色ID */ + /** + * 角色ID + */ private Long roleId; - public SysUser() - { + private String gitLinkUsername; + + private String gitLinkPassword; + + public SysUser() { } - public SysUser(Long userId) - { + public SysUser(Long userId) { this.userId = userId; } - public Long getUserId() - { + public Long getUserId() { return userId; } - public void setUserId(Long userId) - { + public void setUserId(Long userId) { this.userId = userId; } - public boolean isAdmin() - { + public boolean isAdmin() { return isAdmin(this.userId); } - public static boolean isAdmin(Long userId) - { + public static boolean isAdmin(Long userId) { return userId != null && 1L == userId; } - public Long getDeptId() - { + public Long getDeptId() { return deptId; } - public void setDeptId(Long deptId) - { + public void setDeptId(Long deptId) { this.deptId = deptId; } @Xss(message = "用户昵称不能包含脚本字符") @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") - public String getNickName() - { + public String getNickName() { return nickName; } - public void setNickName(String nickName) - { + public void setNickName(String nickName) { this.nickName = nickName; } @Xss(message = "用户账号不能包含脚本字符") @NotBlank(message = "用户账号不能为空") @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") - public String getUserName() - { + public String getUserName() { return userName; } - public void setUserName(String userName) - { + public void setUserName(String userName) { this.userName = userName; } @Email(message = "邮箱格式不正确") @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") - public String getEmail() - { + public String getEmail() { return email; } - public void setEmail(String email) - { + public void setEmail(String email) { this.email = email; } @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") - public String getPhonenumber() - { + public String getPhonenumber() { return phonenumber; } - public void setPhonenumber(String phonenumber) - { + public void setPhonenumber(String phonenumber) { this.phonenumber = phonenumber; } - public String getSex() - { + public String getSex() { return sex; } - public void setSex(String sex) - { + public void setSex(String sex) { this.sex = sex; } - public String getAvatar() - { + public String getAvatar() { return avatar; } - public void setAvatar(String avatar) - { + public void setAvatar(String avatar) { this.avatar = avatar; } - public String getPassword() - { + public String getPassword() { return password; } - public void setPassword(String password) - { + public void setPassword(String password) { this.password = password; } - public String getStatus() - { + public String getStatus() { return status; } - public void setStatus(String status) - { + public void setStatus(String status) { this.status = status; } - public String getDelFlag() - { + public String getDelFlag() { return delFlag; } - public void setDelFlag(String delFlag) - { + public void setDelFlag(String delFlag) { this.delFlag = delFlag; } - public String getLoginIp() - { + public String getLoginIp() { return loginIp; } - public void setLoginIp(String loginIp) - { + public void setLoginIp(String loginIp) { this.loginIp = loginIp; } - public Date getLoginDate() - { + public Date getLoginDate() { return loginDate; } - public void setLoginDate(Date loginDate) - { + public void setLoginDate(Date loginDate) { this.loginDate = loginDate; } - public SysDept getDept() - { + public SysDept getDept() { return dept; } - public void setDept(SysDept dept) - { + public void setDept(SysDept dept) { this.dept = dept; } - public List getRoles() - { + public List getRoles() { return roles; } - public void setRoles(List roles) - { + public void setRoles(List roles) { this.roles = roles; } - public Long[] getRoleIds() - { + public Long[] getRoleIds() { return roleIds; } - public void setRoleIds(Long[] roleIds) - { + public void setRoleIds(Long[] roleIds) { this.roleIds = roleIds; } - public Long[] getPostIds() - { + public Long[] getPostIds() { return postIds; } - public void setPostIds(Long[] postIds) - { + public void setPostIds(Long[] postIds) { this.postIds = postIds; } - public Long getRoleId() - { + public Long getRoleId() { return roleId; } - public void setRoleId(Long roleId) - { + public void setRoleId(Long roleId) { this.roleId = roleId; } + + public void setGitLinkUsername(String gitLinkUsername) { + this.gitLinkUsername = gitLinkUsername; + } + + public String getGitLinkUsername() { + return gitLinkUsername; + } + + public void setGitLinkPassword(String gitLinkPassword) { + this.gitLinkPassword = gitLinkPassword; + } + + public String getGitLinkPassword() { + return gitLinkPassword; + } + @Override public String toString() { - return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) - .append("userId", getUserId()) - .append("deptId", getDeptId()) - .append("userName", getUserName()) - .append("nickName", getNickName()) - .append("email", getEmail()) - .append("phonenumber", getPhonenumber()) - .append("sex", getSex()) - .append("avatar", getAvatar()) - .append("password", getPassword()) - .append("status", getStatus()) - .append("delFlag", getDelFlag()) - .append("loginIp", getLoginIp()) - .append("loginDate", getLoginDate()) - .append("createBy", getCreateBy()) - .append("createTime", getCreateTime()) - .append("updateBy", getUpdateBy()) - .append("updateTime", getUpdateTime()) - .append("remark", getRemark()) - .append("dept", getDept()) - .toString(); + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("deptId", getDeptId()) + .append("userName", getUserName()) + .append("nickName", getNickName()) + .append("email", getEmail()) + .append("phonenumber", getPhonenumber()) + .append("sex", getSex()) + .append("avatar", getAvatar()) + .append("password", getPassword()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("loginIp", getLoginIp()) + .append("loginDate", getLoginDate()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("dept", getDept()) + .append("gitLinkUsername", getGitLinkUsername()) + .append("gitLinkPassword", getGitLinkPassword()) + .toString(); } } diff --git a/ruoyi-auth/src/main/resources/bootstrap.yml b/ruoyi-auth/src/main/resources/bootstrap.yml index c8b16589..a6607611 100644 --- a/ruoyi-auth/src/main/resources/bootstrap.yml +++ b/ruoyi-auth/src/main/resources/bootstrap.yml @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,4 +26,9 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true + - data-id: ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true \ No newline at end of file diff --git a/ruoyi-gateway/src/main/resources/bootstrap.yml b/ruoyi-gateway/src/main/resources/bootstrap.yml index d3abcc61..cce74447 100644 --- a/ruoyi-gateway/src/main/resources/bootstrap.yml +++ b/ruoyi-gateway/src/main/resources/bootstrap.yml @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,7 +26,12 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true + - data-id: ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true sentinel: # 取消控制台懒加载 eager: true @@ -33,7 +42,7 @@ spring: datasource: ds1: nacos: - server-addr: nacos-ci4s.ci4s-test.svc:8848 + server-addr: nacos-ci4s.ci4s-test.svc:18848 dataId: sentinel-ruoyi-gateway groupId: DEFAULT_GROUP data-type: json diff --git a/ruoyi-modules/management-platform/pom.xml b/ruoyi-modules/management-platform/pom.xml index 37234ad0..e7c559fd 100644 --- a/ruoyi-modules/management-platform/pom.xml +++ b/ruoyi-modules/management-platform/pom.xml @@ -140,7 +140,17 @@ com.github.docker-java docker-java - 3.1.1 + 3.2.13 + + + commons-beanutils + commons-beanutils + 1.9.4 + + + com.github.docker-java + docker-java-transport-httpclient5 + 3.2.13 com.baomidou @@ -216,7 +226,22 @@ 3.0.8 compile - + + commons-lang + commons-lang + 2.6 + compile + + + org.eclipse.jgit + org.eclipse.jgit + 5.13.0.202109080827-r + + + redis.clients + jedis + 3.6.0 + diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/constant/Constant.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/constant/Constant.java new file mode 100644 index 00000000..0c7a09fc --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/constant/Constant.java @@ -0,0 +1,21 @@ +package com.ruoyi.platform.constant; + +public class Constant { + + public final static int Image_Type_Pub = 1; // 公共镜像 + public final static int Image_Type_Pri = 0; // 私有镜像 + + public final static int Code_Repo_Pub = 1; // 代码仓库可见性-公开 + public final static int Code_Repo_Pri = 0; // 代码仓库可见性-私有 + + public final static int State_valid = 1; // 有效 + public final static int State_invalid = 0; // 无效 + + public final static int Used_State_used = 1; // 已占用 + public final static int Used_State_unused = 0; // 未占用 + + + public final static String Computing_Resource_CPU = "CPU"; // 计算资源_CPU + + public final static String Computing_Resource_GPU = "GPU"; // 计算资源_GPU +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/codeConfig/CodeConfigController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/codeConfig/CodeConfigController.java new file mode 100644 index 00000000..3aa6c37f --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/codeConfig/CodeConfigController.java @@ -0,0 +1,69 @@ +package com.ruoyi.platform.controller.codeConfig; + +import com.ruoyi.common.core.web.controller.BaseController; +import com.ruoyi.common.core.web.domain.GenericsAjaxResult; +import com.ruoyi.platform.domain.CodeConfig; +import com.ruoyi.platform.service.CodeConfigService; +import io.swagger.annotations.Api; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +@RestController +@RequestMapping("codeConfig") +@Api("代码配置") +public class CodeConfigController extends BaseController { + + @Resource + private CodeConfigService codeConfigService; + + /** + * 分页查询 + * + * @param codeConfig 筛选条件 + * @param page 页数 + * @param size 每页大小 + * @return 查询结果 + */ + @GetMapping + public GenericsAjaxResult> queryByPage(@RequestParam("page") int page, + @RequestParam("size") int size, + @RequestParam(value = "code_repo_name", required = false) String codeRepoName, + @RequestParam(value = "code_repo_vis", required = false)Integer codeRepoVis) { + PageRequest pageRequest = PageRequest.of(page, size); + CodeConfig codeConfig = new CodeConfig(); + codeConfig.setCodeRepoName(codeRepoName); + codeConfig.setCodeRepoVis(codeRepoVis); + return genericsSuccess(this.codeConfigService.queryByPage(codeConfig, pageRequest)); + } + + /** + * 通过主键查询单条数据 + * + * @param id + * @return 单条数据 + */ + @GetMapping("{id}") + public GenericsAjaxResult queryById(@PathVariable("id") Long id) { + return genericsSuccess(this.codeConfigService.queryById(id)); + } + + + @PostMapping + public GenericsAjaxResult add(@RequestBody CodeConfig codeConfig) { + return genericsSuccess(this.codeConfigService.insert(codeConfig)); + } + + @PutMapping + public GenericsAjaxResult update(@RequestBody CodeConfig codeConfig) { + return genericsSuccess(this.codeConfigService.update(codeConfig)); + } + + @DeleteMapping("{id}") + public GenericsAjaxResult delete(@PathVariable("id") Long id) { + return genericsSuccess(this.codeConfigService.removeById(id)); + } +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java index cbd87f41..8e364719 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java @@ -224,5 +224,7 @@ public class DatasetController { public AjaxResult uploadDatasetPipeline(@RequestBody(required =false) DatasetVersion datasetVersion) throws Exception { return AjaxResult.success(this.datasetService.uploadDatasetPipeline(datasetVersion)); } + + } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/NewDatasetFromGitController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/NewDatasetFromGitController.java new file mode 100644 index 00000000..636154db --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/NewDatasetFromGitController.java @@ -0,0 +1,115 @@ +package com.ruoyi.platform.controller.dataset; + +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.platform.domain.Dataset; +import com.ruoyi.platform.service.DatasetService; +import com.ruoyi.platform.vo.DatasetVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.core.io.InputStreamResource; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +@RestController +@RequestMapping("newdataset") +@Api(value = "新数据集管理") +public class NewDatasetFromGitController { + /** + * 服务对象 + */ + @Resource + private DatasetService datasetService; + + + + /** + * 新增数据集与版本新 + * + * @param datasetVo 实体 + * @return 新增结果 + */ + @PostMapping("/addDatasetAndVersion") + @ApiOperation("添加数据集和版本") + public AjaxResult addDatasetAndVersion(@RequestBody DatasetVo datasetVo) throws Exception { + return AjaxResult.success(this.datasetService.newCreateDataset(datasetVo)); + + } + + + /** + * 新增数据集与版本新 + * + * @param datasetVo 实体 + * @return 新增结果 + */ + @PostMapping("/addVersion") + @ApiOperation("添加版本") + public AjaxResult addVersion(@RequestBody DatasetVo datasetVo) throws Exception { + return AjaxResult.success(this.datasetService.newCreateVersion(datasetVo)); + + } + + + /** + * 上传数据集 + * + * @param files 上传的数据集文件 + * @param uuid 上传唯一标识,构建url + * @return 上传结果 + */ + @CrossOrigin(origins = "*", allowedHeaders = "*") + @PostMapping("/upload") + @ApiOperation(value = "上传数据集") + public AjaxResult uploadDataset(@RequestParam("file") MultipartFile[] files, @RequestParam("uuid") String uuid) throws Exception { + return AjaxResult.success(this.datasetService.uploadDatasetlocal(files,uuid)); + } + + /** + * 数据集打包下载 + * + * @param version 数据集版本 + * @return 单条数据 + */ + @GetMapping("/downloadAllFiles") + @ApiOperation(value = "下载同一版本下所有数据集,并打包") + public ResponseEntity downloadAllDatasetFiles(@RequestParam("repository_name") String repositoryName, @RequestParam("version") String version) throws Exception { + return datasetService.downloadAllDatasetFilesNew(repositoryName, version); + } + + /** + * 下载数据集 + * + * @param dataset_version_id ps:这里的id是dataset_version表的主键 + * @return 单条数据 + */ + + @GetMapping("/download/{dataset_version_id}") + @ApiOperation(value = "下载单个数据集文件", notes = "根据数据集版本表id下载单个数据集文件") + public ResponseEntity downloadDataset(@PathVariable("dataset_version_id") Integer dataset_version_id) throws Exception { + return datasetService.downloadDataset(dataset_version_id); + } + + @GetMapping("/queryDatasets") + @ApiOperation("数据集广场公开数据集分页查询,根据data_type,data_tag筛选,true公开false私有") + public AjaxResult queryDatasets(Dataset dataset, @RequestParam("page") int page, + @RequestParam("size") int size, + @RequestParam(value = "is_public") Boolean isPublic, + @RequestParam(value = "data_type", required = false) String dataType, + @RequestParam(value = "data_tag", required = false) String dataTag) throws Exception { + PageRequest pageRequest = PageRequest.of(page, size); + if(isPublic){ + return AjaxResult.success(this.datasetService.newPubilcQueryByPage(dataset, pageRequest)); + }else { + return AjaxResult.success(this.datasetService.newPersonalQueryByPage(dataset, pageRequest)); + } + } + + @GetMapping("/getdatasetDetail") + @ApiOperation(value = "获取数据集详情") + public AjaxResult getDatasetVersions(@PathVariable("datasetId") Integer datasetId) throws Exception { + return AjaxResult.success(this.datasetService.getDatasetVersions(datasetId)); + } +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java index a0b117d8..624ff5e0 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java @@ -45,7 +45,7 @@ public class ImageController extends BaseController { @RequestParam("size") int size, @RequestParam(value = "image_type") int imageType) { image.setImageType(imageType); - PageRequest pageRequest = PageRequest.of(page,size); + PageRequest pageRequest = PageRequest.of(page, size); return genericsSuccess(this.imageService.queryByPage(image, pageRequest)); } @@ -72,22 +72,21 @@ public class ImageController extends BaseController { public GenericsAjaxResult> queryByName(@PathVariable("name") String name) { return genericsSuccess(this.imageService.queryByName(name)); } + /** * 新增数据 * * @param image 实体 * @return 新增结果 */ - @PostMapping @ApiOperation("新增镜像,不包含镜像版本") public GenericsAjaxResult add(@RequestBody Image image) { return genericsSuccess(this.imageService.insert(image)); } /** - * 新增镜像和版本 - * * @param imageVo 实体 + * 新增镜像和版本 @PostMapping * @return 新增结果 */ @PostMapping("/addImageAndVersion") @@ -123,21 +122,20 @@ public class ImageController extends BaseController { @PostMapping("/net") @ApiOperation("从网络上传构建镜像") public GenericsAjaxResult> createImageFromNet(@RequestParam("name") String imageName, - @RequestParam("tag") String imageTag, - @RequestParam("path") String path) throws Exception { - return genericsSuccess(this.imageService.createImageFromNet(imageName,imageTag,path)); + @RequestParam("tag") String imageTag, + @RequestParam("path") String path) throws Exception { + return genericsSuccess(this.imageService.createImageFromNet(imageName, imageTag, path)); } @PostMapping("/local") @ApiOperation("从本地上传构建镜像") public GenericsAjaxResult> createImageFromLocal(@RequestParam("name") String imageName, - @RequestParam("tag") String imageTag, - @RequestParam("path") String path) throws Exception { - return genericsSuccess(this.imageService.createImageFromLocal(imageName,imageTag,path)); + @RequestParam("tag") String imageTag, + @RequestParam("path") String path) throws Exception { + return genericsSuccess(this.imageService.createImageFromLocal(imageName, imageTag, path)); } - /** * 镜像上传 * @@ -146,8 +144,14 @@ public class ImageController extends BaseController { @PostMapping("/upload") @ApiOperation(value = "上传镜像文件", notes = "上传镜像tar包,返回存储路径") public GenericsAjaxResult> uploadImageFiles(@RequestParam("file") MultipartFile file) throws Exception { - return genericsSuccess(this.imageService.uploadImageFiles(file)); + return genericsSuccess(this.imageService.uploadImageFiles(file)); } + + @PostMapping("/saveImage") + @ApiOperation(value = "保存环境为镜像", notes = "docker commit方式保存,并推送到horbor") + public void saveImage(@RequestBody ImageVo imageVo) { + this.imageService.saveImage(imageVo); + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/jupyter/JupyterController.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/jupyter/JupyterController.java index 3167e2ec..02bff0db 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/jupyter/JupyterController.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/jupyter/JupyterController.java @@ -4,9 +4,12 @@ import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.domain.GenericsAjaxResult; import com.ruoyi.platform.domain.DevEnvironment; +import com.ruoyi.platform.service.DatasetService; import com.ruoyi.platform.service.JupyterService; +import com.ruoyi.platform.vo.DatasetVo; import com.ruoyi.platform.vo.FrameLogPathVo; import com.ruoyi.platform.vo.PodStatusVo; +import com.ruoyi.platform.vo.VersionVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -17,6 +20,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; @RestController @RequestMapping("/jupyter") @@ -24,6 +29,8 @@ import java.io.InputStream; public class JupyterController extends BaseController { @Resource private JupyterService jupyterService; + @Resource + private DatasetService datasetService; @GetMapping(value = "/getURL") @ApiOperation("得到访问地址") public GenericsAjaxResult getURL() throws IOException { @@ -79,4 +86,21 @@ public class JupyterController extends BaseController { jupyterService.mlflow(); return AjaxResult.success(); } + + @GetMapping(value = "/testdvc") + public AjaxResult testdvc() throws Exception { + DatasetVo datasetVo = new DatasetVo(); + datasetVo.setName("testdassad23"); + datasetVo.setDescription("sss"); + datasetVo.setAvailableRange(0); + datasetVo.setDataTag("计算机视觉"); + datasetVo.setDataType("机器翻译"); + datasetVo.setVersion("dev"); + List datasetVersionVos = new ArrayList<>(); + VersionVo versionVo = new VersionVo(); + versionVo.setUrl("E:/test/bb/data/xssa.doc"); + datasetVersionVos.add(versionVo); + datasetVo.setDatasetVersionVos(datasetVersionVos); + return AjaxResult.success(datasetService.newCreateDataset(datasetVo)); + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/CodeConfig.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/CodeConfig.java new file mode 100644 index 00000000..e5a0c680 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/CodeConfig.java @@ -0,0 +1,57 @@ +package com.ruoyi.platform.domain; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class CodeConfig implements Serializable { + + + private Long id; + + @ApiModelProperty(name = "code_repo_name",value = "代码仓库名称") + private String codeRepoName; + + @ApiModelProperty(name = "code_repo_vis", value = "代码仓库可见性(1-公开,0-私有)") + private Integer codeRepoVis; + + @ApiModelProperty(name = "git_url", value = "Git地址") + private String gitUrl; + + @ApiModelProperty(name = "git_branch", value = "代码分支/Tag") + private String gitBranch; + + @ApiModelProperty(name = "verify_mode", value = "验证方式(0-用户名密码,1-SSH-Key)") + private Integer verifyMode; + + @ApiModelProperty(name = "git_user_name", value = "Git用户名") + private String gitUserName; + + @ApiModelProperty(name = "git_password", value = "Git密码") + private String gitPassword; + + @ApiModelProperty(name = "ssh_key",value = "SSH Key") + private String sshKey; + + @ApiModelProperty(name = "create_by", value = "创建者") + private String createBy; + + @ApiModelProperty(name = "create_time", value = "创建时间") + private Date createTime; + + @ApiModelProperty(name = "update_by", value = "更新者") + private String updateBy; + + @ApiModelProperty(name = "update_time", value = "更新时间") + private Date updateTime; + + @ApiModelProperty(name = "state", value = "状态,0失效1生效") + private Integer state; + +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ComputingResource.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ComputingResource.java index 47d7892d..d0551fa8 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ComputingResource.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ComputingResource.java @@ -46,7 +46,11 @@ private Integer id; @ApiModelProperty(value = "状态标识", notes = "0表示失效,1表示生效") private Integer state; + @ApiModelProperty(value = "占用情况(1-占用,0-未占用)") + private Integer usedState; + @ApiModelProperty(value = "节点") + private String node; public Integer getId() { return id; @@ -122,5 +126,20 @@ private Integer id; this.state = state; } + public Integer getUsedState() { + return usedState; + } + + public void setUsedState(Integer usedState) { + this.usedState = usedState; + } + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ImageVersion.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ImageVersion.java index ca20c4f2..64413332 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ImageVersion.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ImageVersion.java @@ -3,6 +3,7 @@ package com.ruoyi.platform.domain; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; import java.util.Date; import java.io.Serializable; @@ -14,6 +15,7 @@ import java.io.Serializable; * @since 2024-03-05 15:00:02 */ @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +@Data public class ImageVersion implements Serializable { private static final long serialVersionUID = 251017725389874890L; /** @@ -56,102 +58,7 @@ public class ImageVersion implements Serializable { @ApiModelProperty(value = "状态,0失效,1生效") private Integer state; - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public Integer getImageId() { - return imageId; - } - - public void setImageId(Integer imageId) { - this.imageId = imageId; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getTagName() { - return tagName; - } - - public void setTagName(String tagName) { - this.tagName = tagName; - } - - public String getFileSize() { - return fileSize; - } - - public void setFileSize(String fileSize) { - this.fileSize = fileSize; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public String getCreateBy() { - return createBy; - } - - public void setCreateBy(String createBy) { - this.createBy = createBy; - } - - public Date getCreateTime() { - return createTime; - } - - public void setCreateTime(Date createTime) { - this.createTime = createTime; - } - - public String getUpdateBy() { - return updateBy; - } - - public void setUpdateBy(String updateBy) { - this.updateBy = updateBy; - } - - public Date getUpdateTime() { - return updateTime; - } - - public void setUpdateTime(Date updateTime) { - this.updateTime = updateTime; - } - - public Integer getState() { - return state; - } - - public void setState(Integer state) { - this.state = state; - } - + @ApiModelProperty(value = "镜像所在主机ip") + private String hostIp; } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/CodeConfigDao.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/CodeConfigDao.java new file mode 100644 index 00000000..9025960a --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/CodeConfigDao.java @@ -0,0 +1,22 @@ +package com.ruoyi.platform.mapper; + +import com.ruoyi.platform.domain.CodeConfig; +import org.apache.ibatis.annotations.Param; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +public interface CodeConfigDao { + + long count(@Param("codeConfig") CodeConfig codeConfig); + + List queryAllByLimit(@Param("codeConfig") CodeConfig codeConfig, @Param("pageable") Pageable pageable); + + CodeConfig queryById(Long id); + + Long queryByCodeRepoName(@Param("codeRepoName") String codeRepoName); + + int insert(@Param("codeConfig") CodeConfig codeConfig); + + int update(@Param("codeConfig") CodeConfig codeConfig); +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ComputingResourceDao.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ComputingResourceDao.java index b9a5de6d..93cdaaf7 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ComputingResourceDao.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ComputingResourceDao.java @@ -73,6 +73,8 @@ public interface ComputingResourceDao { */ int update(@Param("computingResource") ComputingResource computingResource); + int updateUsedStateByNode(@Param("node")String node, @Param("usedState") Integer usedState); + /** * 通过主键删除数据 * diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/CodeConfigService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/CodeConfigService.java new file mode 100644 index 00000000..260c01d4 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/CodeConfigService.java @@ -0,0 +1,19 @@ +package com.ruoyi.platform.service; + +import com.ruoyi.platform.domain.CodeConfig; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; + +public interface CodeConfigService { + + Page queryByPage(CodeConfig codeConfig, PageRequest pageRequest); + + CodeConfig queryById(Long id); + + CodeConfig insert(CodeConfig codeConfig); + + CodeConfig update(CodeConfig codeConfig); + + String removeById(Long id); + +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DatasetService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DatasetService.java index edfe8cbe..a22e7101 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DatasetService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DatasetService.java @@ -3,14 +3,17 @@ package com.ruoyi.platform.service; import com.ruoyi.platform.domain.Dataset; import com.ruoyi.platform.domain.DatasetVersion; import com.ruoyi.platform.vo.DatasetVo; +import com.ruoyi.platform.vo.NewDatasetVo; import org.springframework.core.io.InputStreamResource; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; /** * (Dataset)表服务接口 @@ -84,4 +87,19 @@ DatasetService { ResponseEntity downloadAllDatasetFiles(Integer datasetId, String version) throws Exception; List> exportDataset(String path, String uuid) throws Exception; + + + + + + CompletableFuture newCreateDataset(DatasetVo datasetVo) throws Exception; + CompletableFuture newCreateVersion(DatasetVo datasetVo); + + + + List> uploadDatasetlocal(MultipartFile[] files, String uuid) throws Exception; + + ResponseEntity downloadAllDatasetFilesNew(String repositoryName, String version) throws IOException, Exception; + Page newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception; + Page newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception; } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DvcService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DvcService.java new file mode 100644 index 00000000..34c5ab25 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DvcService.java @@ -0,0 +1,8 @@ +package com.ruoyi.platform.service; + +public interface DvcService { + + //使用dvc初始化,跟踪,push到远程仓库的接口 + public void initaddpushDvc(String localPath) throws Exception ; + +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java index 15c5d34e..046e0186 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java @@ -31,7 +31,7 @@ public interface ExperimentInsService { /** * 根据实验ID查找所有具有相同ID的实例,并将它们添加到实验列表中 * - * @param experimentId 实验id,不是实例id + * @param experimentId 实验id,不是实验实例id * @return 实例列表 */ List getByExperimentId(Integer experimentId) throws IOException; diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/GitService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/GitService.java new file mode 100644 index 00000000..e130896b --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/GitService.java @@ -0,0 +1,17 @@ +package com.ruoyi.platform.service; + +import com.ruoyi.platform.vo.GitProjectVo; + +import java.util.Map; + +public interface GitService { + //登录方法,返回token + String login(String username, String password); + + //输入token,项目名,tag,创建新项目,返回项目地址 + Map createProject(String token, GitProjectVo gitProjectVo) throws Exception; + + void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception; + + void createTopic(String token, Integer id, String topicName) throws Exception; +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java index 59614ac9..d75ac86d 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java @@ -93,6 +93,5 @@ public interface ImageService { Map createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception; Map uploadImageFiles(MultipartFile file) throws Exception; - - + void saveImage(ImageVo imageVo); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/CodeConfigServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/CodeConfigServiceImpl.java new file mode 100644 index 00000000..445c0954 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/CodeConfigServiceImpl.java @@ -0,0 +1,89 @@ +package com.ruoyi.platform.service.impl; + +import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.platform.constant.Constant; +import com.ruoyi.platform.domain.CodeConfig; +import com.ruoyi.platform.mapper.CodeConfigDao; +import com.ruoyi.platform.service.CodeConfigService; +import com.ruoyi.system.api.model.LoginUser; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +@Service("codeConfigService") +public class CodeConfigServiceImpl implements CodeConfigService { + + @Resource + private CodeConfigDao codeConfigDao; + + + @Override + public Page queryByPage(CodeConfig codeConfig, PageRequest pageRequest) { + long total = this.codeConfigDao.count(codeConfig); + List codeConfigList = this.codeConfigDao.queryAllByLimit(codeConfig, pageRequest); + + return new PageImpl<>(codeConfigList, pageRequest, total); + } + + @Override + public CodeConfig queryById(Long id) { + return this.codeConfigDao.queryById(id); + } + + @Override + public CodeConfig insert(CodeConfig codeConfig) { + Long id = this.codeConfigDao.queryByCodeRepoName(codeConfig.getCodeRepoName()); + if(id != null){ + throw new IllegalStateException("代码仓库名称已存在"); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + codeConfig.setCreateBy(loginUser.getUsername()); + codeConfig.setUpdateBy(loginUser.getUsername()); + codeConfig.setCreateTime(new Date()); + codeConfig.setUpdateTime(new Date()); + this.codeConfigDao.insert(codeConfig); + return codeConfig; + } + + @Override + public CodeConfig update(CodeConfig codeConfig) { + Long id = this.codeConfigDao.queryByCodeRepoName(codeConfig.getCodeRepoName()); + if(id != null && !id.equals(codeConfig.getId())){ + throw new IllegalStateException("代码仓库名称已存在"); + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + codeConfig.setUpdateBy(loginUser.getUsername()); + + if (codeConfig.getCodeRepoVis().equals(Constant.Code_Repo_Pub)) { + codeConfig.setVerifyMode(null); + codeConfig.setGitUserName(null); + codeConfig.setGitPassword(null); + codeConfig.setSshKey(null); + } + this.codeConfigDao.update(codeConfig); + return this.codeConfigDao.queryById(codeConfig.getId()); + } + + @Override + public String removeById(Long id) { + CodeConfig codeConfig = this.codeConfigDao.queryById(id); + if (codeConfig == null) { + return "代码配置不存在"; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + String username = loginUser.getUsername(); + String createBy = codeConfig.getCreateBy(); + if (!(StringUtils.equals(username, "admin") || StringUtils.equals(username, createBy))) { + return "无权限删除该代码配置"; + } + codeConfig.setState(Constant.State_invalid); + return this.codeConfigDao.update(codeConfig) > 0 ? "删除成功" : "删除失败"; + } +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetServiceImpl.java index 835eb58b..55284187 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetServiceImpl.java @@ -1,6 +1,6 @@ package com.ruoyi.platform.service.impl; - +import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.platform.annotations.CheckDuplicate; import com.ruoyi.platform.domain.AssetIcon; @@ -8,17 +8,15 @@ import com.ruoyi.platform.domain.Dataset; import com.ruoyi.platform.domain.DatasetVersion; import com.ruoyi.platform.mapper.DatasetDao; import com.ruoyi.platform.mapper.DatasetVersionDao; -import com.ruoyi.platform.service.AssetIconService; -import com.ruoyi.platform.service.DatasetService; -import com.ruoyi.platform.service.DatasetVersionService; -import com.ruoyi.platform.service.MinioService; -import com.ruoyi.platform.utils.BeansUtils; -import com.ruoyi.platform.utils.FileUtil; -import com.ruoyi.platform.utils.MinioUtil; -import com.ruoyi.platform.vo.VersionVo; +import com.ruoyi.platform.service.*; +import com.ruoyi.platform.utils.*; import com.ruoyi.platform.vo.DatasetVo; +import com.ruoyi.platform.vo.GitProjectVo; +import com.ruoyi.platform.vo.NewDatasetVo; +import com.ruoyi.platform.vo.VersionVo; import com.ruoyi.system.api.model.LoginUser; import io.minio.messages.Item; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.InputStreamResource; @@ -32,14 +30,17 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import redis.clients.jedis.Jedis; import javax.annotation.Resource; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; +import java.io.*; import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -67,6 +68,12 @@ public class DatasetServiceImpl implements DatasetService { @Resource private MinioService minioService; + @Resource + private GitService gitService; + + @Resource + private DvcService dvcService; + // 固定存储桶名 @Value("${minio.dataReleaseBucketName}") private String bucketName; @@ -74,7 +81,16 @@ public class DatasetServiceImpl implements DatasetService { @Resource private MinioUtil minioUtil; - + @Value("${spring.redis.host}") + private String redisHost; + @Value("${minio.accessKey}") + String accessKeyId; + @Value("${minio.secretKey}") + String secretAccessKey; + @Value("${minio.endpoint}") + String endpoint; + @Value("${git.endpoint}") + String gitendpoint; /** * 通过ID查询单条数据 @@ -370,7 +386,7 @@ public class DatasetServiceImpl implements DatasetService { } @Override - public ResponseEntity downloadAllDatasetFiles(Integer datasetId, String version) throws Exception { + public ResponseEntity downloadAllDatasetFiles(Integer datasetId, String version) throws Exception { // 根据数据集id查数据名 Dataset dataset = this.datasetDao.queryById(datasetId); String datasetName = dataset.getName(); @@ -440,4 +456,294 @@ public class DatasetServiceImpl implements DatasetService { return results; } + + + @Override + public CompletableFuture newCreateDataset(DatasetVo datasetVo) { + return CompletableFuture.supplyAsync(() -> { + try { + String token = gitService.login("fanshuai", "h1n2x3j4y5@"); + LoginUser loginUser = SecurityUtils.getLoginUser(); + String ci4sUsername = loginUser.getUsername(); + Jedis jedis = new Jedis(redisHost); + String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); + Map userInfo = JsonUtils.jsonToMap(userReq); + Integer userId = (Integer) userInfo.get("user_id"); + // 拼接project + String repositoryName = ci4sUsername + "_dataset_" + DateUtils.dateTimeNow(); + GitProjectVo gitProjectVo = new GitProjectVo(); + gitProjectVo.setRepositoryName(repositoryName); + gitProjectVo.setName(datasetVo.getName()); + gitProjectVo.setDescription(datasetVo.getDescription()); + gitProjectVo.setPrivate(datasetVo.getAvailableRange() == 0); + gitProjectVo.setUserId(userId); + // 创建项目 + Map project = gitService.createProject(token, gitProjectVo); + // 创建分支 + String branchName = datasetVo.getVersion(); + gitService.createBranch(token, (String) userInfo.get("login"), repositoryName, branchName, "master"); + // 定义标签 标签1:ci4s_dataset 标签2:DataTag 标签3:DataType + gitService.createTopic(token, (Integer) project.get("id"), "ci4s_dataset"); + gitService.createTopic(token, (Integer) project.get("id"), "DataTag_" + datasetVo.getDataTag()); + gitService.createTopic(token, (Integer) project.get("id"), "DataType_" + datasetVo.getDataType()); + // 得到项目地址 + String projectUrl = gitendpoint + "/" +(String) userInfo.get("login") + "/" + repositoryName + ".git"; + + // 得到用户操作的路径 + String url = datasetVo.getDatasetVersionVos().get(0).getUrl(); + String localPath = "E:/test/" + datasetVo.getName(); + String sourcePath = url.substring(0, url.lastIndexOf("/")); + // 命令行操作 git clone 项目地址 + DVCUtils.gitClone(localPath, projectUrl, branchName, "fanshuai", "h1n2x3j4y5@"); + String s3Path = "management-platform-files/" + ci4sUsername + "/datasets/" + repositoryName + "/" + branchName; + //拼接生产的元数据后写入yaml文件 + YamlUtils.generateYamlFile(JsonUtils.objectToMap(datasetVo),sourcePath, "dataset"); + + DVCUtils.moveFiles(sourcePath, localPath); + + + + // dvc init 初始化 + DVCUtils.dvcInit(localPath); + // 配置远程S3地址 + DVCUtils.dvcRemoteAdd(localPath, s3Path); + DVCUtils.dvcConfigS3Credentials(localPath, endpoint); + DVCUtils.dvcConfigS3Credentials2(localPath, accessKeyId); + DVCUtils.dvcConfigS3Credentials3(localPath, secretAccessKey); + // dvc 跟踪 + DVCUtils.dvcAdd(localPath, "data"); + // git commit + DVCUtils.gitAdd(localPath, "."); + DVCUtils.gitCommit(localPath, "commit from ci4s with " + loginUser.getUsername()); + DVCUtils.gitPush(localPath, "fanshuai", "h1n2x3j4y5@"); + // dvc push 到远程S3 + DVCUtils.dvcPush(localPath); + return "新增数据集成功"; + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + @Override + public CompletableFuture newCreateVersion(DatasetVo datasetVo) { + return CompletableFuture.supplyAsync(() -> { + try { + String token = gitService.login("fanshuai", "h1n2x3j4y5@"); + LoginUser loginUser = SecurityUtils.getLoginUser(); + String ci4sUsername = loginUser.getUsername(); + Jedis jedis = new Jedis(redisHost); + String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); + Map userInfo = JsonUtils.jsonToMap(userReq); + // 创建分支 + String branchName = StringUtils.isEmpty(datasetVo.getVersion())? "master" : datasetVo.getVersion(); + String repositoryName = datasetVo.getRepositoryName(); + if (StringUtils.equals(branchName, "master")) { + gitService.createBranch(token, (String) userInfo.get("login"), repositoryName, branchName, "master"); + } + // 得到项目地址 + String projectUrl = gitendpoint + "/" +(String) userInfo.get("login") + "/" + repositoryName + ".git"; + + // 得到用户操作的路径 + String url = datasetVo.getDatasetVersionVos().get(0).getUrl(); + String localPath = "E:/test/"+ loginUser.getUsername()+"/datasets/"+ datasetVo.getName(); + String sourcePath = url.substring(0, url.lastIndexOf("/")); + // 命令行操作 git clone 项目地址 + DVCUtils.gitClone(localPath, projectUrl, branchName, "fanshuai", "h1n2x3j4y5@"); + String s3Path = "management-platform-files/" + ci4sUsername + "/datasets/" + repositoryName + "/" + branchName; + //拼接生产的元数据后写入yaml文件 + YamlUtils.generateYamlFile(JsonUtils.objectToMap(datasetVo),sourcePath, "dataset"); + + DVCUtils.moveFiles(sourcePath, localPath); + // dvc init 初始化 + DVCUtils.dvcInit(localPath); + // 配置远程S3地址 + DVCUtils.dvcRemoteAdd(localPath, s3Path); + DVCUtils.dvcConfigS3Credentials(localPath, endpoint); + DVCUtils.dvcConfigS3Credentials2(localPath, accessKeyId); + DVCUtils.dvcConfigS3Credentials3(localPath, secretAccessKey); + // dvc 跟踪 + DVCUtils.dvcAdd(localPath, "data"); + // git commit + DVCUtils.gitAdd(localPath, "."); + DVCUtils.gitCommit(localPath, "commit from ci4s with " + loginUser.getUsername()); + DVCUtils.gitPush(localPath, "fanshuai", "h1n2x3j4y5@"); + // dvc push 到远程S3 + DVCUtils.dvcPush(localPath); + return "新增数据集成功"; + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + + @Override + public Page newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { + LoginUser loginUser = SecurityUtils.getLoginUser(); + String token = gitService.login("fanshuai", "h1n2x3j4y5@"); + String ci4sUsername = loginUser.getUsername(); + Jedis jedis = new Jedis(redisHost); + String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); + Map userInfo = JsonUtils.jsonToMap(userReq); + //拼接查询url + String datasetTagName = dataset.getDatasetTagName(); + String datasetTypeName = dataset.getDatasetTypeName(); + String topic_name = "ci4s_dataset"; + topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatag_" + datasetTagName; + topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatype_" + datasetTypeName; + String url = gitendpoint + "/api/users/"+(String) userInfo.get("login")+"/projects.json?page="+pageRequest.getPageNumber()+"&limit="+pageRequest.getPageSize()+"&category=manage&topic_name="+topic_name; + String req = HttpUtils.sendGetWithToken(url,null,token); + Map stringObjectMap = JacksonUtil.parseJSONStr2Map(req); + Integer total = (Integer) stringObjectMap.get("count"); + List> projects = (List>) stringObjectMap.get("projects"); + return new PageImpl<>(convert(projects), pageRequest, total); + } + + @Override + public Page newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { + + LoginUser loginUser = SecurityUtils.getLoginUser(); + String token = gitService.login("fanshuai", "h1n2x3j4y5@"); + String ci4sUsername = loginUser.getUsername(); + Jedis jedis = new Jedis(redisHost); + String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); + Map userInfo = JsonUtils.jsonToMap(userReq); + Integer userId = (Integer) userInfo.get("user_id"); + //拼接查询url + String datasetTagName = dataset.getDatasetTagName(); + String datasetTypeName = dataset.getDatasetTypeName(); + String topic_name = "ci4s_dataset"; + topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatag_" + datasetTagName; + topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatype_" + datasetTypeName; + + String url = gitendpoint + "/api/projects.json?user_id="+userId+"&page="+pageRequest.getPageNumber()+"&limit="+pageRequest.getPageSize()+"&sort_by=praises_count&topic_name="+topic_name; + String req = HttpUtils.sendGetWithToken(url,null,token); + Map stringObjectMap = JacksonUtil.parseJSONStr2Map(req); + Integer total = (Integer) stringObjectMap.get("total_count"); + List> projects = (List>) stringObjectMap.get("projects"); + return new PageImpl<>(convert(projects), pageRequest, total); + + } + + @Override + public List> uploadDatasetlocal(MultipartFile[] files, String uuid) throws Exception { + List> results = new ArrayList<>(); + + for (MultipartFile file:files){ + // 构建objectName + String username = SecurityUtils.getLoginUser().getUsername(); + String fileName = file.getOriginalFilename(); + String path = "/temp/"+ username +"/datasets/"+ uuid + "/"+"/data/" + fileName; + long sizeInBytes = file.getSize(); + String formattedSize = FileUtil.formatFileSize(sizeInBytes); + File targetFile = new File(path, file.getOriginalFilename()); + // 确保目录存在 + targetFile.getParentFile().mkdirs(); + // 保存文件到目标路径 + FileUtils.copyInputStreamToFile(file.getInputStream(), targetFile); + // 返回上传文件的路径 + String absolutePath = targetFile.getAbsolutePath(); + Map result = new HashMap<>(); + result.put("fileName", fileName); + result.put("url", absolutePath); // objectName根据实际情况定义 + result.put("fileSize", formattedSize); + results.add(result); + } + return results; + } + + @Override + public ResponseEntity downloadAllDatasetFilesNew(String repositoryName, String version) throws Exception { + // 命令行操作 git clone 项目地址 + LoginUser loginUser = SecurityUtils.getLoginUser(); + String token = gitService.login("fanshuai", "h1n2x3j4y5@"); + String ci4sUsername = loginUser.getUsername(); + Jedis jedis = new Jedis(redisHost); + String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); + Map userInfo = JsonUtils.jsonToMap(userReq); + Integer userId = (Integer) userInfo.get("user_id"); + String projectUrl = gitendpoint + "/" +(String) userInfo.get("login") + "/" + repositoryName + ".git"; + String localPath = "E:/test/"+ loginUser.getUsername()+"/datasets/" +repositoryName; + File folder = new File(localPath); + if(folder.exists() && folder.isDirectory()){ + //切换分支 + DVCUtils.gitCheckoutBranch(localPath, version); + //pull + DVCUtils.gitPull(localPath,"fanshuai", "h1n2x3j4y5@"); + //dvc pull + DVCUtils.dvcPull(localPath); + }else { + DVCUtils.gitClone(localPath, projectUrl, version, "fanshuai", "h1n2x3j4y5@"); + } + + // 打包 data 文件夹 + String dataFolderPath = localPath + "/data"; + String zipFilePath = localPath + "/data.zip"; + try (FileOutputStream fos = new FileOutputStream(zipFilePath); + ZipOutputStream zos = new ZipOutputStream(fos)) { + Path sourcePath = Paths.get(dataFolderPath); + Files.walk(sourcePath).forEach(path -> { + if (!Files.isDirectory(path)) { + ZipEntry zipEntry = new ZipEntry(sourcePath.relativize(path).toString()); + try { + zos.putNextEntry(zipEntry); + Files.copy(path, zos); + zos.closeEntry(); + } catch (IOException e) { + throw new RuntimeException("Error while zipping: " + path, e); + } + } + }); + } + + // 返回压缩文件的输入流 + File zipFile = new File(zipFilePath); + InputStreamResource resource = new InputStreamResource(new FileInputStream(zipFile)); + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=data.zip") + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .contentLength(zipFile.length()) + .body(resource); + + } + + + + public List convert(List> lst) { + if (lst != null && lst.size() > 0) { + List newDatasetVos = ConvertUtil.convertListMapToObjectList(lst, NewDatasetVo.class); + + for (NewDatasetVo newDatasetVo : newDatasetVos) { + Map map = lst.stream() + .filter(m -> m.get("repo_id").equals(newDatasetVo.getRepoId())) + .findFirst() + .orElse(null); + + if (map != null) { + List> topics = (List>) map.get("topics"); + if (topics != null) { + topics.forEach(topic -> { + String name = (String) topic.get("name"); + if (name != null) { + if (name.startsWith("datatag_")) { + newDatasetVo.setDataTag(name.substring("datatag_".length())); + } else if (name.startsWith("datatype_")) { + newDatasetVo.setDataType(name.substring("datatype_".length())); + } + } + }); + } + + Map author = (Map) map.get("author"); + newDatasetVo.setCreateBy((String) author.get("name")); + } + } + + return newDatasetVos; + } + return new ArrayList<>(); + } + } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DvcServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DvcServiceImpl.java new file mode 100644 index 00000000..a962588f --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DvcServiceImpl.java @@ -0,0 +1,34 @@ +package com.ruoyi.platform.service.impl; + +import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.platform.service.DvcService; +import com.ruoyi.platform.utils.DVCUtils; +import com.ruoyi.system.api.model.LoginUser; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class DvcServiceImpl implements DvcService { + @Value("${minio.accessKey}") + String accessKeyId; + @Value("${minio.secretKey}") + String secretAccessKey; + @Value("${minio.endpoint}") + String endpoint; + @Override + public void initaddpushDvc(String localPath) throws Exception { + LoginUser loginUser = SecurityUtils.getLoginUser(); + // dvc init 初始化 + DVCUtils.dvcInit(localPath); + // 配置远程S3地址 + DVCUtils.dvcRemoteAdd(localPath,""); +// DVCUtils.dvcConfigS3Credentials(localPath,endpoint, accessKeyId, secretAccessKey); + // dvc 跟踪 + DVCUtils.dvcAdd(localPath , "data"); + // git commit + DVCUtils.gitCommit(localPath, "commit from ci4s with "+loginUser.getUsername()); + // dvc push 到远程S3 + DVCUtils.dvcPush(localPath); + } + +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/GitServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/GitServiceImpl.java new file mode 100644 index 00000000..40980dc9 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/GitServiceImpl.java @@ -0,0 +1,98 @@ +package com.ruoyi.platform.service.impl; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.platform.service.GitService; +import com.ruoyi.platform.utils.HttpUtils; +import com.ruoyi.platform.utils.JsonUtils; +import com.ruoyi.platform.vo.GitProjectVo; +import com.ruoyi.system.api.model.LoginUser; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import redis.clients.jedis.Jedis; + +import java.util.HashMap; +import java.util.Map; + +@Service +public class GitServiceImpl implements GitService { + + @Value("${spring.redis.host}") + private String redisHost; + + private static final Logger log = LoggerFactory.getLogger(GitServiceImpl.class); + + @Override + public String login(String username, String password) { + // 构建请求参数 + Map params = new HashMap<>(); + params.put("grant_type", "password"); + params.put("username", username); + params.put("password", password); + params.put("client_id", "jEdGwrIJixCUIJM9vj2MwA6zmoTVhUdXxiSAaaCiXwA"); + params.put("client_secret", "L3wBKTNnRo-wPen7bxR3F1myCvtVDgpWa6MnpfyWeJE"); + try { + // 发送POST请求 + String req = HttpUtils.sendPostRequest("https://www.gitlink.org.cn/oauth/token",null, JsonUtils.mapToJson(params)); + // 解析响应JSON + if (StringUtils.isEmpty(req)) { + throw new RuntimeException("终止响应内容为空。"); + } + // 将响应的JSON字符串转换为Map对象 + Map runResMap = JsonUtils.jsonToMap(req); + // 提取access_token + // 提取access_token + String accessToken = (String) runResMap.get("access_token"); + + //通过access_token获取用户信息 + String userReq = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/users/get_user_info.json",null, accessToken); + if (StringUtils.isEmpty(userReq)) { + throw new RuntimeException("终止响应内容为空。"); + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + String ci4sUsername = loginUser.getUsername(); + // 将access_token存入Redis + Jedis jedis = new Jedis(redisHost); + jedis.set(ci4sUsername+"_gitToken", accessToken); + jedis.set(ci4sUsername+"_gitUserInfo", userReq); + return accessToken; + } catch (Exception e) { + log.error("登录GitLink失败。", e); + return null; + } + } + + @Override + public Map createProject(String token, GitProjectVo gitProjectVo) throws Exception { + String userReq = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/projects.json",JsonUtils.objectToJson(gitProjectVo),token); + return JsonUtils.jsonToMap(userReq); + } + + @Override + public void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception { + //https://www.gitlink.org.cn/api/v1/fanshuai/testdssa8755/branches.json +// { +// "new_branch_name": "SsS", +// "old_branch_name": "master" +// } + String createBranchUrl = "https://www.gitlink.org.cn/api/v1/"+ owner + "/" + projectName + "/branches.json"; + Map resMap = new HashMap<>(); + resMap.put("new_branch_name", branchName); + resMap.put("old_branch_name", oldBranchName); + String req = HttpUtils.sendPostWithToken(createBranchUrl,JsonUtils.objectToJson(resMap),token); + System.out.println(req); + } + + @Override + public void createTopic(String token, Integer id, String topicName) throws Exception { + // https://www.gitlink.org.cn/api/v1/project_topics.json + Map resMap = new HashMap<>(); + resMap.put("project_id", id); + resMap.put("name", topicName); + String req = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/v1/project_topics.json",JsonUtils.objectToJson(resMap),token); + System.out.println(req); + } +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java index 336776ea..582af8c9 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java @@ -2,24 +2,29 @@ package com.ruoyi.platform.service.impl; import com.alibaba.fastjson2.util.DateUtils; import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.platform.constant.Constant; +import com.ruoyi.platform.domain.DevEnvironment; import com.ruoyi.platform.domain.Image; import com.ruoyi.platform.domain.ImageVersion; +import com.ruoyi.platform.mapper.DevEnvironmentDao; import com.ruoyi.platform.mapper.ImageDao; import com.ruoyi.platform.mapper.ImageVersionDao; import com.ruoyi.platform.service.ImageService; import com.ruoyi.platform.service.ImageVersionService; import com.ruoyi.platform.service.MinioService; +import com.ruoyi.platform.utils.DockerClientUtil; import com.ruoyi.platform.utils.FileUtil; import com.ruoyi.platform.utils.K8sClientUtil; import com.ruoyi.platform.vo.ImageVo; import com.ruoyi.system.api.model.LoginUser; -import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; import io.kubernetes.client.openapi.models.V1Pod; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -27,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -40,16 +46,19 @@ import java.util.concurrent.CompletableFuture; public class ImageServiceImpl implements ImageService { @Resource private ImageDao imageDao; - + @Resource + private ImageVersionDao imageVersionDao; + @Resource + private DevEnvironmentDao devEnvironmentDao; @Resource private ImageVersionService imageVersionService; - - @Resource - private ImageVersionDao imageVersionDao; @Resource private K8sClientUtil k8sClientUtil; + @Resource + private DockerClientUtil dockerClientUtil; + @Resource private MinioService minioService; @Value("${harbor.bucketName}") @@ -75,6 +84,9 @@ public class ImageServiceImpl implements ImageService { private String proxyUrl; @Value("${minio.pvcName}") private String pvcName; + @Value("${jupyter.namespace}") + private String namespace; + /** * 通过ID查询单条数据 * @@ -89,8 +101,8 @@ public class ImageServiceImpl implements ImageService { /** * 分页查询 * - * @param image 筛选条件 - * @param pageRequest 分页对象 + * @param image 筛选条件 + * @param pageRequest 分页对象 * @return 查询结果 */ @Override @@ -100,7 +112,6 @@ public class ImageServiceImpl implements ImageService { } - /** * 新增数据 * @@ -128,7 +139,7 @@ public class ImageServiceImpl implements ImageService { @Override public Image update(Image image) { int currentState = image.getState(); - if(currentState == 0){ + if (currentState == 0) { throw new RuntimeException("镜像已被删除,无法更新。"); } LoginUser loginUser = SecurityUtils.getLoginUser(); @@ -153,7 +164,7 @@ public class ImageServiceImpl implements ImageService { @Override public String removeById(Integer id) throws Exception { Image image = this.imageDao.queryById(id); - if (image == null){ + if (image == null) { throw new Exception("镜像不存在"); } @@ -163,14 +174,20 @@ public class ImageServiceImpl implements ImageService { String createdBy = image.getCreateBy(); - if (!(StringUtils.equals(username,"admin") || !StringUtils.equals(username,createdBy))){ + if (!(StringUtils.equals(username, "admin") || !StringUtils.equals(username, createdBy))) { throw new Exception("无权限删除该镜像"); } - if (!imageVersionService.queryByImageId(id).isEmpty()){ - throw new Exception("请先删除该镜像下的版本文件"); +// if (!imageVersionService.queryByImageId(id).isEmpty()){ +// throw new Exception("请先删除该镜像下的版本文件"); +// } + List imageVersions = imageVersionService.queryByImageId(id); + + for (ImageVersion imageVersion :imageVersions) { + dockerClientUtil.removeImage(imageVersion.getUrl(), imageVersion.getHostIp()); } + image.setState(0); - return this.imageDao.update(image)>0?"删除成功":"删除失败"; + return this.imageDao.update(image) > 0 ? "删除成功" : "删除失败"; } @@ -197,7 +214,7 @@ public class ImageServiceImpl implements ImageService { public String insertImageAndVersion(ImageVo imageVo) throws Exception { Image existingImage = getByName(imageVo.getName()); Image imageToUse; - if(existingImage == null) { + if (existingImage == null) { // 如果不存在相同名称的镜像,则创建新的镜像记录 Image newImage = new Image(); newImage.setName(imageVo.getName()); @@ -207,7 +224,7 @@ public class ImageServiceImpl implements ImageService { if (imageToUse == null) { throw new Exception("新增镜像失败"); } - }else{ + } else { // 如果已存在相同名称的镜像,使用已存在的镜像 imageToUse = existingImage; } @@ -225,9 +242,9 @@ public class ImageServiceImpl implements ImageService { CompletableFuture.supplyAsync(() -> { Map resultMap = new HashMap<>(); try { - if(imageVo.getUploadType()==0){ - resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); - }else{ + if (imageVo.getUploadType() == 0) { + resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); + } else { resultMap = createImageFromLocal(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); } } catch (Exception e) { @@ -236,7 +253,7 @@ public class ImageServiceImpl implements ImageService { throw new RuntimeException("镜像构建失败: " + e.getMessage(), e); } return resultMap; - }).thenAccept(resultMap ->{ + }).thenAccept(resultMap -> { try { String imageUrl = resultMap.get("url"); String fileSize = resultMap.get("fileSize"); @@ -262,27 +279,27 @@ public class ImageServiceImpl implements ImageService { // 得到容器 V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); if (pod == null) { - String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); - pod = k8sClientUtil.createPodWithEnv(podName,serviceNS,proxyUrl,mountPath,pvcName,image); + String podName = deploymentName + "-" + DateUtils.formatYMD10(new Date()); + pod = k8sClientUtil.createPodWithEnv(podName, serviceNS, proxyUrl, mountPath, pvcName, image); } - String loginCmd = "docker login -u " + harborUser +" -p "+harborpassword+" "+harborUrl; + String loginCmd = "docker login -u " + harborUser + " -p " + harborpassword + " " + harborUrl; // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 - String loginlog = k8sClientUtil.executeCommand(pod,loginCmd); + String loginlog = k8sClientUtil.executeCommand(pod, loginCmd); // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag String username = SecurityUtils.getLoginUser().getUsername(); // - String logs2 = k8sClientUtil.executeCommand(pod,"docker pull "+ netPath); + String logs2 = k8sClientUtil.executeCommand(pod, "docker pull " + netPath); // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag - if (StringUtils.isNoneBlank(logs2)){ + if (StringUtils.isNoneBlank(logs2)) { String[] lines = logs2.split("\n"); String lastLine = lines[lines.length - 1].trim(); String tagCmd = "docker tag " + lastLine + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; - String pushCmd = "docker push " + imageUrl; + String pushCmd = "docker push " + imageUrl; String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; String s = k8sClientUtil.executeCommand(pod, tagCmd); - if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){ + if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))) { resultMap.put("url", imageUrl); //得到镜像文件大小 String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); @@ -291,10 +308,10 @@ public class ImageServiceImpl implements ImageService { resultMap.put("fileSize", formattedImageSize); return resultMap; - }else { + } else { throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); } - }else { + } else { throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); } } @@ -305,27 +322,27 @@ public class ImageServiceImpl implements ImageService { // 得到容器 V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); if (pod == null) { - String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); - pod = k8sClientUtil.createPodWithEnv(podName,serviceNS,proxyUrl,mountPath,pvcName,image); + String podName = deploymentName + "-" + DateUtils.formatYMD10(new Date()); + pod = k8sClientUtil.createPodWithEnv(podName, serviceNS, proxyUrl, mountPath, pvcName, image); } - String loginCmd = "docker login -u " + harborUser +" -p "+harborpassword+" "+harborUrl; + String loginCmd = "docker login -u " + harborUser + " -p " + harborpassword + " " + harborUrl; // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 - String loginlog = k8sClientUtil.executeCommand(pod,loginCmd); + String loginlog = k8sClientUtil.executeCommand(pod, loginCmd); // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag String username = SecurityUtils.getLoginUser().getUsername(); // - String filePath = "/data/argo-workflow/" + bucketName + "/" +path; - String logs2 = k8sClientUtil.executeCommand(pod,"docker load -i "+filePath); + String filePath = "/data/argo-workflow/" + bucketName + "/" + path; + String logs2 = k8sClientUtil.executeCommand(pod, "docker load -i " + filePath); // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag - if (StringUtils.isNoneBlank(logs2)){ - String substring = logs2.substring(logs2.indexOf(":")+1).trim(); + if (StringUtils.isNoneBlank(logs2)) { + String substring = logs2.substring(logs2.indexOf(":") + 1).trim(); String tagCmd = "docker tag " + substring + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; - String pushCmd = "docker push " + imageUrl; + String pushCmd = "docker push " + imageUrl; String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; String s = k8sClientUtil.executeCommand(pod, tagCmd); - if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){ + if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))) { resultMap.put("url", imageUrl); //得到镜像文件大小 String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); @@ -333,18 +350,79 @@ public class ImageServiceImpl implements ImageService { String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小 resultMap.put("fileSize", formattedImageSize); return resultMap; - }else { + } else { throw new Exception("解析镜像压缩包失败,请检查镜像文件"); } - }else { + } else { throw new Exception("解析镜像压缩包失败,请检查镜像文件"); } } + @Override public Map uploadImageFiles(MultipartFile file) throws Exception { LoginUser loginUser = SecurityUtils.getLoginUser(); - String path = loginUser.getUsername()+"/"+file.getOriginalFilename(); + String path = loginUser.getUsername() + "/" + file.getOriginalFilename(); return minioService.uploadFile(bucketName, path, file); } + + @Override + @Transactional + @Async + public void saveImage(ImageVo imageVo) { + Image oldImage = imageDao.getByName(imageVo.getName()); + if (oldImage != null) { + List oldImageVersions = imageVersionDao.queryByImageId(oldImage.getId()); + for (ImageVersion oldImageVersion : oldImageVersions) { + if(oldImageVersion.getTagName().equals(imageVo.getTagName())){ + throw new IllegalStateException("镜像tag不能重复"); + } + } + } + + LoginUser loginUser = SecurityUtils.getLoginUser(); + String username = loginUser.getUsername().toLowerCase(); + String podName = username + "-editor-pod" + "-" + imageVo.getDevEnvironmentId().toString(); + + try { + String containerId = k8sClientUtil.getPodContainerId(podName, namespace); + String hostIp = k8sClientUtil.getHostIp(podName, namespace); + + dockerClientUtil.commitImage(imageVo, containerId, hostIp, username); + HashMap resultMap = dockerClientUtil.pushImageToHorbor(imageVo, hostIp); + + Image image = new Image(); + BeanUtils.copyProperties(imageVo, image); + image.setImageType(Constant.Image_Type_Pri); + image.setCreateBy(username); + image.setUpdateBy(username); + image.setUpdateTime(new Date()); + image.setCreateTime(new Date()); + image.setState(1); + imageDao.insert(image); + + ImageVersion imageVersion = new ImageVersion(); + imageVersion.setImageId(image.getId()); + imageVersion.setVersion(imageVo.getVersion()); + imageVersion.setUrl(resultMap.get("imageName")); + imageVersion.setTagName(imageVo.getTagName()); + imageVersion.setFileSize(resultMap.get("size")); + imageVersion.setCreateBy(username); + imageVersion.setUpdateBy(username); + imageVersion.setHostIp(hostIp); + imageVersion.setUpdateTime(new Date()); + imageVersion.setCreateTime(new Date()); + imageVersion.setState(1); + imageVersion.setStatus("available"); + imageVersionDao.insert(imageVersion); + + //更新dev环境的镜像信息 + DevEnvironment devEnvironment = new DevEnvironment(); + devEnvironment.setId(imageVo.getDevEnvironmentId()); + devEnvironment.setImage(resultMap.get("imageName")); + devEnvironmentDao.update(devEnvironment); + } catch (Exception e) { + throw new RuntimeException("保存镜像失败:" + e); + } + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java index 038e6d91..e6380f3a 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java @@ -2,8 +2,10 @@ package com.ruoyi.platform.service.impl; import com.ruoyi.common.redis.service.RedisService; import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.platform.constant.Constant; import com.ruoyi.platform.domain.DevEnvironment; import com.ruoyi.platform.domain.PodStatus; +import com.ruoyi.platform.mapper.ComputingResourceDao; import com.ruoyi.platform.mapper.DevEnvironmentDao; import com.ruoyi.platform.service.DevEnvironmentService; import com.ruoyi.platform.service.JupyterService; @@ -54,6 +56,9 @@ public class JupyterServiceImpl implements JupyterService { @Resource private DevEnvironmentDao devEnvironmentDao; + @Resource + private ComputingResourceDao computingResourceDao; + @Resource @Lazy private DevEnvironmentService devEnvironmentService; @@ -70,27 +75,29 @@ public class JupyterServiceImpl implements JupyterService { LoginUser loginUser = SecurityUtils.getLoginUser(); String podName = loginUser.getUsername().toLowerCase() + "-editor-pod"; String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; - V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage,storageClassName); + V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); Integer podPort = k8sClientUtil.createPod(podName, namespace, port, mountPath, pvc, image); return masterIp + ":" + podPort; + } @Override public String runJupyterService(Integer id) throws Exception { DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); - if(devEnvironment == null){ + if (devEnvironment == null) { throw new Exception("开发环境配置不存在"); } // 提取数据集,模型信息,得到数据集模型的path Map dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); - String datasetPath = (String) dataset.get("path"); + String datasetPath = "argo-workflow" + "/" + dataset.get("path"); + Map model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel()); - String modelPath = (String) model.get("path"); + String modelPath = "argo-workflow" + "/" + model.get("path"); LoginUser loginUser = SecurityUtils.getLoginUser(); - //手动构造pod名称 - String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + id; + //构造pod名称 + String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; //新建编辑器的pvc V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); @@ -98,41 +105,46 @@ public class JupyterServiceImpl implements JupyterService { //TODO 设置镜像可配置,这里先用默认镜像启动pod // 调用修改后的 createPod 方法,传入额外的参数 - Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, image, minioPvcName, datasetPath, modelPath); -// // 简单的延迟,以便 Pod 有时间启动 -// Thread.sleep(2500); -// //查询pod状态,更新到数据库 -// String podStatus = k8sClientUtil.getPodStatus(podName, namespace); + Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath); String url = masterIp + ":" + podPort; - redisService.setCacheObject(podName,masterIp + ":" + podPort); + redisService.setCacheObject(podName, masterIp + ":" + podPort); devEnvironment.setStatus("Pending"); devEnvironment.setUrl(url); this.devEnvironmentService.update(devEnvironment); - return url ; + return url; } + @Override public String stopJupyterService(Integer id) throws Exception { DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); - if (devEnvironment==null){ + if (devEnvironment == null) { throw new Exception("开发环境配置不存在"); } LoginUser loginUser = SecurityUtils.getLoginUser(); - //手动构造pod名称 - String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + id; + //构造pod和svc名称 + String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; + String svcName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id + "-svc"; //得到pod V1Pod pod = k8sClientUtil.getNSPodList(namespace, podName); - if(pod == null){ + if (pod == null) { return "pod不存在!"; } + + if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { + computingResourceDao.updateUsedStateByNode(pod.getSpec().getNodeName(), Constant.Used_State_unused); + } + // 使用 Kubernetes API 删除 Pod String deleteResult = k8sClientUtil.deletePod(podName, namespace); - + // 删除service + k8sClientUtil.deleteService(svcName, namespace); devEnvironment.setStatus("Terminated"); this.devEnvironmentService.update(devEnvironment); return deleteResult + ",编辑器已停止"; + } @Override @@ -140,11 +152,11 @@ public class JupyterServiceImpl implements JupyterService { String status = PodStatus.Terminated.getName(); PodStatusVo JupyterStatusVo = new PodStatusVo(); JupyterStatusVo.setStatus(status); - if (devEnvironment==null){ + if (devEnvironment == null) { return JupyterStatusVo; } LoginUser loginUser = SecurityUtils.getLoginUser(); - String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + devEnvironment.getId(); + String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + devEnvironment.getId(); try { // 查询相应pod状态 @@ -170,7 +182,7 @@ public class JupyterServiceImpl implements JupyterService { @Override public void upload(InputStream inputStream) { try { - minioUtil.uploadObject("platform-data","/pytorch/testupload4008208820",inputStream); + minioUtil.uploadObject("platform-data", "/pytorch/testupload4008208820", inputStream); } catch (Exception e) { e.printStackTrace(); } @@ -185,7 +197,4 @@ public class JupyterServiceImpl implements JupyterService { } - - - } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/AIM64EncoderUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/AIM64EncoderUtil.java index 0cffc705..29b97cc2 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/AIM64EncoderUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/AIM64EncoderUtil.java @@ -19,58 +19,91 @@ public class AIM64EncoderUtil { } public static String aim64encode(Map value) { + // 将Map对象转换为JSON字符串 String jsonEncoded = JSON.toJSONString(value); + // 将JSON字符串进行Base64编码 String base64Encoded = Base64.getEncoder().encodeToString(jsonEncoded.getBytes()); String aim64Encoded = base64Encoded; + // 替换Base64编码中的特定字符 for (Map.Entry entry : BS64_REPLACE_CHARACTERS_ENCODING.entrySet()) { aim64Encoded = aim64Encoded.replace(entry.getKey(), entry.getValue()); } + // 返回带有前缀的AIM64编码字符串 return AIM64_ENCODING_PREFIX + aim64Encoded; } + + // 这是一个静态方法,用于将 Map 对象 value 编码为字符串 public static String encode(Map value, boolean oneWayHashing) { + // 如果 oneWayHashing 参数为 true,表示使用一种不可逆的哈希算法 if (oneWayHashing) { + // 使用 MD5 算法将 value 对象转换为字符串 return md5(JSON.toJSONString(value)); } + // 如果 oneWayHashing 参数为 false,表示使用一种可逆的编码算法 return aim64encode(value); } + + // MD5 加密函数,用于将输入字符串转换为 MD5 加密后的字符串。 private static String md5(String input) { + // 尝试获取 MD5 加密对象 try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); + // 使用 MD5 对象对输入字符串进行加密 byte[] array = md.digest(input.getBytes()); + // 创建一个 StringBuilder 对象,用于将加密后的字节转换为字符串 StringBuilder sb = new StringBuilder(); + // 遍历加密后的字节数组 for (byte b : array) { + // 将每个字节转换为 16 进制字符串 sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3)); } + // 返回加密后的字符串 return sb.toString(); } catch (java.security.NoSuchAlgorithmException e) { + // 如果在获取 MD5 加密对象时出现了错误,则打印错误信息 e.printStackTrace(); } + // 如果出现了错误,则返回 null return null; } + // 这是一个 decode 方法,用于将 runIds 列表转换为查询字符串 public static String decode(List runIds) { // 确保 runIds 列表的大小为 3 if (runIds == null || runIds.size() == 0) { + // 如果 runIds 为空,抛出 IllegalArgumentException 异常 throw new IllegalArgumentException("runIds 不能为空"); } // 构建查询字符串 StringBuilder queryBuilder = new StringBuilder("run.hash in ["); + // 遍历 runIds 列表 for (int i = 0; i < runIds.size(); i++) { + // 如果当前不是第一个元素,添加逗号 if (i > 0) { queryBuilder.append(","); } + // 将当前元素添加到查询字符串中,使用双引号括起来 queryBuilder.append("\"").append(runIds.get(i)).append("\""); } + // 将查询字符串闭合 queryBuilder.append("]"); + // 将查询字符串转换为字符串 String query = queryBuilder.toString(); + // 创建一个 Map 对象,用于存储查询参数 Map map = new HashMap<>(); + // 将查询字符串添加到 Map 中 map.put("query", query); + // 将 advancedMode 设置为 true map.put("advancedMode", true); + // 将 advancedQuery 设置为查询字符串 map.put("advancedQuery", query); + // 使用 encode 方法将 Map 对象转换为查询字符串 String searchQuery = encode(map, false); + // 返回查询字符串 return searchQuery; + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/BeansUtils.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/BeansUtils.java index aa4f578f..06c95c9d 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/BeansUtils.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/BeansUtils.java @@ -9,19 +9,30 @@ import java.util.Set; public class BeansUtils { + // 获取一个 Java 对象中所有为空的属性名称。: public static String[] getNullPropertyNames(Object source) { + // 创建一个 BeanWrapper 对象,参数为给定的 Java 对象 final BeanWrapper src = new BeanWrapperImpl(source); + // 获取该对象所有属性描述符 java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); + // 创建一个集合,用于存储为空的属性名称 Set emptyNames = new HashSet(); + // 遍历所有属性描述符 for(java.beans.PropertyDescriptor pd : pds) { + // 获取属性值 Object srcValue = src.getPropertyValue(pd.getName()); + // 如果属性值为空,则将属性名称添加到集合中 if (srcValue == null) emptyNames.add(pd.getName()); } + // 创建一个字符串数组,用于存储为空的属性名称 String[] result = new String[emptyNames.size()]; + // 将为空的属性名称存储到字符串数组中 return emptyNames.toArray(result); } + public static void copyPropertiesIgnoreNull(Object src, Object target){ + // 使用 BeanUtils 工具类将源对象中的非空属性复制到目标对象中 BeanUtils.copyProperties(src, target, getNullPropertyNames(src)); } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ConvertUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ConvertUtil.java index bd02e12f..ca138614 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ConvertUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ConvertUtil.java @@ -4,10 +4,13 @@ package com.ruoyi.platform.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; - +import org.apache.commons.beanutils.PropertyUtils; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; /** @@ -19,6 +22,13 @@ import java.util.List; public class ConvertUtil { public static final Logger logger = LoggerFactory.getLogger(ConvertUtil.class); + + /** + * 将实体对象转换为VO对象 + * @param source 源实体对象 + * @param target 目标VO对象的类 + * @return 转换后的VO对象 + */ public static T entityToVo(Object source, Class target) { if (source == null) { return null; @@ -33,6 +43,8 @@ public class ConvertUtil { return targetObject; } + + // 将实体对象列表转换为目标类型的列表 public static List entityToVoList(Collection sourceList, Class target) { if (sourceList == null) { return null; @@ -50,5 +62,65 @@ public class ConvertUtil { } return targetList; } + + public static List convertListMapToObjectList(List> listMap, Class targetClass) { + List resultList = new ArrayList<>(); + + if (listMap != null) { + for (Map map : listMap) { + T targetObject = convertMapToObject(map, targetClass); + if (targetObject != null) { + resultList.add(targetObject); + } + } + } + + return resultList; + } + + private static T convertMapToObject(Map map, Class targetClass) { + try { + T targetObject = targetClass.newInstance(); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + String camelCaseKey = toCamelCase(key); + if (hasProperty(targetClass, camelCaseKey)) { + PropertyUtils.setProperty(targetObject, camelCaseKey, value); + } + } + return targetObject; + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + e.printStackTrace(); + } + return null; + } + + private static boolean hasProperty(Class clazz, String propertyName) { + try { + Field field = clazz.getDeclaredField(propertyName); + return field != null; + } catch (NoSuchFieldException e) { + return false; + } + } + + private static String toCamelCase(String key) { + StringBuilder sb = new StringBuilder(); + boolean nextUpperCase = false; + for (char c : key.toCharArray()) { + if (c == '_') { + nextUpperCase = true; + } else { + if (nextUpperCase) { + sb.append(Character.toUpperCase(c)); + nextUpperCase = false; + } else { + sb.append(c); + } + } + } + return sb.toString(); + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DVCUtils.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DVCUtils.java new file mode 100644 index 00000000..387f09ab --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DVCUtils.java @@ -0,0 +1,165 @@ +package com.ruoyi.platform.utils; + +import org.eclipse.jgit.api.*; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.storage.file.FileRepositoryBuilder; +import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; + +import java.io.*; +import java.nio.file.*; + +public class DVCUtils { + + private static void runCommand(String command, String workingDir) throws Exception { + ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); + processBuilder.directory(new File(workingDir)); + Process process = processBuilder.start(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + int exitCode = process.waitFor(); + if (exitCode != 0) { + throw new Exception("Command failed with exit code " + exitCode); + } + } + + public static void moveFiles(String sourcePath, String targetPath) throws Exception { + Path sourceDir = Paths.get(sourcePath); + Path targetDir = Paths.get(targetPath).resolve(sourceDir.getFileName()); + + if (!Files.exists(targetDir)) { + Files.createDirectories(targetDir); + } + + Files.move(sourceDir, targetDir, StandardCopyOption.REPLACE_EXISTING); + } + + public static void gitClone(String localPath, String repoUrl, String branch, String username, String password) throws GitAPIException { + CloneCommand cloneCommand = Git.cloneRepository() + .setURI(repoUrl) + .setBranch(branch) + .setDirectory(new java.io.File(localPath)) + .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password)); + + cloneCommand.call(); + } + + public static void gitAdd(String localPath, String filePath) throws IOException, GitAPIException { + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + Repository repository = builder.setGitDir(new File(localPath, ".git")) + .readEnvironment() + .findGitDir() + .build(); + + try (Git git = new Git(repository)) { + AddCommand addCommand = git.add(); + addCommand.addFilepattern(filePath).call(); + } + } + + public static void gitCommit(String localPath, String commitMessage) throws IOException, GitAPIException { + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + Repository repository = builder.setGitDir(new File(localPath, ".git")) + .readEnvironment() + .findGitDir() + .build(); + + try (Git git = new Git(repository)) { + // 添加所有文件 + AddCommand addCommand = git.add(); + addCommand.addFilepattern(".").call(); + + // 提交更改 + CommitCommand commitCommand = git.commit(); + commitCommand.setMessage(commitMessage).call(); + } + } + + public static void gitPush(String localPath, String username, String password) throws IOException, GitAPIException { + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + Repository repository = builder.setGitDir(new File(localPath, ".git")) + .readEnvironment() + .findGitDir() + .build(); + + try (Git git = new Git(repository)) { + CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(username, password); + PushCommand pushCommand = git.push(); + pushCommand.setCredentialsProvider(credentialsProvider) + .setForce(true) + .call(); + } + } + + public static void gitCheckoutBranch(String localPath, String branchName) throws IOException, GitAPIException { + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + Repository repository = builder.setGitDir(new File(localPath, ".git")) + .readEnvironment() + .findGitDir() + .build(); + + try (Git git = new Git(repository)) { + CheckoutCommand checkoutCommand = git.checkout(); + checkoutCommand.setName(branchName).call(); + } + } + + public static void gitPull(String localPath, String username, String password) throws IOException, GitAPIException { + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + Repository repository = builder.setGitDir(new File(localPath, ".git")) + .readEnvironment() + .findGitDir() + .build(); + + try (Git git = new Git(repository)) { + CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(username, password); + PullCommand pullCommand = git.pull(); + pullCommand.setCredentialsProvider(credentialsProvider).call(); + } + } + + public static void dvcInit(String localPath) throws Exception { + String command = "dvc init"; + runCommand(command, localPath); + } + + public static void dvcAdd(String localPath, String filePath) throws Exception { + String command = "dvc add " + filePath; + runCommand(command, localPath); + } + + public static void dvcRemoteAdd(String localPath, String s3RemoteUrl) throws Exception { + String command = "dvc remote add -d myremote s3://" + s3RemoteUrl; + runCommand(command, localPath); + } + + public static void dvcConfigS3Credentials(String localPath, String endpointurl) throws Exception { + String command = "dvc remote modify myremote endpointurl " + endpointurl; + runCommand(command, localPath); + } + + public static void dvcConfigS3Credentials2(String localPath, String accessKeyId) throws Exception { + String command = "dvc remote modify myremote access_key_id " + accessKeyId; + runCommand(command, localPath); + } + + public static void dvcConfigS3Credentials3(String localPath, String secretAccessKey) throws Exception { + String command = "dvc remote modify myremote secret_access_key " + secretAccessKey; + runCommand(command, localPath); + } + + public static void dvcPush(String localPath) throws Exception { + String command = "dvc push"; + runCommand(command, localPath); + } + + // 更新的 dvcPull 方法 + public static void dvcPull(String localPath) throws Exception { + String command = "dvc pull"; + runCommand(command, localPath); + } +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java new file mode 100644 index 00000000..552b025a --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java @@ -0,0 +1,114 @@ +package com.ruoyi.platform.utils; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CommitCmd; +import com.github.dockerjava.api.command.InspectImageResponse; +import com.github.dockerjava.api.model.AuthConfig; +import com.github.dockerjava.core.DefaultDockerClientConfig; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.DockerClientImpl; +import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; +import com.github.dockerjava.transport.DockerHttpClient; +import com.ruoyi.platform.vo.ImageVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.HashMap; + +@Slf4j +@Component +public class DockerClientUtil { + + @Value("${harbor.bucketName}") + private String bucketName; + @Value("${harbor.repository}") + private String repository; + @Value("${harbor.harborUrl}") + private String harborUrl; + @Value("${harbor.harborUser}") + private String harborUser; + @Value("${harbor.harborpassword}") + private String harborpassword; + + public DockerClient getDockerClient(String dockerServerUrl) { + + //创建DefaultDockerClientConfig(指定docker服务器的配置) + DockerClientConfig config = DefaultDockerClientConfig + .createDefaultConfigBuilder() + .withDockerHost("tcp://" + dockerServerUrl + ":2375") + .withDockerTlsVerify(false) + .withApiVersion("1.40") +// .withDockerCertPath(dcokerCertPath) +// .withRegistryUsername(registryUser) +// .withRegistryPassword(registryPass) +// .withRegistryEmail(registryMail) +// .withRegistryUrl(registryUrl) + .build(); + + //创建DockerHttpClient + DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder() + .dockerHost(config.getDockerHost()) + .sslConfig(config.getSSLConfig()) + .maxConnections(1000) + .connectionTimeout(Duration.ofSeconds(300)) + .responseTimeout(Duration.ofSeconds(450)) + .build(); + + //创建DockerClient + return DockerClientImpl.getInstance(config, httpClient); + + } + + public String commitImage(ImageVo imageVo, String containerId, String hostIp, String userName) { + DockerClient dockerClient = getDockerClient(hostIp); + + // 提交容器为镜像,这里的"new_image"和"new_tag"是新镜像的名字和标签 + CommitCmd commitCmd = dockerClient.commitCmd(containerId) + .withRepository(imageVo.getName()) + .withTag(imageVo.getTagName()) + .withAuthor(userName) + .withMessage(imageVo.getDescription()); + return commitCmd.exec(); + } + + public HashMap pushImageToHorbor(ImageVo imageVo, String hostIp) { + + DockerClient dockerClient = getDockerClient(hostIp); + //Harbor登录信息 + AuthConfig autoConfig = new AuthConfig().withRegistryAddress(harborUrl).withUsername(harborUser).withPassword(harborpassword); + + + String localImageName = imageVo.getName() + ":" + imageVo.getTagName(); + String imageName = harborUrl + "/" + bucketName + "/" + imageVo.getName(); + + //给镜像打上tag + dockerClient.tagImageCmd(localImageName, imageName, imageVo.getTagName()).exec(); + //推送镜像至镜像仓库 + try { + dockerClient.pushImageCmd(imageName).withAuthConfig(autoConfig).start().awaitCompletion(); + //push成功后,删除本地加载的镜像 + dockerClient.removeImageCmd(localImageName).exec(); + + String totalImageName = imageName + ":" + imageVo.getTagName(); + InspectImageResponse exec = dockerClient.inspectImageCmd(totalImageName).exec(); + + String size = String.format("%.1f GB", (float) exec.getSize() / 1073741824.0); + + HashMap resultMap = new HashMap<>(); + resultMap.put("imageName",totalImageName); + resultMap.put("size",size); + + return resultMap; + } catch (InterruptedException e) { + throw new RuntimeException("推送镜像失败:" + e); + } + + } + + public void removeImage(String imageName, String hostIp){ + DockerClient dockerClient = getDockerClient(hostIp); + dockerClient.removeImageCmd(imageName).withForce(true).exec(); + } +} \ No newline at end of file diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/FileUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/FileUtil.java index cc8a9537..aab81e56 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/FileUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/FileUtil.java @@ -2,20 +2,29 @@ package com.ruoyi.platform.utils; public class FileUtil { + // 格式化文件大小为可读的字符串表示 public static String formatFileSize(long sizeInBytes) { + // 检查文件大小是否为负数 if (sizeInBytes < 0) { throw new IllegalArgumentException("File size cannot be negative."); } + // 如果文件大小小于1KB,直接返回字节数 if (sizeInBytes < 1024) { return sizeInBytes + " B"; - } else if (sizeInBytes < 1024 * 1024) { + } + // 如果文件大小小于1MB,转换为KB并返回 + else if (sizeInBytes < 1024 * 1024) { double sizeInKB = sizeInBytes / 1024.0; return String.format("%.2f KB", sizeInKB); - } else if (sizeInBytes < 1024 * 1024 * 1024) { + } + // 如果文件大小小于1GB,转换为MB并返回 + else if (sizeInBytes < 1024 * 1024 * 1024) { double sizeInMB = sizeInBytes / (1024.0 * 1024); return String.format("%.2f MB", sizeInMB); - } else { + } + // 如果文件大小大于或等于1GB,转换为GB并返回 + else { double sizeInGB = sizeInBytes / (1024.0 * 1024 * 1024); return String.format("%.2f GB", sizeInGB); } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/HttpUtils.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/HttpUtils.java index 910d9981..504c4c6a 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/HttpUtils.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/HttpUtils.java @@ -11,6 +11,7 @@ import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpClient; @@ -89,6 +90,110 @@ public class HttpUtils { public static String sendGet(String url, String param) { return sendGet(url, param, "UTF-8"); } +// /** +// * 向指定 URL 发送带token的GET方法的请求 +// * +// * @param url 发送请求的 URL +// * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 +// * @return 所代表远程资源的响应结果 +// */ +// public static String sendGetWithToken(String url, String param,String token) { +// return sendGet(url, param, "UTF-8",token); +// } + /** + * 向指定 URL 发送带 token 的 GET 方法的请求,使用 Apache HttpClient + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param token 认证 token + * @return 所代表远程资源的响应结果 + */ + public static String sendGetWithToken(String url, String param, String token) { + String result = ""; + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + URIBuilder uriBuilder = new URIBuilder(url); + if (param != null && !param.isEmpty()) { + String[] pairs = param.split("&"); + for (String pair : pairs) { + int idx = pair.indexOf("="); + if (idx != -1) { + uriBuilder.setParameter(pair.substring(0, idx), pair.substring(idx + 1)); + } + } + } + + URI uri = uriBuilder.build(); + HttpGet httpGet = new HttpGet(uri); + + httpGet.setHeader("Content-Type", "application/json"); + httpGet.setHeader("Authorization", "Bearer " + token); + + log.info("Executing request: " + httpGet.getRequestLine()); + + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == 200) { + result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } else { + throw new IOException("HTTP request failed with response code: " + statusCode); + } + log.info("Response: " + result); + } + } catch (URISyntaxException e) { + log.error("URISyntaxException, url=" + url + ", param=" + param, e); + } catch (IOException e) { + log.error("IOException, url=" + url + ", param=" + param, e); + } + return result; + } + /** + * 向指定 URL 发送带token的GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType,String token) { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try { + String urlNameString = url + "?" + param; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.setRequestProperty("Authorization", "Bearer " + token); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + log.info("recv - {}", result); + } catch (ConnectException e) { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } catch (SocketTimeoutException e) { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } catch (IOException e) { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } catch (Exception e) { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } finally { + try { + if (in != null) { + in.close(); + } + } catch (Exception ex) { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** * 向指定 URL 发送GET方法的请求 @@ -108,7 +213,6 @@ public class HttpUtils { URLConnection connection = realUrl.openConnection(); connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); - connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); connection.connect(); in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); String line; @@ -136,6 +240,42 @@ public class HttpUtils { return result.toString(); } + /** + * 向指定 URL 发送带token的POST方法的请求 + * + * @param url 发送请求的 URL + * @param + * @return 所代表远程资源的响应结果 + */ + public static String sendPostWithToken(String url, Object params, String token) throws Exception { + String resultStr = null; + HttpPost httpPost = new HttpPost(url); + if (params != null) { + StringEntity entity; + if (params instanceof Map) { + entity = new StringEntity(dealPostParams((HashMap) params, "UTF-8")); + } else if (params instanceof String) { + entity = new StringEntity((String) params, "UTF-8"); + } else if (params instanceof List) { + entity = new UrlEncodedFormEntity((List) params, "UTF-8"); + } else { + throw new Exception("参数有误!"); + } + httpPost.setHeader("Content-Type", "application/json"); + httpPost.setHeader("Authorization", "Bearer " + token); + httpPost.setEntity(entity); + } + try { + HttpResponse response = httpClient.execute(httpPost); + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + resultStr = EntityUtils.toString(response.getEntity()); + } + } catch (IOException e) { + e.printStackTrace(); + } + return resultStr; + } + /** * 向指定 URL 发送POST方法的请求 * diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/JsonUtils.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/JsonUtils.java index 186173eb..2aa0ba02 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/JsonUtils.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/JsonUtils.java @@ -37,10 +37,8 @@ public class JsonUtils { // 将JSON字符串转换为扁平化的Map public static Map flattenJson(String prefix, Map map) { Map flatMap = new HashMap<>(); - Iterator> entries = map.entrySet().iterator(); - while (entries.hasNext()) { - Map.Entry entry = entries.next(); + for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); @@ -53,4 +51,9 @@ public class JsonUtils { return flatMap; } + + // 将Object转换为Map + public static Map objectToMap(Object object) throws IOException { + return objectMapper.convertValue(object, Map.class); + } } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java index fe12a71d..dbd4d7a2 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java @@ -1,25 +1,25 @@ package com.ruoyi.platform.utils; -import com.alibaba.nacos.shaded.com.google.gson.reflect.TypeToken; +import com.ruoyi.platform.constant.Constant; +import com.ruoyi.platform.domain.DevEnvironment; +import com.ruoyi.platform.mapper.ComputingResourceDao; import io.kubernetes.client.Exec; import io.kubernetes.client.custom.IntOrString; import io.kubernetes.client.custom.Quantity; import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.ApiResponse; import io.kubernetes.client.openapi.apis.CoreV1Api; import io.kubernetes.client.openapi.models.*; import io.kubernetes.client.util.ClientBuilder; -import io.kubernetes.client.util.Watch; import io.kubernetes.client.util.credentials.AccessTokenAuthentication; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; -import org.apache.poi.ss.formula.functions.T; +import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import javax.annotation.Resource; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.*; @@ -40,6 +40,9 @@ public class K8sClientUtil { */ private static ApiClient apiClient; + @Resource + private ComputingResourceDao computingResourceDao; + /** * 构建集群POD内通过SA访问的客户端 * loading the in-cluster config, including: @@ -133,11 +136,11 @@ public class K8sClientUtil { } catch (ApiException e) { log.error("获取 SVC 异常:", e); } - if (v1ServiceList!=null) { + if (v1ServiceList != null) { for (V1Service svc : v1ServiceList.getItems()) { if (StringUtils.equals(svc.getMetadata().getName(), serviceName)) { - // PVC 已存在 - return svc; + // SVC 已存在 + return svc; } } } @@ -177,22 +180,22 @@ public class K8sClientUtil { /** * 创建k8s PVC * - * @param namespace 命名空间 - * @param pvcName 服务名称 + * @param namespace 命名空间 + * @param pvcName 服务名称 * @return 创建成功的service对象 */ - public V1PersistentVolumeClaim createPvc(String namespace, String pvcName ,String storage, String storageClassName){ + public V1PersistentVolumeClaim createPvc(String namespace, String pvcName, String storage, String storageClassName) { CoreV1Api api = new CoreV1Api(apiClient); V1PersistentVolumeClaimList pvcList = null; try { - pvcList = api.listNamespacedPersistentVolumeClaim(namespace, null,null, null, null, null,null,null, null, null, null); + pvcList = api.listNamespacedPersistentVolumeClaim(namespace, null, null, null, null, null, null, null, null, null, null); } catch (ApiException e) { log.error("获取 PVC 异常:", e); } - if (pvcList!=null) { + if (pvcList != null) { for (V1PersistentVolumeClaim pvc1 : pvcList.getItems()) { - if (StringUtils.equals(pvc1.getMetadata().getName(),pvcName)) { + if (StringUtils.equals(pvc1.getMetadata().getName(), pvcName)) { // PVC 已存在 return pvc1; } @@ -227,16 +230,17 @@ public class K8sClientUtil { /** * 创建k8s 临时POD + * * @param podName pod name - * @param namespace 命名空间 - * @param port port + * @param namespace 命名空间 + * @param port port * @param mountPath 映射路径 - * @param pvc 存储 - * @param image 镜像 + * @param pvc 存储 + * @param image 镜像 * @return 创建成功的pod,的nodePort端口 */ - public Integer createPod(String podName, String namespace, Integer port ,String mountPath, V1PersistentVolumeClaim pvc, String image){ + public Integer createPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image) { Map selector = new LinkedHashMap(); selector.put("k8s-jupyter", podName); @@ -248,7 +252,7 @@ public class K8sClientUtil { } catch (ApiException e) { log.error("获取 POD 异常:", e); } - if (v1PodList!=null) { + if (v1PodList != null) { for (V1Pod pod1 : v1PodList.getItems()) { if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { // PVC 已存在 @@ -296,17 +300,18 @@ public class K8sClientUtil { /** * 创建k8s 临时POD + * * @param podName pod name - * @param namespace 命名空间 - * @param port port + * @param namespace 命名空间 + * @param port port * @param mountPath 映射路径 - * @param subPath pvc子路径 - * @param pvcName 存储名 - * @param image 镜像 + * @param subPath pvc子路径 + * @param pvcName 存储名 + * @param image 镜像 * @return 创建成功的pod,的nodePort端口 */ - public Integer createPodWithSubPath(String podName, String namespace, Integer port ,String mountPath,String subPath,String pvcName, String image){ + public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String pvcName, String image) { Map selector = new LinkedHashMap(); selector.put("k8s-jupyter", podName); @@ -318,7 +323,7 @@ public class K8sClientUtil { } catch (ApiException e) { log.error("获取 POD 异常:", e); } - if (v1PodList!=null) { + if (v1PodList != null) { for (V1Pod pod1 : v1PodList.getItems()) { if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { // PVC 已存在 @@ -375,11 +380,51 @@ public class K8sClientUtil { return service.getSpec().getPorts().get(0).getNodePort(); } + // 创建配置好的Pod + public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, DevEnvironment devEnvironment, String dataPvcName, String datasetPath, String modelPath) { - public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image, String dataPvcName, String datasetPath, String modelPath) { + //设置选择节点,pod反亲和性 Map selector = new LinkedHashMap<>(); - selector.put("k8s-jupyter", podName); + Map nodeSelector = new LinkedHashMap<>(); + V1Affinity v1Affinity = new V1Affinity(); + if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { + selector.put("k8s-jupyter", "CPU-GPU"); + nodeSelector.put("resource-type", "CPU-GPU"); + + V1LabelSelectorRequirement labelSelectorRequirement = new V1LabelSelectorRequirement() + .key("k8s-jupyter").operator("NotIn").values(Collections.singletonList("CPU-GPU")); + + V1LabelSelector labelSelector = new V1LabelSelector() + .matchExpressions(Collections.singletonList(labelSelectorRequirement)); + + V1PodAffinityTerm podAffinityTerm = new V1PodAffinityTerm() + .labelSelector(labelSelector) + .namespaces(Collections.singletonList(namespace)) + .topologyKey("kubernetes.io/hostname"); + + V1PodAffinity podAffinity = new V1PodAffinity() + .requiredDuringSchedulingIgnoredDuringExecution(Collections.singletonList(podAffinityTerm)); + V1LabelSelectorRequirement antiLabelSelectorRequirement = new V1LabelSelectorRequirement() + .key("k8s-jupyter").operator("In").values(Collections.singletonList("CPU-GPU")); + + V1LabelSelector antiLabelSelector = new V1LabelSelector() + .matchExpressions(Collections.singletonList(antiLabelSelectorRequirement)); + + V1PodAffinityTerm antiPodAffinityTerm = new V1PodAffinityTerm() + .labelSelector(antiLabelSelector) + .namespaces(Collections.singletonList(namespace)) + .topologyKey("kubernetes.io/hostname"); + + V1PodAntiAffinity podAntiAffinity = new V1PodAntiAffinity() + .requiredDuringSchedulingIgnoredDuringExecution(Collections.singletonList(antiPodAffinityTerm)); + + v1Affinity.podAffinity(podAffinity).podAntiAffinity(podAntiAffinity); + } else { + selector.put("k8s-jupyter", "CPU"); + } + + // 创建Pod CoreV1Api api = new CoreV1Api(apiClient); V1PodList v1PodList = null; try { @@ -402,14 +447,34 @@ public class K8sClientUtil { // 配置卷和卷挂载 List volumeMounts = new ArrayList<>(); volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); - volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/datasets").subPath(datasetPath).readOnly(true)); - volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/model").subPath(modelPath).readOnly(true)); + volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true)); + volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true)); List volumes = new ArrayList<>(); volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); + //配置资源 + JSONObject standardJson = new JSONObject(devEnvironment.getStandard()); + JSONObject valueJson = (JSONObject) standardJson.get("value"); + int cpu = (int) valueJson.get("cpu"); + String memory = (String) valueJson.get("memory"); + memory = memory.substring(0, memory.length() - 1).concat("i"); + int gpu = (int) valueJson.get("gpu"); + + HashMap limitMap = new HashMap<>(); + if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { + limitMap.put("nvidia.com/gpu", new Quantity(String.valueOf(gpu))); + } + limitMap.put("cpu", new Quantity(String.valueOf(cpu))); + limitMap.put("memory", new Quantity(memory)); + limitMap.put("ephemeral-storage", new Quantity("100Gi")); + + V1ResourceRequirements v1ResourceRequirements = new V1ResourceRequirements(); + v1ResourceRequirements.setRequests(limitMap); + v1ResourceRequirements.setLimits(limitMap); + V1Pod pod = new V1PodBuilder() .withNewMetadata() .withName(podName) @@ -418,21 +483,27 @@ public class K8sClientUtil { .withNewSpec() .addNewContainer() .withName(podName) - .withImage(image) + .withImage(devEnvironment.getImage()) .withPorts(new V1ContainerPort().containerPort(port).protocol("TCP")) .withVolumeMounts(volumeMounts) + .withResources(v1ResourceRequirements) .endContainer() .withVolumes(volumes) - .withTerminationGracePeriodSeconds(14400L) + .withNodeSelector(nodeSelector) + .withAffinity(v1Affinity) .endSpec() .build(); try { pod = api.createNamespacedPod(namespace, pod, null, null, null); + String nodeName = getNodeName(podName, namespace); + if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { + computingResourceDao.updateUsedStateByNode(nodeName, Constant.Used_State_used); + } } catch (ApiException e) { - log.error("创建pod异常:" + e.getResponseBody(), e); + throw new RuntimeException("创建pod异常:" + e.getResponseBody()); } catch (Exception e) { - log.error("创建pod系统异常:", e); + throw new RuntimeException("创建pod系统异常:", e); } V1Service service = createService(namespace, podName + "-svc", port, selector); @@ -440,14 +511,12 @@ public class K8sClientUtil { } - - /** * 根据获取namespace,deploymentName的Pod Name * * @return podList */ - public V1Pod getNSPodList(String namespace,String deploymentName) throws Exception { + public V1Pod getNSPodList(String namespace, String deploymentName) throws Exception { // new a CoreV1Api CoreV1Api api = new CoreV1Api(apiClient); V1PodList v1PodList = null; @@ -468,12 +537,12 @@ public class K8sClientUtil { return null; } - public String executeCommand(V1Pod item, String command) { + public String executeCommand(V1Pod item, String command) { try { // 创建API实例 // 创建Exec实例 Exec exec = new Exec(apiClient); - String[] cmd = { "/bin/sh", "-c", command}; + String[] cmd = {"/bin/sh", "-c", command}; Process proc = exec.exec(item, cmd, false); // 读取输出 BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream())); @@ -498,19 +567,49 @@ public class K8sClientUtil { /** * 根据Pod的名称和Namespace查询Pod的状态 - * @param podName Pod的名称 + * + * @param podName Pod的名称 * @param namespace Pod所在的Namespace */ - public String getPodStatus(String podName, String namespace) throws Exception { + public String getPodStatus(String podName, String namespace) throws Exception { CoreV1Api api = new CoreV1Api(apiClient); V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); return pod.getStatus().getPhase(); } - public String getPodLogs(String podName,String namespace,String container,int line) { + /** + * 根据Pod的名称和Namespace查询Pod的容器信息 + * + * @param podName Pod的名称 + * @param namespace Pod所在的Namespace + */ + public String getPodContainerId(String podName, String namespace) throws Exception { + CoreV1Api api = new CoreV1Api(apiClient); + V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); + + if (pod.getStatus().getContainerStatuses().size() != 1) { + throw new RuntimeException("容器错误"); + } + String containerId = pod.getStatus().getContainerStatuses().get(0).getContainerID().split("//")[1]; + return containerId; + } + + public String getHostIp(String podName, String namespace) throws Exception { + CoreV1Api api = new CoreV1Api(apiClient); + V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); + return pod.getStatus().getHostIP(); + } + + public String getNodeName(String podName, String namespace) throws Exception { + CoreV1Api api = new CoreV1Api(apiClient); + V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); + return pod.getSpec().getNodeName(); + } + + public String getPodLogs(String podName, String namespace, String container, int line) { CoreV1Api api = new CoreV1Api(apiClient); try { - String log = api.readNamespacedPodLog(podName, namespace, StringUtils.isEmpty(container)?null:container, null, null, null, null,null, null, line, null); + String log = api.readNamespacedPodLog(podName, namespace, StringUtils.isEmpty(container) ? null : container, null, null, null, null, null, null, line, null); return log; } catch (ApiException e) { throw new RuntimeException("获取Pod日志异常", e); @@ -519,7 +618,7 @@ public class K8sClientUtil { } - public V1Pod createPodWithEnv(String podName,String namespace,String proxyUrl ,String mountPath,String pvcName, String image){ + public V1Pod createPodWithEnv(String podName, String namespace, String proxyUrl, String mountPath, String pvcName, String image) { CoreV1Api api = new CoreV1Api(apiClient); V1PodList v1PodList = null; V1Pod pod = new V1PodBuilder() @@ -563,7 +662,7 @@ public class K8sClientUtil { /** * 删除 Pod * - * @param podName Pod 名称 + * @param podName Pod 名称 * @param namespace 命名空间 * @throws ApiException 异常 */ @@ -578,10 +677,30 @@ public class K8sClientUtil { } } + + /** + * 删除 Service + * + * @param svcName Service 名称 + * @param namespace 命名空间 + * @throws ApiException 异常 + */ + public String deleteService(String svcName, String namespace) throws ApiException { + CoreV1Api api = new CoreV1Api(apiClient); + try { + V1Status result = api.deleteNamespacedService(svcName, namespace, null, null, null, null, null, null); + return "Service " + svcName + " 删除请求已发送"; + } catch (ApiException e) { + log.error("删除service异常:" + e.getResponseBody(), e); + throw e; + } + } + + /** * 检查 Pod 是否存在 * - * @param podName Pod 名称 + * @param podName Pod 名称 * @param namespace 命名空间 * @return 是否存在 * @throws ApiException 异常 @@ -589,7 +708,7 @@ public class K8sClientUtil { public boolean checkPodExists(String podName, String namespace) throws ApiException { CoreV1Api api = new CoreV1Api(apiClient); try { - api.readNamespacedPod(podName, namespace, null,false,false); + api.readNamespacedPod(podName, namespace, null, false, false); return true; } catch (ApiException e) { if (e.getCode() == 404) { diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/MlflowUtil.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/MlflowUtil.java index 0745b1df..f3c9bbbd 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/MlflowUtil.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/MlflowUtil.java @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component; import java.util.List; @Component -public class MlflowUtil { +public class +MlflowUtil { private static String trackingUri = "http://172.20.32.181:32005"; private MlflowClient client; diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/YamlUtils.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/YamlUtils.java new file mode 100644 index 00000000..395e78b3 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/YamlUtils.java @@ -0,0 +1,28 @@ +package com.ruoyi.platform.utils; + +import org.yaml.snakeyaml.Yaml; + +import java.io.FileWriter; +import java.io.IOException; +import java.util.Map; + +public class YamlUtils { + + /** + * 将Map对象转换为YAML格式并写入指定路径的文件中 + * + * @param data Map对象 + * @param path 文件路径 + * @param fileName 文件名 + */ + public static void generateYamlFile(Map data, String path, String fileName) { + Yaml yaml = new Yaml(); + String fullPath = path + "/" + fileName + ".yaml"; + + try (FileWriter writer = new FileWriter(fullPath)) { + yaml.dump(data, writer); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/DatasetVo.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/DatasetVo.java index 5eafbdf8..2a1dcc06 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/DatasetVo.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/DatasetVo.java @@ -3,11 +3,13 @@ package com.ruoyi.platform.vo; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.annotation.JsonNaming; import io.swagger.annotations.ApiModelProperty; +import lombok.Data; import java.io.Serializable; import java.util.List; @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +@Data public class DatasetVo implements Serializable { @@ -25,6 +27,7 @@ public class DatasetVo implements Serializable { private String dataType; @ApiModelProperty(name = "data_tag") private String dataTag; + /** * 版本 */ @@ -33,73 +36,17 @@ public class DatasetVo implements Serializable { @ApiModelProperty(name = "dataset_version_vos") private List datasetVersionVos; + /** * 可用集群 */ @ApiModelProperty(name = "available_cluster") private String availableCluster; - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public int getAvailableRange() { - return availableRange; - } - - public void setAvailableRange(int availableRange) { - this.availableRange = availableRange; - } - - public String getDataType() { - return dataType; - } - - public void setDataType(String dataType) { - this.dataType = dataType; - } - public String getDataTag() { - return dataTag; - } - - public void setDataTag(String dataTag) { - this.dataTag = dataTag; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public List getDatasetVersionVos() { - return datasetVersionVos; - } - - public void setDatasetVersionVos(List datasetVersionVos) { - this.datasetVersionVos = datasetVersionVos; - } - - public String getAvailableCluster() { - return availableCluster; - } - - public void setAvailableCluster(String availableCluster) { - this.availableCluster = availableCluster; - } + /** + * 数据集仓库名称 + */ + @ApiModelProperty(name = "repository_name") + private String repositoryName; } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/GitProjectVo.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/GitProjectVo.java new file mode 100644 index 00000000..a31a7cd1 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/GitProjectVo.java @@ -0,0 +1,67 @@ +package com.ruoyi.platform.vo; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +@ApiModel(description = "Git项目信息") +@Data +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +public class GitProjectVo implements Serializable { + + @ApiModelProperty(value = "用户或组织ID", required = true) + private int userId; + + @ApiModelProperty(value = "项目名称", required = true) + private String name; + + @ApiModelProperty(value = "项目描述", required = false) + private String description; + + @ApiModelProperty(value = "项目标识", required = true) + private String repositoryName; + +// @ApiModelProperty(value = "项目分类ID", required = false) +// private int projectCategoryId; +// +// @ApiModelProperty(value = "项目语言ID", required = false) +// private int projectLanguageId; + +// @ApiModelProperty(value = "项目忽略文件ID", required = false) +// private int ignoreId; + +// @ApiModelProperty(value = "项目许可证ID", required = false) +// private int licenseId; + + @ApiModelProperty(value = "项目是否为私有项目", required = false) + private boolean isPrivate; + +// @ApiModelProperty(value = "是否为区块链激励项目", required = false) +// private boolean blockchain; +// +// @ApiModelProperty(value = "区块链激励金额总数", required = false) +// private int blockchainTokenAll; + +// +// @Override +// public String toString() { +// return "GitProjectVo{" + +// "userId=" + userId + +// ", name='" + name + '\'' + +// ", description='" + description + '\'' + +// ", repositoryName='" + repositoryName + '\'' + +// ", projectCategoryId=" + projectCategoryId + +// ", projectLanguageId=" + projectLanguageId + +// ", ignoreId=" + ignoreId + +// ", licenseId=" + licenseId + +// ", isPrivate=" + isPrivate + +// ", blockchain=" + blockchain + +// ", blockchainTokenAll=" + blockchainTokenAll + +// '}'; +// } +} + diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java index c4b313c2..8345f214 100644 --- a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java @@ -57,13 +57,16 @@ public class ImageVo implements Serializable { @ApiModelProperty(name = "status") private String status; - @ApiModelProperty(value = "上传方式, 基于公网上传0,基于本地上传1") + @ApiModelProperty(name = "upload_type", value = "上传方式, 基于公网上传0,基于本地上传1") private Integer uploadType; @ApiModelProperty(value = "镜像上传路径") private String path; + @ApiModelProperty(name = "dev_environment_id", value = "环境id") + private Integer devEnvironmentId; + // public Integer getId() { // return id; // } @@ -147,7 +150,17 @@ public class ImageVo implements Serializable { public String getPath() { return path; } + public void setPath(String path) { this.path = path; } + + public Integer getDevEnvironmentId() { + return devEnvironmentId; + } + + public void setDevEnvironmentId(Integer devEnvironmentId) { + this.devEnvironmentId = devEnvironmentId; + } + } diff --git a/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/NewDatasetVo.java b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/NewDatasetVo.java new file mode 100644 index 00000000..3548c470 --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/NewDatasetVo.java @@ -0,0 +1,43 @@ +package com.ruoyi.platform.vo; + +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.apache.ibatis.annotations.MapKey; + +import java.io.Serializable; +import java.util.List; + +@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) +@Data +public class NewDatasetVo implements Serializable { + + + @ApiModelProperty(name = "name") + private String name; + /** + * 数据集仓库名称 + */ + @ApiModelProperty(name = "identifier") + private String identifier; + @ApiModelProperty(name = "description") + private String description; + /** + * 是否公开1公开,0私有 + */ + @ApiModelProperty(name = "is_public") + private Boolean isPublic; + @ApiModelProperty(name = "data_type") + private String dataType; + @ApiModelProperty(name = "data_tag") + private String dataTag; + @ApiModelProperty(name = "time_ago") + private String timeAgo; + @ApiModelProperty(name = "repo_id") + private Integer repoId; + @ApiModelProperty(name = "visits") + private Integer visits; + @ApiModelProperty(name = "create_by") + private String createBy; +} diff --git a/ruoyi-modules/management-platform/src/main/resources/bootstrap.yml b/ruoyi-modules/management-platform/src/main/resources/bootstrap.yml index 70d87bb0..11095bb1 100644 --- a/ruoyi-modules/management-platform/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/management-platform/src/main/resources/bootstrap.yml @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,4 +26,9 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true + - data-id: management-platform-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true \ No newline at end of file diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/CodeConfigDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/CodeConfigDaoMapper.xml new file mode 100644 index 00000000..8dce9ccf --- /dev/null +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/CodeConfigDaoMapper.xml @@ -0,0 +1,115 @@ + + + + + + insert into code_config(code_repo_name, code_repo_vis, git_url, git_branch, verify_mode, git_user_name, + git_password, ssh_key, create_by, create_time, update_by, update_time) + values (#{codeConfig.codeRepoName}, #{codeConfig.codeRepoVis}, #{codeConfig.gitUrl}, #{codeConfig.gitBranch}, + #{codeConfig.verifyMode}, #{codeConfig.gitUserName}, #{codeConfig.gitPassword}, + #{codeConfig.sshKey}, #{codeConfig.createBy}, #{codeConfig.createTime}, #{codeConfig.updateBy}, + #{codeConfig.updateTime}) + + + + update code_config + + + code_repo_name = #{codeConfig.codeRepoName}, + + + code_repo_vis = #{codeConfig.codeRepoVis}, + + + git_url = #{codeConfig.gitUrl}, + + + git_branch = #{codeConfig.gitBranch}, + + verify_mode = #{codeConfig.verifyMode}, + git_user_name = #{codeConfig.gitUserName}, + git_password = #{codeConfig.gitPassword}, + ssh_key = #{codeConfig.sshKey}, + + create_by = #{codeConfig.createBy}, + + + create_time = #{codeConfig.createTime}, + + + update_by = #{codeConfig.updateBy}, + + + state = #{codeConfig.state}, + + update_time = sysdate() + + where id = #{codeConfig.id} + + + + + + + + + + + + + + state = 1 + + and id = #{codeConfig.id} + + + and code_repo_name LIKE CONCAT('%', #{codeConfig.codeRepoName}, '%') + + + and code_repo_vis = #{codeConfig.codeRepoVis} + + + and git_url = #{codeConfig.gitUrl} + + + and git_branch = #{codeConfig.gitBranch} + + + and verify_mode = #{codeConfig.verifyMode} + + + and git_user_name = #{codeConfig.gitUserName} + + + and create_by = #{codeConfig.createBy} + + + and create_time = #{codeConfig.createTime} + + + and update_by = #{codeConfig.updateBy} + + + and update_time = #{codeConfig.updateTime} + + + + \ No newline at end of file diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ComputingResourceDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ComputingResourceDaoMapper.xml index 885da316..162a12f7 100644 --- a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ComputingResourceDaoMapper.xml +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ComputingResourceDaoMapper.xml @@ -156,6 +156,10 @@ computing_resource = values(computing_resource)standard = values(standard)descri where id = #{computingResource.id} + + update computing_resource set used_state = #{usedState} where node = #{node} + + delete from computing_resource where id = #{id} diff --git a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageVersionDaoMapper.xml b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageVersionDaoMapper.xml index d7775b1f..63710901 100644 --- a/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageVersionDaoMapper.xml +++ b/ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageVersionDaoMapper.xml @@ -15,6 +15,7 @@ + diff --git a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml index e2649cf0..30ee8b10 100644 --- a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,4 +26,6 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true diff --git a/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml index 664f5312..b2f67919 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,4 +26,6 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true diff --git a/ruoyi-modules/ruoyi-job/pom.xml b/ruoyi-modules/ruoyi-job/pom.xml index e295d995..7b22bc72 100644 --- a/ruoyi-modules/ruoyi-job/pom.xml +++ b/ruoyi-modules/ruoyi-job/pom.xml @@ -65,7 +65,7 @@ com.mysql mysql-connector-j - + com.ruoyi @@ -77,7 +77,13 @@ com.ruoyi ruoyi-common-swagger - + + + + com.ruoyi + ruoyi-common-datasource + + diff --git a/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml index c1821584..8c79d3ad 100644 --- a/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml @@ -3,7 +3,7 @@ server: port: 9203 # Spring -spring: +spring: application: # 应用名称 name: ruoyi-job @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,4 +26,9 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true + - data-id: ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java index bcbbb6ad..713c6cd2 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java @@ -1,22 +1,5 @@ package com.ruoyi.system.controller; -import java.io.IOException; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.ArrayUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.multipart.MultipartFile; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; @@ -32,22 +15,27 @@ import com.ruoyi.system.api.domain.SysDept; import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.model.LoginUser; -import com.ruoyi.system.service.ISysConfigService; -import com.ruoyi.system.service.ISysDeptService; -import com.ruoyi.system.service.ISysPermissionService; -import com.ruoyi.system.service.ISysPostService; -import com.ruoyi.system.service.ISysRoleService; -import com.ruoyi.system.service.ISysUserService; +import com.ruoyi.system.service.*; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; /** * 用户信息 - * + * * @author ruoyi */ @RestController @RequestMapping("/user") -public class SysUserController extends BaseController -{ +public class SysUserController extends BaseController { @Autowired private ISysUserService userService; @@ -71,8 +59,7 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:list") @GetMapping("/list") - public TableDataInfo list(SysUser user) - { + public TableDataInfo list(SysUser user) { startPage(); List list = userService.selectUserList(user); return getDataTable(list); @@ -81,8 +68,7 @@ public class SysUserController extends BaseController @Log(title = "用户管理", businessType = BusinessType.EXPORT) @RequiresPermissions("system:user:export") @PostMapping("/export") - public void export(HttpServletResponse response, SysUser user) - { + public void export(HttpServletResponse response, SysUser user) { List list = userService.selectUserList(user); ExcelUtil util = new ExcelUtil(SysUser.class); util.exportExcel(response, list, "用户数据"); @@ -91,8 +77,7 @@ public class SysUserController extends BaseController @Log(title = "用户管理", businessType = BusinessType.IMPORT) @RequiresPermissions("system:user:import") @PostMapping("/importData") - public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception - { + public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception { ExcelUtil util = new ExcelUtil(SysUser.class); List userList = util.importExcel(file.getInputStream()); String operName = SecurityUtils.getUsername(); @@ -101,8 +86,7 @@ public class SysUserController extends BaseController } @PostMapping("/importTemplate") - public void importTemplate(HttpServletResponse response) throws IOException - { + public void importTemplate(HttpServletResponse response) throws IOException { ExcelUtil util = new ExcelUtil(SysUser.class); util.importTemplateExcel(response, "用户数据"); } @@ -112,11 +96,9 @@ public class SysUserController extends BaseController */ @InnerAuth @GetMapping("/info/{username}") - public R info(@PathVariable("username") String username) - { + public R info(@PathVariable("username") String username) { SysUser sysUser = userService.selectUserByUserName(username); - if (StringUtils.isNull(sysUser)) - { + if (StringUtils.isNull(sysUser)) { return R.fail("用户名或密码错误"); } // 角色集合 @@ -135,15 +117,12 @@ public class SysUserController extends BaseController */ @InnerAuth @PostMapping("/register") - public R register(@RequestBody SysUser sysUser) - { + public R register(@RequestBody SysUser sysUser) { String username = sysUser.getUserName(); - if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) - { + if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) { return R.fail("当前系统没有开启注册功能!"); } - if (!userService.checkUserNameUnique(sysUser)) - { + if (!userService.checkUserNameUnique(sysUser)) { return R.fail("保存用户'" + username + "'失败,注册账号已存在"); } return R.ok(userService.registerUser(sysUser)); @@ -151,12 +130,11 @@ public class SysUserController extends BaseController /** * 获取用户信息 - * + * * @return 用户信息 */ @GetMapping("getInfo") - public AjaxResult getInfo() - { + public AjaxResult getInfo() { SysUser user = userService.selectUserById(SecurityUtils.getUserId()); // 角色集合 Set roles = permissionService.getRolePermission(user); @@ -173,16 +151,15 @@ public class SysUserController extends BaseController * 根据用户编号获取详细信息 */ @RequiresPermissions("system:user:query") - @GetMapping(value = { "/", "/{userId}" }) - public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) - { + @GetMapping(value = {"/", "/{userId}"}) + public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) { userService.checkUserDataScope(userId); AjaxResult ajax = AjaxResult.success(); List roles = roleService.selectRoleAll(); - ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + ajax.put("roles", roles); +// ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("posts", postService.selectPostAll()); - if (StringUtils.isNotNull(userId)) - { + if (StringUtils.isNotNull(userId)) { SysUser sysUser = userService.selectUserById(userId); ajax.put(AjaxResult.DATA_TAG, sysUser); ajax.put("postIds", postService.selectPostListByUserId(userId)); @@ -197,22 +174,19 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:add") @Log(title = "用户管理", businessType = BusinessType.INSERT) @PostMapping - public AjaxResult add(@Validated @RequestBody SysUser user) - { - if (!userService.checkUserNameUnique(user)) - { + public AjaxResult add(@Validated @RequestBody SysUser user) { + if (!userService.checkUserNameUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); - } - else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); - } - else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } else if (StringUtils.isNotEmpty(user.getGitLinkUsername()) && !userService.checktGitLinkUsernameUnique(user)) { + return error("新增用户'" + user.getUserName() + "'失败,gitLink用户名已存在"); } user.setCreateBy(SecurityUtils.getUsername()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + user.setGitLinkPassword(SecurityUtils.encryptPassword(user.getGitLinkPassword())); return toAjax(userService.insertUser(user)); } @@ -222,23 +196,25 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping - public AjaxResult edit(@Validated @RequestBody SysUser user) - { + public AjaxResult edit(@Validated @RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); - if (!userService.checkUserNameUnique(user)) - { + if (!userService.checkUserNameUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); - } - else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); - } - else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) - { + } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } else if (StringUtils.isNotEmpty(user.getGitLinkUsername()) && !userService.checktGitLinkUsernameUnique(user)) { + return error("新增用户'" + user.getUserName() + "'失败,gitLink用户名已存在"); } user.setUpdateBy(SecurityUtils.getUsername()); + if(StringUtils.isNotEmpty(user.getPassword())){ + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + } + if(StringUtils.isNotEmpty(user.getGitLinkPassword())){ + user.setGitLinkPassword(SecurityUtils.encryptPassword(user.getGitLinkPassword())); + } return toAjax(userService.updateUser(user)); } @@ -248,10 +224,8 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:remove") @Log(title = "用户管理", businessType = BusinessType.DELETE) @DeleteMapping("/{userIds}") - public AjaxResult remove(@PathVariable Long[] userIds) - { - if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) - { + public AjaxResult remove(@PathVariable Long[] userIds) { + if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) { return error("当前用户不能删除"); } return toAjax(userService.deleteUserByIds(userIds)); @@ -263,8 +237,7 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/resetPwd") - public AjaxResult resetPwd(@RequestBody SysUser user) - { + public AjaxResult resetPwd(@RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); @@ -278,8 +251,7 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") - public AjaxResult changeStatus(@RequestBody SysUser user) - { + public AjaxResult changeStatus(@RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); user.setUpdateBy(SecurityUtils.getUsername()); @@ -291,8 +263,7 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:query") @GetMapping("/authRole/{userId}") - public AjaxResult authRole(@PathVariable("userId") Long userId) - { + public AjaxResult authRole(@PathVariable("userId") Long userId) { AjaxResult ajax = AjaxResult.success(); SysUser user = userService.selectUserById(userId); List roles = roleService.selectRolesByUserId(userId); @@ -307,8 +278,7 @@ public class SysUserController extends BaseController @RequiresPermissions("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.GRANT) @PutMapping("/authRole") - public AjaxResult insertAuthRole(Long userId, Long[] roleIds) - { + public AjaxResult insertAuthRole(Long userId, Long[] roleIds) { userService.checkUserDataScope(userId); userService.insertUserAuth(userId, roleIds); return success(); @@ -319,8 +289,7 @@ public class SysUserController extends BaseController */ @RequiresPermissions("system:user:list") @GetMapping("/deptTree") - public AjaxResult deptTree(SysDept dept) - { + public AjaxResult deptTree(SysDept dept) { return success(deptService.selectDeptTreeList(dept)); } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java index 2624ad88..58a622e9 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java @@ -124,4 +124,6 @@ public interface SysUserMapper * @return 结果 */ public SysUser checkEmailUnique(String email); + + public SysUser checktGitLinkUsernameUnique(String gitLinkUsername); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java index 8f30fa38..e1c718a6 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -90,6 +90,8 @@ public interface ISysUserService */ public boolean checkEmailUnique(SysUser user); + public boolean checktGitLinkUsernameUnique(SysUser user); + /** * 校验用户是否允许操作 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index ec165dc1..8ea6cb4a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -212,6 +212,17 @@ public class SysUserServiceImpl implements ISysUserService return UserConstants.UNIQUE; } + @Override + public boolean checktGitLinkUsernameUnique(SysUser user) { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checktGitLinkUsernameUnique(user.getGitLinkUsername()); + if(StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + /** * 校验用户是否允许操作 * diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml index 62cc1c2a..c7ddcd4e 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,4 +26,6 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml index eca36942..5d1900b1 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -1,221 +1,286 @@ + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + + + - + - - - - - - + + + + + + - - - select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, - d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, - r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status + + + select u.user_id, + u.dept_id, + u.user_name, + u.nick_name, + u.email, + u.avatar, + u.phonenumber, + u.password, + u.git_link_username, + u.git_link_password, + u.sex, + u.status, + u.del_flag, + u.login_ip, + u.login_date, + u.create_by, + u.create_time, + u.remark, + d.dept_id, + d.parent_id, + d.ancestors, + d.dept_name, + d.order_num, + d.leader, + d.status as dept_status, + r.role_id, + r.role_name, + r.role_key, + r.role_sort, + r.data_scope, + r.status as role_status from sys_user u - left join sys_dept d on u.dept_id = d.dept_id - left join sys_user_role ur on u.user_id = ur.user_id - left join sys_role r on r.role_id = ur.role_id + left join sys_dept d on u.dept_id = d.dept_id + left join sys_user_role ur on u.user_id = ur.user_id + left join sys_role r on r.role_id = ur.role_id - + - - - - - - - - - - - - - - - - - insert into sys_user( - user_id, - dept_id, - user_name, - nick_name, - email, - avatar, - phonenumber, - sex, - password, - status, - create_by, - remark, - create_time - )values( - #{userId}, - #{deptId}, - #{userName}, - #{nickName}, - #{email}, - #{avatar}, - #{phonenumber}, - #{sex}, - #{password}, - #{status}, - #{createBy}, - #{remark}, - sysdate() - ) - - - - update sys_user - - dept_id = #{deptId}, - user_name = #{userName}, - nick_name = #{nickName}, - email = #{email}, - phonenumber = #{phonenumber}, - sex = #{sex}, - avatar = #{avatar}, - password = #{password}, - status = #{status}, - login_ip = #{loginIp}, - login_date = #{loginDate}, - update_by = #{updateBy}, - remark = #{remark}, - update_time = sysdate() - - where user_id = #{userId} - - - - update sys_user set status = #{status} where user_id = #{userId} - - - - update sys_user set avatar = #{avatar} where user_name = #{userName} - - - - update sys_user set password = #{password} where user_name = #{userName} - - - - update sys_user set del_flag = '2' where user_id = #{userId} - - - - update sys_user set del_flag = '2' where user_id in - - #{userId} - - - + select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, + u.git_link_username, + u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader + from sys_user u + left join sys_dept d on u.dept_id = d.dept_id + where u.del_flag = '0' + + AND u.user_id = #{userId} + + + AND u.user_name like concat('%', #{userName}, '%') + + + AND u.status = #{status} + + + AND u.phonenumber like concat('%', #{phonenumber}, '%') + + + AND date_format(u.create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d') + + + AND date_format(u.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d') + + + AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, + ancestors) )) + + + ${params.dataScope} + + + + + + + + + + + + + + + + + + + + insert into sys_user( + user_id, + dept_id, + user_name, + nick_name, + email, + avatar, + phonenumber, + sex, + password, + status, + create_by, + remark, + git_link_username, + git_link_password, + create_time + )values( + #{userId}, + #{deptId}, + #{userName}, + #{nickName}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + #{createBy}, + #{remark}, + #{gitLinkUsername}, + #{gitLinkPassword}, + sysdate() + ) + + + + update sys_user + + dept_id = #{deptId}, + user_name = #{userName}, + nick_name = #{nickName}, + email = #{email}, + phonenumber = #{phonenumber}, + sex = #{sex}, + avatar = #{avatar}, + password = #{password}, + status = #{status}, + login_ip = #{loginIp}, + login_date = #{loginDate}, + update_by = #{updateBy}, + remark = #{remark}, + git_link_username = #{gitLinkUsername}, + git_link_password = #{gitLinkPassword}, + update_time = sysdate() + + where user_id = #{userId} + + + + update sys_user + set status = #{status} + where user_id = #{userId} + + + + update sys_user + set avatar = #{avatar} + where user_name = #{userName} + + + + update sys_user + set password = #{password} + where user_name = #{userName} + + + + update sys_user + set del_flag = '2' + where user_id = #{userId} + + + + update sys_user set del_flag = '2' where user_id in + + #{userId} + + + \ No newline at end of file diff --git a/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml b/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml index 394a74d2..c2876a08 100644 --- a/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml +++ b/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml @@ -15,6 +15,10 @@ spring: discovery: # 服务注册地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 + username: nacos + password: nacos + retry: + enabled: true config: # 配置中心地址 server-addr: nacos-ci4s.ci4s-test.svc:8848 @@ -22,4 +26,6 @@ spring: file-extension: yml # 共享配置 shared-configs: - - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + group: DEFAULT_GROUP + refresh: true