Browse Source

Merge branch 'dev' into dev-zw

pull/126/head
cp3hnu 1 year ago
parent
commit
127ba543a7
59 changed files with 2713 additions and 865 deletions
  1. +0
    -61
      react-ui/src/pages/Dataset/components/ResourceItem/index.less
  2. +0
    -54
      react-ui/src/pages/Dataset/components/ResourceItem/index.tsx
  3. +150
    -129
      ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java
  4. +10
    -1
      ruoyi-auth/src/main/resources/bootstrap.yml
  5. +11
    -2
      ruoyi-gateway/src/main/resources/bootstrap.yml
  6. +27
    -2
      ruoyi-modules/management-platform/pom.xml
  7. +21
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/constant/Constant.java
  8. +69
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/codeConfig/CodeConfigController.java
  9. +2
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java
  10. +115
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/NewDatasetFromGitController.java
  11. +16
    -12
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java
  12. +24
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/jupyter/JupyterController.java
  13. +57
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/CodeConfig.java
  14. +19
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ComputingResource.java
  15. +4
    -97
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ImageVersion.java
  16. +22
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/CodeConfigDao.java
  17. +2
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ComputingResourceDao.java
  18. +19
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/CodeConfigService.java
  19. +18
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DatasetService.java
  20. +8
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DvcService.java
  21. +1
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java
  22. +17
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/GitService.java
  23. +1
    -2
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java
  24. +89
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/CodeConfigServiceImpl.java
  25. +320
    -14
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetServiceImpl.java
  26. +34
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DvcServiceImpl.java
  27. +98
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/GitServiceImpl.java
  28. +121
    -43
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java
  29. +33
    -24
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java
  30. +33
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/AIM64EncoderUtil.java
  31. +11
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/BeansUtils.java
  32. +73
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ConvertUtil.java
  33. +165
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DVCUtils.java
  34. +114
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java
  35. +12
    -3
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/FileUtil.java
  36. +141
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/HttpUtils.java
  37. +6
    -3
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/JsonUtils.java
  38. +167
    -48
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java
  39. +2
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/MlflowUtil.java
  40. +28
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/YamlUtils.java
  41. +9
    -62
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/DatasetVo.java
  42. +67
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/GitProjectVo.java
  43. +14
    -1
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java
  44. +43
    -0
      ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/NewDatasetVo.java
  45. +10
    -1
      ruoyi-modules/management-platform/src/main/resources/bootstrap.yml
  46. +115
    -0
      ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/CodeConfigDaoMapper.xml
  47. +4
    -0
      ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ComputingResourceDaoMapper.xml
  48. +1
    -0
      ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageVersionDaoMapper.xml
  49. +7
    -1
      ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml
  50. +7
    -1
      ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml
  51. +8
    -2
      ruoyi-modules/ruoyi-job/pom.xml
  52. +11
    -2
      ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml
  53. +56
    -87
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
  54. +2
    -0
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
  55. +2
    -0
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
  56. +11
    -0
      ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
  57. +7
    -1
      ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml
  58. +272
    -207
      ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
  59. +7
    -1
      ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml

+ 0
- 61
react-ui/src/pages/Dataset/components/ResourceItem/index.less View File

@@ -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: '';
}
}

+ 0
- 54
react-ui/src/pages/Dataset/components/ResourceItem/index.tsx View File

@@ -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 (
<div className={styles['resource-item']} onClick={() => onClick(item)}>
<Flex justify="space-between" align="center" style={{ marginBottom: '20px', height: '32px' }}>
<Typography.Paragraph
className={styles['resource-item__name']}
ellipsis={{ tooltip: item.name }}
>
{item.name}
</Typography.Paragraph>
{!isPublic && (
<Button
type="text"
shape="circle"
onClick={(e) => {
e.stopPropagation();
onRemove(item);
}}
>
<KFIcon type="icon-shanchu" font={17} />
</Button>
)}
</Flex>
<div className={styles['resource-item__description']}>{item.description}</div>
<Flex justify="space-between">
<div className={styles['resource-item__time']}>
<img style={{ width: '17px', marginRight: '6px' }} src={creatByImg} alt="" />
<span>{item.create_by}</span>
</div>
<div className={styles['resource-item__time']}>
<img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" />
<span>最近更新: {formatDate(item.update_time, 'YYYY-MM-DD')}</span>
</div>
</Flex>
</div>
);
}

export default ResourceItem;

+ 150
- 129
ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java View File

@@ -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<SysRole> 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<SysRole> getRoles()
{
public List<SysRole> getRoles() {
return roles;
}

public void setRoles(List<SysRole> roles)
{
public void setRoles(List<SysRole> 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();
}
}

+ 10
- 1
ruoyi-auth/src/main/resources/bootstrap.yml View File

@@ -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

+ 11
- 2
ruoyi-gateway/src/main/resources/bootstrap.yml View File

@@ -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


+ 27
- 2
ruoyi-modules/management-platform/pom.xml View File

@@ -140,7 +140,17 @@
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java</artifactId>
<version>3.1.1</version>
<version>3.2.13</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<version>3.2.13</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
@@ -216,7 +226,22 @@
<version>3.0.8</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>5.13.0.202109080827-r</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.0</version>
</dependency>

</dependencies>



+ 21
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/constant/Constant.java View File

@@ -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
}

+ 69
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/codeConfig/CodeConfigController.java View File

@@ -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<Page<CodeConfig>> 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<CodeConfig> queryById(@PathVariable("id") Long id) {
return genericsSuccess(this.codeConfigService.queryById(id));
}


@PostMapping
public GenericsAjaxResult<CodeConfig> add(@RequestBody CodeConfig codeConfig) {
return genericsSuccess(this.codeConfigService.insert(codeConfig));
}

@PutMapping
public GenericsAjaxResult<CodeConfig> update(@RequestBody CodeConfig codeConfig) {
return genericsSuccess(this.codeConfigService.update(codeConfig));
}

@DeleteMapping("{id}")
public GenericsAjaxResult<String> delete(@PathVariable("id") Long id) {
return genericsSuccess(this.codeConfigService.removeById(id));
}
}

+ 2
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/DatasetController.java View File

@@ -224,5 +224,7 @@ public class DatasetController {
public AjaxResult uploadDatasetPipeline(@RequestBody(required =false) DatasetVersion datasetVersion) throws Exception {
return AjaxResult.success(this.datasetService.uploadDatasetPipeline(datasetVersion));
}


}


+ 115
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/dataset/NewDatasetFromGitController.java View File

@@ -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<InputStreamResource> 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<InputStreamResource> 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));
}
}

+ 16
- 12
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/image/ImageController.java View File

@@ -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<Page<Image>> queryByName(@PathVariable("name") String name) {
return genericsSuccess(this.imageService.queryByName(name));
}

/**
* 新增数据
*
* @param image 实体
* @return 新增结果
*/
@PostMapping
@ApiOperation("新增镜像,不包含镜像版本")
public GenericsAjaxResult<Image> 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<Map<String, String>> 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<Map<String, String>> 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<Map<String, String>> 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);
}
}


+ 24
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/controller/jupyter/JupyterController.java View File

@@ -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<String> 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<VersionVo> 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));
}
}

+ 57
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/CodeConfig.java View File

@@ -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;

}

+ 19
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ComputingResource.java View File

@@ -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;
}
}


+ 4
- 97
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/domain/ImageVersion.java View File

@@ -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;
}


+ 22
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/CodeConfigDao.java View File

@@ -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<CodeConfig> 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);
}

+ 2
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/mapper/ComputingResourceDao.java View File

@@ -73,6 +73,8 @@ public interface ComputingResourceDao {
*/
int update(@Param("computingResource") ComputingResource computingResource);

int updateUsedStateByNode(@Param("node")String node, @Param("usedState") Integer usedState);

/**
* 通过主键删除数据
*


+ 19
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/CodeConfigService.java View File

@@ -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<CodeConfig> queryByPage(CodeConfig codeConfig, PageRequest pageRequest);

CodeConfig queryById(Long id);

CodeConfig insert(CodeConfig codeConfig);

CodeConfig update(CodeConfig codeConfig);

String removeById(Long id);

}

+ 18
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DatasetService.java View File

@@ -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<InputStreamResource> downloadAllDatasetFiles(Integer datasetId, String version) throws Exception;

List<Map<String, String>> exportDataset(String path, String uuid) throws Exception;





CompletableFuture<String> newCreateDataset(DatasetVo datasetVo) throws Exception;
CompletableFuture<String> newCreateVersion(DatasetVo datasetVo);



List<Map<String, String>> uploadDatasetlocal(MultipartFile[] files, String uuid) throws Exception;

ResponseEntity<InputStreamResource> downloadAllDatasetFilesNew(String repositoryName, String version) throws IOException, Exception;
Page<NewDatasetVo> newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception;
Page<NewDatasetVo> newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception;
}

+ 8
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/DvcService.java View File

@@ -0,0 +1,8 @@
package com.ruoyi.platform.service;

public interface DvcService {

//使用dvc初始化,跟踪,push到远程仓库的接口
public void initaddpushDvc(String localPath) throws Exception ;

}

+ 1
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ExperimentInsService.java View File

@@ -31,7 +31,7 @@ public interface ExperimentInsService {
/**
* 根据实验ID查找所有具有相同ID的实例,并将它们添加到实验列表中
*
* @param experimentId 实验id,不是实例id
* @param experimentId 实验id,不是实验实例id
* @return 实例列表
*/
List<ExperimentIns> getByExperimentId(Integer experimentId) throws IOException;


+ 17
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/GitService.java View File

@@ -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;
}

+ 1
- 2
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/ImageService.java View File

@@ -93,6 +93,5 @@ public interface ImageService {
Map<String, String> createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception;
Map<String, String> uploadImageFiles(MultipartFile file) throws Exception;



void saveImage(ImageVo imageVo);
}

+ 89
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/CodeConfigServiceImpl.java View File

@@ -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<CodeConfig> queryByPage(CodeConfig codeConfig, PageRequest pageRequest) {
long total = this.codeConfigDao.count(codeConfig);
List<CodeConfig> 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 ? "删除成功" : "删除失败";
}
}

+ 320
- 14
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DatasetServiceImpl.java View File

@@ -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<InputStreamResource> downloadAllDatasetFiles(Integer datasetId, String version) throws Exception {
public ResponseEntity<InputStreamResource> 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<String> 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<String, Object> 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<String> 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<String, Object> 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<NewDatasetVo> 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<String, Object> 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<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req);
Integer total = (Integer) stringObjectMap.get("count");
List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects");
return new PageImpl<>(convert(projects), pageRequest, total);
}

@Override
public Page<NewDatasetVo> 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<String, Object> 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<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req);
Integer total = (Integer) stringObjectMap.get("total_count");
List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects");
return new PageImpl<>(convert(projects), pageRequest, total);

}

@Override
public List<Map<String, String>> uploadDatasetlocal(MultipartFile[] files, String uuid) throws Exception {
List<Map<String, String>> 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<String, String> result = new HashMap<>();
result.put("fileName", fileName);
result.put("url", absolutePath); // objectName根据实际情况定义
result.put("fileSize", formattedSize);
results.add(result);
}
return results;
}

@Override
public ResponseEntity<InputStreamResource> 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<String, Object> 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<NewDatasetVo> convert(List<Map<String, Object>> lst) {
if (lst != null && lst.size() > 0) {
List<NewDatasetVo> newDatasetVos = ConvertUtil.convertListMapToObjectList(lst, NewDatasetVo.class);

for (NewDatasetVo newDatasetVo : newDatasetVos) {
Map<String, Object> map = lst.stream()
.filter(m -> m.get("repo_id").equals(newDatasetVo.getRepoId()))
.findFirst()
.orElse(null);

if (map != null) {
List<Map<String, Object>> topics = (List<Map<String, Object>>) 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<String, Object> author = (Map<String, Object>) map.get("author");
newDatasetVo.setCreateBy((String) author.get("name"));
}
}

return newDatasetVos;
}
return new ArrayList<>();
}

}

+ 34
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/DvcServiceImpl.java View File

@@ -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);
}

}

+ 98
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/GitServiceImpl.java View File

@@ -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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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);
}
}

+ 121
- 43
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/ImageServiceImpl.java View File

@@ -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<ImageVersion> 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<String, String> 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<String, String> 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<ImageVersion> 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<String, String> 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);
}
}
}

+ 33
- 24
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/service/impl/JupyterServiceImpl.java View File

@@ -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<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset());
String datasetPath = (String) dataset.get("path");
String datasetPath = "argo-workflow" + "/" + dataset.get("path");

Map<String, Object> 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 {
}





}

+ 33
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/AIM64EncoderUtil.java View File

@@ -19,58 +19,91 @@ public class AIM64EncoderUtil {
}

public static String aim64encode(Map<String, Object> value) {
// 将Map对象转换为JSON字符串
String jsonEncoded = JSON.toJSONString(value);
// 将JSON字符串进行Base64编码
String base64Encoded = Base64.getEncoder().encodeToString(jsonEncoded.getBytes());
String aim64Encoded = base64Encoded;
// 替换Base64编码中的特定字符
for (Map.Entry<String, String> 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<String, Object> 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<String> 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<String, Object> 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;

}
}

+ 11
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/BeansUtils.java View File

@@ -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<String> emptyNames = new HashSet<String>();
// 遍历所有属性描述符
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));
}
}

+ 73
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/ConvertUtil.java View File

@@ -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> T entityToVo(Object source, Class<T> target) {
if (source == null) {
return null;
@@ -33,6 +43,8 @@ public class ConvertUtil {
return targetObject;
}


// 将实体对象列表转换为目标类型的列表
public static <T> List<T> entityToVoList(Collection<?> sourceList, Class<T> target) {
if (sourceList == null) {
return null;
@@ -50,5 +62,65 @@ public class ConvertUtil {
}
return targetList;
}

public static <T> List<T> convertListMapToObjectList(List<Map<String, Object>> listMap, Class<T> targetClass) {
List<T> resultList = new ArrayList<>();

if (listMap != null) {
for (Map<String, Object> map : listMap) {
T targetObject = convertMapToObject(map, targetClass);
if (targetObject != null) {
resultList.add(targetObject);
}
}
}

return resultList;
}

private static <T> T convertMapToObject(Map<String, Object> map, Class<T> targetClass) {
try {
T targetObject = targetClass.newInstance();
for (Map.Entry<String, Object> 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();
}
}


+ 165
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DVCUtils.java View File

@@ -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);
}
}

+ 114
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/DockerClientUtil.java View File

@@ -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<String, String> 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<String, String> 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();
}
}

+ 12
- 3
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/FileUtil.java View File

@@ -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);
}


+ 141
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/HttpUtils.java View File

@@ -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<String, String>) params, "UTF-8"));
} else if (params instanceof String) {
entity = new StringEntity((String) params, "UTF-8");
} else if (params instanceof List) {
entity = new UrlEncodedFormEntity((List<? extends NameValuePair>) 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方法的请求
*


+ 6
- 3
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/JsonUtils.java View File

@@ -37,10 +37,8 @@ public class JsonUtils {
// 将JSON字符串转换为扁平化的Map
public static Map<String, Object> flattenJson(String prefix, Map<String, Object> map) {
Map<String, Object> flatMap = new HashMap<>();
Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator();

while (entries.hasNext()) {
Map.Entry<String, Object> entry = entries.next();
for (Map.Entry<String, Object> 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<String, Object> objectToMap(Object object) throws IOException {
return objectMapper.convertValue(object, Map.class);
}
}

+ 167
- 48
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/K8sClientUtil.java View File

@@ -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<String, String> selector = new LinkedHashMap<String, String>();
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<String, String> selector = new LinkedHashMap<String, String>();
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<String, String> selector = new LinkedHashMap<>();
selector.put("k8s-jupyter", podName);
Map<String, String> 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<V1VolumeMount> 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<V1Volume> 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<String, Quantity> 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) {


+ 2
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/MlflowUtil.java View File

@@ -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;



+ 28
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/utils/YamlUtils.java View File

@@ -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<String, Object> 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();
}
}
}

+ 9
- 62
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/DatasetVo.java View File

@@ -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<VersionVo> 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<VersionVo> getDatasetVersionVos() {
return datasetVersionVos;
}

public void setDatasetVersionVos(List<VersionVo> datasetVersionVos) {
this.datasetVersionVos = datasetVersionVos;
}

public String getAvailableCluster() {
return availableCluster;
}

public void setAvailableCluster(String availableCluster) {
this.availableCluster = availableCluster;
}
/**
* 数据集仓库名称
*/
@ApiModelProperty(name = "repository_name")
private String repositoryName;
}

+ 67
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/GitProjectVo.java View File

@@ -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 +
// '}';
// }
}


+ 14
- 1
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/ImageVo.java View File

@@ -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;
}

}

+ 43
- 0
ruoyi-modules/management-platform/src/main/java/com/ruoyi/platform/vo/NewDatasetVo.java View File

@@ -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;
}

+ 10
- 1
ruoyi-modules/management-platform/src/main/resources/bootstrap.yml View File

@@ -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

+ 115
- 0
ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/CodeConfigDaoMapper.xml View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.platform.mapper.CodeConfigDao">

<insert id="insert">
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})
</insert>

<update id="update">
update code_config
<set>
<if test="codeConfig.codeRepoName != null and codeConfig.codeRepoName != ''">
code_repo_name = #{codeConfig.codeRepoName},
</if>
<if test="codeConfig.codeRepoVis != null">
code_repo_vis = #{codeConfig.codeRepoVis},
</if>
<if test="codeConfig.gitUrl != null">
git_url = #{codeConfig.gitUrl},
</if>
<if test="codeConfig.gitBranch != null and codeConfig.gitBranch != ''">
git_branch = #{codeConfig.gitBranch},
</if>
verify_mode = #{codeConfig.verifyMode},
git_user_name = #{codeConfig.gitUserName},
git_password = #{codeConfig.gitPassword},
ssh_key = #{codeConfig.sshKey},
<if test="codeConfig.createBy != null and codeConfig.createBy != ''">
create_by = #{codeConfig.createBy},
</if>
<if test="codeConfig.createTime != null">
create_time = #{codeConfig.createTime},
</if>
<if test="codeConfig.updateBy != null and codeConfig.updateBy != ''">
update_by = #{codeConfig.updateBy},
</if>
<if test="codeConfig.state != null">
state = #{codeConfig.state},
</if>
update_time = sysdate()
</set>
where id = #{codeConfig.id}
</update>


<select id="count" resultType="java.lang.Long">
select count(1)
from code_config
<include refid="common_condition"></include>
</select>

<select id="queryAllByLimit" resultType="com.ruoyi.platform.domain.CodeConfig">
select * from code_config
<include refid="common_condition"></include>
limit #{pageable.offset}, #{pageable.pageSize}
</select>

<select id="queryById" resultType="com.ruoyi.platform.domain.CodeConfig">
select *
from code_config
where id = #{id}
and state = 1
</select>

<select id="queryByCodeRepoName" resultType="java.lang.Long">
select id
from code_config
where code_repo_name = #{codeRepoName}
and state = 1
</select>

<sql id="common_condition">
<where>
state = 1
<if test="codeConfig.id != null">
and id = #{codeConfig.id}
</if>
<if test="codeConfig.codeRepoName != null and codeConfig.codeRepoName != ''">
and code_repo_name LIKE CONCAT('%', #{codeConfig.codeRepoName}, '%')
</if>
<if test="codeConfig.codeRepoVis != null">
and code_repo_vis = #{codeConfig.codeRepoVis}
</if>
<if test="codeConfig.gitUrl != null">
and git_url = #{codeConfig.gitUrl}
</if>
<if test="codeConfig.gitBranch != null and codeConfig.gitBranch != ''">
and git_branch = #{codeConfig.gitBranch}
</if>
<if test="codeConfig.verifyMode != null">
and verify_mode = #{codeConfig.verifyMode}
</if>
<if test="codeConfig.gitUserName != null and codeConfig.gitUserName != ''">
and git_user_name = #{codeConfig.gitUserName}
</if>
<if test="codeConfig.createBy != null and codeConfig.createBy != ''">
and create_by = #{codeConfig.createBy}
</if>
<if test="codeConfig.createTime != null">
and create_time = #{codeConfig.createTime}
</if>
<if test="codeConfig.updateBy != null and codeConfig.updateBy != ''">
and update_by = #{codeConfig.updateBy}
</if>
<if test="codeConfig.updateTime != null">
and update_time = #{codeConfig.updateTime}
</if>
</where>
</sql>
</mapper>

+ 4
- 0
ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ComputingResourceDaoMapper.xml View File

@@ -156,6 +156,10 @@ computing_resource = values(computing_resource)standard = values(standard)descri
where id = #{computingResource.id}
</update>

<update id="updateUsedStateByNode">
update computing_resource set used_state = #{usedState} where node = #{node}
</update>

<!--通过主键删除-->
<delete id="deleteById">
delete from computing_resource where id = #{id}


+ 1
- 0
ruoyi-modules/management-platform/src/main/resources/mapper/managementPlatform/ImageVersionDaoMapper.xml View File

@@ -15,6 +15,7 @@
<result property="updateBy" column="update_by" jdbcType="VARCHAR"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
<result property="state" column="state" jdbcType="INTEGER"/>
<result property="hostIp" column="host_ip" jdbcType="VARCHAR"/>
</resultMap>

<!--根据模型id返回版本列表-->


+ 7
- 1
ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml View File

@@ -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

+ 7
- 1
ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml View File

@@ -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

+ 8
- 2
ruoyi-modules/ruoyi-job/pom.xml View File

@@ -65,7 +65,7 @@
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- RuoYi Common Log -->
<dependency>
<groupId>com.ruoyi</groupId>
@@ -77,7 +77,13 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>

<!-- RuoYi Common DataSource -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
</dependency>

</dependencies>

<build>


+ 11
- 2
ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml View File

@@ -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

+ 56
- 87
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java View File

@@ -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<SysUser> 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<SysUser> list = userService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(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<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
List<SysUser> 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<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
util.importTemplateExcel(response, "用户数据");
}
@@ -112,11 +96,9 @@ public class SysUserController extends BaseController
*/
@InnerAuth
@GetMapping("/info/{username}")
public R<LoginUser> info(@PathVariable("username") String username)
{
public R<LoginUser> 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<Boolean> register(@RequestBody SysUser sysUser)
{
public R<Boolean> 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<String> 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<SysRole> 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<SysRole> 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));
}
}

+ 2
- 0
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java View File

@@ -124,4 +124,6 @@ public interface SysUserMapper
* @return 结果
*/
public SysUser checkEmailUnique(String email);

public SysUser checktGitLinkUsernameUnique(String gitLinkUsername);
}

+ 2
- 0
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java View File

@@ -90,6 +90,8 @@ public interface ISysUserService
*/
public boolean checkEmailUnique(SysUser user);

public boolean checktGitLinkUsernameUnique(SysUser user);

/**
* 校验用户是否允许操作
*


+ 11
- 0
ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java View File

@@ -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;
}

/**
* 校验用户是否允许操作
*


+ 7
- 1
ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml View File

@@ -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

+ 272
- 207
ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml View File

@@ -1,221 +1,286 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.SysUserMapper">

<resultMap type="SysUser" id="SysUserResult">
<id property="userId" column="user_id" />
<result property="deptId" column="dept_id" />
<result property="userName" column="user_name" />
<result property="nickName" column="nick_name" />
<result property="email" column="email" />
<result property="phonenumber" column="phonenumber" />
<result property="sex" column="sex" />
<result property="avatar" column="avatar" />
<result property="password" column="password" />
<result property="status" column="status" />
<result property="delFlag" column="del_flag" />
<result property="loginIp" column="login_ip" />
<result property="loginDate" column="login_date" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
<association property="dept" javaType="SysDept" resultMap="deptResult" />
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
<id property="userId" column="user_id"/>
<result property="deptId" column="dept_id"/>
<result property="userName" column="user_name"/>
<result property="nickName" column="nick_name"/>
<result property="email" column="email"/>
<result property="phonenumber" column="phonenumber"/>
<result property="sex" column="sex"/>
<result property="avatar" column="avatar"/>
<result property="password" column="password"/>
<result property="status" column="status"/>
<result property="delFlag" column="del_flag"/>
<result property="loginIp" column="login_ip"/>
<result property="loginDate" column="login_date"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="remark" column="remark"/>
<result property="gitLinkUsername" column="git_link_username"/>
<result property="gitLinkPassword" column="git_link_password"/>
<association property="dept" javaType="SysDept" resultMap="deptResult"/>
<collection property="roles" javaType="java.util.List" resultMap="RoleResult"/>
</resultMap>
<resultMap id="deptResult" type="SysDept">
<id property="deptId" column="dept_id" />
<result property="parentId" column="parent_id" />
<result property="deptName" column="dept_name" />
<result property="ancestors" column="ancestors" />
<result property="orderNum" column="order_num" />
<result property="leader" column="leader" />
<result property="status" column="dept_status" />
<id property="deptId" column="dept_id"/>
<result property="parentId" column="parent_id"/>
<result property="deptName" column="dept_name"/>
<result property="ancestors" column="ancestors"/>
<result property="orderNum" column="order_num"/>
<result property="leader" column="leader"/>
<result property="status" column="dept_status"/>
</resultMap>
<resultMap id="RoleResult" type="SysRole">
<id property="roleId" column="role_id" />
<result property="roleName" column="role_name" />
<result property="roleKey" column="role_key" />
<result property="roleSort" column="role_sort" />
<result property="dataScope" column="data_scope" />
<result property="status" column="role_status" />
<id property="roleId" column="role_id"/>
<result property="roleName" column="role_name"/>
<result property="roleKey" column="role_key"/>
<result property="roleSort" column="role_sort"/>
<result property="dataScope" column="data_scope"/>
<result property="status" column="role_status"/>
</resultMap>
<sql id="selectUserVo">
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

<sql id="selectUserVo">
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
</sql>
<select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, 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'
<if test="userId != null and userId != 0">
AND u.user_id = #{userId}
</if>
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="status != null and status != ''">
AND u.status = #{status}
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
<if test="deptId != null and deptId != 0">
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) ))
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
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
where u.del_flag = '0' and r.role_id = #{roleId}
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
<select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time
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
where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{roleId})
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.user_name = #{userName} and u.del_flag = '0'
</select>
<select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.user_id = #{userId}
</select>
<select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
select user_id, user_name from sys_user where user_name = #{userName} and del_flag = '0' limit 1
</select>
<select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} and del_flag = '0' limit 1
</select>
<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1
</select>
<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
insert into sys_user(
<if test="userId != null and userId != 0">user_id,</if>
<if test="deptId != null and deptId != 0">dept_id,</if>
<if test="userName != null and userName != ''">user_name,</if>
<if test="nickName != null and nickName != ''">nick_name,</if>
<if test="email != null and email != ''">email,</if>
<if test="avatar != null and avatar != ''">avatar,</if>
<if test="phonenumber != null and phonenumber != ''">phonenumber,</if>
<if test="sex != null and sex != ''">sex,</if>
<if test="password != null and password != ''">password,</if>
<if test="status != null and status != ''">status,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="remark != null and remark != ''">remark,</if>
create_time
)values(
<if test="userId != null and userId != ''">#{userId},</if>
<if test="deptId != null and deptId != ''">#{deptId},</if>
<if test="userName != null and userName != ''">#{userName},</if>
<if test="nickName != null and nickName != ''">#{nickName},</if>
<if test="email != null and email != ''">#{email},</if>
<if test="avatar != null and avatar != ''">#{avatar},</if>
<if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if>
<if test="sex != null and sex != ''">#{sex},</if>
<if test="password != null and password != ''">#{password},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="remark != null and remark != ''">#{remark},</if>
sysdate()
)
</insert>
<update id="updateUser" parameterType="SysUser">
update sys_user
<set>
<if test="deptId != null and deptId != 0">dept_id = #{deptId},</if>
<if test="userName != null and userName != ''">user_name = #{userName},</if>
<if test="nickName != null and nickName != ''">nick_name = #{nickName},</if>
<if test="email != null ">email = #{email},</if>
<if test="phonenumber != null ">phonenumber = #{phonenumber},</if>
<if test="sex != null and sex != ''">sex = #{sex},</if>
<if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
<if test="password != null and password != ''">password = #{password},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if>
<if test="loginDate != null">login_date = #{loginDate},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="remark != null">remark = #{remark},</if>
update_time = sysdate()
</set>
where user_id = #{userId}
</update>
<update id="updateUserStatus" parameterType="SysUser">
update sys_user set status = #{status} where user_id = #{userId}
</update>
<update id="updateUserAvatar" parameterType="SysUser">
update sys_user set avatar = #{avatar} where user_name = #{userName}
</update>
<update id="resetUserPwd" parameterType="SysUser">
update sys_user set password = #{password} where user_name = #{userName}
</update>
<delete id="deleteUserById" parameterType="Long">
update sys_user set del_flag = '2' where user_id = #{userId}
</delete>
<delete id="deleteUserByIds" parameterType="Long">
update sys_user set del_flag = '2' where user_id in
<foreach collection="array" item="userId" open="(" separator="," close=")">
#{userId}
</foreach>
</delete>
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'
<if test="userId != null and userId != 0">
AND u.user_id = #{userId}
</if>
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="status != null and status != ''">
AND u.status = #{status}
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(u.create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(u.create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if>
<if test="deptId != null and deptId != 0">
AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId},
ancestors) ))
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>

<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time, u.git_link_username
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
where u.del_flag = '0' and r.role_id = #{roleId}
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>

<select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time ,u.git_link_username
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
where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and
ur.role_id = #{roleId})
<if test="userName != null and userName != ''">
AND u.user_name like concat('%', #{userName}, '%')
</if>
<if test="phonenumber != null and phonenumber != ''">
AND u.phonenumber like concat('%', #{phonenumber}, '%')
</if>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>

<select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.user_name = #{userName} and u.del_flag = '0'
</select>

<select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
<include refid="selectUserVo"/>
where u.user_id = #{userId}
</select>

<select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
select user_id, user_name
from sys_user
where user_name = #{userName}
and del_flag = '0' limit 1
</select>

<select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
select user_id, phonenumber
from sys_user
where phonenumber = #{phonenumber}
and del_flag = '0' limit 1
</select>

<select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
select user_id, email
from sys_user
where email = #{email}
and del_flag = '0' limit 1
</select>

<select id="checktGitLinkUsernameUnique" resultType="com.ruoyi.system.api.domain.SysUser">
select user_id, git_link_username
from sys_user
where git_link_username = #{gitLinkUsername}
and del_flag = '0' limit 1
</select>

<insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
insert into sys_user(
<if test="userId != null and userId != 0">user_id,</if>
<if test="deptId != null and deptId != 0">dept_id,</if>
<if test="userName != null and userName != ''">user_name,</if>
<if test="nickName != null and nickName != ''">nick_name,</if>
<if test="email != null and email != ''">email,</if>
<if test="avatar != null and avatar != ''">avatar,</if>
<if test="phonenumber != null and phonenumber != ''">phonenumber,</if>
<if test="sex != null and sex != ''">sex,</if>
<if test="password != null and password != ''">password,</if>
<if test="status != null and status != ''">status,</if>
<if test="createBy != null and createBy != ''">create_by,</if>
<if test="remark != null and remark != ''">remark,</if>
<if test="remark != null and remark != ''">git_link_username,</if>
<if test="remark != null and remark != ''">git_link_password,</if>
create_time
)values(
<if test="userId != null and userId != ''">#{userId},</if>
<if test="deptId != null and deptId != ''">#{deptId},</if>
<if test="userName != null and userName != ''">#{userName},</if>
<if test="nickName != null and nickName != ''">#{nickName},</if>
<if test="email != null and email != ''">#{email},</if>
<if test="avatar != null and avatar != ''">#{avatar},</if>
<if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if>
<if test="sex != null and sex != ''">#{sex},</if>
<if test="password != null and password != ''">#{password},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="createBy != null and createBy != ''">#{createBy},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<if test="gitLinkUsername != null and gitLinkUsername != ''">#{gitLinkUsername},</if>
<if test="gitLinkPassword != null and gitLinkPassword != ''">#{gitLinkPassword},</if>
sysdate()
)
</insert>

<update id="updateUser" parameterType="SysUser">
update sys_user
<set>
<if test="deptId != null and deptId != 0">dept_id = #{deptId},</if>
<if test="userName != null and userName != ''">user_name = #{userName},</if>
<if test="nickName != null and nickName != ''">nick_name = #{nickName},</if>
<if test="email != null ">email = #{email},</if>
<if test="phonenumber != null ">phonenumber = #{phonenumber},</if>
<if test="sex != null and sex != ''">sex = #{sex},</if>
<if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
<if test="password != null and password != ''">password = #{password},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if>
<if test="loginDate != null">login_date = #{loginDate},</if>
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="gitLinkUsername != null and gitLinkUsername != ''">git_link_username = #{gitLinkUsername},</if>
<if test="gitLinkPassword != null and gitLinkPassword != ''">git_link_password = #{gitLinkPassword},</if>
update_time = sysdate()
</set>
where user_id = #{userId}
</update>

<update id="updateUserStatus" parameterType="SysUser">
update sys_user
set status = #{status}
where user_id = #{userId}
</update>

<update id="updateUserAvatar" parameterType="SysUser">
update sys_user
set avatar = #{avatar}
where user_name = #{userName}
</update>

<update id="resetUserPwd" parameterType="SysUser">
update sys_user
set password = #{password}
where user_name = #{userName}
</update>

<delete id="deleteUserById" parameterType="Long">
update sys_user
set del_flag = '2'
where user_id = #{userId}
</delete>

<delete id="deleteUserByIds" parameterType="Long">
update sys_user set del_flag = '2' where user_id in
<foreach collection="array" item="userId" open="(" separator="," close=")">
#{userId}
</foreach>
</delete>

</mapper>

+ 7
- 1
ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml View File

@@ -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

Loading…
Cancel
Save