Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f48ba95a2 | ||
|
|
f420315d3e | ||
|
|
2b8d64da45 | ||
|
|
4fb4afdd53 | ||
|
|
1decd92bd9 | ||
|
|
91b25b8d0c | ||
|
|
af8fedbe44 | ||
|
|
142c0fff1d | ||
|
|
f5b07ee906 | ||
|
|
d52c1f4d88 | ||
|
|
d6a021b4d9 | ||
|
|
8ecb5a687e | ||
|
|
cdf10770d6 | ||
|
|
e04e14a6e4 | ||
|
|
f146989a1a | ||
|
|
c14c0248cb | ||
|
|
b6ee28731b | ||
|
|
c8c947d8a8 | ||
|
|
c66e62623e | ||
|
|
f1207be0ec | ||
|
|
be87c930e2 | ||
|
|
e057ab858f | ||
|
|
30e0d23d11 | ||
|
|
c46fa28d25 |
@@ -26,7 +26,7 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
当前版本: **1.0.5**
|
||||
当前版本: **1.0.6**
|
||||
|
||||
**github:** https://github.com/lijiahangmax/orion-ops-pro
|
||||
**gitee:** https://gitee.com/lijiahangmax/orion-ops-pro
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
orion-ops-pro:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-ops-pro:1.0.5
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-ops-pro:1.0.6
|
||||
ports:
|
||||
- 1081:80
|
||||
environment:
|
||||
@@ -13,6 +13,7 @@ services:
|
||||
- SECRET_KEY=uQeacXV8b3isvKLK
|
||||
volumes:
|
||||
- /data/orion-ops-pro-space/docker-volumes/orion-ops-pro/logs:/root/orion/logs/orion-ops-pro
|
||||
- /data/orion-ops-pro-space/docker-volumes/orion-ops-pro/app:/root/orion/orion-ops-pro
|
||||
depends_on:
|
||||
- orion-ops-pro-db
|
||||
- orion-ops-pro-redis
|
||||
@@ -34,11 +35,12 @@ services:
|
||||
- /data/orion-ops-pro-space/docker-volumes/mysql/etc-mysql:/etc/mysql
|
||||
orion-ops-pro-redis:
|
||||
image: redis:6.0.16-alpine
|
||||
command: redis-server --requirepass Data@123456
|
||||
command: redis-server --appendonly yes --requirepass Data@123456
|
||||
ports:
|
||||
- 6380:6379
|
||||
volumes:
|
||||
- /data/orion-ops-pro-space/docker-volumes/redis/data:/data
|
||||
- /data/orion-ops-pro-space/docker-volumes/redis/redis.conf:/usr/local/etc/redis/redis.conf
|
||||
orion-ops-pro-adminer:
|
||||
image: adminer
|
||||
ports:
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
mv ../../orion-ops-launch/target/orion-ops-launch.jar ./
|
||||
mv ../../orion-ops-ui/dist ./dist
|
||||
docker build -t orion-ops-pro:1.0.5 .
|
||||
docker build -t orion-ops-pro:1.0.6 .
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</a>
|
||||
</p>
|
||||
|
||||
当前版本: **1.0.5**
|
||||
当前版本: **1.0.6**
|
||||
|
||||
**github:** https://github.com/lijiahangmax/orion-ops-pro
|
||||
**gitee:** https://gitee.com/lijiahangmax/orion-ops-pro
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# orion-ops-pro <small>1.0.5</small>
|
||||
# orion-ops-pro <small>1.0.6</small>
|
||||
|
||||
> 一款开箱即用的运维平台。
|
||||
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
> 版本号严格遵循 Semver 规范。
|
||||
|
||||
* ⚡ **sql 脚本可以在 adminer 中执行。**
|
||||
* ⚡ **应用不支持跨版本升级, 可以进行多次升级。**
|
||||
### 升级须知
|
||||
|
||||
## v1.0.5
|
||||
* 应用 **不支持** 跨版本升级, 可以进行 **多次升级**。
|
||||
* docker 安装的 sql 脚本可以在 `adminer` 中执行。
|
||||
* 执行完成菜单 sql 后请刷新缓存 `系统设置` > `系统菜单` > `刷新缓存`
|
||||
* 执行完成字典 sql 后请刷新缓存 `系统设置` > `数据字典项` > `刷新缓存`
|
||||
|
||||
### v1.0.6
|
||||
|
||||
`2024-04-26` `release`
|
||||
|
||||
* 🐞 修复 终端页签关闭后不会自动切换
|
||||
* 🩰 修改 命令执行日志 UI 修改
|
||||
* 🌈 新增 命令执行模板配置默认主机
|
||||
* 🌈 新增 主机终端书签路径
|
||||
* 🌈 新增 命令执行日志添加 `ansi` 日志 `app.exec-log.append-ansi`
|
||||
* 🌈 新增 定时删除命令执行日志文件 `app.exec-log.auto-clear`
|
||||
* 🌈 新增 终端设置添加了几个全局快捷键
|
||||
* 🔨 优化 通用分组模型添加 `userId`
|
||||
* 🔨 优化 退出登录不重定向
|
||||
* 🔨 优化 动态设置页面标题
|
||||
* 🔨 优化 终端断开后回车重连
|
||||
* 🔨 优化 自动删除未使用的命令片段分组
|
||||
* 🔨 优化 添加分布式锁工具类
|
||||
|
||||
[如何升级](/update/v1.0.6.md)
|
||||
|
||||
### v1.0.5
|
||||
|
||||
`2024-04-22` `release`
|
||||
|
||||
@@ -28,7 +52,7 @@
|
||||
|
||||
[如何升级](/update/v1.0.5.md)
|
||||
|
||||
## v1.0.4
|
||||
### v1.0.4
|
||||
|
||||
`2024-04-15` `release`
|
||||
|
||||
@@ -50,7 +74,7 @@
|
||||
|
||||
[如何升级](/update/v1.0.4.md)
|
||||
|
||||
## v1.0.3
|
||||
### v1.0.3
|
||||
|
||||
`2024-03-25` `release`
|
||||
|
||||
@@ -65,7 +89,7 @@
|
||||
|
||||
[如何升级](/update/v1.0.3.md)
|
||||
|
||||
## v1.0.2
|
||||
### v1.0.2
|
||||
|
||||
`2024-03-22` `release`
|
||||
|
||||
@@ -84,7 +108,7 @@
|
||||
|
||||
[如何升级](/update/v1.0.2.md)
|
||||
|
||||
## v1.0.1
|
||||
### v1.0.1
|
||||
|
||||
`2024-03-06` `release`
|
||||
|
||||
@@ -99,7 +123,7 @@
|
||||
|
||||
[如何升级](/update/v1.0.1.md)
|
||||
|
||||
## v1.0.0
|
||||
### v1.0.0
|
||||
|
||||
`2024-03-01` `release`
|
||||
|
||||
@@ -108,7 +132,7 @@
|
||||
|
||||
[如何升级](/update/v1.0.0.md)
|
||||
|
||||
## v1.0.0-beta.1
|
||||
### v1.0.0-beta.1
|
||||
|
||||
`2024-02-28` `preview`
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
## 功能排期
|
||||
|
||||
* 默认主机
|
||||
* 批量上传
|
||||
* 文件夹书签
|
||||
* 站内消息
|
||||
* 终端背景图片
|
||||
* 资产授权 UI 改版
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
数据库的数据都采用了逻辑删除, 可以将已删除的数据中的 `deleted` 字段改为 `0`
|
||||
如果不知道数据是哪一条, 可以查询用户操作日志, 点击 `参数` 寻找操作的id
|
||||
|
||||
> ##### 2. 是否支持维护 Windows 主机?
|
||||
|
||||
支持, 但是 Windows 的 ssh 命令兼容性不好, 一切需要执行ssh命令的地方都不友好
|
||||
|
||||
> ##### 3. 执行命令时为什么会找不到环境变量?
|
||||
> ##### 2. 执行命令时为什么会找不到环境变量?
|
||||
|
||||
可以在执行命令的第一行设置 `source /etc/profile` 来加载环境变量
|
||||
|
||||
> ##### 4. 命令中途执行失败如何设置中断执行?
|
||||
> ##### 3. 命令中途执行失败如何设置中断执行?
|
||||
|
||||
可以在执行命令的第一行设置 `set -e`
|
||||
作用是: 当执行出现意料之外的情况时, 立即退出
|
||||
|
||||
> ##### 5. 在调度任务、批量执行 命令执行成功的依据是什么?
|
||||
> ##### 4. 在调度任务、批量执行 命令执行成功的依据是什么?
|
||||
|
||||
是获取命令的 `exitcode` 判断是否为 `0` 如果非0则代表命令执行失败
|
||||
同理, 在命令的最后一行设置 `exit 1` 结果将会是失败, 可以用此来中断后续流程
|
||||
|
||||
> ##### 5. 调度任务、批量执行 的日志文件中如何只保存原始输出?
|
||||
|
||||
修改 application.yaml `app.exec-log.append-ansi` 为 false
|
||||
|
||||
> ##### 6. 为什么使用秘钥认证还是无法连接机器?
|
||||
|
||||
```
|
||||
|
||||
@@ -3,9 +3,104 @@
|
||||
> sql 脚本 - DDL
|
||||
|
||||
```sql
|
||||
-- 数据分组添加 userId
|
||||
ALTER TABLE `data_group`
|
||||
ADD COLUMN `user_id` bigint(0) NULL COMMENT '用户id' AFTER `type`,
|
||||
MODIFY COLUMN `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组名称' AFTER `user_id`,
|
||||
DROP INDEX `idx_type`,
|
||||
ADD INDEX `idx_type_user`(`type`, `user_id`) USING BTREE;
|
||||
|
||||
ALTER TABLE `data_group_rel`
|
||||
MODIFY COLUMN `type` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组类型' AFTER `id`,
|
||||
ADD COLUMN `user_id` bigint(0) NULL COMMENT '用户id' AFTER `type`,
|
||||
DROP INDEX `idx_type`,
|
||||
ADD INDEX `idx_type_user`(`type`, `user_id`) USING BTREE;
|
||||
|
||||
-- 执行模板主机表
|
||||
DROP TABLE IF EXISTS `exec_template_host`;
|
||||
CREATE TABLE `exec_template_host`
|
||||
(
|
||||
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`template_id` bigint(0) NULL DEFAULT NULL COMMENT '模板id',
|
||||
`host_id` bigint(0) NULL DEFAULT NULL COMMENT '主机id',
|
||||
`create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人',
|
||||
`deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `template_id` (`template_id`) USING BTREE
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 1
|
||||
CHARACTER SET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '执行模板主机'
|
||||
ROW_FORMAT = Dynamic;
|
||||
|
||||
-- 路径书签表
|
||||
DROP TABLE IF EXISTS `path_bookmark`;
|
||||
CREATE TABLE `path_bookmark`
|
||||
(
|
||||
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
`user_id` bigint(0) NULL DEFAULT NULL COMMENT '用户id',
|
||||
`group_id` bigint(0) NULL DEFAULT NULL COMMENT '分组id',
|
||||
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',
|
||||
`type` char(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型',
|
||||
`path` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路径',
|
||||
`create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间',
|
||||
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
|
||||
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人',
|
||||
`deleted` tinyint(1) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1已删除',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_user` (`user_id`) USING BTREE
|
||||
) ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 1
|
||||
CHARACTER SET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '路径书签'
|
||||
ROW_FORMAT = Dynamic;
|
||||
|
||||
```
|
||||
|
||||
> sql 脚本 - DML
|
||||
|
||||
```sql
|
||||
-- 设置数据分组 user_id
|
||||
UPDATE data_group SET user_id = 0;
|
||||
UPDATE data_group_rel SET user_id = 0;
|
||||
-- 菜单
|
||||
DELETE FROM `system_menu` WHERE id >= 190;
|
||||
INSERT INTO `system_menu` VALUES (190, 184, '中断计划任务', 'asset:exec-job-log:interrupt', 3, 40, 1, 1, 1, 0, NULL, NULL, NULL, '2024-03-13 15:08:23', '2024-04-12 00:00:33', '1', '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (191, 0, '提交bug', NULL, 1, 1020, 1, 1, 0, 1, 'IconBug', 'https://github.com/lijiahangmax/orion-ops-pro/issues', NULL, '2024-04-26 11:30:18', '2024-04-26 11:30:30', '1', '1', 0);
|
||||
INSERT INTO `system_menu` VALUES (192, 0, '点个赞~', NULL, 1, 1030, 1, 1, 0, 1, 'IconThumbUp', 'https://gitee.com/lijiahangmax/orion-ops-pro', NULL, '2024-04-26 11:32:30', '2024-04-26 11:32:30', '1', '1', 0);
|
||||
-- 字典项
|
||||
DELETE FROM `dict_key` WHERE id = 27 OR id >= 39;
|
||||
INSERT INTO `dict_key` VALUES (27, 'hostConnectType', 'STRING', '[{\"name\": \"color\", \"type\": \"COLOR\"}]', '主机连接类型', '2023-12-26 23:23:08', '2024-04-24 16:37:48', '1', '1', 0);
|
||||
INSERT INTO `dict_key` VALUES (39, 'pathBookmarkType', 'STRING', '[]', '路径标签类型', '2024-04-24 13:43:12', '2024-04-24 13:43:12', '1', '1', 0);
|
||||
-- 字典值
|
||||
DELETE FROM `dict_value` WHERE id IN (7, 9, 18, 21, 176, 193) OR id >= 274;
|
||||
INSERT INTO `dict_value` VALUES (7, 5, 'systemMenuStatus', '1', '启用', '{\"color\": \"arcoblue\"}', 20, '2023-10-26 17:00:54', '2024-04-24 16:35:09', '1', '1', 0);
|
||||
INSERT INTO `dict_value` VALUES (9, 6, 'systemMenuVisible', '1', '显示', '{\"color\": \"arcoblue\"}', 20, '2023-10-27 00:25:30', '2024-04-24 16:35:05', '1', '1', 0);
|
||||
INSERT INTO `dict_value` VALUES (18, 9, 'systemUserStatus', '1', '启用', '{\"color\": \"arcoblue\"}', 20, '2023-10-27 12:13:17', '2024-04-24 16:35:00', '1', '1', 0);
|
||||
INSERT INTO `dict_value` VALUES (21, 10, 'systemRoleStatus', '1', '启用', '{\"color\": \"arcoblue\", \"status\": \"default\"}', 20, '2023-10-27 12:33:56', '2024-04-24 16:34:52', '1', '1', 0);
|
||||
INSERT INTO `dict_value` VALUES (176, 27, 'hostConnectType', 'SSH', 'SSH', '{\"color\": \"arcoblue\"}', 10, '2023-12-26 23:23:18', '2024-04-24 16:38:28', '1', '1', 0);
|
||||
INSERT INTO `dict_value` VALUES (193, 27, 'hostConnectType', 'SFTP', 'SFTP', '{\"color\": \"purple\"}', 20, '2024-02-04 18:23:10', '2024-04-24 16:38:22', '1', '1', 0);
|
||||
INSERT INTO `dict_value` VALUES (274, 39, 'pathBookmarkType', 'FILE', '文件', '{}', 10, '2024-04-24 13:43:28', '2024-04-24 13:43:28', '1', '1', 0);
|
||||
INSERT INTO `dict_value` VALUES (275, 39, 'pathBookmarkType', 'DIR', '文件夹', '{}', 20, '2024-04-24 13:43:39', '2024-04-24 13:43:39', '1', '1', 0);
|
||||
```
|
||||
|
||||
> sql 脚本 - 命令分组初始化
|
||||
|
||||
```sql
|
||||
-- 插入命令片段分组
|
||||
INSERT INTO `data_group` (`parent_id`, `type`, `user_id`, `name`, `sort`, `creator`, `updater`, `deleted`)
|
||||
SELECT 0, 'COMMAND_SNIPPET', user_id, name, id, creator, updater, deleted
|
||||
FROM command_snippet_group;
|
||||
|
||||
-- 需要命令分组 groupId
|
||||
UPDATE command_snippet s
|
||||
LEFT JOIN data_group g ON g.type = 'COMMAND_SNIPPET' AND g.sort = s.group_id
|
||||
SET s.group_id = g.id;
|
||||
|
||||
-- 删除命令片段分组表
|
||||
DROP TABLE IF EXISTS `command_snippet_group`;
|
||||
```
|
||||
|
||||
11
docs/update/v1.0.7.md
Normal file
11
docs/update/v1.0.7.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## v1.0.7
|
||||
|
||||
> sql 脚本 - DDL
|
||||
|
||||
```sql
|
||||
```
|
||||
|
||||
> sql 脚本 - DML
|
||||
|
||||
```sql
|
||||
```
|
||||
@@ -14,7 +14,7 @@
|
||||
<url>https://github.com/lijiahangmax/orion-ops-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>1.0.5</revision>
|
||||
<revision>1.0.6</revision>
|
||||
<spring.boot.version>2.7.17</spring.boot.version>
|
||||
<spring.boot.admin.version>2.7.15</spring.boot.admin.version>
|
||||
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>
|
||||
|
||||
@@ -14,7 +14,7 @@ public interface AppConst extends OrionConst {
|
||||
/**
|
||||
* 同 ${orion.version} 迭代时候需要手动更改
|
||||
*/
|
||||
String VERSION = "1.0.5";
|
||||
String VERSION = "1.0.6";
|
||||
|
||||
String ORION_OPS_PRO = "orion-ops-pro";
|
||||
|
||||
@@ -22,6 +22,6 @@ public interface AppConst extends OrionConst {
|
||||
|
||||
String GITEE = "https://gitee.com/lijiahangmax/orion-ops-pro";
|
||||
|
||||
String ISSUES = "https://gitee.com/lijiahangmax/orion-ops-pro/issues";
|
||||
String ISSUES = "https://github.com/lijiahangmax/orion-ops-pro/issues";
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ public class PathUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取应用路径
|
||||
*
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.orion.ops.framework.mybatis.core.generator.template.Table;
|
||||
import com.orion.ops.framework.mybatis.core.generator.template.Template;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 代码生成器
|
||||
@@ -33,7 +34,7 @@ public class CodeGenerators {
|
||||
// .enableProviderApi()
|
||||
// .disableUnitTest()
|
||||
// .cache("dict:keys", "字典配置项")
|
||||
// .expire(1, TimeUnit.DAYS)
|
||||
// .expire(8, TimeUnit.HOURS)
|
||||
// .vue("system", "dict-key")
|
||||
// .enableRowSelection()
|
||||
// .enableCardView()
|
||||
@@ -44,20 +45,15 @@ public class CodeGenerators {
|
||||
// .color("blue", "gray", "red", "green", "white")
|
||||
// .valueUseFields()
|
||||
// .build(),
|
||||
Template.create("exec_job", "计划任务", "exec")
|
||||
// Template.create("exec_template_host", "执行模板主机", "exec")
|
||||
// .disableUnitTest()
|
||||
// .vue("exec", "exec-template-host")
|
||||
// .build(),
|
||||
Template.create("path_bookmark", "路径标签", "path")
|
||||
.disableUnitTest()
|
||||
.vue("exec", "exec-job")
|
||||
.enableDrawerForm()
|
||||
.dict("execJobStatus", "status")
|
||||
.comment("计划任务状态")
|
||||
.field("execJobStatus")
|
||||
.fields("DISABLED", "ENABLED")
|
||||
.labels("禁用", "启用")
|
||||
.values(0, 1)
|
||||
.build(),
|
||||
Template.create("exec_job_host", "计划任务主机", "exec")
|
||||
.disableUnitTest()
|
||||
.vue("exec", "exec-job-host")
|
||||
.cache("path:bookmark:list:{}", "路径标签列表 ${userId}")
|
||||
.expire(8, TimeUnit.HOURS)
|
||||
.vue("host", "path-bookmark")
|
||||
.build(),
|
||||
};
|
||||
// jdbc 配置 - 使用配置文件
|
||||
|
||||
@@ -2,7 +2,10 @@ package com.orion.ops.framework.redis.configuration;
|
||||
|
||||
import com.orion.ops.framework.common.constant.AutoConfigureOrderConst;
|
||||
import com.orion.ops.framework.redis.configuration.config.RedissonConfig;
|
||||
import com.orion.ops.framework.redis.core.lock.RedisLocker;
|
||||
import com.orion.ops.framework.redis.core.utils.RedisLocks;
|
||||
import com.orion.ops.framework.redis.core.utils.RedisUtils;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
@@ -56,5 +59,16 @@ public class OrionRedisAutoConfiguration {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param redissonClient redissonClient
|
||||
* @return redis 分布式锁
|
||||
*/
|
||||
@Bean
|
||||
public RedisLocker redisLocker(RedissonClient redissonClient) {
|
||||
RedisLocker redisLocker = new RedisLocker(redissonClient);
|
||||
RedisLocks.setRedisLocker(redisLocker);
|
||||
return redisLocker;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.orion.ops.framework.redis.core.lock;
|
||||
|
||||
import com.orion.lang.utils.Exceptions;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* redis 分布式锁
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/25 16:42
|
||||
*/
|
||||
@Slf4j
|
||||
public class RedisLocker {
|
||||
|
||||
private final RedissonClient redissonClient;
|
||||
|
||||
public RedisLocker(RedissonClient redissonClient) {
|
||||
this.redissonClient = redissonClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取锁
|
||||
*
|
||||
* @param key key
|
||||
* @param run run
|
||||
* @return 是否获取到锁
|
||||
*/
|
||||
public boolean tryLock(String key, Runnable run) {
|
||||
// 获取锁
|
||||
RLock lock = redissonClient.getLock(key);
|
||||
// 未获取到直接返回
|
||||
if (!lock.tryLock()) {
|
||||
log.info("RedisLocks.tryLock failed {}", key);
|
||||
return false;
|
||||
}
|
||||
// 执行
|
||||
try {
|
||||
run.run();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取锁
|
||||
*
|
||||
* @param key key
|
||||
* @param call call
|
||||
* @param <T> T
|
||||
* @return 执行结果
|
||||
*/
|
||||
public <T> T tryLock(String key, Supplier<T> call) {
|
||||
// 获取锁
|
||||
RLock lock = redissonClient.getLock(key);
|
||||
// 未获取到直接返回
|
||||
if (!lock.tryLock()) {
|
||||
log.info("RedisLocks.tryLock failed {}", key);
|
||||
throw Exceptions.lock();
|
||||
}
|
||||
// 执行
|
||||
try {
|
||||
return call.get();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.orion.ops.framework.redis.core.utils;
|
||||
|
||||
import com.orion.lang.utils.Exceptions;
|
||||
import com.orion.ops.framework.redis.core.lock.RedisLocker;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* redis 分布式锁工具类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/25 16:42
|
||||
*/
|
||||
@Slf4j
|
||||
public class RedisLocks {
|
||||
|
||||
private static RedisLocker redisLocker;
|
||||
|
||||
private RedisLocks() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取锁
|
||||
*
|
||||
* @param key key
|
||||
* @param run run
|
||||
* @return 是否获取到锁
|
||||
*/
|
||||
public static boolean tryLock(String key, Runnable run) {
|
||||
return redisLocker.tryLock(key, run);
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取锁
|
||||
*
|
||||
* @param key key
|
||||
* @param call call
|
||||
* @param <T> T
|
||||
* @return 执行结果
|
||||
*/
|
||||
public static <T> T tryLock(String key, Supplier<T> call) {
|
||||
return redisLocker.tryLock(key, call);
|
||||
}
|
||||
|
||||
public static void setRedisLocker(RedisLocker redisLocker) {
|
||||
if (RedisLocks.redisLocker != null) {
|
||||
// unmodified
|
||||
throw Exceptions.state();
|
||||
}
|
||||
RedisLocks.redisLocker = redisLocker;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -177,6 +177,14 @@ app:
|
||||
upload-present-backup: true
|
||||
# 备份文件名称
|
||||
backup-file-name: bk_${fileName}_${timestamp}
|
||||
# 执行日志
|
||||
exec-log:
|
||||
# 是否拼接 ansi 执行状态日志
|
||||
append-ansi: true
|
||||
# 自动清理执行文件
|
||||
auto-clear: true
|
||||
# 保留周期 (天)
|
||||
keep-period: 60
|
||||
|
||||
# orion framework config
|
||||
orion:
|
||||
|
||||
@@ -66,6 +66,15 @@ public class ExecTemplateController {
|
||||
return execTemplateService.getExecTemplateById(id);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/get-with-authorized")
|
||||
@Operation(summary = "查询执行模板 (查询认证的主机)")
|
||||
@Parameter(name = "id", description = "id", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('asset:exec-template:query')")
|
||||
public ExecTemplateVO getExecTemplateWithAuthorized(@RequestParam("id") Long id) {
|
||||
return execTemplateService.getExecTemplateWithAuthorized(id);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@PostMapping("/query")
|
||||
@Operation(summary = "分页查询执行模板")
|
||||
@@ -83,6 +92,5 @@ public class ExecTemplateController {
|
||||
return execTemplateService.deleteExecTemplateById(id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
### 创建路径标签
|
||||
POST {{baseUrl}}/asset/path-bookmark/create
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"name": "",
|
||||
"path": ""
|
||||
}
|
||||
|
||||
|
||||
### 更新路径标签
|
||||
PUT {{baseUrl}}/asset/path-bookmark/update
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"id": "",
|
||||
"name": "",
|
||||
"path": ""
|
||||
}
|
||||
|
||||
|
||||
### 查询全部路径标签
|
||||
GET {{baseUrl}}/asset/path-bookmark/list
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 删除路径标签
|
||||
DELETE {{baseUrl}}/asset/path-bookmark/delete?id=1
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
###
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.orion.ops.module.asset.controller;
|
||||
|
||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkWrapperVO;
|
||||
import com.orion.ops.module.asset.service.PathBookmarkService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 路径标签 api
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Tag(name = "asset - 路径标签服务")
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestWrapper
|
||||
@RestController
|
||||
@RequestMapping("/asset/path-bookmark")
|
||||
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||
public class PathBookmarkController {
|
||||
|
||||
@Resource
|
||||
private PathBookmarkService pathBookmarkService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建路径标签")
|
||||
public Long createPathBookmark(@Validated @RequestBody PathBookmarkCreateRequest request) {
|
||||
return pathBookmarkService.createPathBookmark(request);
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新路径标签")
|
||||
public Integer updatePathBookmark(@Validated @RequestBody PathBookmarkUpdateRequest request) {
|
||||
return pathBookmarkService.updatePathBookmarkById(request);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "查询全部路径标签")
|
||||
public PathBookmarkWrapperVO getPathBookmarkList() {
|
||||
return pathBookmarkService.getPathBookmark();
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除路径标签")
|
||||
@Parameter(name = "id", description = "id", required = true)
|
||||
public Integer deletePathBookmark(@RequestParam("id") Long id) {
|
||||
return pathBookmarkService.deletePathBookmarkById(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
### 创建路径标签分组
|
||||
POST {{baseUrl}}/asset/path-bookmark-group/create
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"name": ""
|
||||
}
|
||||
|
||||
|
||||
### 更新路径标签分组
|
||||
PUT {{baseUrl}}/asset/path-bookmark-group/update
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
{
|
||||
"id": "",
|
||||
"name": ""
|
||||
}
|
||||
|
||||
|
||||
### 查询全部路径标签分组
|
||||
GET {{baseUrl}}/asset/path-bookmark-group/list
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 删除路径标签分组
|
||||
DELETE {{baseUrl}}/asset/path-bookmark-group/delete?id=1
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
###
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.orion.ops.module.asset.controller;
|
||||
|
||||
import com.orion.ops.framework.common.validator.group.Id;
|
||||
import com.orion.ops.framework.log.core.annotation.IgnoreLog;
|
||||
import com.orion.ops.framework.log.core.enums.IgnoreLogMode;
|
||||
import com.orion.ops.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupDeleteRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||
import com.orion.ops.module.asset.service.PathBookmarkGroupService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 路径标签分组 api
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
@Tag(name = "asset - 路径标签分组服务")
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestWrapper
|
||||
@RestController
|
||||
@RequestMapping("/asset/path-bookmark-group")
|
||||
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||
public class PathBookmarkGroupController {
|
||||
|
||||
@Resource
|
||||
private PathBookmarkGroupService pathBookmarkGroupService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建路径标签分组")
|
||||
public Long createPathBookmarkGroup(@Validated @RequestBody PathBookmarkGroupCreateRequest request) {
|
||||
return pathBookmarkGroupService.createPathBookmarkGroup(request);
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新路径标签分组")
|
||||
public Integer updatePathBookmarkGroup(@Validated @RequestBody PathBookmarkGroupUpdateRequest request) {
|
||||
return pathBookmarkGroupService.updatePathBookmarkGroupById(request);
|
||||
}
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "查询全部路径标签分组")
|
||||
public List<PathBookmarkGroupVO> getPathBookmarkGroupList() {
|
||||
return pathBookmarkGroupService.getPathBookmarkGroupList();
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除路径标签分组")
|
||||
public Integer deletePathBookmarkGroup(@Validated(Id.class) @RequestBody PathBookmarkGroupDeleteRequest request) {
|
||||
return pathBookmarkGroupService.deletePathBookmarkGroup(request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.orion.ops.module.asset.convert;
|
||||
|
||||
import com.orion.ops.module.asset.entity.domain.CommandSnippetGroupDO;
|
||||
import com.orion.ops.module.asset.entity.dto.CommandSnippetGroupCacheDTO;
|
||||
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.CommandSnippetGroupVO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 命令片段分组 内部对象转换器
|
||||
*
|
||||
@@ -22,16 +21,10 @@ public interface CommandSnippetGroupConvert {
|
||||
|
||||
CommandSnippetGroupConvert MAPPER = Mappers.getMapper(CommandSnippetGroupConvert.class);
|
||||
|
||||
CommandSnippetGroupDO to(CommandSnippetGroupCreateRequest request);
|
||||
DataGroupCreateDTO to(CommandSnippetGroupCreateRequest request);
|
||||
|
||||
CommandSnippetGroupDO to(CommandSnippetGroupUpdateRequest request);
|
||||
DataGroupRenameDTO to(CommandSnippetGroupUpdateRequest request);
|
||||
|
||||
CommandSnippetGroupVO to(CommandSnippetGroupDO domain);
|
||||
|
||||
List<CommandSnippetGroupVO> to(List<CommandSnippetGroupDO> list);
|
||||
|
||||
CommandSnippetGroupVO to(CommandSnippetGroupCacheDTO cache);
|
||||
|
||||
CommandSnippetGroupCacheDTO toCache(CommandSnippetGroupDO domain);
|
||||
CommandSnippetGroupVO to(DataGroupDTO domain);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.orion.ops.module.asset.convert;
|
||||
|
||||
import com.orion.ops.module.asset.entity.domain.PathBookmarkDO;
|
||||
import com.orion.ops.module.asset.entity.dto.PathBookmarkCacheDTO;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 路径标签 内部对象转换器
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Mapper
|
||||
public interface PathBookmarkConvert {
|
||||
|
||||
PathBookmarkConvert MAPPER = Mappers.getMapper(PathBookmarkConvert.class);
|
||||
|
||||
PathBookmarkDO to(PathBookmarkCreateRequest request);
|
||||
|
||||
PathBookmarkDO to(PathBookmarkUpdateRequest request);
|
||||
|
||||
PathBookmarkVO to(PathBookmarkDO domain);
|
||||
|
||||
List<PathBookmarkVO> to(List<PathBookmarkDO> list);
|
||||
|
||||
PathBookmarkVO to(PathBookmarkCacheDTO cache);
|
||||
|
||||
PathBookmarkCacheDTO toCache(PathBookmarkDO domain);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.orion.ops.module.asset.convert;
|
||||
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 路径标签分组 内部对象转换器
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
@Mapper
|
||||
public interface PathBookmarkGroupConvert {
|
||||
|
||||
PathBookmarkGroupConvert MAPPER = Mappers.getMapper(PathBookmarkGroupConvert.class);
|
||||
|
||||
DataGroupCreateDTO to(PathBookmarkGroupCreateRequest request);
|
||||
|
||||
DataGroupRenameDTO to(PathBookmarkGroupUpdateRequest request);
|
||||
|
||||
PathBookmarkGroupVO to(DataGroupDTO domain);
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.orion.ops.module.asset.dao;
|
||||
|
||||
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
|
||||
import com.orion.ops.module.asset.entity.domain.CommandSnippetGroupDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 命令片段分组 Mapper 接口
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
@Mapper
|
||||
public interface CommandSnippetGroupDAO extends IMapper<CommandSnippetGroupDO> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.orion.ops.module.asset.dao;
|
||||
|
||||
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecTemplateHostDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 执行模板主机 Mapper 接口
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-22 12:13
|
||||
*/
|
||||
@Mapper
|
||||
public interface ExecTemplateHostDAO extends IMapper<ExecTemplateHostDO> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.orion.ops.module.asset.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
|
||||
import com.orion.ops.module.asset.entity.domain.PathBookmarkDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 路径标签 Mapper 接口
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Mapper
|
||||
public interface PathBookmarkDAO extends IMapper<PathBookmarkDO> {
|
||||
|
||||
/**
|
||||
* 设置 groupId 为 null
|
||||
*
|
||||
* @param groupId groupId
|
||||
* @return effect
|
||||
*/
|
||||
default int setGroupIdWithNull(Long groupId) {
|
||||
LambdaUpdateWrapper<PathBookmarkDO> wrapper = Wrappers.<PathBookmarkDO>lambdaUpdate()
|
||||
.set(PathBookmarkDO::getGroupId, null)
|
||||
.eq(PathBookmarkDO::getGroupId, groupId);
|
||||
return this.update(null, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 groupId 删除
|
||||
*
|
||||
* @param groupId groupId
|
||||
* @return effect
|
||||
*/
|
||||
default int deleteByGroupId(Long groupId) {
|
||||
LambdaQueryWrapper<PathBookmarkDO> wrapper = this.lambda()
|
||||
.eq(PathBookmarkDO::getGroupId, groupId);
|
||||
return this.delete(wrapper);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import com.orion.lang.define.cache.key.CacheKeyBuilder;
|
||||
import com.orion.lang.define.cache.key.CacheKeyDefine;
|
||||
import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
|
||||
import com.orion.ops.module.asset.entity.dto.CommandSnippetCacheDTO;
|
||||
import com.orion.ops.module.asset.entity.dto.CommandSnippetGroupCacheDTO;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -22,15 +21,7 @@ public interface CommandSnippetCacheKeyDefine {
|
||||
.desc("命令片段列表 ${userId}")
|
||||
.type(CommandSnippetCacheDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine SNIPPET_GROUP = new CacheKeyBuilder()
|
||||
.key("command:snippet:group:{}")
|
||||
.desc("命令片段分组 ${userId}")
|
||||
.type(CommandSnippetGroupCacheDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public interface HostCacheKeyDefine {
|
||||
.desc("主机列表")
|
||||
.type(HostCacheDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine HOST_KEY = new CacheKeyBuilder()
|
||||
@@ -31,7 +31,7 @@ public interface HostCacheKeyDefine {
|
||||
.desc("主机秘钥列表")
|
||||
.type(HostKeyCacheDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine HOST_IDENTITY = new CacheKeyBuilder()
|
||||
@@ -39,7 +39,7 @@ public interface HostCacheKeyDefine {
|
||||
.desc("主机身份列表")
|
||||
.type(HostIdentityCacheDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.orion.ops.module.asset.define.cache;
|
||||
|
||||
import com.orion.lang.define.cache.key.CacheKeyBuilder;
|
||||
import com.orion.lang.define.cache.key.CacheKeyDefine;
|
||||
import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
|
||||
import com.orion.ops.module.asset.entity.dto.PathBookmarkCacheDTO;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 路径标签缓存 key
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
public interface PathBookmarkCacheKeyDefine {
|
||||
|
||||
CacheKeyDefine PATH_BOOKMARK = new CacheKeyBuilder()
|
||||
.key("path:bookmark:list:{}")
|
||||
.desc("路径标签列表 ${userId}")
|
||||
.type(PathBookmarkCacheDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.orion.ops.module.asset.define.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 应用执行日志配置
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/25 13:36
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "app.exec-log")
|
||||
public class AppExecLogConfig {
|
||||
|
||||
/**
|
||||
* 是否拼接 ansi 执行状态日志
|
||||
*/
|
||||
private Boolean appendAnsi;
|
||||
|
||||
/**
|
||||
* 自动清理执行文件
|
||||
*/
|
||||
private Boolean autoClear;
|
||||
|
||||
/**
|
||||
* 保留周期 (天)
|
||||
*/
|
||||
private Integer keepPeriod;
|
||||
|
||||
public AppExecLogConfig() {
|
||||
this.appendAnsi = true;
|
||||
this.autoClear = true;
|
||||
this.keepPeriod = 60;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.orion.ops.module.asset.entity.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.orion.ops.framework.mybatis.core.domain.BaseDO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 执行模板主机 实体对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-22 12:13
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName(value = "exec_template_host", autoResultMap = true)
|
||||
@Schema(name = "ExecTemplateHostDO", description = "执行模板主机 实体对象")
|
||||
public class ExecTemplateHostDO extends BaseDO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "id")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "模板id")
|
||||
@TableField("template_id")
|
||||
private Long templateId;
|
||||
|
||||
@Schema(description = "主机id")
|
||||
@TableField("host_id")
|
||||
private Long hostId;
|
||||
|
||||
}
|
||||
@@ -9,20 +9,20 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* 命令片段分组 实体对象
|
||||
* 路径标签 实体对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName(value = "command_snippet_group", autoResultMap = true)
|
||||
@Schema(name = "CommandSnippetGroupDO", description = "命令片段分组 实体对象")
|
||||
public class CommandSnippetGroupDO extends BaseDO {
|
||||
@TableName(value = "path_bookmark", autoResultMap = true)
|
||||
@Schema(name = "PathBookmarkDO", description = "路径标签 实体对象")
|
||||
public class PathBookmarkDO extends BaseDO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -34,8 +34,20 @@ public class CommandSnippetGroupDO extends BaseDO {
|
||||
@TableField("user_id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "分组名称")
|
||||
@Schema(description = "分组id")
|
||||
@TableField("group_id")
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "名称")
|
||||
@TableField("name")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "类型")
|
||||
@TableField("type")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "路径")
|
||||
@TableField("path")
|
||||
private String path;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.orion.ops.module.asset.entity.dto;
|
||||
|
||||
import com.orion.lang.define.cache.key.model.LongCacheIdModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 路径标签 缓存对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkCacheDTO", description = "路径标签 缓存对象")
|
||||
public class PathBookmarkCacheDTO implements LongCacheIdModel, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分组id")
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "路径")
|
||||
private String path;
|
||||
|
||||
}
|
||||
@@ -26,14 +26,14 @@ public class CommandSnippetCreateRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "分组id")
|
||||
private Long groupId;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 64)
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "分组id")
|
||||
private Long groupId;
|
||||
|
||||
@NotBlank
|
||||
@Schema(description = "代码片段")
|
||||
private String command;
|
||||
|
||||
@@ -12,6 +12,7 @@ import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 执行模板 创建请求对象
|
||||
@@ -51,4 +52,7 @@ public class ExecTemplateCreateRequest implements Serializable {
|
||||
@Schema(description = "参数定义")
|
||||
private String parameterSchema;
|
||||
|
||||
@Schema(description = "模板主机")
|
||||
private List<Long> hostIdList;
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 执行模板 更新请求对象
|
||||
@@ -55,4 +56,7 @@ public class ExecTemplateUpdateRequest implements Serializable {
|
||||
@Schema(description = "参数定义")
|
||||
private String parameterSchema;
|
||||
|
||||
@Schema(description = "模板主机")
|
||||
private List<Long> hostIdList;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.orion.ops.module.asset.entity.request.path;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 路径标签 创建请求对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkCreateRequest", description = "路径标签 创建请求对象")
|
||||
public class PathBookmarkCreateRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "分组id")
|
||||
private Long groupId;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 64)
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 4)
|
||||
@Schema(description = "类型")
|
||||
private String type;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 1024)
|
||||
@Schema(description = "路径")
|
||||
private String path;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.orion.ops.module.asset.entity.request.path;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 路径标签分组 创建请求对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkGroupCreateRequest", description = "路径标签分组 创建请求对象")
|
||||
public class PathBookmarkGroupCreateRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 64)
|
||||
@Schema(description = "分组名称")
|
||||
private String name;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.orion.ops.module.asset.entity.request.path;
|
||||
|
||||
import com.orion.ops.framework.common.validator.group.Id;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 路径标签分组 删除请求对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkGroupDeleteRequest", description = "路径标签分组 删除请求对象")
|
||||
public class PathBookmarkGroupDeleteRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotNull(groups = Id.class)
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@NotNull
|
||||
@Schema(description = "是否删除组内数据")
|
||||
private Boolean deleteItem;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.orion.ops.module.asset.entity.request.path;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 路径标签分组 更新请求对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkGroupUpdateRequest", description = "路径标签分组 更新请求对象")
|
||||
public class PathBookmarkGroupUpdateRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotNull
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 64)
|
||||
@Schema(description = "分组名称")
|
||||
private String name;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.orion.ops.module.asset.entity.request.path;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 路径标签 更新请求对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkUpdateRequest", description = "路径标签 更新请求对象")
|
||||
public class PathBookmarkUpdateRequest implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotNull
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分组id")
|
||||
private Long groupId;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 64)
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 4)
|
||||
@Schema(description = "类型")
|
||||
private String type;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 1024)
|
||||
@Schema(description = "路径")
|
||||
private String path;
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 执行模板 视图响应对象
|
||||
@@ -55,4 +56,7 @@ public class ExecTemplateVO implements Serializable {
|
||||
@Schema(description = "修改人")
|
||||
private String updater;
|
||||
|
||||
@Schema(description = "模板主机")
|
||||
private Set<Long> hostIdList;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.ops.module.asset.entity.dto;
|
||||
package com.orion.ops.module.asset.entity.vo;
|
||||
|
||||
import com.orion.lang.define.cache.key.model.LongCacheIdModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@@ -8,9 +7,10 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 命令片段分组 缓存对象
|
||||
* 路径标签分组 视图响应对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
@@ -20,8 +20,8 @@ import java.io.Serializable;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "CommandSnippetGroupCacheDTO", description = "命令片段分组 缓存对象")
|
||||
public class CommandSnippetGroupCacheDTO implements LongCacheIdModel, Serializable {
|
||||
@Schema(name = "PathBookmarkGroupVO", description = "路径标签分组 视图响应对象")
|
||||
public class PathBookmarkGroupVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -31,4 +31,7 @@ public class CommandSnippetGroupCacheDTO implements LongCacheIdModel, Serializab
|
||||
@Schema(description = "分组名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "路径标签列表")
|
||||
private List<PathBookmarkVO> items;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.orion.ops.module.asset.entity.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 路径标签 视图响应对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkVO", description = "路径标签 视图响应对象")
|
||||
public class PathBookmarkVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "分组id")
|
||||
private Long groupId;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "路径")
|
||||
private String path;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.orion.ops.module.asset.entity.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 路径标签组合 视图响应对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/1/24 17:30
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "PathBookmarkWrapperVO", description = "路径标签组合 视图响应对象")
|
||||
public class PathBookmarkWrapperVO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "分组")
|
||||
private List<PathBookmarkGroupVO> groups;
|
||||
|
||||
@Schema(description = "未分组的路径标签")
|
||||
private List<PathBookmarkVO> ungroupedItems;
|
||||
|
||||
}
|
||||
@@ -25,13 +25,25 @@ public class ExecCommandDTO {
|
||||
@Schema(description = "hostId")
|
||||
private Long logId;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "执行描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "执行序列")
|
||||
private Integer execSeq;
|
||||
|
||||
@Schema(description = "超时时间")
|
||||
private Integer timeout;
|
||||
|
||||
@Schema(description = "是否使用脚本执行")
|
||||
private Boolean scriptExec;
|
||||
|
||||
@Schema(description = "主机")
|
||||
@Schema(description = "执行主机")
|
||||
private List<ExecCommandHostDTO> hosts;
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,12 @@ public class ExecCommandHostDTO {
|
||||
@Schema(description = "hostId")
|
||||
private Long hostId;
|
||||
|
||||
@Schema(description = "主机名称")
|
||||
private String hostName;
|
||||
|
||||
@Schema(description = "主机地址")
|
||||
private String hostAddress;
|
||||
|
||||
@Schema(description = "日志文件路径")
|
||||
private String logPath;
|
||||
|
||||
@@ -35,6 +41,9 @@ public class ExecCommandHostDTO {
|
||||
@Schema(description = "执行命令")
|
||||
private String command;
|
||||
|
||||
@Schema(description = "主机用户")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "命令编码")
|
||||
private String charset;
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ import com.orion.lang.exception.ConnectionRuntimeException;
|
||||
import com.orion.lang.exception.SftpException;
|
||||
import com.orion.lang.exception.argument.InvalidArgumentException;
|
||||
import com.orion.lang.support.timeout.TimeoutChecker;
|
||||
import com.orion.lang.support.timeout.TimeoutEndpoint;
|
||||
import com.orion.lang.utils.Booleans;
|
||||
import com.orion.lang.utils.Exceptions;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.ansi.AnsiAppender;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.net.host.SessionStore;
|
||||
import com.orion.net.host.sftp.SftpExecutor;
|
||||
@@ -31,14 +33,14 @@ import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 命令执行器
|
||||
* 命令执行器 基类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/12 11:30
|
||||
* @since 2024/4/25 18:35
|
||||
*/
|
||||
@Slf4j
|
||||
public class ExecCommandHandler implements IExecCommandHandler {
|
||||
public abstract class BaseExecCommandHandler implements IExecCommandHandler {
|
||||
|
||||
private final FileClient fileClient = SpringHolder.getBean("logsFileClient");
|
||||
|
||||
@@ -48,32 +50,35 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
|
||||
private final ExecHostLogDAO execHostLogDAO = SpringHolder.getBean(ExecHostLogDAO.class);
|
||||
|
||||
private final ExecCommandDTO execCommand;
|
||||
protected final ExecCommandDTO execCommand;
|
||||
|
||||
private final ExecCommandHostDTO execHostCommand;
|
||||
protected final ExecCommandHostDTO execHostCommand;
|
||||
|
||||
private final TimeoutChecker timeoutChecker;
|
||||
private final TimeoutChecker<TimeoutEndpoint> timeoutChecker;
|
||||
|
||||
@Getter
|
||||
private ExecHostStatusEnum status;
|
||||
protected ExecHostStatusEnum status;
|
||||
|
||||
protected ExecHostLogDO updateRecord;
|
||||
|
||||
private OutputStream logOutputStream;
|
||||
|
||||
private SessionStore sessionStore;
|
||||
|
||||
private CommandExecutor executor;
|
||||
|
||||
private OutputStream logOutputStream;
|
||||
|
||||
private volatile boolean closed;
|
||||
|
||||
private volatile boolean interrupted;
|
||||
|
||||
public ExecCommandHandler(ExecCommandDTO execCommand,
|
||||
ExecCommandHostDTO execHostCommand,
|
||||
TimeoutChecker timeoutChecker) {
|
||||
public BaseExecCommandHandler(ExecCommandDTO execCommand,
|
||||
ExecCommandHostDTO execHostCommand,
|
||||
TimeoutChecker<TimeoutEndpoint> timeoutChecker) {
|
||||
this.status = ExecHostStatusEnum.WAITING;
|
||||
this.execCommand = execCommand;
|
||||
this.execHostCommand = execHostCommand;
|
||||
this.timeoutChecker = timeoutChecker;
|
||||
this.updateRecord = new ExecHostLogDO();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -90,23 +95,25 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
} catch (Exception e) {
|
||||
log.error("ExecCommandHandler run error id: {}", id, e);
|
||||
ex = e;
|
||||
}
|
||||
// 执行完成回调
|
||||
try {
|
||||
// 回调
|
||||
this.onFinishCallback(ex);
|
||||
} finally {
|
||||
// 释放资源
|
||||
Streams.close(this);
|
||||
}
|
||||
// 执行回调
|
||||
if (this.interrupted) {
|
||||
// 中断执行
|
||||
this.updateStatus(ExecHostStatusEnum.INTERRUPTED, null);
|
||||
} else if (ex != null) {
|
||||
// 执行失败
|
||||
this.updateStatus(ExecHostStatusEnum.FAILED, ex);
|
||||
} else if (executor.isTimeout()) {
|
||||
// 更新执行超时
|
||||
this.updateStatus(ExecHostStatusEnum.TIMEOUT, null);
|
||||
} else {
|
||||
// 更新执行完成
|
||||
this.updateStatus(ExecHostStatusEnum.COMPLETED, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化日志输出流
|
||||
*
|
||||
* @throws Exception Exception
|
||||
*/
|
||||
protected void initLogOutputStream() throws Exception {
|
||||
// 打开日志流
|
||||
this.logOutputStream = fileClient.getContentOutputStream(execHostCommand.getLogPath());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,9 +121,9 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
*
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
private void execCommand() throws Exception {
|
||||
// 打开日志流
|
||||
this.logOutputStream = fileClient.getContentOutputStream(execHostCommand.getLogPath());
|
||||
protected void execCommand() throws Exception {
|
||||
// 初始化日志
|
||||
this.initLogOutputStream();
|
||||
// 打开会话
|
||||
this.sessionStore = hostTerminalService.openSessionStore(execHostCommand.getHostId());
|
||||
if (Booleans.isTrue(execCommand.getScriptExec())) {
|
||||
@@ -140,7 +147,7 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
/**
|
||||
* 上传脚本文件
|
||||
*/
|
||||
private void uploadScriptFile() {
|
||||
protected void uploadScriptFile() {
|
||||
SftpExecutor sftpExecutor = null;
|
||||
try {
|
||||
// 打开 sftp
|
||||
@@ -165,6 +172,42 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行完成回调
|
||||
*
|
||||
* @param e e
|
||||
*/
|
||||
protected void onFinishCallback(Exception e) {
|
||||
// 执行回调
|
||||
if (this.interrupted) {
|
||||
// 中断执行
|
||||
this.updateStatus(ExecHostStatusEnum.INTERRUPTED, null);
|
||||
} else if (e != null) {
|
||||
// 执行失败
|
||||
this.updateStatus(ExecHostStatusEnum.FAILED, e);
|
||||
} else if (executor.isTimeout()) {
|
||||
// 更新执行超时
|
||||
this.updateStatus(ExecHostStatusEnum.TIMEOUT, null);
|
||||
} else {
|
||||
// 更新执行完成
|
||||
this.updateStatus(ExecHostStatusEnum.COMPLETED, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接日志
|
||||
*
|
||||
* @param appender appender
|
||||
*/
|
||||
protected void appendLog(AnsiAppender appender) {
|
||||
try {
|
||||
logOutputStream.write(Strings.bytes(appender.toString()));
|
||||
logOutputStream.flush();
|
||||
} catch (Exception e) {
|
||||
log.error("BaseExecCommandHandler.appendLog error", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
*
|
||||
@@ -175,30 +218,29 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
this.status = status;
|
||||
Long id = execHostCommand.getHostLogId();
|
||||
String statusName = status.name();
|
||||
log.info("ExecCommandHandler.updateStatus start id: {}, status: {}", id, statusName);
|
||||
ExecHostLogDO update = new ExecHostLogDO();
|
||||
update.setId(id);
|
||||
update.setStatus(statusName);
|
||||
log.info("BaseExecCommandHandler.updateStatus start id: {}, status: {}", id, statusName);
|
||||
updateRecord.setId(id);
|
||||
updateRecord.setStatus(statusName);
|
||||
if (ExecHostStatusEnum.RUNNING.equals(status)) {
|
||||
// 运行中
|
||||
update.setStartTime(new Date());
|
||||
updateRecord.setStartTime(new Date());
|
||||
} else if (ExecHostStatusEnum.COMPLETED.equals(status)) {
|
||||
// 完成
|
||||
update.setFinishTime(new Date());
|
||||
update.setExitStatus(executor.getExitCode());
|
||||
updateRecord.setFinishTime(new Date());
|
||||
updateRecord.setExitStatus(executor.getExitCode());
|
||||
} else if (ExecHostStatusEnum.FAILED.equals(status)) {
|
||||
// 失败
|
||||
update.setFinishTime(new Date());
|
||||
update.setErrorMessage(this.getErrorMessage(ex));
|
||||
updateRecord.setFinishTime(new Date());
|
||||
updateRecord.setErrorMessage(this.getErrorMessage(ex));
|
||||
} else if (ExecHostStatusEnum.TIMEOUT.equals(status)) {
|
||||
// 超时
|
||||
update.setFinishTime(new Date());
|
||||
updateRecord.setFinishTime(new Date());
|
||||
} else if (ExecHostStatusEnum.INTERRUPTED.equals(status)) {
|
||||
// 中断
|
||||
update.setFinishTime(new Date());
|
||||
updateRecord.setFinishTime(new Date());
|
||||
}
|
||||
int effect = execHostLogDAO.updateById(update);
|
||||
log.info("ExecCommandHandler.updateStatus finish id: {}, effect: {}", id, effect);
|
||||
int effect = execHostLogDAO.updateById(updateRecord);
|
||||
log.info("BaseExecCommandHandler.updateStatus finish id: {}, effect: {}", id, effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,20 +249,21 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interrupted() {
|
||||
log.info("ExecCommandHandler.interrupted id: {}, interrupted: {}, closed: {}",
|
||||
public void interrupt() {
|
||||
log.info("BaseExecCommandHandler.interrupt id: {}, interrupted: {}, closed: {}",
|
||||
execHostCommand.getHostLogId(), interrupted, closed);
|
||||
if (this.interrupted || this.closed) {
|
||||
return;
|
||||
}
|
||||
// 关闭
|
||||
this.interrupted = true;
|
||||
this.close();
|
||||
Streams.close(executor);
|
||||
Streams.close(sessionStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
log.info("ExecCommandHandler.closed id: {}, closed: {}",
|
||||
log.info("BaseExecCommandHandler.closed id: {}, closed: {}",
|
||||
execHostCommand.getHostLogId(), closed);
|
||||
if (this.closed) {
|
||||
return;
|
||||
@@ -238,7 +281,7 @@ public class ExecCommandHandler implements IExecCommandHandler {
|
||||
* @param ex ex
|
||||
* @return errorMessage
|
||||
*/
|
||||
private String getErrorMessage(Exception ex) {
|
||||
protected String getErrorMessage(Exception ex) {
|
||||
String message;
|
||||
if (ex instanceof InvalidArgumentException) {
|
||||
message = ex.getMessage();
|
||||
@@ -0,0 +1,177 @@
|
||||
package com.orion.ops.module.asset.handler.host.exec.command.handler;
|
||||
|
||||
import com.orion.lang.support.timeout.TimeoutChecker;
|
||||
import com.orion.lang.support.timeout.TimeoutEndpoint;
|
||||
import com.orion.lang.utils.Booleans;
|
||||
import com.orion.lang.utils.ansi.AnsiAppender;
|
||||
import com.orion.lang.utils.ansi.style.AnsiFont;
|
||||
import com.orion.lang.utils.ansi.style.color.AnsiForeground;
|
||||
import com.orion.lang.utils.time.Dates;
|
||||
import com.orion.net.host.ssh.ExitCode;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.module.asset.enums.ExecHostStatusEnum;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
|
||||
/**
|
||||
* 命令执行器 ansi 日志输出
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/25 18:19
|
||||
*/
|
||||
public class ExecCommandAnsiHandler extends BaseExecCommandHandler {
|
||||
|
||||
public ExecCommandAnsiHandler(ExecCommandDTO execCommand, ExecCommandHostDTO execHostCommand, TimeoutChecker<TimeoutEndpoint> timeoutChecker) {
|
||||
super(execCommand, execHostCommand, timeoutChecker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initLogOutputStream() throws Exception {
|
||||
super.initLogOutputStream();
|
||||
// 拼接启动日志
|
||||
AnsiAppender appender = AnsiAppender.create()
|
||||
.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 准备执行命令 ")
|
||||
.append(Dates.current())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行记录: ")
|
||||
.append(execCommand.getLogId())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行描述: ")
|
||||
.append(execCommand.getDescription())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行用户: ")
|
||||
.append(execCommand.getUsername());
|
||||
// 非系统用户执行添加 userId
|
||||
if (Const.SYSTEM_USER_ID.equals(execCommand.getUserId())) {
|
||||
appender.newLine();
|
||||
} else {
|
||||
appender.append(" (")
|
||||
.append(execCommand.getUserId())
|
||||
.append(")")
|
||||
.newLine();
|
||||
}
|
||||
// 执行序列
|
||||
if (execCommand.getExecSeq() != null) {
|
||||
appender.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行序列: ")
|
||||
.append('#')
|
||||
.append(execCommand.getExecSeq())
|
||||
.newLine();
|
||||
}
|
||||
appender.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行主机: ")
|
||||
.append(execHostCommand.getHostName())
|
||||
.append(" (")
|
||||
.append(execHostCommand.getHostId())
|
||||
.append(")")
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "主机地址: ")
|
||||
.append(execHostCommand.getHostAddress())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "超时时间: ")
|
||||
.append(execCommand.getTimeout())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "脚本执行: ")
|
||||
.append(execCommand.getScriptExec())
|
||||
.newLine()
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 执行命令 ")
|
||||
.newLine()
|
||||
.append(execHostCommand.getCommand())
|
||||
.newLine()
|
||||
.newLine();
|
||||
// 非脚本执行拼接开始执行日志
|
||||
if (!Booleans.isTrue(execCommand.getScriptExec())) {
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 开始执行命令 ")
|
||||
.append(Dates.current())
|
||||
.newLine();
|
||||
}
|
||||
this.appendLog(appender);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void uploadScriptFile() {
|
||||
try {
|
||||
// 拼接上传日志
|
||||
AnsiAppender startAppender = AnsiAppender.create()
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 准备上传脚本 ")
|
||||
.append(Dates.current())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "文件路径: ")
|
||||
.append(execHostCommand.getScriptPath())
|
||||
.newLine();
|
||||
this.appendLog(startAppender);
|
||||
// 上传脚本文件
|
||||
super.uploadScriptFile();
|
||||
// 拼接完成日志
|
||||
AnsiAppender finishAppender = AnsiAppender.create()
|
||||
.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "< 脚本上传成功 ")
|
||||
.append(Dates.current())
|
||||
.newLine()
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 开始执行脚本 ")
|
||||
.append(Dates.current())
|
||||
.newLine();
|
||||
this.appendLog(finishAppender);
|
||||
} catch (Exception e) {
|
||||
// 拼接失败日志
|
||||
AnsiAppender errorAppender = AnsiAppender.create()
|
||||
.append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), "< 脚本上传失败 ")
|
||||
.append(Dates.current())
|
||||
.newLine();
|
||||
this.appendLog(errorAppender);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishCallback(Exception e) {
|
||||
// 执行完成回调
|
||||
super.onFinishCallback(e);
|
||||
// 拼接日志
|
||||
AnsiAppender appender = AnsiAppender.create()
|
||||
.newLine();
|
||||
if (this.status == ExecHostStatusEnum.INTERRUPTED) {
|
||||
// 中断执行
|
||||
appender.append(AnsiForeground.BRIGHT_YELLOW.and(AnsiFont.BOLD), "< 命令执行中断 ")
|
||||
.append(Dates.current())
|
||||
.newLine();
|
||||
} else if (this.status == ExecHostStatusEnum.FAILED) {
|
||||
// 执行失败
|
||||
appender.append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), "< 命令执行失败 ")
|
||||
.append(Dates.current())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), "错误原因: ")
|
||||
.append(this.getErrorMessage(e))
|
||||
.newLine();
|
||||
} else if (this.status == ExecHostStatusEnum.TIMEOUT) {
|
||||
// 更新执行超时
|
||||
appender.append(AnsiForeground.BRIGHT_YELLOW.and(AnsiFont.BOLD), "< 命令执行超时 ")
|
||||
.append(Dates.current())
|
||||
.newLine();
|
||||
} else {
|
||||
long ms = this.updateRecord.getFinishTime().getTime() - this.updateRecord.getStartTime().getTime();
|
||||
Integer exitStatus = this.updateRecord.getExitStatus();
|
||||
// 执行完成
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "< 命令执行完成 ")
|
||||
.append(Dates.current())
|
||||
.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "exit: ");
|
||||
if (ExitCode.isSuccess(exitStatus)) {
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), exitStatus);
|
||||
} else {
|
||||
appender.append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), exitStatus);
|
||||
}
|
||||
appender.newLine()
|
||||
.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "used: ")
|
||||
.append(Dates.interval(ms, false, "d ", "h ", "m ", "s"))
|
||||
.append(" (")
|
||||
.append(ms)
|
||||
.append(" ms)")
|
||||
.newLine();
|
||||
}
|
||||
// 拼接日志
|
||||
this.appendLog(appender);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.orion.ops.module.asset.handler.host.exec.command.handler;
|
||||
|
||||
import com.orion.lang.support.timeout.TimeoutChecker;
|
||||
import com.orion.lang.support.timeout.TimeoutEndpoint;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 命令执行器 原始日志输出
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/12 11:30
|
||||
*/
|
||||
@Slf4j
|
||||
public class ExecCommandOriginHandler extends BaseExecCommandHandler {
|
||||
|
||||
public ExecCommandOriginHandler(ExecCommandDTO execCommand, ExecCommandHostDTO execHostCommand, TimeoutChecker<TimeoutEndpoint> timeoutChecker) {
|
||||
super(execCommand, execHostCommand, timeoutChecker);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,11 +3,13 @@ package com.orion.ops.module.asset.handler.host.exec.command.handler;
|
||||
import com.orion.lang.support.timeout.TimeoutChecker;
|
||||
import com.orion.lang.support.timeout.TimeoutCheckers;
|
||||
import com.orion.lang.support.timeout.TimeoutEndpoint;
|
||||
import com.orion.lang.utils.Booleans;
|
||||
import com.orion.lang.utils.Threads;
|
||||
import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.ops.module.asset.dao.ExecLogDAO;
|
||||
import com.orion.ops.module.asset.define.AssetThreadPools;
|
||||
import com.orion.ops.module.asset.define.config.AppExecLogConfig;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecLogDO;
|
||||
import com.orion.ops.module.asset.enums.ExecStatusEnum;
|
||||
import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
@@ -34,6 +36,8 @@ public class ExecTaskHandler implements IExecTaskHandler {
|
||||
|
||||
private static final ExecTaskManager execTaskManager = SpringHolder.getBean(ExecTaskManager.class);
|
||||
|
||||
private static final AppExecLogConfig appExecLogConfig = SpringHolder.getBean(AppExecLogConfig.class);
|
||||
|
||||
private final ExecCommandDTO execCommand;
|
||||
|
||||
private TimeoutChecker<TimeoutEndpoint> timeoutChecker;
|
||||
@@ -73,9 +77,9 @@ public class ExecTaskHandler implements IExecTaskHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interrupted() {
|
||||
log.info("ExecTaskHandler-interrupted id: {}", execCommand.getLogId());
|
||||
handlers.forEach(IExecCommandHandler::interrupted);
|
||||
public void interrupt() {
|
||||
log.info("ExecTaskHandler-interrupt id: {}", execCommand.getLogId());
|
||||
handlers.forEach(IExecCommandHandler::interrupt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,18 +97,34 @@ public class ExecTaskHandler implements IExecTaskHandler {
|
||||
List<ExecCommandHostDTO> hosts = execCommand.getHosts();
|
||||
if (hosts.size() == 1) {
|
||||
// 单个主机直接执行
|
||||
ExecCommandHandler handler = new ExecCommandHandler(execCommand, hosts.get(0), timeoutChecker);
|
||||
IExecCommandHandler handler = this.createCommandHandler(hosts.get(0));
|
||||
handlers.add(handler);
|
||||
handler.run();
|
||||
} else {
|
||||
hosts.stream()
|
||||
.map(s -> new ExecCommandHandler(execCommand, s, timeoutChecker))
|
||||
.map(this::createCommandHandler)
|
||||
.forEach(handlers::add);
|
||||
// 多个主机异步阻塞执行
|
||||
Threads.blockRun(handlers, AssetThreadPools.EXEC_HOST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建命令执行器
|
||||
*
|
||||
* @param host host
|
||||
* @return handler
|
||||
*/
|
||||
private IExecCommandHandler createCommandHandler(ExecCommandHostDTO host) {
|
||||
if (Booleans.isTrue(appExecLogConfig.getAppendAnsi())) {
|
||||
// ansi 日志
|
||||
return new ExecCommandAnsiHandler(execCommand, host, timeoutChecker);
|
||||
} else {
|
||||
// 原始日志
|
||||
return new ExecCommandOriginHandler(execCommand, host, timeoutChecker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新状态
|
||||
*
|
||||
|
||||
@@ -22,7 +22,7 @@ public interface IExecCommandHandler extends Runnable, SafeCloseable {
|
||||
/**
|
||||
* 中断执行
|
||||
*/
|
||||
void interrupted();
|
||||
void interrupt();
|
||||
|
||||
/**
|
||||
* 获取当前状态
|
||||
|
||||
@@ -23,6 +23,6 @@ public interface IExecTaskHandler extends Runnable, SafeCloseable {
|
||||
/**
|
||||
* 中断执行
|
||||
*/
|
||||
void interrupted();
|
||||
void interrupt();
|
||||
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public class SftpSession extends TerminalSession implements ISftpSession {
|
||||
throw Exceptions.ioRuntime(e);
|
||||
} finally {
|
||||
// 同关闭 transfer downloader
|
||||
// 关闭 inputStream 可能会被阻塞 ??..?? 只能关闭 executor
|
||||
// 关闭 inputStream 可能会被阻塞 ???...??? 只能关闭 executor
|
||||
Streams.close(this.executor);
|
||||
this.connect();
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
|
||||
|
||||
@Override
|
||||
protected void closeStream() {
|
||||
// 关闭 inputStream 可能会被阻塞 ??..?? 只能关闭 executor
|
||||
// 关闭 inputStream 可能会被阻塞 ???...??? 只能关闭 executor
|
||||
Streams.close(this.executor);
|
||||
this.executor = null;
|
||||
this.inputStream = null;
|
||||
|
||||
@@ -47,4 +47,9 @@ public interface CommandSnippetGroupService {
|
||||
*/
|
||||
Integer deleteCommandSnippetGroup(CommandSnippetGroupDeleteRequest request);
|
||||
|
||||
/**
|
||||
* 清理未使用的分组
|
||||
*/
|
||||
void clearUnusedGroup();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 执行模板主机 服务类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-22 12:13
|
||||
*/
|
||||
public interface ExecTemplateHostService {
|
||||
|
||||
/**
|
||||
* 查询模板主机
|
||||
*
|
||||
* @param templateId templateId
|
||||
* @return hostId
|
||||
*/
|
||||
Set<Long> getHostByTemplateId(Long templateId);
|
||||
|
||||
/**
|
||||
* 查询模板主机
|
||||
*
|
||||
* @param templateIdList templateIdList
|
||||
* @return hostIdMap
|
||||
*/
|
||||
Map<Long, Set<Long>> getHostByTemplateIdList(List<Long> templateIdList);
|
||||
|
||||
/**
|
||||
* 设置模板主机
|
||||
*
|
||||
* @param templateId templateId
|
||||
* @param hostList hostList
|
||||
*/
|
||||
void setTemplateHost(Long templateId, List<Long> hostList);
|
||||
|
||||
/**
|
||||
* 通过 templateId 删除
|
||||
*
|
||||
* @param templateId templateId
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteByTemplateId(Long templateId);
|
||||
|
||||
/**
|
||||
* 通过 hostId 删除
|
||||
*
|
||||
* @param hostId hostId
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteByHostId(Long hostId);
|
||||
|
||||
}
|
||||
@@ -39,6 +39,14 @@ public interface ExecTemplateService {
|
||||
*/
|
||||
ExecTemplateVO getExecTemplateById(Long id);
|
||||
|
||||
/**
|
||||
* 查询执行模板 (查询认证的主机)
|
||||
*
|
||||
* @param id id
|
||||
* @return row
|
||||
*/
|
||||
ExecTemplateVO getExecTemplateWithAuthorized(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询执行模板
|
||||
*
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupDeleteRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 路径标签分组 服务类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
public interface PathBookmarkGroupService {
|
||||
|
||||
/**
|
||||
* 创建路径标签分组
|
||||
*
|
||||
* @param request request
|
||||
* @return id
|
||||
*/
|
||||
Long createPathBookmarkGroup(PathBookmarkGroupCreateRequest request);
|
||||
|
||||
/**
|
||||
* 更新路径标签分组
|
||||
*
|
||||
* @param request request
|
||||
* @return effect
|
||||
*/
|
||||
Integer updatePathBookmarkGroupById(PathBookmarkGroupUpdateRequest request);
|
||||
|
||||
/**
|
||||
* 查询全部路径标签分组
|
||||
*
|
||||
* @return rows
|
||||
*/
|
||||
List<PathBookmarkGroupVO> getPathBookmarkGroupList();
|
||||
|
||||
/**
|
||||
* 删除路径标签分组
|
||||
*
|
||||
* @param request request
|
||||
* @return effect
|
||||
*/
|
||||
Integer deletePathBookmarkGroup(PathBookmarkGroupDeleteRequest request);
|
||||
|
||||
/**
|
||||
* 清理未使用的分组
|
||||
*/
|
||||
void clearUnusedGroup();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.orion.ops.module.asset.service;
|
||||
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkWrapperVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 路径标签 服务类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
public interface PathBookmarkService {
|
||||
|
||||
/**
|
||||
* 创建路径标签
|
||||
*
|
||||
* @param request request
|
||||
* @return id
|
||||
*/
|
||||
Long createPathBookmark(PathBookmarkCreateRequest request);
|
||||
|
||||
/**
|
||||
* 更新路径标签
|
||||
*
|
||||
* @param request request
|
||||
* @return effect
|
||||
*/
|
||||
Integer updatePathBookmarkById(PathBookmarkUpdateRequest request);
|
||||
|
||||
/**
|
||||
* 查询路径标签
|
||||
*
|
||||
* @return rows
|
||||
*/
|
||||
PathBookmarkWrapperVO getPathBookmark();
|
||||
|
||||
/**
|
||||
* 查询全部路径标签
|
||||
*
|
||||
* @return rows
|
||||
*/
|
||||
List<PathBookmarkVO> getPathBookmarkList();
|
||||
|
||||
/**
|
||||
* 删除路径标签
|
||||
*
|
||||
* @param id id
|
||||
* @return effect
|
||||
*/
|
||||
Integer deletePathBookmarkById(Long id);
|
||||
|
||||
/**
|
||||
* 设置分组为 null
|
||||
*
|
||||
* @param userId userId
|
||||
* @param groupId groupId
|
||||
* @return effect
|
||||
*/
|
||||
Integer setGroupNull(Long userId, Long groupId);
|
||||
|
||||
/**
|
||||
* 通过 groupId 删除
|
||||
*
|
||||
* @param userId userId
|
||||
* @param groupId groupId
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteByGroupId(Long userId, Long groupId);
|
||||
|
||||
}
|
||||
@@ -1,24 +1,26 @@
|
||||
package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.utils.Booleans;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.framework.redis.core.utils.RedisMaps;
|
||||
import com.orion.ops.framework.redis.core.utils.barrier.CacheBarriers;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.module.asset.convert.CommandSnippetGroupConvert;
|
||||
import com.orion.ops.module.asset.dao.CommandSnippetGroupDAO;
|
||||
import com.orion.ops.module.asset.define.cache.CommandSnippetCacheKeyDefine;
|
||||
import com.orion.ops.module.asset.entity.domain.CommandSnippetGroupDO;
|
||||
import com.orion.ops.module.asset.entity.dto.CommandSnippetGroupCacheDTO;
|
||||
import com.orion.ops.module.asset.dao.CommandSnippetDAO;
|
||||
import com.orion.ops.module.asset.entity.domain.CommandSnippetDO;
|
||||
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupDeleteRequest;
|
||||
import com.orion.ops.module.asset.entity.request.command.CommandSnippetGroupUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.CommandSnippetGroupVO;
|
||||
import com.orion.ops.module.asset.service.CommandSnippetGroupService;
|
||||
import com.orion.ops.module.asset.service.CommandSnippetService;
|
||||
import com.orion.ops.module.infra.api.DataGroupApi;
|
||||
import com.orion.ops.module.infra.api.DataGroupUserApi;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
|
||||
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -26,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -40,7 +43,13 @@ import java.util.stream.Collectors;
|
||||
public class CommandSnippetGroupServiceImpl implements CommandSnippetGroupService {
|
||||
|
||||
@Resource
|
||||
private CommandSnippetGroupDAO commandSnippetGroupDAO;
|
||||
private DataGroupApi dataGroupApi;
|
||||
|
||||
@Resource
|
||||
private DataGroupUserApi dataGroupUserApi;
|
||||
|
||||
@Resource
|
||||
private CommandSnippetDAO commandSnippetDAO;
|
||||
|
||||
@Resource
|
||||
private CommandSnippetService commandSnippetService;
|
||||
@@ -49,110 +58,81 @@ public class CommandSnippetGroupServiceImpl implements CommandSnippetGroupServic
|
||||
public Long createCommandSnippetGroup(CommandSnippetGroupCreateRequest request) {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
log.info("CommandSnippetGroupService-createCommandSnippetGroup request: {}", JSON.toJSONString(request));
|
||||
// 转换
|
||||
CommandSnippetGroupDO record = CommandSnippetGroupConvert.MAPPER.to(request);
|
||||
record.setUserId(userId);
|
||||
// 查询数据是否冲突
|
||||
this.checkCommandSnippetGroupPresent(record);
|
||||
// 插入
|
||||
int effect = commandSnippetGroupDAO.insert(record);
|
||||
Long id = record.getId();
|
||||
log.info("CommandSnippetGroupService-createCommandSnippetGroup id: {}, effect: {}", id, effect);
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET_GROUP.format(userId);
|
||||
RedisMaps.delete(cacheKey);
|
||||
return id;
|
||||
// 创建
|
||||
DataGroupCreateDTO create = CommandSnippetGroupConvert.MAPPER.to(request);
|
||||
create.setParentId(Const.ROOT_PARENT_ID);
|
||||
return dataGroupUserApi.createDataGroup(DataGroupTypeEnum.COMMAND_SNIPPET, userId, create);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer updateCommandSnippetGroupById(CommandSnippetGroupUpdateRequest request) {
|
||||
Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING);
|
||||
log.info("CommandSnippetGroupService-updateCommandSnippetGroupById id: {}, request: {}", id, JSON.toJSONString(request));
|
||||
// 查询
|
||||
CommandSnippetGroupDO record = commandSnippetGroupDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 转换
|
||||
CommandSnippetGroupDO updateRecord = CommandSnippetGroupConvert.MAPPER.to(request);
|
||||
updateRecord.setUserId(record.getUserId());
|
||||
// 查询数据是否冲突
|
||||
this.checkCommandSnippetGroupPresent(updateRecord);
|
||||
// 更新
|
||||
int effect = commandSnippetGroupDAO.updateById(updateRecord);
|
||||
log.info("CommandSnippetGroupService-updateCommandSnippetGroupById effect: {}", effect);
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET_GROUP.format(record.getUserId());
|
||||
RedisMaps.delete(cacheKey);
|
||||
return effect;
|
||||
// 重命名
|
||||
DataGroupRenameDTO rename = CommandSnippetGroupConvert.MAPPER.to(request);
|
||||
return dataGroupApi.renameDataGroup(rename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommandSnippetGroupVO> getCommandSnippetGroupList() {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
// 查询缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET_GROUP.format(userId);
|
||||
List<CommandSnippetGroupCacheDTO> list = RedisMaps.valuesJson(cacheKey, CommandSnippetCacheKeyDefine.SNIPPET_GROUP);
|
||||
if (list.isEmpty()) {
|
||||
// 查询数据库
|
||||
list = commandSnippetGroupDAO.of()
|
||||
.createWrapper()
|
||||
.eq(CommandSnippetGroupDO::getUserId, userId)
|
||||
.then()
|
||||
.list(CommandSnippetGroupConvert.MAPPER::toCache);
|
||||
// 设置屏障 防止穿透
|
||||
CacheBarriers.checkBarrier(list, CommandSnippetGroupCacheDTO::new);
|
||||
// 设置缓存
|
||||
RedisMaps.putAllJson(cacheKey, s -> s.getId().toString(), list);
|
||||
}
|
||||
// 删除屏障
|
||||
CacheBarriers.removeBarrier(list);
|
||||
// 转换
|
||||
return list.stream()
|
||||
// 查询分组
|
||||
return dataGroupUserApi.getDataGroupList(DataGroupTypeEnum.COMMAND_SNIPPET, userId)
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(DataGroupDTO::getSort))
|
||||
.map(CommandSnippetGroupConvert.MAPPER::to)
|
||||
.sorted(Comparator.comparing(CommandSnippetGroupVO::getId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer deleteCommandSnippetGroup(CommandSnippetGroupDeleteRequest request) {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
Long id = request.getId();
|
||||
log.info("CommandSnippetGroupService-deleteCommandSnippetGroupById id: {}", id);
|
||||
// 检查数据是否存在
|
||||
CommandSnippetGroupDO record = commandSnippetGroupDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
Long userId = record.getUserId();
|
||||
// 删除
|
||||
int effect = commandSnippetGroupDAO.deleteById(id);
|
||||
log.info("CommandSnippetGroupService-deleteCommandSnippetGroupById id: {}, effect: {}", id, effect);
|
||||
// 删除分组
|
||||
Integer effect = dataGroupApi.deleteDataGroupById(id);
|
||||
if (Booleans.isTrue(request.getDeleteItem())) {
|
||||
// 删除组内数据
|
||||
commandSnippetService.deleteByGroupId(userId, id);
|
||||
effect += commandSnippetService.deleteByGroupId(userId, id);
|
||||
} else {
|
||||
// 移动到根节点
|
||||
commandSnippetService.setGroupNull(userId, id);
|
||||
effect += commandSnippetService.setGroupNull(userId, id);
|
||||
}
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET_GROUP.format(userId);
|
||||
RedisMaps.delete(cacheKey, id);
|
||||
return effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否存在
|
||||
*
|
||||
* @param domain domain
|
||||
*/
|
||||
private void checkCommandSnippetGroupPresent(CommandSnippetGroupDO domain) {
|
||||
// 构造条件
|
||||
LambdaQueryWrapper<CommandSnippetGroupDO> wrapper = commandSnippetGroupDAO.wrapper()
|
||||
// 更新时忽略当前记录
|
||||
.ne(CommandSnippetGroupDO::getId, domain.getId())
|
||||
// 用其他字段做重复校验
|
||||
.eq(CommandSnippetGroupDO::getUserId, domain.getUserId())
|
||||
.eq(CommandSnippetGroupDO::getName, domain.getName());
|
||||
// 检查是否存在
|
||||
boolean present = commandSnippetGroupDAO.of(wrapper).present();
|
||||
Valid.isFalse(present, ErrorMessage.DATA_PRESENT);
|
||||
@Override
|
||||
public void clearUnusedGroup() {
|
||||
// 查询全部 groupId
|
||||
Map<Long, List<Long>> userGroupMap = commandSnippetDAO.of()
|
||||
.createWrapper()
|
||||
.select(CommandSnippetDO::getUserId, CommandSnippetDO::getGroupId)
|
||||
.isNotNull(CommandSnippetDO::getGroupId)
|
||||
.groupBy(CommandSnippetDO::getGroupId)
|
||||
.then()
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(CommandSnippetDO::getUserId,
|
||||
Collectors.mapping(CommandSnippetDO::getGroupId, Collectors.toList())));
|
||||
userGroupMap.forEach((k, v) -> {
|
||||
// 查询用户分组
|
||||
List<DataGroupDTO> groups = dataGroupUserApi.getDataGroupList(DataGroupTypeEnum.COMMAND_SNIPPET, k);
|
||||
if (groups.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 不存在的则移除
|
||||
List<Long> deleteGroupList = groups.stream()
|
||||
.map(DataGroupDTO::getId)
|
||||
.filter(s -> !v.contains(s))
|
||||
.collect(Collectors.toList());
|
||||
if (deleteGroupList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
log.info("CommandSnippetGroupService.clearUnusedGroup userId: {}, deleteGroupList: {}", k, deleteGroupList);
|
||||
// 删除分组
|
||||
Integer effect = dataGroupUserApi.deleteDataGroupByIdList(DataGroupTypeEnum.COMMAND_SNIPPET, k, deleteGroupList);
|
||||
log.info("CommandSnippetGroupService.clearUnusedGroup userId: {}, effect: {}", k, effect);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
@@ -55,18 +56,18 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
||||
// 转换
|
||||
CommandSnippetDO record = CommandSnippetConvert.MAPPER.to(request);
|
||||
record.setUserId(userId);
|
||||
// 查询数据是否冲突
|
||||
this.checkCommandSnippetPresent(record);
|
||||
// 插入
|
||||
int effect = commandSnippetDAO.insert(record);
|
||||
Long id = record.getId();
|
||||
log.info("CommandSnippetService-createCommandSnippet id: {}, effect: {}", id, effect);
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET.format(userId);
|
||||
RedisMaps.delete(cacheKey);
|
||||
RedisMaps.delete(CommandSnippetCacheKeyDefine.SNIPPET.format(userId));
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer updateCommandSnippetById(CommandSnippetUpdateRequest request) {
|
||||
Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING);
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
@@ -74,6 +75,9 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
||||
// 查询
|
||||
CommandSnippetDO record = commandSnippetDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 查询数据是否冲突
|
||||
CommandSnippetDO updateRecord = CommandSnippetConvert.MAPPER.to(request);
|
||||
this.checkCommandSnippetPresent(updateRecord);
|
||||
// 更新
|
||||
LambdaUpdateWrapper<CommandSnippetDO> update = Wrappers.<CommandSnippetDO>lambdaUpdate()
|
||||
.set(CommandSnippetDO::getGroupId, request.getGroupId())
|
||||
@@ -84,8 +88,7 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
||||
int effect = commandSnippetDAO.update(null, update);
|
||||
log.info("CommandSnippetService-updateCommandSnippetById effect: {}", effect);
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET.format(userId);
|
||||
RedisMaps.delete(cacheKey);
|
||||
RedisMaps.delete(CommandSnippetCacheKeyDefine.SNIPPET.format(userId));
|
||||
return effect;
|
||||
}
|
||||
|
||||
@@ -130,7 +133,7 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
||||
// 设置屏障 防止穿透
|
||||
CacheBarriers.checkBarrier(list, CommandSnippetCacheDTO::new);
|
||||
// 设置缓存
|
||||
RedisMaps.putAllJson(CommandSnippetCacheKeyDefine.SNIPPET, s -> s.getId().toString(), list);
|
||||
RedisMaps.putAllJson(cacheKey, CommandSnippetCacheKeyDefine.SNIPPET, s -> s.getId().toString(), list);
|
||||
}
|
||||
// 删除屏障
|
||||
CacheBarriers.removeBarrier(list);
|
||||
@@ -153,8 +156,7 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
||||
int effect = commandSnippetDAO.deleteById(id);
|
||||
log.info("CommandSnippetService-deleteCommandSnippetById id: {}, effect: {}", id, effect);
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET.format(userId);
|
||||
RedisMaps.delete(cacheKey, id);
|
||||
RedisMaps.delete(CommandSnippetCacheKeyDefine.SNIPPET.format(userId), id);
|
||||
return effect;
|
||||
}
|
||||
|
||||
@@ -162,8 +164,7 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
||||
public Integer setGroupNull(Long userId, Long groupId) {
|
||||
int effect = commandSnippetDAO.setGroupIdWithNull(groupId);
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET.format(userId);
|
||||
RedisMaps.delete(cacheKey);
|
||||
RedisMaps.delete(CommandSnippetCacheKeyDefine.SNIPPET.format(userId));
|
||||
return effect;
|
||||
}
|
||||
|
||||
@@ -171,9 +172,27 @@ public class CommandSnippetServiceImpl implements CommandSnippetService {
|
||||
public Integer deleteByGroupId(Long userId, Long groupId) {
|
||||
int effect = commandSnippetDAO.deleteByGroupId(groupId);
|
||||
// 删除缓存
|
||||
String cacheKey = CommandSnippetCacheKeyDefine.SNIPPET.format(userId);
|
||||
RedisMaps.delete(cacheKey);
|
||||
RedisMaps.delete(CommandSnippetCacheKeyDefine.SNIPPET.format(userId));
|
||||
return effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否存在
|
||||
*
|
||||
* @param domain domain
|
||||
*/
|
||||
private void checkCommandSnippetPresent(CommandSnippetDO domain) {
|
||||
// 构造条件
|
||||
LambdaQueryWrapper<CommandSnippetDO> wrapper = commandSnippetDAO.wrapper()
|
||||
// 更新时忽略当前记录
|
||||
.ne(CommandSnippetDO::getId, domain.getId())
|
||||
// 用其他字段做重复校验
|
||||
.eq(CommandSnippetDO::getUserId, domain.getUserId())
|
||||
.eq(CommandSnippetDO::getGroupId, domain.getGroupId())
|
||||
.eq(CommandSnippetDO::getName, domain.getName());
|
||||
// 检查是否存在
|
||||
boolean present = commandSnippetDAO.of(wrapper).present();
|
||||
Valid.isFalse(present, ErrorMessage.DATA_PRESENT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -197,9 +197,12 @@ public class ExecCommandServiceImpl implements ExecCommandService {
|
||||
return ExecCommandHostDTO.builder()
|
||||
.hostId(s.getHostId())
|
||||
.hostLogId(s.getId())
|
||||
.hostName(s.getHostName())
|
||||
.hostAddress(s.getHostAddress())
|
||||
.command(s.getCommand())
|
||||
.logPath(s.getLogPath())
|
||||
.scriptPath(s.getScriptPath())
|
||||
.username(config.getUsername())
|
||||
.charset(config.getCharset())
|
||||
.fileNameCharset(config.getFileNameCharset())
|
||||
.fileContentCharset(config.getFileContentCharset())
|
||||
@@ -208,6 +211,10 @@ public class ExecCommandServiceImpl implements ExecCommandService {
|
||||
// 执行信息
|
||||
ExecCommandDTO exec = ExecCommandDTO.builder()
|
||||
.logId(execLog.getId())
|
||||
.userId(execLog.getUserId())
|
||||
.username(execLog.getUsername())
|
||||
.description(execLog.getDescription())
|
||||
.execSeq(execLog.getExecSeq())
|
||||
.timeout(execLog.getTimeout())
|
||||
.scriptExec(ScriptExecEnum.isEnabled(execLog.getScriptExec()))
|
||||
.hosts(hosts)
|
||||
|
||||
@@ -79,7 +79,7 @@ public class ExecHostLogServiceImpl implements ExecHostLogService {
|
||||
.flatMap(s -> s.stream()
|
||||
.filter(h -> h.getHostId().equals(record.getHostId()))
|
||||
.findFirst())
|
||||
.ifPresent(IExecCommandHandler::interrupted);
|
||||
.ifPresent(IExecCommandHandler::interrupt);
|
||||
// 删除
|
||||
int effect = execHostLogDAO.deleteById(id);
|
||||
log.info("ExecHostLogService-deleteExecHostLogById id: {}, effect: {}", id, effect);
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.orion.lang.utils.Objects1;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.ops.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
@@ -175,7 +176,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
ExecLogDO record = execLogDAO.selectByIdSource(id, source);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 中断命令执行
|
||||
this.interruptedTask(Lists.singleton(id));
|
||||
this.interruptTask(Lists.singleton(id));
|
||||
// 删除执行日志
|
||||
int effect = execLogDAO.deleteById(id);
|
||||
// 删除主机日志
|
||||
@@ -199,7 +200,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
.intValue();
|
||||
Valid.isTrue(idList.size() == count, ErrorMessage.DATA_MODIFIED);
|
||||
// 中断命令执行
|
||||
this.interruptedTask(idList);
|
||||
this.interruptTask(idList);
|
||||
// 删除执行日志
|
||||
int effect = execLogDAO.deleteBatchIds(idList);
|
||||
// 删除主机日志
|
||||
@@ -229,7 +230,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
int effect = 0;
|
||||
if (!idList.isEmpty()) {
|
||||
// 中断命令执行
|
||||
this.interruptedTask(idList);
|
||||
this.interruptTask(idList);
|
||||
// 删除执行日志
|
||||
effect = execLogDAO.delete(wrapper);
|
||||
// 删除主机日志
|
||||
@@ -255,9 +256,9 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
// 中断执行
|
||||
IExecTaskHandler task = execTaskManager.getTask(logId);
|
||||
if (task != null) {
|
||||
log.info("ExecLogService.interruptExec interrupted logId: {}", logId);
|
||||
log.info("ExecLogService.interruptExec interrupt logId: {}", logId);
|
||||
// 中断
|
||||
task.interrupted();
|
||||
task.interrupt();
|
||||
} else {
|
||||
log.info("ExecLogService.interruptExec updateStatus start logId: {}", logId);
|
||||
// 不存在则直接修改状态
|
||||
@@ -298,7 +299,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
// 中断执行
|
||||
IExecTaskHandler task = execTaskManager.getTask(logId);
|
||||
if (task != null) {
|
||||
log.info("ExecLogService.interruptHostExec interrupted logId: {}, hostLogId: {}", logId, hostLogId);
|
||||
log.info("ExecLogService.interruptHostExec interrupt logId: {}, hostLogId: {}", logId, hostLogId);
|
||||
IExecCommandHandler handler = task.getHandlers()
|
||||
.stream()
|
||||
.filter(s -> s.getHostId().equals(hostLog.getHostId()))
|
||||
@@ -306,7 +307,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
.orElse(null);
|
||||
// 中断
|
||||
if (handler != null) {
|
||||
handler.interrupted();
|
||||
handler.interrupt();
|
||||
}
|
||||
} else {
|
||||
log.info("ExecLogService.interruptHostExec updateStatus start logId: {}, hostLogId: {}", logId, hostLogId);
|
||||
@@ -405,6 +406,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
@Override
|
||||
public void downloadLogFile(Long id, String source, HttpServletResponse response) {
|
||||
log.info("ExecLogService.downloadLogFile id: {}, source: {}", id, source);
|
||||
InputStream in = null;
|
||||
try {
|
||||
// 获取主机执行日志
|
||||
ExecHostLogDO hostLog = execHostLogDAO.selectById(id);
|
||||
@@ -418,11 +420,12 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
OperatorLogs.add(OperatorLogs.HOST_ID, hostLog.getHostId());
|
||||
OperatorLogs.add(OperatorLogs.HOST_NAME, hostLog.getHostName());
|
||||
// 获取日志
|
||||
InputStream in = logsFileClient.getContentInputStream(logPath);
|
||||
in = logsFileClient.getContentInputStream(logPath);
|
||||
// 返回
|
||||
Servlets.transfer(response, in, Files1.getFileName(logPath));
|
||||
} catch (Exception e) {
|
||||
log.error("ExecLogService.downloadLogFile error id: {}", id, e);
|
||||
Streams.close(in);
|
||||
String errorMessage = ErrorMessage.FILE_READ_ERROR;
|
||||
if (e instanceof InvalidArgumentException) {
|
||||
errorMessage = e.getMessage();
|
||||
@@ -462,11 +465,11 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
*
|
||||
* @param idList idList
|
||||
*/
|
||||
private void interruptedTask(List<Long> idList) {
|
||||
private void interruptTask(List<Long> idList) {
|
||||
idList.stream()
|
||||
.map(execTaskManager::getTask)
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(IExecTaskHandler::interrupted);
|
||||
.forEach(IExecTaskHandler::interrupt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.function.Functions;
|
||||
import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.ops.module.asset.dao.ExecTemplateHostDAO;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecTemplateHostDO;
|
||||
import com.orion.ops.module.asset.service.ExecTemplateHostService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 执行模板主机 服务实现类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-22 12:13
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ExecTemplateHostServiceImpl implements ExecTemplateHostService {
|
||||
|
||||
@Resource
|
||||
private ExecTemplateHostDAO execTemplateHostDAO;
|
||||
|
||||
@Override
|
||||
public Set<Long> getHostByTemplateId(Long templateId) {
|
||||
return execTemplateHostDAO.of()
|
||||
.createWrapper()
|
||||
.select(ExecTemplateHostDO::getHostId)
|
||||
.eq(ExecTemplateHostDO::getTemplateId, templateId)
|
||||
.then()
|
||||
.stream()
|
||||
.map(ExecTemplateHostDO::getHostId)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, Set<Long>> getHostByTemplateIdList(List<Long> templateIdList) {
|
||||
return execTemplateHostDAO.of()
|
||||
.createWrapper()
|
||||
.select(ExecTemplateHostDO::getTemplateId, ExecTemplateHostDO::getHostId)
|
||||
.in(ExecTemplateHostDO::getTemplateId, templateIdList)
|
||||
.then()
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
ExecTemplateHostDO::getTemplateId,
|
||||
Collectors.mapping(ExecTemplateHostDO::getHostId, Collectors.toSet())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTemplateHost(Long templateId, List<Long> hostList) {
|
||||
LambdaQueryWrapper<ExecTemplateHostDO> wrapper = execTemplateHostDAO.wrapper()
|
||||
.eq(ExecTemplateHostDO::getTemplateId, templateId);
|
||||
if (Lists.isEmpty(hostList)) {
|
||||
// 为空移除
|
||||
execTemplateHostDAO.delete(wrapper);
|
||||
} else {
|
||||
// 查询主机
|
||||
wrapper.select(ExecTemplateHostDO::getId, ExecTemplateHostDO::getHostId);
|
||||
Map<Long, Long> hostMap = execTemplateHostDAO.of(wrapper)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ExecTemplateHostDO::getHostId,
|
||||
ExecTemplateHostDO::getId,
|
||||
Functions.right()));
|
||||
// 插入主机
|
||||
List<ExecTemplateHostDO> insertRecords = hostList.stream()
|
||||
.filter(s -> !hostMap.containsKey(s))
|
||||
.map(s -> ExecTemplateHostDO.builder()
|
||||
.templateId(templateId)
|
||||
.hostId(s)
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
if (!insertRecords.isEmpty()) {
|
||||
execTemplateHostDAO.insertBatch(insertRecords);
|
||||
}
|
||||
// 删除主机
|
||||
List<Long> deleteIdList = hostMap.keySet()
|
||||
.stream()
|
||||
.filter(s -> !hostList.contains(s))
|
||||
.map(hostMap::get)
|
||||
.collect(Collectors.toList());
|
||||
if (!deleteIdList.isEmpty()) {
|
||||
execTemplateHostDAO.deleteBatchIds(deleteIdList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByTemplateId(Long templateId) {
|
||||
LambdaQueryWrapper<ExecTemplateHostDO> wrapper = execTemplateHostDAO.lambda()
|
||||
.eq(ExecTemplateHostDO::getTemplateId, templateId);
|
||||
log.info("ExecTemplateHostService-deleteByTemplateId idList: {}", templateId);
|
||||
int effect = execTemplateHostDAO.delete(wrapper);
|
||||
log.info("ExecTemplateHostService-deleteByTemplateId effect: {}", effect);
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByHostId(Long hostId) {
|
||||
LambdaQueryWrapper<ExecTemplateHostDO> wrapper = execTemplateHostDAO.lambda()
|
||||
.eq(ExecTemplateHostDO::getHostId, hostId);
|
||||
log.info("ExecTemplateHostService-deleteByHostId idList: {}", hostId);
|
||||
int effect = execTemplateHostDAO.delete(wrapper);
|
||||
log.info("ExecTemplateHostService-deleteByHostId effect: {}", effect);
|
||||
return effect;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,8 +3,10 @@ package com.orion.ops.module.asset.service.impl;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.module.asset.convert.ExecTemplateConvert;
|
||||
import com.orion.ops.module.asset.dao.ExecTemplateDAO;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecTemplateDO;
|
||||
@@ -12,12 +14,17 @@ import com.orion.ops.module.asset.entity.request.exec.ExecTemplateCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecTemplateQueryRequest;
|
||||
import com.orion.ops.module.asset.entity.request.exec.ExecTemplateUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.ExecTemplateVO;
|
||||
import com.orion.ops.module.asset.enums.HostConfigTypeEnum;
|
||||
import com.orion.ops.module.asset.enums.ScriptExecEnum;
|
||||
import com.orion.ops.module.asset.service.AssetAuthorizedDataService;
|
||||
import com.orion.ops.module.asset.service.ExecTemplateHostService;
|
||||
import com.orion.ops.module.asset.service.ExecTemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 执行模板 服务实现类
|
||||
@@ -33,6 +40,12 @@ public class ExecTemplateServiceImpl implements ExecTemplateService {
|
||||
@Resource
|
||||
private ExecTemplateDAO execTemplateDAO;
|
||||
|
||||
@Resource
|
||||
private ExecTemplateHostService execTemplateHostService;
|
||||
|
||||
@Resource
|
||||
private AssetAuthorizedDataService assetAuthorizedDataService;
|
||||
|
||||
@Override
|
||||
public Long createExecTemplate(ExecTemplateCreateRequest request) {
|
||||
log.info("ExecTemplateService-createExecTemplate request: {}", JSON.toJSONString(request));
|
||||
@@ -41,9 +54,11 @@ public class ExecTemplateServiceImpl implements ExecTemplateService {
|
||||
ExecTemplateDO record = ExecTemplateConvert.MAPPER.to(request);
|
||||
// 查询数据是否冲突
|
||||
this.checkExecTemplatePresent(record);
|
||||
// 插入
|
||||
// 插入模板
|
||||
int effect = execTemplateDAO.insert(record);
|
||||
Long id = record.getId();
|
||||
// 修改模板主机
|
||||
execTemplateHostService.setTemplateHost(id, request.getHostIdList());
|
||||
log.info("ExecTemplateService-createExecTemplate id: {}, effect: {}", id, effect);
|
||||
return id;
|
||||
}
|
||||
@@ -60,26 +75,51 @@ public class ExecTemplateServiceImpl implements ExecTemplateService {
|
||||
ExecTemplateDO updateRecord = ExecTemplateConvert.MAPPER.to(request);
|
||||
// 查询数据是否冲突
|
||||
this.checkExecTemplatePresent(updateRecord);
|
||||
// 更新
|
||||
// 更新模板
|
||||
int effect = execTemplateDAO.updateById(updateRecord);
|
||||
// 修改模板主机
|
||||
execTemplateHostService.setTemplateHost(id, request.getHostIdList());
|
||||
log.info("ExecTemplateService-updateExecTemplateById effect: {}", effect);
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecTemplateVO getExecTemplateById(Long id) {
|
||||
// 查询
|
||||
// 查询模板
|
||||
ExecTemplateDO record = execTemplateDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 转换
|
||||
return ExecTemplateConvert.MAPPER.to(record);
|
||||
ExecTemplateVO template = ExecTemplateConvert.MAPPER.to(record);
|
||||
// 查询模板主机
|
||||
Set<Long> hosts = execTemplateHostService.getHostByTemplateId(id);
|
||||
template.setHostIdList(hosts);
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecTemplateVO getExecTemplateWithAuthorized(Long id) {
|
||||
// 查询模板
|
||||
ExecTemplateDO record = execTemplateDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 转换
|
||||
ExecTemplateVO template = ExecTemplateConvert.MAPPER.to(record);
|
||||
// 查询模板主机
|
||||
Set<Long> hostIdList = execTemplateHostService.getHostByTemplateId(id);
|
||||
if (Lists.isEmpty(hostIdList)) {
|
||||
return template;
|
||||
}
|
||||
// 过滤认证的主机
|
||||
List<Long> authorizedHostIdList = assetAuthorizedDataService.getUserAuthorizedHostIdWithEnabledConfig(SecurityUtils.getLoginUserId(), HostConfigTypeEnum.SSH);
|
||||
hostIdList.removeIf(s -> !authorizedHostIdList.contains(s));
|
||||
template.setHostIdList(hostIdList);
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataGrid<ExecTemplateVO> getExecTemplatePage(ExecTemplateQueryRequest request) {
|
||||
// 条件
|
||||
LambdaQueryWrapper<ExecTemplateDO> wrapper = this.buildQueryWrapper(request);
|
||||
// 查询
|
||||
// 查询模板
|
||||
return execTemplateDAO.of(wrapper)
|
||||
.page(request)
|
||||
.dataGrid(ExecTemplateConvert.MAPPER::to);
|
||||
@@ -91,9 +131,11 @@ public class ExecTemplateServiceImpl implements ExecTemplateService {
|
||||
// 检查数据是否存在
|
||||
ExecTemplateDO record = execTemplateDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 删除
|
||||
// 删除模板
|
||||
int effect = execTemplateDAO.deleteById(id);
|
||||
log.info("ExecTemplateService-deleteExecTemplateById id: {}, effect: {}", id, effect);
|
||||
// 删除模板主机
|
||||
effect += execTemplateHostService.deleteByTemplateId(id);
|
||||
return effect;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,13 @@ import com.orion.ops.module.asset.entity.request.host.HostQueryRequest;
|
||||
import com.orion.ops.module.asset.entity.request.host.HostUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.HostVO;
|
||||
import com.orion.ops.module.asset.service.ExecJobHostService;
|
||||
import com.orion.ops.module.asset.service.ExecTemplateHostService;
|
||||
import com.orion.ops.module.asset.service.HostConfigService;
|
||||
import com.orion.ops.module.asset.service.HostService;
|
||||
import com.orion.ops.module.infra.api.DataExtraApi;
|
||||
import com.orion.ops.module.infra.api.DataGroupRelApi;
|
||||
import com.orion.ops.module.infra.api.FavoriteApi;
|
||||
import com.orion.ops.module.infra.api.TagRelApi;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupRelCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.tag.TagDTO;
|
||||
import com.orion.ops.module.infra.enums.DataExtraTypeEnum;
|
||||
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||
@@ -70,6 +70,9 @@ public class HostServiceImpl implements HostService {
|
||||
@Resource
|
||||
private ExecJobHostService execJobHostService;
|
||||
|
||||
@Resource
|
||||
private ExecTemplateHostService execTemplateHostService;
|
||||
|
||||
@Resource
|
||||
private TagRelApi tagRelApi;
|
||||
|
||||
@@ -99,13 +102,7 @@ public class HostServiceImpl implements HostService {
|
||||
// 引用分组
|
||||
List<Long> groupIdList = request.getGroupIdList();
|
||||
if (!Lists.isEmpty(groupIdList)) {
|
||||
List<DataGroupRelCreateDTO> groupRelList = groupIdList.stream()
|
||||
.map(s -> DataGroupRelCreateDTO.builder()
|
||||
.groupId(s)
|
||||
.relId(id)
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
dataGroupRelApi.addGroupRel(groupRelList);
|
||||
dataGroupRelApi.updateRelGroup(DataGroupTypeEnum.HOST, request.getGroupIdList(), id);
|
||||
}
|
||||
// 创建配置
|
||||
hostConfigService.initHostConfig(id);
|
||||
@@ -130,7 +127,7 @@ public class HostServiceImpl implements HostService {
|
||||
int effect = hostDAO.updateById(updateRecord);
|
||||
log.info("HostService-updateHostById effect: {}", effect);
|
||||
// 引用分组
|
||||
dataGroupRelApi.updateGroupRel(DataGroupTypeEnum.HOST, request.getGroupIdList(), id);
|
||||
dataGroupRelApi.updateRelGroup(DataGroupTypeEnum.HOST, request.getGroupIdList(), id);
|
||||
// 更新 tag
|
||||
tagRelApi.setTagRel(TagTypeEnum.HOST, id, request.getTags());
|
||||
// 删除缓存
|
||||
@@ -219,6 +216,8 @@ public class HostServiceImpl implements HostService {
|
||||
hostConfigDAO.deleteByHostId(id);
|
||||
// 删除计划任务主机
|
||||
execJobHostService.deleteByHostId(id);
|
||||
// 删除执行模板主机
|
||||
execTemplateHostService.deleteByHostId(id);
|
||||
// 删除分组
|
||||
dataGroupRelApi.deleteByRelId(DataGroupTypeEnum.HOST, id);
|
||||
// 删除 tag 引用
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.orion.lang.utils.Booleans;
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.module.asset.convert.PathBookmarkGroupConvert;
|
||||
import com.orion.ops.module.asset.dao.PathBookmarkDAO;
|
||||
import com.orion.ops.module.asset.entity.domain.PathBookmarkDO;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupDeleteRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkGroupUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||
import com.orion.ops.module.asset.service.PathBookmarkGroupService;
|
||||
import com.orion.ops.module.asset.service.PathBookmarkService;
|
||||
import com.orion.ops.module.infra.api.DataGroupApi;
|
||||
import com.orion.ops.module.infra.api.DataGroupUserApi;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupRenameDTO;
|
||||
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 路径标签分组 服务实现类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024-1-24 12:28
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PathBookmarkGroupServiceImpl implements PathBookmarkGroupService {
|
||||
|
||||
@Resource
|
||||
private DataGroupApi dataGroupApi;
|
||||
|
||||
@Resource
|
||||
private DataGroupUserApi dataGroupUserApi;
|
||||
|
||||
@Resource
|
||||
private PathBookmarkDAO pathBookmarkDAO;
|
||||
|
||||
@Resource
|
||||
private PathBookmarkService pathBookmarkService;
|
||||
|
||||
@Override
|
||||
public Long createPathBookmarkGroup(PathBookmarkGroupCreateRequest request) {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
log.info("PathBookmarkGroupService-createPathBookmarkGroup request: {}", JSON.toJSONString(request));
|
||||
// 创建
|
||||
DataGroupCreateDTO create = PathBookmarkGroupConvert.MAPPER.to(request);
|
||||
create.setParentId(Const.ROOT_PARENT_ID);
|
||||
return dataGroupUserApi.createDataGroup(DataGroupTypeEnum.PATH_BOOKMARK, userId, create);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer updatePathBookmarkGroupById(PathBookmarkGroupUpdateRequest request) {
|
||||
Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING);
|
||||
log.info("PathBookmarkGroupService-updatePathBookmarkGroupById id: {}, request: {}", id, JSON.toJSONString(request));
|
||||
// 重命名
|
||||
DataGroupRenameDTO rename = PathBookmarkGroupConvert.MAPPER.to(request);
|
||||
return dataGroupApi.renameDataGroup(rename);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PathBookmarkGroupVO> getPathBookmarkGroupList() {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
// 查询分组
|
||||
return dataGroupUserApi.getDataGroupList(DataGroupTypeEnum.PATH_BOOKMARK, userId)
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(DataGroupDTO::getSort))
|
||||
.map(PathBookmarkGroupConvert.MAPPER::to)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Integer deletePathBookmarkGroup(PathBookmarkGroupDeleteRequest request) {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
Long id = request.getId();
|
||||
log.info("PathBookmarkGroupService-deletePathBookmarkGroupById id: {}", id);
|
||||
// 删除分组
|
||||
Integer effect = dataGroupApi.deleteDataGroupById(id);
|
||||
if (Booleans.isTrue(request.getDeleteItem())) {
|
||||
// 删除组内数据
|
||||
effect += pathBookmarkService.deleteByGroupId(userId, id);
|
||||
} else {
|
||||
// 移动到根节点
|
||||
effect += pathBookmarkService.setGroupNull(userId, id);
|
||||
}
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearUnusedGroup() {
|
||||
// 查询全部 groupId
|
||||
Map<Long, List<Long>> userGroupMap = pathBookmarkDAO.of()
|
||||
.createWrapper()
|
||||
.select(PathBookmarkDO::getUserId, PathBookmarkDO::getGroupId)
|
||||
.isNotNull(PathBookmarkDO::getGroupId)
|
||||
.groupBy(PathBookmarkDO::getGroupId)
|
||||
.then()
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(PathBookmarkDO::getUserId,
|
||||
Collectors.mapping(PathBookmarkDO::getGroupId, Collectors.toList())));
|
||||
userGroupMap.forEach((k, v) -> {
|
||||
// 查询用户分组
|
||||
List<DataGroupDTO> groups = dataGroupUserApi.getDataGroupList(DataGroupTypeEnum.PATH_BOOKMARK, k);
|
||||
if (groups.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 不存在的则移除
|
||||
List<Long> deleteGroupList = groups.stream()
|
||||
.map(DataGroupDTO::getId)
|
||||
.filter(s -> !v.contains(s))
|
||||
.collect(Collectors.toList());
|
||||
if (deleteGroupList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
log.info("PathBookmarkGroupService.clearUnusedGroup userId: {}, deleteGroupList: {}", k, deleteGroupList);
|
||||
// 删除分组
|
||||
Integer effect = dataGroupUserApi.deleteDataGroupByIdList(DataGroupTypeEnum.PATH_BOOKMARK, k, deleteGroupList);
|
||||
log.info("PathBookmarkGroupService.clearUnusedGroup userId: {}, effect: {}", k, effect);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.orion.ops.module.asset.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.orion.ops.framework.common.constant.ErrorMessage;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.framework.redis.core.utils.RedisMaps;
|
||||
import com.orion.ops.framework.redis.core.utils.barrier.CacheBarriers;
|
||||
import com.orion.ops.framework.security.core.utils.SecurityUtils;
|
||||
import com.orion.ops.module.asset.convert.PathBookmarkConvert;
|
||||
import com.orion.ops.module.asset.dao.PathBookmarkDAO;
|
||||
import com.orion.ops.module.asset.define.cache.PathBookmarkCacheKeyDefine;
|
||||
import com.orion.ops.module.asset.entity.domain.PathBookmarkDO;
|
||||
import com.orion.ops.module.asset.entity.dto.PathBookmarkCacheDTO;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkCreateRequest;
|
||||
import com.orion.ops.module.asset.entity.request.path.PathBookmarkUpdateRequest;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkGroupVO;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkVO;
|
||||
import com.orion.ops.module.asset.entity.vo.PathBookmarkWrapperVO;
|
||||
import com.orion.ops.module.asset.service.PathBookmarkGroupService;
|
||||
import com.orion.ops.module.asset.service.PathBookmarkService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 路径标签 服务实现类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.6
|
||||
* @since 2024-4-23 23:15
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PathBookmarkServiceImpl implements PathBookmarkService {
|
||||
|
||||
@Resource
|
||||
private PathBookmarkDAO pathBookmarkDAO;
|
||||
|
||||
@Resource
|
||||
private PathBookmarkGroupService pathBookmarkGroupService;
|
||||
|
||||
@Override
|
||||
public Long createPathBookmark(PathBookmarkCreateRequest request) {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
log.info("PathBookmarkService-createPathBookmark request: {}", JSON.toJSONString(request));
|
||||
// 转换
|
||||
PathBookmarkDO record = PathBookmarkConvert.MAPPER.to(request);
|
||||
record.setUserId(userId);
|
||||
// 查询数据是否冲突
|
||||
this.checkPathBookmarkPresent(record);
|
||||
// 插入
|
||||
int effect = pathBookmarkDAO.insert(record);
|
||||
Long id = record.getId();
|
||||
log.info("PathBookmarkService-createPathBookmark id: {}, effect: {}", id, effect);
|
||||
// 删除缓存
|
||||
RedisMaps.delete(PathBookmarkCacheKeyDefine.PATH_BOOKMARK.format(userId));
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer updatePathBookmarkById(PathBookmarkUpdateRequest request) {
|
||||
Long id = Valid.notNull(request.getId(), ErrorMessage.ID_MISSING);
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
log.info("PathBookmarkService-updatePathBookmarkById id: {}, request: {}", id, JSON.toJSONString(request));
|
||||
// 查询
|
||||
PathBookmarkDO record = pathBookmarkDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 查询数据是否冲突
|
||||
PathBookmarkDO updateRecord = PathBookmarkConvert.MAPPER.to(request);
|
||||
this.checkPathBookmarkPresent(updateRecord);
|
||||
// 更新
|
||||
LambdaUpdateWrapper<PathBookmarkDO> update = Wrappers.<PathBookmarkDO>lambdaUpdate()
|
||||
.set(PathBookmarkDO::getGroupId, request.getGroupId())
|
||||
.set(PathBookmarkDO::getName, request.getName())
|
||||
.set(PathBookmarkDO::getPath, request.getPath())
|
||||
.eq(PathBookmarkDO::getId, id)
|
||||
.eq(PathBookmarkDO::getUserId, userId);
|
||||
int effect = pathBookmarkDAO.update(null, update);
|
||||
log.info("PathBookmarkService-updatePathBookmarkById effect: {}", effect);
|
||||
// 删除缓存
|
||||
RedisMaps.delete(PathBookmarkCacheKeyDefine.PATH_BOOKMARK.format(userId));
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathBookmarkWrapperVO getPathBookmark() {
|
||||
// 查询分组
|
||||
List<PathBookmarkGroupVO> groups = pathBookmarkGroupService.getPathBookmarkGroupList();
|
||||
// 查询命令片段
|
||||
List<PathBookmarkVO> items = this.getPathBookmarkList();
|
||||
// 设置组内数据
|
||||
Map<Long, PathBookmarkGroupVO> groupMap = groups.stream()
|
||||
.collect(Collectors.toMap(PathBookmarkGroupVO::getId, Function.identity()));
|
||||
groupMap.forEach((groupId, group) -> {
|
||||
List<PathBookmarkVO> groupedItems = items.stream()
|
||||
.filter(s -> groupId.equals(s.getGroupId()))
|
||||
.collect(Collectors.toList());
|
||||
group.setItems(groupedItems);
|
||||
});
|
||||
// 未分组数据
|
||||
List<PathBookmarkVO> ungroupedItems = items.stream()
|
||||
.filter(s -> s.getGroupId() == null)
|
||||
.collect(Collectors.toList());
|
||||
return PathBookmarkWrapperVO.builder()
|
||||
.groups(groups)
|
||||
.ungroupedItems(ungroupedItems)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PathBookmarkVO> getPathBookmarkList() {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
String cacheKey = PathBookmarkCacheKeyDefine.PATH_BOOKMARK.format(userId);
|
||||
// 查询缓存
|
||||
List<PathBookmarkCacheDTO> list = RedisMaps.valuesJson(cacheKey, PathBookmarkCacheKeyDefine.PATH_BOOKMARK);
|
||||
if (list.isEmpty()) {
|
||||
// 查询数据库
|
||||
list = pathBookmarkDAO.of()
|
||||
.createWrapper()
|
||||
.eq(PathBookmarkDO::getUserId, userId)
|
||||
.then()
|
||||
.list(PathBookmarkConvert.MAPPER::toCache);
|
||||
// 设置屏障 防止穿透
|
||||
CacheBarriers.checkBarrier(list, PathBookmarkCacheDTO::new);
|
||||
// 设置缓存
|
||||
RedisMaps.putAllJson(cacheKey, PathBookmarkCacheKeyDefine.PATH_BOOKMARK, s -> s.getId().toString(), list);
|
||||
}
|
||||
// 删除屏障
|
||||
CacheBarriers.removeBarrier(list);
|
||||
// 转换
|
||||
return list.stream()
|
||||
.map(PathBookmarkConvert.MAPPER::to)
|
||||
.sorted(Comparator.comparing(PathBookmarkVO::getId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deletePathBookmarkById(Long id) {
|
||||
Long userId = SecurityUtils.getLoginUserId();
|
||||
log.info("PathBookmarkService-deletePathBookmarkById id: {}", id);
|
||||
// 检查数据是否存在
|
||||
PathBookmarkDO record = pathBookmarkDAO.selectById(id);
|
||||
Valid.notNull(record, ErrorMessage.DATA_ABSENT);
|
||||
// 删除
|
||||
int effect = pathBookmarkDAO.deleteById(id);
|
||||
log.info("PathBookmarkService-deletePathBookmarkById id: {}, effect: {}", id, effect);
|
||||
// 删除缓存
|
||||
RedisMaps.delete(PathBookmarkCacheKeyDefine.PATH_BOOKMARK.format(userId), id);
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer setGroupNull(Long userId, Long groupId) {
|
||||
int effect = pathBookmarkDAO.setGroupIdWithNull(groupId);
|
||||
// 删除缓存
|
||||
RedisMaps.delete(PathBookmarkCacheKeyDefine.PATH_BOOKMARK.format(userId));
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByGroupId(Long userId, Long groupId) {
|
||||
int effect = pathBookmarkDAO.deleteByGroupId(groupId);
|
||||
// 删除缓存
|
||||
RedisMaps.delete(PathBookmarkCacheKeyDefine.PATH_BOOKMARK.format(userId));
|
||||
return effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否存在
|
||||
*
|
||||
* @param domain domain
|
||||
*/
|
||||
private void checkPathBookmarkPresent(PathBookmarkDO domain) {
|
||||
// 构造条件
|
||||
LambdaQueryWrapper<PathBookmarkDO> wrapper = pathBookmarkDAO.wrapper()
|
||||
// 更新时忽略当前记录
|
||||
.ne(PathBookmarkDO::getId, domain.getId())
|
||||
// 用其他字段做重复校验
|
||||
.eq(PathBookmarkDO::getUserId, domain.getUserId())
|
||||
.eq(PathBookmarkDO::getGroupId, domain.getGroupId())
|
||||
.eq(PathBookmarkDO::getName, domain.getName());
|
||||
// 检查是否存在
|
||||
boolean present = pathBookmarkDAO.of(wrapper).present();
|
||||
Valid.isFalse(present, ErrorMessage.DATA_PRESENT);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.orion.ops.module.asset.task;
|
||||
|
||||
import com.orion.ops.framework.redis.core.utils.RedisLocks;
|
||||
import com.orion.ops.module.asset.service.CommandSnippetGroupService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 定时清理未使用的命令片段分组
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/24 23:50
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CommandSnippetGroupAutoClearTask {
|
||||
|
||||
/**
|
||||
* 分布式锁名称
|
||||
*/
|
||||
private static final String LOCK_KEY = "clear:csg:lock";
|
||||
|
||||
@Resource
|
||||
private CommandSnippetGroupService commandSnippetGroupService;
|
||||
|
||||
/**
|
||||
* 清理
|
||||
*/
|
||||
@Scheduled(cron = "0 10 2 * * ?")
|
||||
public void clear() {
|
||||
log.info("CommandSnippetGroupAutoClearTask.clear start");
|
||||
// 获取锁并清理
|
||||
RedisLocks.tryLock(LOCK_KEY, commandSnippetGroupService::clearUnusedGroup);
|
||||
log.info("CommandSnippetGroupAutoClearTask.clear finish");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.orion.ops.module.asset.task;
|
||||
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.time.Dates;
|
||||
import com.orion.ops.framework.common.file.FileClient;
|
||||
import com.orion.ops.framework.redis.core.utils.RedisLocks;
|
||||
import com.orion.ops.module.asset.dao.ExecHostLogDAO;
|
||||
import com.orion.ops.module.asset.define.config.AppExecLogConfig;
|
||||
import com.orion.ops.module.asset.entity.domain.ExecHostLogDO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 执行日志文件自动清理
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/24 23:50
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@ConditionalOnProperty(value = "app.exec-log.auto-clear", havingValue = "true", matchIfMissing = true)
|
||||
public class ExecLogFileAutoClearTask {
|
||||
|
||||
/**
|
||||
* 分布式锁名称
|
||||
*/
|
||||
private static final String LOCK_KEY = "clear:elf:lock";
|
||||
|
||||
@Resource
|
||||
private AppExecLogConfig appExecLogConfig;
|
||||
|
||||
@Resource
|
||||
private FileClient logsFileClient;
|
||||
|
||||
@Resource
|
||||
private ExecHostLogDAO execHostLogDAO;
|
||||
|
||||
/**
|
||||
* 清理
|
||||
*/
|
||||
@Scheduled(cron = "0 0 3 * * ?")
|
||||
public void clear() {
|
||||
log.info("ExecLogFileAutoClearTask.clear start");
|
||||
// 获取锁并且执行
|
||||
RedisLocks.tryLock(LOCK_KEY, this::doClearFile);
|
||||
log.info("ExecLogFileAutoClearTask.clear finish");
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行清理文件
|
||||
*/
|
||||
private void doClearFile() {
|
||||
// 删除的时间区间
|
||||
String maxPeriod = Dates.stream()
|
||||
.subDay(appExecLogConfig.getKeepPeriod())
|
||||
.format();
|
||||
// 获取需要删除的最大id
|
||||
ExecHostLogDO hostLog = execHostLogDAO.of()
|
||||
.createWrapper()
|
||||
.select(ExecHostLogDO::getLogId, ExecHostLogDO::getLogPath)
|
||||
.lt(ExecHostLogDO::getCreateTime, maxPeriod)
|
||||
.orderByDesc(ExecHostLogDO::getId)
|
||||
.then()
|
||||
.getOne();
|
||||
if (hostLog == null) {
|
||||
return;
|
||||
}
|
||||
// 获取执行日志根目录
|
||||
String hostLogPath = logsFileClient.getAbsolutePath(hostLog.getLogPath());
|
||||
String execLogPath = Files1.getParentPath(hostLogPath);
|
||||
String parentPath = Files1.getParentPath(execLogPath);
|
||||
// 获取需要删除的文件
|
||||
List<File> files = Files1.listFilesFilter(parentPath, s -> {
|
||||
if (!Strings.isInteger(s.getName())) {
|
||||
return false;
|
||||
}
|
||||
return Long.parseLong(s.getName()) <= hostLog.getLogId();
|
||||
}, false, true);
|
||||
if (files.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// 删除日志文件
|
||||
files.forEach(Files1::delete);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.orion.ops.module.asset.task;
|
||||
|
||||
import com.orion.ops.framework.redis.core.utils.RedisLocks;
|
||||
import com.orion.ops.module.asset.service.PathBookmarkGroupService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 定时清理未使用的路径标签分组
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/4/24 23:50
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class PathBookmarkGroupAutoClearTask {
|
||||
|
||||
/**
|
||||
* 分布式锁名称
|
||||
*/
|
||||
private static final String LOCK_KEY = "clear:pbg:lock";
|
||||
|
||||
@Resource
|
||||
private PathBookmarkGroupService pathBookmarkGroupService;
|
||||
|
||||
/**
|
||||
* 清理
|
||||
*/
|
||||
@Scheduled(cron = "0 20 2 * * ?")
|
||||
public void clear() {
|
||||
log.info("PathBookmarkGroupAutoClearTask.clear start");
|
||||
// 获取锁并清理
|
||||
RedisLocks.tryLock(LOCK_KEY, pathBookmarkGroupService::clearUnusedGroup);
|
||||
log.info("PathBookmarkGroupAutoClearTask.clear finish");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,11 @@
|
||||
"name": "app.sftp",
|
||||
"type": "com.orion.ops.module.asset.define.config.AppSftpConfig",
|
||||
"sourceType": "com.orion.ops.module.asset.define.config.AppSftpConfig"
|
||||
},
|
||||
{
|
||||
"name": "app.exec-log",
|
||||
"type": "com.orion.ops.module.asset.define.config.AppExecLogConfig",
|
||||
"sourceType": "com.orion.ops.module.asset.define.config.AppExecLogConfig"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
@@ -41,6 +46,24 @@
|
||||
"type": "java.lang.String",
|
||||
"description": "备份文件名称.",
|
||||
"defaultValue": "bk_${fileName}_${timestamp}"
|
||||
},
|
||||
{
|
||||
"name": "app.exec-log.append-ansi",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "是否拼接 ansi 执行状态日志.",
|
||||
"defaultValue": "true"
|
||||
},
|
||||
{
|
||||
"name": "app.exec-log.auto-clear",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "自动清理执行文件.",
|
||||
"defaultValue": "true"
|
||||
},
|
||||
{
|
||||
"name": "app.exec-log.keep-period",
|
||||
"type": "java.lang.Integer",
|
||||
"description": "保留周期 (天)",
|
||||
"defaultValue": "60"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?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.orion.ops.module.asset.dao.ExecTemplateHostDAO">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.orion.ops.module.asset.entity.domain.ExecTemplateHostDO">
|
||||
<id column="id" property="id"/>
|
||||
<result column="template_id" property="templateId"/>
|
||||
<result column="host_id" property="hostId"/>
|
||||
<result column="create_time" property="createTime"/>
|
||||
<result column="update_time" property="updateTime"/>
|
||||
<result column="creator" property="creator"/>
|
||||
<result column="updater" property="updater"/>
|
||||
<result column="deleted" property="deleted"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, template_id, host_id, create_time, update_time, creator, updater, deleted
|
||||
</sql>
|
||||
|
||||
</mapper>
|
||||
@@ -1,12 +1,15 @@
|
||||
<?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.orion.ops.module.asset.dao.CommandSnippetGroupDAO">
|
||||
<mapper namespace="com.orion.ops.module.asset.dao.PathBookmarkDAO">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="com.orion.ops.module.asset.entity.domain.CommandSnippetGroupDO">
|
||||
<resultMap id="BaseResultMap" type="com.orion.ops.module.asset.entity.domain.PathBookmarkDO">
|
||||
<id column="id" property="id"/>
|
||||
<result column="user_id" property="userId"/>
|
||||
<result column="group_id" property="groupId"/>
|
||||
<result column="name" property="name"/>
|
||||
<result column="type" property="type"/>
|
||||
<result column="path" property="path"/>
|
||||
<result column="create_time" property="createTime"/>
|
||||
<result column="update_time" property="updateTime"/>
|
||||
<result column="creator" property="creator"/>
|
||||
@@ -16,7 +19,7 @@
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, user_id, name, create_time, update_time, creator, updater, deleted
|
||||
id, user_id, group_id, name, type, path, create_time, update_time, creator, updater, deleted
|
||||
</sql>
|
||||
|
||||
</mapper>
|
||||
@@ -74,4 +74,13 @@ public interface DataGroupApi {
|
||||
*/
|
||||
Integer deleteDataGroupById(Long id);
|
||||
|
||||
/**
|
||||
* 删除数据分组
|
||||
*
|
||||
* @param type type
|
||||
* @param idList idList
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteDataGroupByIdList(DataGroupTypeEnum type, List<Long> idList);
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface DataGroupRelApi {
|
||||
* @param groupIdList groupIdList
|
||||
* @param relId relId
|
||||
*/
|
||||
void updateGroupRel(DataGroupTypeEnum type, List<Long> groupIdList, Long relId);
|
||||
void updateRelGroup(DataGroupTypeEnum type, List<Long> groupIdList, Long relId);
|
||||
|
||||
/**
|
||||
* 添加关联
|
||||
@@ -40,14 +40,14 @@ public interface DataGroupRelApi {
|
||||
* @param groupId groupId
|
||||
* @param relId relId
|
||||
*/
|
||||
void addGroupRel(Long groupId, Long relId);
|
||||
void addGroupRel(DataGroupTypeEnum type, Long groupId, Long relId);
|
||||
|
||||
/**
|
||||
* 批量添加关联
|
||||
*
|
||||
* @param list list
|
||||
*/
|
||||
void addGroupRel(List<DataGroupRelCreateDTO> list);
|
||||
void addGroupRel(DataGroupTypeEnum type, List<DataGroupRelCreateDTO> list);
|
||||
|
||||
/**
|
||||
* 通过 type 查询 relId 缓存
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.orion.ops.module.infra.api;
|
||||
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据分组用户 对外服务类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-11-7 18:44
|
||||
*/
|
||||
public interface DataGroupUserApi {
|
||||
|
||||
/**
|
||||
* 创建数据分组
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param dto dto
|
||||
* @return id
|
||||
*/
|
||||
Long createDataGroup(DataGroupTypeEnum type, Long userId, DataGroupCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 通过缓存查询数据分组
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @return rows
|
||||
*/
|
||||
List<DataGroupDTO> getDataGroupList(DataGroupTypeEnum type, Long userId);
|
||||
|
||||
/**
|
||||
* 通过缓存查询数据分组
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @return rows
|
||||
*/
|
||||
List<DataGroupDTO> getDataGroupTree(DataGroupTypeEnum type, Long userId);
|
||||
|
||||
/**
|
||||
* 删除数据分组
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param idList idList
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteDataGroupByIdList(DataGroupTypeEnum type, Long userId, List<Long> idList);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.orion.ops.module.infra.api;
|
||||
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupRelCreateDTO;
|
||||
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* 数据分组用户关联 对外服务类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-11-7 18:44
|
||||
*/
|
||||
public interface DataGroupUserRelApi {
|
||||
|
||||
/**
|
||||
* 设置关联
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param groupIdList groupIdList
|
||||
* @param relId relId
|
||||
*/
|
||||
void updateGroupRel(DataGroupTypeEnum type, Long userId, List<Long> groupIdList, Long relId);
|
||||
|
||||
/**
|
||||
* 添加关联
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param groupId groupId
|
||||
* @param relId relId
|
||||
*/
|
||||
void addGroupRel(DataGroupTypeEnum type, Long userId, Long groupId, Long relId);
|
||||
|
||||
/**
|
||||
* 批量添加关联
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param list list
|
||||
*/
|
||||
void addGroupRel(DataGroupTypeEnum type, Long userId, List<DataGroupRelCreateDTO> list);
|
||||
|
||||
/**
|
||||
* 通过 type 查询 relId 缓存
|
||||
* <p>
|
||||
* groupId - relId
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @return rows
|
||||
*/
|
||||
Map<Long, Set<Long>> getGroupRelList(DataGroupTypeEnum type, Long userId);
|
||||
|
||||
/**
|
||||
* 通过 groupId 查询 relId 缓存
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param groupId groupId
|
||||
* @return relId
|
||||
*/
|
||||
Set<Long> getGroupRelIdByGroupId(DataGroupTypeEnum type, Long userId, Long groupId);
|
||||
|
||||
/**
|
||||
* 通过 relId 查询 groupId
|
||||
*
|
||||
* @param type type
|
||||
* @param relId relId
|
||||
* @return groupId
|
||||
*/
|
||||
Future<Set<Long>> getGroupIdByRelIdAsync(DataGroupTypeEnum type, Long userId, Long relId);
|
||||
|
||||
/**
|
||||
* 删除数据分组关联
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param relId relId
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteByRelId(DataGroupTypeEnum type, Long userId, Long relId);
|
||||
|
||||
/**
|
||||
* 批量删除数据分组关联
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param relIdList relIdList
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteByRelIdList(DataGroupTypeEnum type, Long userId, List<Long> relIdList);
|
||||
|
||||
/**
|
||||
* 批量删除数据分组关联
|
||||
*
|
||||
* @param type type
|
||||
* @param userId userId
|
||||
* @param groupIdList groupIdList
|
||||
* @return effect
|
||||
*/
|
||||
Integer deleteByGroupIdList(DataGroupTypeEnum type, Long userId, List<Long> groupIdList);
|
||||
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public interface FavoriteApi {
|
||||
* @param userId userId
|
||||
* @return relIdList
|
||||
*/
|
||||
Future<List<Long>> getFavoriteRelIdListAsync(FavoriteTypeEnum type, java.lang.Long userId);
|
||||
Future<List<Long>> getFavoriteRelIdListAsync(FavoriteTypeEnum type, Long userId);
|
||||
|
||||
/**
|
||||
* 通过 relId 删除收藏
|
||||
|
||||
@@ -19,6 +19,11 @@ public enum DataGroupTypeEnum {
|
||||
*/
|
||||
COMMAND_SNIPPET,
|
||||
|
||||
/**
|
||||
* 路径书签
|
||||
*/
|
||||
PATH_BOOKMARK,
|
||||
|
||||
;
|
||||
|
||||
public static DataGroupTypeEnum of(String type) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.orion.ops.module.infra.api.impl;
|
||||
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.module.infra.api.DataGroupApi;
|
||||
import com.orion.ops.module.infra.convert.DataGroupProviderConvert;
|
||||
@@ -44,6 +45,7 @@ public class DataGroupApiImpl implements DataGroupApi {
|
||||
Valid.valid(dto);
|
||||
DataGroupCreateRequest request = DataGroupProviderConvert.MAPPER.toRequest(dto);
|
||||
request.setType(type.name());
|
||||
request.setUserId(Const.SYSTEM_USER_ID);
|
||||
return dataGroupService.createDataGroup(request);
|
||||
}
|
||||
|
||||
@@ -63,13 +65,13 @@ public class DataGroupApiImpl implements DataGroupApi {
|
||||
|
||||
@Override
|
||||
public List<DataGroupDTO> getDataGroupList(DataGroupTypeEnum type) {
|
||||
List<DataGroupCacheDTO> rows = dataGroupService.getDataGroupListByCache(type.name());
|
||||
List<DataGroupCacheDTO> rows = dataGroupService.getDataGroupListByCache(type.name(), Const.SYSTEM_USER_ID);
|
||||
return DataGroupProviderConvert.MAPPER.toList(rows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataGroupDTO> getDataGroupTree(DataGroupTypeEnum type) {
|
||||
List<DataGroupCacheDTO> rows = dataGroupService.getDataGroupTreeByCache(type.name());
|
||||
List<DataGroupCacheDTO> rows = dataGroupService.getDataGroupTreeByCache(type.name(), Const.SYSTEM_USER_ID);
|
||||
return DataGroupProviderConvert.MAPPER.toList(rows);
|
||||
}
|
||||
|
||||
@@ -86,4 +88,9 @@ public class DataGroupApiImpl implements DataGroupApi {
|
||||
return dataGroupService.deleteDataGroupById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteDataGroupByIdList(DataGroupTypeEnum type, List<Long> idList) {
|
||||
return dataGroupService.deleteDataGroupByIdList(type.name(), Const.SYSTEM_USER_ID, idList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.orion.ops.module.infra.api.impl;
|
||||
|
||||
import com.orion.ops.framework.common.constant.Const;
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.module.infra.api.DataGroupRelApi;
|
||||
import com.orion.ops.module.infra.convert.DataGroupRelProviderConvert;
|
||||
@@ -43,28 +44,28 @@ public class DataGroupRelApiImpl implements DataGroupRelApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateGroupRel(DataGroupTypeEnum type, List<Long> groupIdList, Long relId) {
|
||||
public void updateRelGroup(DataGroupTypeEnum type, List<Long> groupIdList, Long relId) {
|
||||
Valid.notNull(relId);
|
||||
dataGroupRelService.updateGroupRel(type.name(), groupIdList, relId);
|
||||
dataGroupRelService.updateRelGroup(type.name(), Const.SYSTEM_USER_ID, groupIdList, relId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroupRel(Long groupId, Long relId) {
|
||||
public void addGroupRel(DataGroupTypeEnum type, Long groupId, Long relId) {
|
||||
Valid.notNull(groupId);
|
||||
Valid.notNull(relId);
|
||||
dataGroupRelService.addGroupRel(groupId, relId);
|
||||
dataGroupRelService.addGroupRel(type.name(), groupId, Const.SYSTEM_USER_ID, relId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroupRel(List<DataGroupRelCreateDTO> list) {
|
||||
public void addGroupRel(DataGroupTypeEnum type, List<DataGroupRelCreateDTO> list) {
|
||||
Valid.valid(list);
|
||||
List<DataGroupRelCreateRequest> rows = DataGroupRelProviderConvert.MAPPER.toList(list);
|
||||
dataGroupRelService.addGroupRel(rows);
|
||||
dataGroupRelService.addGroupRel(type.name(), Const.SYSTEM_USER_ID, rows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, Set<Long>> getGroupRelList(DataGroupTypeEnum type) {
|
||||
List<DataGroupRelCacheDTO> rows = dataGroupRelService.getGroupRelListByCache(type.name());
|
||||
List<DataGroupRelCacheDTO> rows = dataGroupRelService.getGroupRelListByCache(type.name(), Const.SYSTEM_USER_ID);
|
||||
return rows.stream().collect(
|
||||
Collectors.groupingBy(
|
||||
DataGroupRelCacheDTO::getGroupId,
|
||||
@@ -81,7 +82,7 @@ public class DataGroupRelApiImpl implements DataGroupRelApi {
|
||||
@Override
|
||||
@Async("asyncExecutor")
|
||||
public Future<Set<Long>> getGroupIdByRelIdAsync(DataGroupTypeEnum type, Long relId) {
|
||||
Set<Long> groupIdList = dataGroupRelService.getGroupRelByRelId(type.name(), relId)
|
||||
Set<Long> groupIdList = dataGroupRelService.getGroupRelByRelId(type.name(), Const.SYSTEM_USER_ID, relId)
|
||||
.stream()
|
||||
.map(DataGroupRelDO::getGroupId)
|
||||
.collect(Collectors.toSet());
|
||||
@@ -90,17 +91,17 @@ public class DataGroupRelApiImpl implements DataGroupRelApi {
|
||||
|
||||
@Override
|
||||
public Integer deleteByRelId(DataGroupTypeEnum type, Long relId) {
|
||||
return dataGroupRelService.deleteByRelId(type.name(), relId);
|
||||
return dataGroupRelService.deleteByRelId(type.name(), Const.SYSTEM_USER_ID, relId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByRelIdList(DataGroupTypeEnum type, List<Long> relIdList) {
|
||||
return dataGroupRelService.deleteByRelIdList(type.name(), relIdList);
|
||||
return dataGroupRelService.deleteByRelIdList(type.name(), Const.SYSTEM_USER_ID, relIdList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByGroupIdList(DataGroupTypeEnum type, List<Long> groupIdList) {
|
||||
return dataGroupRelService.deleteByGroupIdList(type.name(), groupIdList);
|
||||
return dataGroupRelService.deleteByGroupIdList(type.name(), Const.SYSTEM_USER_ID, groupIdList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.orion.ops.module.infra.api.impl;
|
||||
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.module.infra.api.DataGroupUserApi;
|
||||
import com.orion.ops.module.infra.convert.DataGroupProviderConvert;
|
||||
import com.orion.ops.module.infra.entity.dto.DataGroupCacheDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupDTO;
|
||||
import com.orion.ops.module.infra.entity.request.data.DataGroupCreateRequest;
|
||||
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||
import com.orion.ops.module.infra.service.DataGroupService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据分组 对外服务实现类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-11-7 18:44
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DataGroupUserApiImpl implements DataGroupUserApi {
|
||||
|
||||
@Resource
|
||||
private DataGroupService dataGroupService;
|
||||
|
||||
@Override
|
||||
public Long createDataGroup(DataGroupTypeEnum type, Long userId, DataGroupCreateDTO dto) {
|
||||
Valid.valid(dto);
|
||||
DataGroupCreateRequest request = DataGroupProviderConvert.MAPPER.toRequest(dto);
|
||||
request.setType(type.name());
|
||||
request.setUserId(userId);
|
||||
return dataGroupService.createDataGroup(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataGroupDTO> getDataGroupList(DataGroupTypeEnum type, Long userId) {
|
||||
List<DataGroupCacheDTO> rows = dataGroupService.getDataGroupListByCache(type.name(), userId);
|
||||
return DataGroupProviderConvert.MAPPER.toList(rows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DataGroupDTO> getDataGroupTree(DataGroupTypeEnum type, Long userId) {
|
||||
List<DataGroupCacheDTO> rows = dataGroupService.getDataGroupTreeByCache(type.name(), userId);
|
||||
return DataGroupProviderConvert.MAPPER.toList(rows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteDataGroupByIdList(DataGroupTypeEnum type, Long userId, List<Long> idList) {
|
||||
return dataGroupService.deleteDataGroupByIdList(type.name(), userId, idList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.orion.ops.module.infra.api.impl;
|
||||
|
||||
import com.orion.ops.framework.common.utils.Valid;
|
||||
import com.orion.ops.module.infra.api.DataGroupUserRelApi;
|
||||
import com.orion.ops.module.infra.convert.DataGroupRelProviderConvert;
|
||||
import com.orion.ops.module.infra.entity.domain.DataGroupRelDO;
|
||||
import com.orion.ops.module.infra.entity.dto.DataGroupRelCacheDTO;
|
||||
import com.orion.ops.module.infra.entity.dto.data.DataGroupRelCreateDTO;
|
||||
import com.orion.ops.module.infra.entity.request.data.DataGroupRelCreateRequest;
|
||||
import com.orion.ops.module.infra.enums.DataGroupTypeEnum;
|
||||
import com.orion.ops.module.infra.service.DataGroupRelService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 数据分组关联 对外服务实现类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-11-7 18:44
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DataGroupUserRelApiImpl implements DataGroupUserRelApi {
|
||||
|
||||
@Resource
|
||||
private DataGroupRelService dataGroupRelService;
|
||||
|
||||
@Override
|
||||
public void updateGroupRel(DataGroupTypeEnum type, Long userId, List<Long> groupIdList, Long relId) {
|
||||
Valid.notNull(relId);
|
||||
dataGroupRelService.updateRelGroup(type.name(), userId, groupIdList, relId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroupRel(DataGroupTypeEnum type, Long userId, Long groupId, Long relId) {
|
||||
Valid.notNull(groupId);
|
||||
Valid.notNull(relId);
|
||||
dataGroupRelService.addGroupRel(type.name(), userId, groupId, relId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGroupRel(DataGroupTypeEnum type, Long userId, List<DataGroupRelCreateDTO> list) {
|
||||
Valid.valid(list);
|
||||
List<DataGroupRelCreateRequest> rows = DataGroupRelProviderConvert.MAPPER.toList(list);
|
||||
dataGroupRelService.addGroupRel(type.name(), userId, rows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, Set<Long>> getGroupRelList(DataGroupTypeEnum type, Long userId) {
|
||||
List<DataGroupRelCacheDTO> rows = dataGroupRelService.getGroupRelListByCache(type.name(), userId);
|
||||
return rows.stream().collect(
|
||||
Collectors.groupingBy(
|
||||
DataGroupRelCacheDTO::getGroupId,
|
||||
Collectors.mapping(DataGroupRelCacheDTO::getRelId, Collectors.toSet())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getGroupRelIdByGroupId(DataGroupTypeEnum type, Long userId, Long groupId) {
|
||||
List<Long> rows = dataGroupRelService.getGroupRelIdListByCache(type.name(), groupId);
|
||||
return new HashSet<>(rows);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Async("asyncExecutor")
|
||||
public Future<Set<Long>> getGroupIdByRelIdAsync(DataGroupTypeEnum type, Long userId, Long relId) {
|
||||
Set<Long> groupIdList = dataGroupRelService.getGroupRelByRelId(type.name(), userId, relId)
|
||||
.stream()
|
||||
.map(DataGroupRelDO::getGroupId)
|
||||
.collect(Collectors.toSet());
|
||||
return CompletableFuture.completedFuture(groupIdList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByRelId(DataGroupTypeEnum type, Long userId, Long relId) {
|
||||
return dataGroupRelService.deleteByRelId(type.name(), userId, relId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByRelIdList(DataGroupTypeEnum type, Long userId, List<Long> relIdList) {
|
||||
return dataGroupRelService.deleteByRelIdList(type.name(), userId, relIdList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer deleteByGroupIdList(DataGroupTypeEnum type, Long userId, List<Long> groupIdList) {
|
||||
return dataGroupRelService.deleteByGroupIdList(type.name(), userId, groupIdList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,4 +40,12 @@ public interface SystemRoleDAO extends IMapper<SystemRoleDO> {
|
||||
*/
|
||||
Long getRoleIdByUserIdAndRoleCode(@Param("userId") Long userId, @Param("code") String code);
|
||||
|
||||
/**
|
||||
* 查询用户角色
|
||||
*
|
||||
* @param userId userId
|
||||
* @return roles
|
||||
*/
|
||||
List<SystemRoleDO> selectRoleByUserId(@Param("userId") Long userId);
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public interface DataExtraCacheKeyDefine {
|
||||
.desc("数据拓展信息 ${userId} ${type} ${item}")
|
||||
.type(String.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -18,19 +18,19 @@ import java.util.concurrent.TimeUnit;
|
||||
public interface DataGroupCacheKeyDefine {
|
||||
|
||||
CacheKeyDefine DATA_GROUP_LIST = new CacheKeyBuilder()
|
||||
.key("data:group-list:{}")
|
||||
.desc("数据分组列表结构 ${type}")
|
||||
.key("data:group-list:{}:{}")
|
||||
.desc("数据分组列表结构 ${type} ${userId}")
|
||||
.type(DataGroupCacheDTO.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine DATA_GROUP_TREE = new CacheKeyBuilder()
|
||||
.key("data:group-tree:{}")
|
||||
.desc("数据分组树结构 ${type}")
|
||||
.key("data:group-tree:{}:{}")
|
||||
.desc("数据分组树结构 ${type} ${userId}")
|
||||
.type(DataGroupCacheDTO.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine DATA_GROUP_REL_GROUP = new CacheKeyBuilder()
|
||||
@@ -38,15 +38,15 @@ public interface DataGroupCacheKeyDefine {
|
||||
.desc("数据分组数据关联-分组 ${groupId}")
|
||||
.type(Long.class)
|
||||
.struct(RedisCacheStruct.LIST)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine DATA_GROUP_REL_TYPE = new CacheKeyBuilder()
|
||||
.key("data:group-rel:type:{}")
|
||||
.desc("数据分组数据关联-类型 ${type}")
|
||||
.key("data:group-rel:type:{}:{}")
|
||||
.desc("数据分组数据关联-类型 ${type} ${userId}")
|
||||
.type(DataGroupRelCacheDTO.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public interface DataPermissionCacheKeyDefine {
|
||||
.desc("用户所有数据权限 ${type} ${userId}")
|
||||
.type(Long.class)
|
||||
.struct(RedisCacheStruct.LIST)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public interface DictCacheKeyDefine {
|
||||
.desc("字典配置项")
|
||||
.type(DictKeyCacheDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine DICT_SCHEMA = new CacheKeyBuilder()
|
||||
@@ -30,7 +30,7 @@ public interface DictCacheKeyDefine {
|
||||
.desc("字典配置项 schema ${key}")
|
||||
.type(JSONObject.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine DICT_VALUE = new CacheKeyBuilder()
|
||||
@@ -38,7 +38,7 @@ public interface DictCacheKeyDefine {
|
||||
.desc("字典配置值 ${key}")
|
||||
.type(JSONObject.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public interface FavoriteCacheKeyDefine {
|
||||
.desc("收藏信息 ${type} ${userId}")
|
||||
.type(Long.class)
|
||||
.struct(RedisCacheStruct.LIST)
|
||||
.timeout(3, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public interface PreferenceCacheKeyDefine {
|
||||
.desc("用户偏好 ${userId} ${type}")
|
||||
.type(Ref.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public interface UserCacheKeyDefine {
|
||||
.desc("用户信息 ${id}")
|
||||
.type(LoginUser.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine USER_LIST = new CacheKeyBuilder()
|
||||
@@ -30,7 +31,7 @@ public interface UserCacheKeyDefine {
|
||||
.desc("用户列表")
|
||||
.type(UserInfoDTO.class)
|
||||
.struct(RedisCacheStruct.HASH)
|
||||
.timeout(1, TimeUnit.DAYS)
|
||||
.timeout(8, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
CacheKeyDefine LOGIN_FAILED_COUNT = new CacheKeyBuilder()
|
||||
@@ -53,7 +54,7 @@ public interface UserCacheKeyDefine {
|
||||
.desc("用户刷新 token ${id} ${time}")
|
||||
.type(LoginTokenDTO.class)
|
||||
.struct(RedisCacheStruct.STRING)
|
||||
.timeout(28, TimeUnit.HOURS)
|
||||
.timeout(32, TimeUnit.HOURS)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ public class DataGroupDO extends BaseDO {
|
||||
@TableField("type")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
@TableField("user_id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "排序")
|
||||
@TableField("sort")
|
||||
private Integer sort;
|
||||
|
||||
@@ -42,4 +42,8 @@ public class DataGroupRelDO extends BaseDO {
|
||||
@TableField("type")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
@TableField("user_id")
|
||||
private Long userId;
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,15 @@ import java.io.Serializable;
|
||||
@Schema(name = "DataGroupCreateRequest", description = "数据分组 创建请求对象")
|
||||
public class DataGroupCreateRequest implements Serializable {
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 16)
|
||||
@Schema(description = "组类型")
|
||||
private String type;
|
||||
|
||||
@NotNull
|
||||
@Schema(description = "用户id")
|
||||
private Long userId;
|
||||
|
||||
@NotNull
|
||||
@Schema(description = "父id")
|
||||
private Long parentId;
|
||||
@@ -34,9 +43,4 @@ public class DataGroupCreateRequest implements Serializable {
|
||||
@Schema(description = "组名称")
|
||||
private String name;
|
||||
|
||||
@NotBlank
|
||||
@Size(max = 16)
|
||||
@Schema(description = "组类型")
|
||||
private String type;
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user