From 2916dce1489a509947071c2c7ac62650f20e3511 Mon Sep 17 00:00:00 2001 From: cnbugs Date: Sat, 18 Jul 2026 19:54:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=2016=20=E4=B8=AA?= =?UTF-8?q?=E4=B8=AD=E9=97=B4=E4=BB=B6=E7=BB=84=E4=BB=B6=EF=BC=8C=E6=80=BB?= =?UTF-8?q?=E8=AE=A1=2042=20=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 数据库: PostgreSQL, Oracle 搜索引擎: Elasticsearch 消息队列: RocketMQ, Kafka 服务治理: Nacos 分布式协调: ZooKeeper, Etcd 容器化: Docker, Docker Compose 日志监控: Logstash, Kibana, Prometheus, Grafana, Zabbix, Syslog 新增分类: 搜索引擎、消息队列、服务治理、分布式协调、容器化、日志监控 更新 README 组件矩阵与侧边栏计数 --- README.md | 18 +- src/components/Sidebar.vue | 2 +- src/schemas/docker-compose.js | 299 ++++++++++++++++++++++++++++++++ src/schemas/docker.js | 270 +++++++++++++++++++++++++++++ src/schemas/elasticsearch.js | 253 ++++++++++++++++++++++++++++ src/schemas/etcd.js | 254 ++++++++++++++++++++++++++++ src/schemas/grafana.js | 250 +++++++++++++++++++++++++++ src/schemas/index.js | 171 +++++++++++++++++-- src/schemas/kafka.js | 247 +++++++++++++++++++++++++++ src/schemas/kibana.js | 197 ++++++++++++++++++++++ src/schemas/logstash.js | 271 +++++++++++++++++++++++++++++ src/schemas/nacos.js | 241 ++++++++++++++++++++++++++ src/schemas/oracle.js | 239 ++++++++++++++++++++++++++ src/schemas/postgresql.js | 229 +++++++++++++++++++++++++ src/schemas/prometheus.js | 245 +++++++++++++++++++++++++++ src/schemas/rocketmq.js | 197 ++++++++++++++++++++++ src/schemas/syslog.js | 309 ++++++++++++++++++++++++++++++++++ src/schemas/zabbix.js | 248 +++++++++++++++++++++++++++ src/schemas/zookeeper.js | 215 +++++++++++++++++++++++ 19 files changed, 4140 insertions(+), 15 deletions(-) create mode 100644 src/schemas/docker-compose.js create mode 100644 src/schemas/docker.js create mode 100644 src/schemas/elasticsearch.js create mode 100644 src/schemas/etcd.js create mode 100644 src/schemas/grafana.js create mode 100644 src/schemas/kafka.js create mode 100644 src/schemas/kibana.js create mode 100644 src/schemas/logstash.js create mode 100644 src/schemas/nacos.js create mode 100644 src/schemas/oracle.js create mode 100644 src/schemas/postgresql.js create mode 100644 src/schemas/prometheus.js create mode 100644 src/schemas/rocketmq.js create mode 100644 src/schemas/syslog.js create mode 100644 src/schemas/zabbix.js create mode 100644 src/schemas/zookeeper.js diff --git a/README.md b/README.md index a797915..4a9a4d1 100644 --- a/README.md +++ b/README.md @@ -37,14 +37,19 @@ --- -## 🧩 支持组件(26 个) +## 🧩 支持组件(42 个) | 分类 | 组件 | 输出格式 | 核心配置项 | |------|------|----------|------------| | 代理与 Web | **NGINX** | `.conf` | HTTP/HTTPS 端口、域名、SSL 证书、反向代理、Gzip、CORS | | 缓存 | **Redis** | `.conf` | 单机/哨兵/集群模式、端口、内存限制、RDB/AOF 持久化、密码 | | 数据库 | **MySQL** | `.cnf` | 版本(5.7/8.0)、Buffer Pool 自动计算、字符集、慢查询、主从复制 | +| 数据库 | **PostgreSQL** | `.conf` | 共享缓冲区、WAL 配置、SSL、连接数、慢查询阈值 | | 数据库 | **MongoDB** | `.conf` | 端口、WiredTiger 引擎、认证、TLS、副本集、Oplog、压缩算法 | +| 数据库 | **Oracle** | `.ora` | SGA/PGA 内存、进程数、字符集、归档日志、审计 | +| 搜索引擎 | **Elasticsearch** | `.yml` | 集群名称、节点角色、发现方式、堆内存、安全、慢日志 | +| 消息队列 | **RocketMQ** | `.conf` | Broker 名称、NameServer 地址、刷盘策略、消息大小 | +| 消息队列 | **Kafka** | `.properties` | Broker ID、分区数、副本因子、ZooKeeper、日志保留 | | K8S 工作负载 | **Pod** | `.yaml` | 容器镜像、端口、资源限制、环境变量、重启策略 | | K8S 工作负载 | **Deployment** | `.yaml` | 镜像、副本数、资源限制、健康检查、滚动更新策略 | | K8S 工作负载 | **StatefulSet** | `.yaml` | 有状态应用、稳定网络标识、PVC 模板、滚动更新 | @@ -65,6 +70,17 @@ | K8S 安全与权限 | **ClusterRoleBinding** | `.yaml` | 将 ClusterRole 绑定到集群级主体 | | K8S 安全与权限 | **NetworkPolicy** | `.yaml` | 入站/出站流量控制、Pod 选择器、CIDR 规则 | | K8S 集群管理 | **Namespace** | `.yaml` | 命名空间创建、标签管理 | +| 服务治理 | **Nacos** | `.properties` | 端口、数据源、认证、集群模式、日志级别 | +| 分布式协调 | **ZooKeeper** | `.cfg` | 端口、数据目录、集群配置、四字命令、自动清理 | +| 分布式协调 | **Etcd** | `.yml` | 节点名称、监听地址、集群配置、TLS、自动压缩 | +| 容器化 | **Docker** | `.json` | 数据目录、存储驱动、日志配置、镜像加速、网络 | +| 容器化 | **Docker Compose** | `.yml` | 服务定义、端口映射、卷挂载、环境变量、资源限制 | +| 日志监控 | **Logstash** | `.conf` | 输入源、Grok 过滤、GeoIP、输出目标、管道配置 | +| 日志监控 | **Kibana** | `.yml` | 端口、Elasticsearch 连接、SSL、国际化、安全 | +| 日志监控 | **Prometheus** | `.yml` | 采集间隔、告警管理器、采集任务、远程读写、保留策略 | +| 日志监控 | **Grafana** | `.ini` | 端口、数据库、SMTP、匿名访问、日志级别 | +| 日志监控 | **Zabbix** | `.conf` | 端口、数据库、缓存、轮询器、清理频率 | +| 日志监控 | **Syslog** | `.conf` | UDP/TCP/RELP 协议、远程日志、按主机分目录、速率限制 | | 自动化运维 | **Ansible** | `.cfg` | SSH 连接、Pipelining、Become 提权、Forks、事实缓存 | | 自动化运维 | **Ansible Playbook** | `.yaml` | 变量、包管理、服务管理、文件复制、模板渲染、Handlers | diff --git a/src/components/Sidebar.vue b/src/components/Sidebar.vue index 9f95a8c..0f910f2 100644 --- a/src/components/Sidebar.vue +++ b/src/components/Sidebar.vue @@ -60,7 +60,7 @@ diff --git a/src/schemas/docker-compose.js b/src/schemas/docker-compose.js new file mode 100644 index 0000000..6242824 --- /dev/null +++ b/src/schemas/docker-compose.js @@ -0,0 +1,299 @@ +export const dockerComposeSchema = { + id: 'docker-compose', + name: 'Docker Compose', + icon: 'Files', + category: '容器化', + description: 'Docker Compose 多容器编排配置', + format: 'yml', + fileName: 'docker-compose.yml', + groups: [ + { + title: '基础配置', + fields: [ + { + key: 'version', + label: 'Compose 版本', + type: 'select', + options: [ + { label: '3.8 (推荐)', value: '3.8' }, + { label: '3.7', value: '3.7' }, + { label: '3.5', value: '3.5' }, + { label: '2.4', value: '2.4' }, + ], + default: '3.8', + }, + { + key: 'serviceName', + label: '服务名称', + type: 'text', + default: 'my-app', + }, + { + key: 'image', + label: '镜像', + type: 'text', + default: 'nginx:latest', + placeholder: '例如: nginx:latest, redis:7-alpine', + }, + { + key: 'containerName', + label: '容器名称', + type: 'text', + default: 'my-app', + }, + { + key: 'restartPolicy', + label: '重启策略', + type: 'select', + options: [ + { label: 'no (不自动重启)', value: 'no' }, + { label: 'always (总是重启)', value: 'always' }, + { label: 'unless-stopped (除非手动停止)', value: 'unless-stopped' }, + { label: 'on-failure (失败时重启)', value: 'on-failure' }, + ], + default: 'unless-stopped', + }, + ], + }, + { + title: '端口映射', + fields: [ + { + key: 'hostPort', + label: '主机端口', + type: 'number', + min: 1, + max: 65535, + default: 80, + }, + { + key: 'containerPort', + label: '容器端口', + type: 'number', + min: 1, + max: 65535, + default: 80, + }, + ], + }, + { + title: '环境变量', + fields: [ + { + key: 'enableEnvVars', + label: '配置环境变量', + type: 'switch', + default: false, + }, + { + key: 'envVars', + label: '环境变量', + type: 'text', + default: 'KEY=value', + placeholder: '每行一个: KEY=value', + dependsOn: { key: 'enableEnvVars', value: true }, + tip: '每行一个 KEY=value 格式', + }, + ], + }, + { + title: '存储卷', + fields: [ + { + key: 'enableVolumes', + label: '挂载存储卷', + type: 'switch', + default: false, + }, + { + key: 'volumes', + label: '卷映射', + type: 'text', + default: './data:/data', + placeholder: '每行一个: host_path:container_path', + dependsOn: { key: 'enableVolumes', value: true }, + tip: '每行一个,格式: 宿主路径:容器路径', + }, + ], + }, + { + title: '网络配置', + fields: [ + { + key: 'enableNetwork', + label: '自定义网络', + type: 'switch', + default: false, + }, + { + key: 'networkName', + label: '网络名称', + type: 'text', + default: 'my-network', + dependsOn: { key: 'enableNetwork', value: true }, + }, + ], + }, + { + title: '依赖服务', + fields: [ + { + key: 'enableDependsOn', + label: '配置依赖服务', + type: 'switch', + default: false, + }, + { + key: 'dependsOnService', + label: '依赖的服务名', + type: 'text', + default: 'db', + placeholder: '例如: db, redis', + dependsOn: { key: 'enableDependsOn', value: true }, + tip: '多个用逗号分隔', + }, + ], + }, + { + title: '资源限制', + fields: [ + { + key: 'cpuLimit', + label: 'CPU 限制', + type: 'text', + default: '1.0', + tip: '例如: 0.5, 1.0, 2.0', + }, + { + key: 'memoryLimit', + label: '内存限制', + type: 'text', + default: '512M', + tip: '例如: 256M, 512M, 1G', + }, + ], + }, + { + title: '健康检查', + fields: [ + { + key: 'enableHealthcheck', + label: '开启健康检查', + type: 'switch', + default: false, + }, + { + key: 'healthcheckCmd', + label: '检查命令', + type: 'text', + default: 'curl -f http://localhost/ || exit 1', + dependsOn: { key: 'enableHealthcheck', value: true }, + }, + { + key: 'healthcheckInterval', + label: '检查间隔', + type: 'text', + default: '30s', + dependsOn: { key: 'enableHealthcheck', value: true }, + }, + { + key: 'healthcheckTimeout', + label: '超时时间', + type: 'text', + default: '10s', + dependsOn: { key: 'enableHealthcheck', value: true }, + }, + { + key: 'healthcheckRetries', + label: '重试次数', + type: 'number', + min: 1, + max: 10, + default: 3, + dependsOn: { key: 'enableHealthcheck', value: true }, + }, + ], + }, + ], +} + +export function generateDockerComposeYml(config) { + const lines = [] + lines.push(`# Docker Compose 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + lines.push(`version: '${config.version}'`) + lines.push(``) + lines.push(`services:`) + lines.push(` ${config.serviceName}:`) + lines.push(` image: ${config.image}`) + lines.push(` container_name: ${config.containerName}`) + lines.push(` restart: ${config.restartPolicy}`) + lines.push(``) + + // 端口映射 + lines.push(` ports:`) + lines.push(` - "${config.hostPort}:${config.containerPort}"`) + lines.push(``) + + // 环境变量 + if (config.enableEnvVars && config.envVars) { + lines.push(` environment:`) + const vars = config.envVars.split('\n').map((v) => v.trim()).filter(Boolean) + for (const v of vars) { + lines.push(` - ${v}`) + } + lines.push(``) + } + + // 存储卷 + if (config.enableVolumes && config.volumes) { + lines.push(` volumes:`) + const vols = config.volumes.split('\n').map((v) => v.trim()).filter(Boolean) + for (const v of vols) { + lines.push(` - ${v}`) + } + lines.push(``) + } + + // 依赖服务 + if (config.enableDependsOn && config.dependsOnService) { + lines.push(` depends_on:`) + const deps = config.dependsOnService.split(',').map((d) => d.trim()).filter(Boolean) + for (const dep of deps) { + lines.push(` - ${dep}`) + } + lines.push(``) + } + + // 资源限制 + lines.push(` deploy:`) + lines.push(` resources:`) + lines.push(` limits:`) + lines.push(` cpus: '${config.cpuLimit}'`) + lines.push(` memory: ${config.memoryLimit}`) + lines.push(``) + + // 健康检查 + if (config.enableHealthcheck) { + lines.push(` healthcheck:`) + lines.push(` test: ["CMD-SHELL", "${config.healthcheckCmd}"]`) + lines.push(` interval: ${config.healthcheckInterval}`) + lines.push(` timeout: ${config.healthcheckTimeout}`) + lines.push(` retries: ${config.healthcheckRetries}`) + lines.push(``) + } + + // 网络配置 + if (config.enableNetwork && config.networkName) { + lines.push(` networks:`) + lines.push(` - ${config.networkName}`) + lines.push(``) + lines.push(`networks:`) + lines.push(` ${config.networkName}:`) + lines.push(` driver: bridge`) + } + + return lines.join('\n') +} diff --git a/src/schemas/docker.js b/src/schemas/docker.js new file mode 100644 index 0000000..d95c424 --- /dev/null +++ b/src/schemas/docker.js @@ -0,0 +1,270 @@ +export const dockerSchema = { + id: 'docker', + name: 'Docker', + icon: 'Box', + category: '容器化', + description: 'Docker 守护进程配置', + format: 'json', + fileName: 'daemon.json', + groups: [ + { + title: '存储配置', + fields: [ + { + key: 'dataRoot', + label: '数据根目录', + type: 'text', + default: '/var/lib/docker', + tip: 'Docker 数据存储路径', + }, + { + key: 'storageDriver', + label: '存储驱动', + type: 'select', + options: [ + { label: 'overlay2 (推荐)', value: 'overlay2' }, + { label: 'aufs', value: 'aufs' }, + { label: 'btrfs', value: 'btrfs' }, + ], + default: 'overlay2', + }, + ], + }, + { + title: '日志配置', + fields: [ + { + key: 'logDriver', + label: '日志驱动', + type: 'select', + options: [ + { label: 'json-file (默认)', value: 'json-file' }, + { label: 'syslog', value: 'syslog' }, + { label: 'journald', value: 'journald' }, + { label: 'fluentd', value: 'fluentd' }, + ], + default: 'json-file', + }, + { + key: 'logMaxSize', + label: '单个日志文件最大大小', + type: 'text', + default: '10m', + tip: '例如 10m、100m、1g', + }, + { + key: 'logMaxFile', + label: '最大日志文件数', + type: 'number', + min: 1, + max: 10, + default: 3, + }, + ], + }, + { + title: '镜像仓库', + fields: [ + { + key: 'registryMirrors', + label: '镜像加速地址', + type: 'text', + default: 'https://mirror.ccs.tencentyun.com', + tip: '多个用逗号分隔', + }, + { + key: 'insecureRegistries', + label: '非安全仓库', + type: 'text', + default: '', + placeholder: '例如: 192.168.1.100:5000', + tip: '留空则不设置', + }, + ], + }, + { + title: '运行时配置', + fields: [ + { + key: 'liveRestore', + label: '实时恢复', + type: 'switch', + default: true, + tip: 'Docker 守护进程重启时保持容器运行', + }, + { + key: 'experimental', + label: '实验性功能', + type: 'switch', + default: false, + tip: '开启实验性特性', + }, + { + key: 'defaultRuntime', + label: '默认运行时', + type: 'select', + options: [ + { label: 'runc (标准)', value: 'runc' }, + { label: 'nvidia (GPU)', value: 'nvidia' }, + ], + default: 'runc', + tip: 'GPU 场景选择 nvidia', + }, + { + key: 'maxConcurrentDownloads', + label: '最大并发下载数', + type: 'number', + min: 1, + max: 20, + default: 3, + }, + { + key: 'maxConcurrentUploads', + label: '最大并发上传数', + type: 'number', + min: 1, + max: 10, + default: 5, + }, + ], + }, + { + title: '网络配置', + fields: [ + { + key: 'bip', + label: 'docker0 网桥 IP', + type: 'text', + default: '172.17.0.1/16', + tip: 'docker0 网桥 IP', + }, + { + key: 'defaultAddressPool', + label: '自定义网络地址池', + type: 'text', + default: '10.10.0.0/16', + placeholder: '例如: 10.10.0.0/16', + tip: '自定义网络地址池', + }, + { + key: 'dns', + label: 'DNS 服务器', + type: 'text', + default: '8.8.8.8,8.8.4.4', + tip: '多个用逗号分隔', + }, + ], + }, + { + title: '监控与指标', + fields: [ + { + key: 'enableMetrics', + label: '开启指标收集', + type: 'switch', + default: false, + tip: '暴露 Prometheus 格式指标', + }, + { + key: 'metricsAddress', + label: '指标监听地址', + type: 'text', + default: '0.0.0.0:9323', + dependsOn: { key: 'enableMetrics', value: true }, + }, + ], + }, + { + title: 'TLS 安全', + fields: [ + { + key: 'enableTls', + label: '启用 TLS', + type: 'switch', + default: false, + tip: '启用 Docker API 的 TLS 加密通信', + }, + { + key: 'tlscacert', + label: 'CA 证书路径', + type: 'text', + default: '/etc/docker/ca.pem', + dependsOn: { key: 'enableTls', value: true }, + }, + { + key: 'tlscert', + label: '服务端证书路径', + type: 'text', + default: '/etc/docker/server.pem', + dependsOn: { key: 'enableTls', value: true }, + }, + { + key: 'tlskey', + label: '服务端私钥路径', + type: 'text', + default: '/etc/docker/server-key.pem', + dependsOn: { key: 'enableTls', value: true }, + }, + ], + }, + ], +} + +export function generateDockerDaemonJson(config) { + const obj = {} + + // 存储配置 + obj['data-root'] = config.dataRoot + obj['storage-driver'] = config.storageDriver + + // 日志配置 + obj['log-driver'] = config.logDriver + obj['log-opts'] = { + 'max-size': config.logMaxSize, + 'max-file': String(config.logMaxFile), + } + + // 镜像仓库 + if (config.registryMirrors) { + obj['registry-mirrors'] = config.registryMirrors.split(',').map((m) => m.trim()) + } + if (config.insecureRegistries) { + obj['insecure-registries'] = config.insecureRegistries.split(',').map((r) => r.trim()) + } + + // 运行时配置 + obj['live-restore'] = config.liveRestore + obj['experimental'] = config.experimental + if (config.defaultRuntime !== 'runc') { + obj['default-runtime'] = config.defaultRuntime + } + obj['max-concurrent-downloads'] = config.maxConcurrentDownloads + obj['max-concurrent-uploads'] = config.maxConcurrentUploads + + // 网络配置 + obj['bip'] = config.bip + if (config.defaultAddressPool) { + obj['default-address-pools'] = [ + { base: config.defaultAddressPool, size: 24 }, + ] + } + if (config.dns) { + obj['dns'] = config.dns.split(',').map((d) => d.trim()) + } + + // 监控与指标 + if (config.enableMetrics) { + obj['metrics-addr'] = config.metricsAddress + obj['experimental'] = true + } + + // TLS 安全 + if (config.enableTls) { + obj['tlsverify'] = true + obj['tlscacert'] = config.tlscacert + obj['tlscert'] = config.tlscert + obj['tlskey'] = config.tlskey + } + + return JSON.stringify(obj, null, 2) +} diff --git a/src/schemas/elasticsearch.js b/src/schemas/elasticsearch.js new file mode 100644 index 0000000..f9e44ca --- /dev/null +++ b/src/schemas/elasticsearch.js @@ -0,0 +1,253 @@ +export const elasticsearchSchema = { + id: 'elasticsearch', + name: 'Elasticsearch', + icon: 'Search', + category: '搜索引擎', + description: '分布式全文搜索和分析引擎', + format: 'yml', + fileName: 'elasticsearch.yml', + groups: [ + { + title: '集群配置', + fields: [ + { + key: 'clusterName', + label: '集群名称', + type: 'text', + default: 'my-cluster', + }, + { + key: 'nodeName', + label: '节点名称', + type: 'text', + default: 'node-1', + }, + { + key: 'nodeRoles', + label: '节点角色', + type: 'select', + options: [ + { label: '主节点+数据+预处理+ML (默认)', value: 'master,data,ingest,ml' }, + { label: '主节点+数据', value: 'master,data' }, + { label: '仅主节点', value: 'master' }, + { label: '仅数据节点', value: 'data' }, + { label: '仅协调节点', value: 'ingest' }, + ], + default: 'master,data,ingest,ml', + tip: '生产环境建议主节点和数据节点分离', + }, + ], + }, + { + title: '网络配置', + fields: [ + { + key: 'networkHost', + label: '绑定地址', + type: 'text', + default: '0.0.0.0', + }, + { + key: 'httpPort', + label: 'HTTP 端口', + type: 'number', + min: 1, + max: 65535, + default: 9200, + }, + { + key: 'transportPort', + label: '传输端口', + type: 'number', + min: 1, + max: 65535, + default: 9300, + }, + ], + }, + { + title: '节点发现', + fields: [ + { + key: 'discoveryType', + label: '发现类型', + type: 'select', + options: [ + { label: 'single-node - 单节点模式', value: 'single-node' }, + { label: 'zen - 集群模式', value: 'zen' }, + ], + default: 'single-node', + }, + { + key: 'initialMasterNodes', + label: '初始主节点列表', + type: 'text', + default: 'node-1', + tip: '仅首次启动集群时需要', + dependsOn: { key: 'discoveryType', value: 'zen' }, + }, + ], + }, + { + title: 'JVM 内存', + fields: [ + { + key: 'heapSize', + label: 'JVM 堆内存', + type: 'select', + options: [ + { label: '1g', value: '1g' }, + { label: '2g', value: '2g' }, + { label: '4g', value: '4g' }, + { label: '8g', value: '8g' }, + ], + default: '1g', + tip: '建议不超过物理内存的 50%,且不超过 32GB', + }, + ], + }, + { + title: '安全配置', + fields: [ + { + key: 'enableXpack', + label: '开启 X-Pack', + type: 'switch', + default: false, + }, + { + key: 'enableSecurity', + label: '开启安全功能', + type: 'switch', + default: false, + dependsOn: { key: 'enableXpack', value: true }, + }, + { + key: 'enableSsl', + label: '开启 SSL', + type: 'switch', + default: false, + dependsOn: { key: 'enableSecurity', value: true }, + }, + ], + }, + { + title: '索引性能', + fields: [ + { + key: 'indicesMemoryIndexBufferSize', + label: '索引缓冲区比例', + type: 'select', + options: [ + { label: '10%', value: '10%' }, + { label: '15%', value: '15%' }, + { label: '20% (推荐)', value: '20%' }, + { label: '25%', value: '25%' }, + ], + default: '20%', + tip: '堆内存中用于索引缓冲的比例', + }, + { + key: 'maxResultWindow', + label: '最大结果窗口', + type: 'number', + min: 1000, + max: 100000, + default: 10000, + tip: 'from+size 的最大值', + }, + ], + }, + { + title: '慢日志', + fields: [ + { + key: 'enableSlowLog', + label: '开启慢日志', + type: 'switch', + default: false, + }, + { + key: 'slowLogThresholdTrace', + label: 'Trace 级别阈值', + type: 'text', + default: '500ms', + dependsOn: { key: 'enableSlowLog', value: true }, + }, + ], + }, + { + title: '路径配置', + fields: [ + { + key: 'pathData', + label: '数据目录', + type: 'text', + default: '/var/lib/elasticsearch', + }, + { + key: 'pathLogs', + label: '日志目录', + type: 'text', + default: '/var/log/elasticsearch', + }, + ], + }, + ], +} + +export function generateElasticsearchYml(config) { + const lines = [] + lines.push(`# Elasticsearch 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + lines.push(`# ======================== 集群配置 ========================`) + lines.push(`cluster.name: ${config.clusterName}`) + lines.push(`node.name: ${config.nodeName}`) + lines.push(`node.roles: [${config.nodeRoles}]`) + lines.push(``) + + lines.push(`# ======================== 网络配置 ========================`) + lines.push(`network.host: ${config.networkHost}`) + lines.push(`http.port: ${config.httpPort}`) + lines.push(`transport.port: ${config.transportPort}`) + lines.push(``) + + lines.push(`# ======================== 节点发现 ========================`) + lines.push(`discovery.type: ${config.discoveryType}`) + if (config.discoveryType === 'zen') { + lines.push(`cluster.initial_master_nodes: [${config.initialMasterNodes}]`) + } + lines.push(``) + + lines.push(`# ======================== 路径配置 ========================`) + lines.push(`path.data: ${config.pathData}`) + lines.push(`path.logs: ${config.pathLogs}`) + lines.push(``) + + lines.push(`# ======================== 索引性能 ========================`) + lines.push(`indices.memory.index_buffer_size: ${config.indicesMemoryIndexBufferSize}`) + lines.push(`index.max_result_window: ${config.maxResultWindow}`) + lines.push(``) + + if (config.enableXpack) { + lines.push(`# ======================== X-Pack 配置 ========================`) + lines.push(`xpack.security.enabled: ${config.enableSecurity}`) + if (config.enableSecurity && config.enableSsl) { + lines.push(`xpack.security.transport.ssl.enabled: true`) + lines.push(`xpack.security.http.ssl.enabled: true`) + } + lines.push(``) + } + + if (config.enableSlowLog) { + lines.push(`# ======================== 慢日志配置 ========================`) + lines.push(`index.search.slowlog.threshold.query.trace: ${config.slowLogThresholdTrace}`) + lines.push(`index.search.slowlog.threshold.fetch.trace: ${config.slowLogThresholdTrace}`) + lines.push(`index.indexing.slowlog.threshold.index.trace: ${config.slowLogThresholdTrace}`) + lines.push(``) + } + + return lines.join('\n') +} diff --git a/src/schemas/etcd.js b/src/schemas/etcd.js new file mode 100644 index 0000000..833522a --- /dev/null +++ b/src/schemas/etcd.js @@ -0,0 +1,254 @@ +export const etcdSchema = { + id: 'etcd', + name: 'Etcd', + icon: 'Connection', + category: '分布式协调', + description: '分布式键值存储,用于配置共享和服务发现', + format: 'yml', + fileName: 'etcd.conf.yml', + groups: [ + { + title: '节点配置', + fields: [ + { + key: 'name', + label: '节点名称', + type: 'text', + default: 'etcd-0', + tip: '集群中每个节点的唯一名称', + }, + { + key: 'dataDir', + label: '数据目录', + type: 'text', + default: '/var/lib/etcd', + }, + ], + }, + { + title: '客户端通信', + fields: [ + { + key: 'listenClientUrls', + label: '监听客户端地址', + type: 'text', + default: 'http://0.0.0.0:2379', + tip: '客户端连接地址,多个用逗号分隔', + }, + { + key: 'advertiseClientUrls', + label: '对外通告客户端地址', + type: 'text', + default: 'http://localhost:2379', + tip: '通知客户端使用的地址', + }, + ], + }, + { + title: '节点间通信', + fields: [ + { + key: 'listenPeerUrls', + label: '监听节点间地址', + type: 'text', + default: 'http://0.0.0.0:2380', + tip: '集群内部通信地址', + }, + { + key: 'initialAdvertisePeerUrls', + label: '对外通告节点间地址', + type: 'text', + default: 'http://localhost:2380', + }, + { + key: 'initialCluster', + label: '初始集群配置', + type: 'text', + default: 'etcd-0=http://localhost:2380', + placeholder: 'node1=http://ip1:2380,node2=http://ip2:2380', + tip: '格式: name1=url1,name2=url2', + }, + { + key: 'initialClusterState', + label: '初始集群状态', + type: 'select', + options: [ + { label: 'new (新建集群)', value: 'new' }, + { label: 'existing (加入已有集群)', value: 'existing' }, + ], + default: 'new', + }, + { + key: 'initialClusterToken', + label: '集群令牌', + type: 'text', + default: 'etcd-cluster', + tip: '防止集群间误加入', + }, + ], + }, + { + title: 'TLS 安全', + fields: [ + { + key: 'enableTls', + label: '启用 TLS', + type: 'switch', + default: false, + tip: '生产环境建议开启', + }, + { + key: 'certFile', + label: '证书文件路径', + type: 'text', + default: '/etc/etcd/server.crt', + dependsOn: { key: 'enableTls', value: true }, + }, + { + key: 'keyFile', + label: '私钥文件路径', + type: 'text', + default: '/etc/etcd/server.key', + dependsOn: { key: 'enableTls', value: true }, + }, + ], + }, + { + title: '压缩与存储', + fields: [ + { + key: 'autoCompactionMode', + label: '自动压缩模式', + type: 'select', + options: [ + { label: 'periodic (按时间)', value: 'periodic' }, + { label: 'revision (按修订版本)', value: 'revision' }, + ], + default: 'periodic', + tip: '定期压缩历史数据以释放空间', + }, + { + key: 'autoCompactionRetention', + label: '自动压缩保留', + type: 'text', + default: '1h', + tip: 'periodic 模式: 1h/1d; revision 模式: 版本数', + }, + { + key: 'quotaBackendBytes', + label: '后端存储配额 (字节)', + type: 'number', + min: 0, + max: 8589934592, + default: 8589934592, + tip: '8GB,0 表示不限制', + }, + { + key: 'maxRequestBytes', + label: '最大请求大小 (字节)', + type: 'number', + min: 1048576, + max: 15728640, + default: 1572864, + tip: '1.5MB', + }, + ], + }, + { + title: '性能与调试', + fields: [ + { + key: 'heartbeatInterval', + label: '心跳间隔 (毫秒)', + type: 'number', + min: 50, + max: 3000, + default: 100, + tip: '建议为 electionTimeout 的 1/5~1/10', + }, + { + key: 'electionTimeout', + label: '选举超时 (毫秒)', + type: 'number', + min: 500, + max: 30000, + default: 1000, + tip: '建议为 heartbeatInterval 的 5~10 倍', + }, + { + key: 'enablePprof', + label: '开启 pprof', + type: 'switch', + default: false, + tip: '调试时开启,生产环境建议关闭', + }, + ], + }, + ], +} + +export function generateEtcdYml(config) { + const lines = [] + lines.push(`# Etcd 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // 节点配置 + lines.push(`# 节点配置`) + lines.push(`name: '${config.name}'`) + lines.push(`data-dir: '${config.dataDir}'`) + lines.push(``) + + // 客户端通信 + lines.push(`# 客户端通信`) + const listenClientUrls = config.listenClientUrls.split(',').map((u) => u.trim()) + lines.push(`listen-client-urls: '${listenClientUrls.join(',')}'`) + const advertiseClientUrls = config.advertiseClientUrls.split(',').map((u) => u.trim()) + lines.push(`advertise-client-urls: '${advertiseClientUrls.join(',')}'`) + lines.push(``) + + // 节点间通信 + lines.push(`# 节点间通信`) + const listenPeerUrls = config.listenPeerUrls.split(',').map((u) => u.trim()) + lines.push(`listen-peer-urls: '${listenPeerUrls.join(',')}'`) + const initialAdvertisePeerUrls = config.initialAdvertisePeerUrls.split(',').map((u) => u.trim()) + lines.push(`initial-advertise-peer-urls: '${initialAdvertisePeerUrls.join(',')}'`) + lines.push(`initial-cluster: '${config.initialCluster}'`) + lines.push(`initial-cluster-state: '${config.initialClusterState}'`) + lines.push(`initial-cluster-token: '${config.initialClusterToken}'`) + lines.push(``) + + // TLS 安全 + if (config.enableTls) { + lines.push(`# TLS 安全`) + lines.push(`client-transport-security:`) + lines.push(` cert-file: '${config.certFile}'`) + lines.push(` key-file: '${config.keyFile}'`) + lines.push(` client-cert-auth: true`) + lines.push(` trusted-ca-file: '/etc/etcd/ca.crt'`) + lines.push(`peer-transport-security:`) + lines.push(` cert-file: '${config.certFile}'`) + lines.push(` key-file: '${config.keyFile}'`) + lines.push(` client-cert-auth: true`) + lines.push(` trusted-ca-file: '/etc/etcd/ca.crt'`) + lines.push(``) + } + + // 压缩与存储 + lines.push(`# 压缩与存储`) + lines.push(`auto-compaction-mode: '${config.autoCompactionMode}'`) + lines.push(`auto-compaction-retention: '${config.autoCompactionRetention}'`) + lines.push(`quota-backend-bytes: ${config.quotaBackendBytes}`) + lines.push(`max-request-bytes: ${config.maxRequestBytes}`) + lines.push(``) + + // 性能与调试 + lines.push(`# 性能与调试`) + lines.push(`heartbeat-interval: ${config.heartbeatInterval}`) + lines.push(`election-timeout: ${config.electionTimeout}`) + lines.push(`enable-pprof: ${config.enablePprof}`) + lines.push(`logger: 'zap'`) + lines.push(`log-outputs: ['stderr']`) + + return lines.join('\n') +} diff --git a/src/schemas/grafana.js b/src/schemas/grafana.js new file mode 100644 index 0000000..5591486 --- /dev/null +++ b/src/schemas/grafana.js @@ -0,0 +1,250 @@ +export const grafanaSchema = { + id: 'grafana', + name: 'Grafana', + icon: 'DataLine', + category: '日志监控', + description: '开源数据可视化与监控仪表盘平台', + format: 'ini', + fileName: 'grafana.ini', + groups: [ + { + title: 'HTTP 服务', + fields: [ + { + key: 'httpPort', + label: 'HTTP 端口', + type: 'number', + min: 1, + max: 65535, + default: 3000, + }, + { + key: 'domain', + label: '域名', + type: 'text', + default: 'localhost', + }, + { + key: 'rootUrl', + label: '根 URL', + type: 'text', + default: 'http://localhost:3000/', + tip: '完整访问地址,含协议和路径', + }, + ], + }, + { + title: '管理员账号', + fields: [ + { + key: 'adminUser', + label: '管理员用户名', + type: 'text', + default: 'admin', + }, + { + key: 'adminPassword', + label: '管理员密码', + type: 'text', + default: 'admin', + tip: '生产务必修改', + }, + ], + }, + { + title: '数据库配置', + fields: [ + { + key: 'dbType', + label: '数据库类型', + type: 'select', + options: [ + { label: 'SQLite3 - 文件数据库 (默认)', value: 'sqlite3' }, + { label: 'MySQL', value: 'mysql' }, + { label: 'PostgreSQL', value: 'postgres' }, + ], + default: 'sqlite3', + }, + { + key: 'dbHost', + label: '数据库主机', + type: 'text', + default: 'localhost:3306', + dependsOn: { key: 'dbType', valueNotIn: ['sqlite3'] }, + }, + { + key: 'dbName', + label: '数据库名称', + type: 'text', + default: 'grafana', + dependsOn: { key: 'dbType', valueNotIn: ['sqlite3'] }, + }, + { + key: 'dbUser', + label: '数据库用户', + type: 'text', + default: 'grafana', + dependsOn: { key: 'dbType', valueNotIn: ['sqlite3'] }, + }, + { + key: 'dbPassword', + label: '数据库密码', + type: 'text', + default: '', + dependsOn: { key: 'dbType', valueNotIn: ['sqlite3'] }, + }, + ], + }, + { + title: '认证与安全', + fields: [ + { + key: 'enableAnonymousAuth', + label: '匿名访问', + type: 'switch', + default: false, + tip: '允许无需登录访问', + }, + { + key: 'enableUserSignUp', + label: '允许用户注册', + type: 'switch', + default: false, + }, + { + key: 'enableAlerting', + label: '启用告警', + type: 'switch', + default: true, + }, + ], + }, + { + title: 'SMTP 邮件', + fields: [ + { + key: 'smtpEnabled', + label: '启用 SMTP', + type: 'switch', + default: false, + tip: '用于发送告警邮件', + }, + { + key: 'smtpHost', + label: 'SMTP 服务器', + type: 'text', + default: 'localhost:25', + dependsOn: { key: 'smtpEnabled', value: true }, + }, + { + key: 'smtpFromAddress', + label: '发件人地址', + type: 'text', + default: 'grafana@localhost', + dependsOn: { key: 'smtpEnabled', value: true }, + }, + ], + }, + { + title: '日志配置', + fields: [ + { + key: 'logMode', + label: '日志输出方式', + type: 'select', + options: [ + { label: 'console - 控制台输出', value: 'console' }, + { label: 'file - 输出到文件', value: 'file' }, + ], + default: 'console', + }, + { + key: 'logLevel', + label: '日志级别', + type: 'select', + options: [ + { label: 'INFO', value: 'Info' }, + { label: 'WARN', value: 'Warn' }, + { label: 'DEBUG', value: 'Debug' }, + { label: 'ERROR', value: 'Error' }, + ], + default: 'Info', + }, + ], + }, + ], +} + +export function generateGrafanaIni(config) { + const lines = [] + lines.push(`# Grafana 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // HTTP + lines.push(`[server]`) + lines.push(`protocol = http`) + lines.push(`http_port = ${config.httpPort}`) + lines.push(`domain = ${config.domain}`) + lines.push(`root_url = ${config.rootUrl}`) + lines.push(``) + + // Database + lines.push(`[database]`) + if (config.dbType === 'sqlite3') { + lines.push(`type = sqlite3`) + lines.push(`path = grafana.db`) + } else { + lines.push(`type = ${config.dbType}`) + lines.push(`host = ${config.dbHost}`) + lines.push(`name = ${config.dbName}`) + lines.push(`user = ${config.dbUser}`) + if (config.dbPassword) { + lines.push(`password = ${config.dbPassword}`) + } + } + lines.push(``) + + // Security + lines.push(`[security]`) + lines.push(`admin_user = ${config.adminUser}`) + lines.push(`admin_password = ${config.adminPassword}`) + lines.push(``) + + // Auth + lines.push(`[auth]`) + lines.push(`disable_login_form = false`) + lines.push(`disable_signout_menu = false`) + if (config.enableAnonymousAuth) { + lines.push(``) + lines.push(`[auth.anonymous]`) + lines.push(`enabled = true`) + } + if (config.enableUserSignUp) { + lines.push(``) + lines.push(`[users]`) + lines.push(`allow_sign_up = true`) + } + lines.push(``) + + // Alerting + lines.push(`[alerting]`) + lines.push(`enabled = ${config.enableAlerting}`) + lines.push(``) + + // SMTP + if (config.smtpEnabled) { + lines.push(`[smtp]`) + lines.push(`enabled = true`) + lines.push(`host = ${config.smtpHost}`) + lines.push(`from_address = ${config.smtpFromAddress}`) + lines.push(``) + } + + // Logging + lines.push(`[log]`) + lines.push(`mode = ${config.logMode}`) + lines.push(`level = ${config.logLevel}`) + + return lines.join('\n') +} diff --git a/src/schemas/index.js b/src/schemas/index.js index e88eabf..27ef2fb 100644 --- a/src/schemas/index.js +++ b/src/schemas/index.js @@ -1,73 +1,163 @@ +// ============ 代理与Web ============ import { nginxSchema, generateNginxConf } from './nginx' + +// ============ 缓存 ============ import { redisSchema, generateRedisConf } from './redis' + +// ============ 数据库 ============ import { mysqlSchema, generateMysqlConf } from './mysql' import { mongodbSchema, generateMongodbConf } from './mongodb' -import { k8sDeploymentSchema, generateK8sDeploymentYaml } from './k8s-deployment' -import { k8sServiceSchema, generateK8sServiceYaml } from './k8s-service' -import { ansibleSchema, generateAnsibleCfg } from './ansible' -import { ansiblePlaybookSchema, generateAnsiblePlaybookYaml } from './ansible-playbook' +import { postgresqlSchema, generatePostgresqlConf } from './postgresql' +import { oracleSchema, generateOracleConf } from './oracle' + +// ============ 搜索引擎 ============ +import { elasticsearchSchema, generateElasticsearchYml } from './elasticsearch' + +// ============ 消息队列 ============ +import { rocketmqSchema, generateRocketmqConf } from './rocketmq' +import { kafkaSchema, generateKafkaProperties } from './kafka' + +// ============ K8S 工作负载 ============ import { k8sPodSchema, generateK8sPodYaml } from './k8s-pod' +import { k8sDeploymentSchema, generateK8sDeploymentYaml } from './k8s-deployment' import { k8sStatefulSetSchema, generateK8sStatefulSetYaml } from './k8s-statefulset' import { k8sDaemonSetSchema, generateK8sDaemonSetYaml } from './k8s-daemonset' import { k8sJobSchema, generateK8sJobYaml } from './k8s-job' import { k8sCronJobSchema, generateK8sCronJobYaml } from './k8s-cronjob' + +// ============ K8S 服务发现 ============ +import { k8sServiceSchema, generateK8sServiceYaml } from './k8s-service' import { k8sIngressSchema, generateK8sIngressYaml } from './k8s-ingress' + +// ============ K8S 存储 ============ import { k8sPvSchema, generateK8sPvYaml } from './k8s-pv' import { k8sPvcSchema, generateK8sPvcYaml } from './k8s-pvc' import { k8sStorageClassSchema, generateK8sStorageClassYaml } from './k8s-storageclass' + +// ============ K8S 配置与密钥 ============ import { k8sConfigMapSchema, generateK8sConfigMapYaml } from './k8s-configmap' import { k8sSecretSchema, generateK8sSecretYaml } from './k8s-secret' + +// ============ K8S 安全与权限 ============ import { k8sServiceAccountSchema, generateK8sServiceAccountYaml } from './k8s-serviceaccount' import { k8sRoleSchema, generateK8sRoleYaml } from './k8s-role' import { k8sClusterRoleSchema, generateK8sClusterRoleYaml } from './k8s-clusterrole' import { k8sRoleBindingSchema, generateK8sRoleBindingYaml } from './k8s-rolebinding' import { k8sClusterRoleBindingSchema, generateK8sClusterRoleBindingYaml } from './k8s-clusterrolebinding' import { k8sNetworkPolicySchema, generateK8sNetworkPolicyYaml } from './k8s-networkpolicy' + +// ============ K8S 集群管理 ============ import { k8sNamespaceSchema, generateK8sNamespaceYaml } from './k8s-namespace' +// ============ 服务治理 ============ +import { nacosSchema, generateNacosProperties } from './nacos' + +// ============ 分布式协调 ============ +import { zookeeperSchema, generateZookeeperCfg } from './zookeeper' +import { etcdSchema, generateEtcdYml } from './etcd' + +// ============ 容器化 ============ +import { dockerSchema, generateDockerDaemonJson } from './docker' +import { dockerComposeSchema, generateDockerComposeYml } from './docker-compose' + +// ============ 日志监控 ============ +import { logstashSchema, generateLogstashConf } from './logstash' +import { kibanaSchema, generateKibanaYml } from './kibana' +import { prometheusSchema, generatePrometheusYml } from './prometheus' +import { grafanaSchema, generateGrafanaIni } from './grafana' +import { zabbixSchema, generateZabbixConf } from './zabbix' +import { syslogSchema, generateSyslogConf } from './syslog' + +// ============ 自动化运维 ============ +import { ansibleSchema, generateAnsibleCfg } from './ansible' +import { ansiblePlaybookSchema, generateAnsiblePlaybookYaml } from './ansible-playbook' + +// ============================================================ +// Schema Registry +// ============================================================ + export const schemas = { + // 代理与Web nginx: nginxSchema, + // 缓存 redis: redisSchema, + // 数据库 mysql: mysqlSchema, mongodb: mongodbSchema, - 'k8s-deployment': k8sDeploymentSchema, - 'k8s-service': k8sServiceSchema, - ansible: ansibleSchema, - 'ansible-playbook': ansiblePlaybookSchema, + postgresql: postgresqlSchema, + oracle: oracleSchema, + // 搜索引擎 + elasticsearch: elasticsearchSchema, + // 消息队列 + rocketmq: rocketmqSchema, + kafka: kafkaSchema, + // K8S 工作负载 'k8s-pod': k8sPodSchema, + 'k8s-deployment': k8sDeploymentSchema, 'k8s-statefulset': k8sStatefulSetSchema, 'k8s-daemonset': k8sDaemonSetSchema, 'k8s-job': k8sJobSchema, 'k8s-cronjob': k8sCronJobSchema, + // K8S 服务发现 + 'k8s-service': k8sServiceSchema, 'k8s-ingress': k8sIngressSchema, + // K8S 存储 'k8s-pv': k8sPvSchema, 'k8s-pvc': k8sPvcSchema, 'k8s-storageclass': k8sStorageClassSchema, + // K8S 配置与密钥 'k8s-configmap': k8sConfigMapSchema, 'k8s-secret': k8sSecretSchema, + // K8S 安全与权限 'k8s-serviceaccount': k8sServiceAccountSchema, 'k8s-role': k8sRoleSchema, 'k8s-clusterrole': k8sClusterRoleSchema, 'k8s-rolebinding': k8sRoleBindingSchema, 'k8s-clusterrolebinding': k8sClusterRoleBindingSchema, 'k8s-networkpolicy': k8sNetworkPolicySchema, + // K8S 集群管理 'k8s-namespace': k8sNamespaceSchema, + // 服务治理 + nacos: nacosSchema, + // 分布式协调 + zookeeper: zookeeperSchema, + etcd: etcdSchema, + // 容器化 + docker: dockerSchema, + 'docker-compose': dockerComposeSchema, + // 日志监控 + logstash: logstashSchema, + kibana: kibanaSchema, + prometheus: prometheusSchema, + grafana: grafanaSchema, + zabbix: zabbixSchema, + syslog: syslogSchema, + // 自动化运维 + ansible: ansibleSchema, + 'ansible-playbook': ansiblePlaybookSchema, } +// ============================================================ +// Generator Registry +// ============================================================ + export const generators = { nginx: generateNginxConf, redis: generateRedisConf, mysql: generateMysqlConf, mongodb: generateMongodbConf, - 'k8s-deployment': generateK8sDeploymentYaml, - 'k8s-service': generateK8sServiceYaml, - ansible: generateAnsibleCfg, - 'ansible-playbook': generateAnsiblePlaybookYaml, + postgresql: generatePostgresqlConf, + oracle: generateOracleConf, + elasticsearch: generateElasticsearchYml, + rocketmq: generateRocketmqConf, + kafka: generateKafkaProperties, 'k8s-pod': generateK8sPodYaml, + 'k8s-deployment': generateK8sDeploymentYaml, 'k8s-statefulset': generateK8sStatefulSetYaml, 'k8s-daemonset': generateK8sDaemonSetYaml, 'k8s-job': generateK8sJobYaml, 'k8s-cronjob': generateK8sCronJobYaml, + 'k8s-service': generateK8sServiceYaml, 'k8s-ingress': generateK8sIngressYaml, 'k8s-pv': generateK8sPvYaml, 'k8s-pvc': generateK8sPvcYaml, @@ -81,8 +171,25 @@ export const generators = { 'k8s-clusterrolebinding': generateK8sClusterRoleBindingYaml, 'k8s-networkpolicy': generateK8sNetworkPolicyYaml, 'k8s-namespace': generateK8sNamespaceYaml, + nacos: generateNacosProperties, + zookeeper: generateZookeeperCfg, + etcd: generateEtcdYml, + docker: generateDockerDaemonJson, + 'docker-compose': generateDockerComposeYml, + logstash: generateLogstashConf, + kibana: generateKibanaYml, + prometheus: generatePrometheusYml, + grafana: generateGrafanaIni, + zabbix: generateZabbixConf, + syslog: generateSyslogConf, + ansible: generateAnsibleCfg, + 'ansible-playbook': generateAnsiblePlaybookYaml, } +// ============================================================ +// Sidebar Categories +// ============================================================ + export const categories = [ { name: '代理与Web', @@ -97,7 +204,17 @@ export const categories = [ { name: '数据库', icon: 'Coin', - items: ['mysql', 'mongodb'], + items: ['mysql', 'postgresql', 'mongodb', 'oracle'], + }, + { + name: '搜索引擎', + icon: 'Search', + items: ['elasticsearch'], + }, + { + name: '消息队列', + icon: 'ChatDotRound', + items: ['rocketmq', 'kafka'], }, { name: 'K8S 工作负载', @@ -129,6 +246,26 @@ export const categories = [ icon: 'Grid', items: ['k8s-namespace'], }, + { + name: '服务治理', + icon: 'Connection', + items: ['nacos'], + }, + { + name: '分布式协调', + icon: 'Connection', + items: ['zookeeper', 'etcd'], + }, + { + name: '容器化', + icon: 'Box', + items: ['docker', 'docker-compose'], + }, + { + name: '日志监控', + icon: 'TrendCharts', + items: ['logstash', 'kibana', 'prometheus', 'grafana', 'zabbix', 'syslog'], + }, { name: '自动化运维', icon: 'Files', @@ -136,6 +273,10 @@ export const categories = [ }, ] +// ============================================================ +// Utility Functions +// ============================================================ + export function getDefaultValues(schema) { const defaults = {} for (const group of schema.groups) { @@ -151,9 +292,13 @@ export function getLanguage(format) { conf: 'ini', cnf: 'ini', cfg: 'ini', + ora: 'ini', + yml: 'yaml', yaml: 'yaml', json: 'json', toml: 'toml', + properties: 'properties', + ini: 'ini', } return map[format] || 'plaintext' } diff --git a/src/schemas/kafka.js b/src/schemas/kafka.js new file mode 100644 index 0000000..77ce64a --- /dev/null +++ b/src/schemas/kafka.js @@ -0,0 +1,247 @@ +export const kafkaSchema = { + id: 'kafka', + name: 'Kafka', + icon: 'ChatLineRound', + category: '消息队列', + description: 'Apache Kafka 分布式流处理平台', + format: 'properties', + fileName: 'server.properties', + groups: [ + { + title: 'Broker 基础配置', + fields: [ + { + key: 'brokerId', + label: 'Broker ID', + type: 'number', + min: 0, + max: 10000, + default: 0, + }, + { + key: 'listeners', + label: '监听地址', + type: 'text', + default: 'PLAINTEXT://0.0.0.0:9092', + }, + { + key: 'advertisedListeners', + label: '外部访问地址', + type: 'text', + default: 'PLAINTEXT://localhost:9092', + tip: '外部访问地址', + }, + ], + }, + { + title: 'Topic 与分区', + fields: [ + { + key: 'numPartitions', + label: '默认分区数', + type: 'number', + min: 1, + max: 100, + default: 3, + }, + { + key: 'defaultReplicationFactor', + label: '默认副本因子', + type: 'number', + min: 1, + max: 10, + default: 2, + }, + { + key: 'autoCreateTopicsEnable', + label: '自动创建 Topic', + type: 'switch', + default: false, + tip: '生产建议关闭', + }, + { + key: 'minInsyncReplicas', + label: '最小同步副本数', + type: 'number', + min: 1, + max: 10, + default: 2, + tip: '配合 acks=all 使用', + }, + ], + }, + { + title: '日志存储', + fields: [ + { + key: 'logDirs', + label: '日志存储目录', + type: 'text', + default: '/tmp/kafka-logs', + }, + { + key: 'logRetentionHours', + label: '日志保留时间', + type: 'number', + min: 1, + max: 720, + default: 168, + tip: '7天', + }, + { + key: 'logSegmentBytes', + label: '日志段大小', + type: 'number', + min: 1048576, + max: 2147483647, + default: 1073741824, + tip: '1GB', + }, + { + key: 'logRetentionBytes', + label: '日志保留大小', + type: 'number', + min: -1, + max: 9223372036854775807, + default: -1, + tip: '-1不限制', + }, + ], + }, + { + title: '线程配置', + fields: [ + { + key: 'numIoThreads', + label: 'IO 线程数', + type: 'number', + min: 1, + max: 32, + default: 8, + tip: '处理网络请求的线程数', + }, + { + key: 'numNetworkThreads', + label: '网络线程数', + type: 'number', + min: 1, + max: 32, + default: 3, + tip: '处理网络请求的线程数', + }, + ], + }, + { + title: '消息配置', + fields: [ + { + key: 'messageMaxBytes', + label: '最大消息大小', + type: 'number', + min: 1024, + max: 104857600, + default: 1000012, + tip: '~1MB', + }, + ], + }, + { + title: 'Zookeeper', + fields: [ + { + key: 'zookeeperConnect', + label: 'Zookeeper 地址', + type: 'text', + default: 'localhost:2181', + tip: '多个用逗号分隔', + }, + { + key: 'offsetsRetentionMinutes', + label: '偏移量保留时间', + type: 'number', + min: 1, + max: 100800, + default: 10080, + tip: '7天', + }, + ], + }, + { + title: '安全配置', + fields: [ + { + key: 'enableSsl', + label: '开启 SSL', + type: 'switch', + default: false, + }, + ], + }, + ], +} + +export function generateKafkaProperties(config) { + const lines = [] + lines.push(`# Kafka Broker 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + lines.push(`# ======================== Broker 基础配置 ========================`) + lines.push(`broker.id=${config.brokerId}`) + lines.push(`listeners=${config.listeners}`) + lines.push(`advertised.listeners=${config.advertisedListeners}`) + lines.push(``) + + lines.push(`# ======================== Topic 与分区 ========================`) + lines.push(`num.partitions=${config.numPartitions}`) + lines.push(`default.replication.factor=${config.defaultReplicationFactor}`) + lines.push(`auto.create.topics.enable=${config.autoCreateTopicsEnable}`) + lines.push(`min.insync.replicas=${config.minInsyncReplicas}`) + lines.push(``) + + lines.push(`# ======================== 日志存储 ========================`) + lines.push(`log.dirs=${config.logDirs}`) + lines.push(`log.retention.hours=${config.logRetentionHours}`) + lines.push(`log.segment.bytes=${config.logSegmentBytes}`) + lines.push(`log.retention.bytes=${config.logRetentionBytes}`) + lines.push(`log.cleanup.policy=delete`) + lines.push(`log.flush.interval.messages=10000`) + lines.push(`log.flush.interval.ms=1000`) + lines.push(``) + + lines.push(`# ======================== 线程配置 ========================`) + lines.push(`num.io.threads=${config.numIoThreads}`) + lines.push(`num.network.threads=${config.numNetworkThreads}`) + lines.push(`num.replica.fetchers=1`) + lines.push(`queued.max.requests=500`) + lines.push(``) + + lines.push(`# ======================== 消息配置 ========================`) + lines.push(`message.max.bytes=${config.messageMaxBytes}`) + lines.push(`replica.fetch.max.bytes=${config.messageMaxBytes}`) + lines.push(`offsets.topic.replication.factor=3`) + lines.push(`transaction.state.log.replication.factor=3`) + lines.push(`transaction.state.log.min.isr=2`) + lines.push(``) + + lines.push(`# ======================== Zookeeper ========================`) + lines.push(`zookeeper.connect=${config.zookeeperConnect}`) + lines.push(`zookeeper.connection.timeout.ms=18000`) + lines.push(`offsets.retention.minutes=${config.offsetsRetentionMinutes}`) + lines.push(`group.initial.rebalance.delay.ms=3000`) + lines.push(``) + + if (config.enableSsl) { + lines.push(`# ======================== SSL 配置 ========================`) + lines.push(`security.inter.broker.protocol=SSL`) + lines.push(`ssl.keystore.location=/etc/kafka/ssl/kafka.keystore.jks`) + lines.push(`ssl.keystore.password=changeit`) + lines.push(`ssl.key.password=changeit`) + lines.push(`ssl.truststore.location=/etc/kafka/ssl/kafka.truststore.jks`) + lines.push(`ssl.truststore.password=changeit`) + lines.push(`ssl.client.auth=required`) + lines.push(``) + } + + return lines.join('\n') +} diff --git a/src/schemas/kibana.js b/src/schemas/kibana.js new file mode 100644 index 0000000..0dabe1a --- /dev/null +++ b/src/schemas/kibana.js @@ -0,0 +1,197 @@ +export const kibanaSchema = { + id: 'kibana', + name: 'Kibana', + icon: 'DataAnalysis', + category: '日志监控', + description: 'Elasticsearch 数据可视化与探索平台', + format: 'yml', + fileName: 'kibana.yml', + groups: [ + { + title: '服务配置', + fields: [ + { + key: 'serverPort', + label: '服务端口', + type: 'number', + min: 1, + max: 65535, + default: 5601, + }, + { + key: 'serverHost', + label: '绑定地址', + type: 'text', + default: '0.0.0.0', + tip: '0.0.0.0 允许外部访问', + }, + { + key: 'serverName', + label: '服务名称', + type: 'text', + default: 'kibana', + }, + { + key: 'serverBasePath', + label: '基础路径', + type: 'text', + default: '', + tip: '反向代理路径前缀,如 /kibana', + }, + { + key: 'locale', + label: '界面语言', + type: 'text', + default: 'zh-CN', + tip: '语言代码,如 zh-CN、en', + }, + ], + }, + { + title: 'Elasticsearch 连接', + fields: [ + { + key: 'elasticsearchHosts', + label: 'Elasticsearch 地址', + type: 'text', + default: 'http://localhost:9200', + tip: '多个地址用逗号分隔', + }, + { + key: 'elasticsearchUsername', + label: 'ES 用户名', + type: 'text', + default: 'kibana_system', + }, + { + key: 'elasticsearchPassword', + label: 'ES 密码', + type: 'text', + default: 'changeme', + tip: '生产环境务必修改', + }, + { + key: 'kibanaIndex', + label: 'Kibana 索引', + type: 'text', + default: '.kibana', + }, + { + key: 'defaultAppId', + label: '默认应用', + type: 'text', + default: 'discover', + tip: '登录后默认打开的页面', + }, + ], + }, + { + title: '安全配置', + fields: [ + { + key: 'enableSsl', + label: '启用 SSL', + type: 'switch', + default: false, + tip: '启用 HTTPS 访问', + }, + { + key: 'sslCert', + label: 'SSL 证书文件', + type: 'text', + default: '/etc/kibana/cert.pem', + dependsOn: { key: 'enableSsl', value: true }, + }, + { + key: 'sslKey', + label: 'SSL 私钥文件', + type: 'text', + default: '/etc/kibana/key.pem', + dependsOn: { key: 'enableSsl', value: true }, + }, + { + key: 'xpackSecurityEnabled', + label: '启用 X-Pack 安全', + type: 'switch', + default: false, + }, + { + key: 'xpackEncryptedSavedObjectsEncryptionKey', + label: '加密密钥', + type: 'text', + default: '', + placeholder: '至少 32 位随机字符串', + tip: '用于加密保存的对象', + dependsOn: { key: 'xpackSecurityEnabled', value: true }, + }, + ], + }, + { + title: '日志配置', + fields: [ + { + key: 'loggingDest', + label: '日志文件路径', + type: 'text', + default: '/var/log/kibana/kibana.log', + }, + { + key: 'loggingSilent', + label: '静默模式', + type: 'switch', + default: false, + tip: '仅输出致命错误', + }, + ], + }, + ], +} + +export function generateKibanaYml(config) { + const lines = [] + lines.push(`# Kibana 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // Server + lines.push(`# ======================== 服务配置 ========================`) + lines.push(`server.port: ${config.serverPort}`) + lines.push(`server.host: "${config.serverHost}"`) + lines.push(`server.name: "${config.serverName}"`) + if (config.serverBasePath) { + lines.push(`server.basePath: "${config.serverBasePath}"`) + } + lines.push(`i18n.locale: "${config.locale}"`) + lines.push(``) + + // Elasticsearch + lines.push(`# ======================== Elasticsearch ========================`) + lines.push(`elasticsearch.hosts: [${config.elasticsearchHosts.split(',').map(h => `"${h.trim()}"`).join(', ')}]`) + lines.push(`elasticsearch.username: "${config.elasticsearchUsername}"`) + lines.push(`elasticsearch.password: "${config.elasticsearchPassword}"`) + lines.push(`kibana.index: "${config.kibanaIndex}"`) + lines.push(`defaultAppId: "${config.defaultAppId}"`) + lines.push(``) + + // Security + lines.push(`# ======================== 安全配置 ========================`) + if (config.enableSsl) { + lines.push(`server.ssl.enabled: true`) + lines.push(`server.ssl.certificate: ${config.sslCert}`) + lines.push(`server.ssl.key: ${config.sslKey}`) + } + if (config.xpackSecurityEnabled) { + lines.push(`xpack.security.enabled: true`) + if (config.xpackEncryptedSavedObjectsEncryptionKey) { + lines.push(`xpack.encryptedSavedObjects.encryptionKey: "${config.xpackEncryptedSavedObjectsEncryptionKey}"`) + } + } + lines.push(``) + + // Logging + lines.push(`# ======================== 日志配置 ========================`) + lines.push(`logging.dest: ${config.loggingDest}`) + lines.push(`logging.silent: ${config.loggingSilent}`) + + return lines.join('\n') +} diff --git a/src/schemas/logstash.js b/src/schemas/logstash.js new file mode 100644 index 0000000..d3c2cff --- /dev/null +++ b/src/schemas/logstash.js @@ -0,0 +1,271 @@ +export const logstashSchema = { + id: 'logstash', + name: 'Logstash', + icon: 'Document', + category: '日志监控', + description: '日志收集、转换与转发的开源数据处理引擎', + format: 'conf', + fileName: 'logstash.conf', + groups: [ + { + title: '输入配置', + fields: [ + { + key: 'inputType', + label: '输入类型', + type: 'select', + options: [ + { label: 'Beats - Filebeat/Winlogbeat 等 (推荐)', value: 'beats' }, + { label: 'File - 文件读取', value: 'file' }, + { label: 'Syslog - 系统日志协议', value: 'syslog' }, + { label: 'TCP - TCP 端口监听', value: 'tcp' }, + { label: 'UDP - UDP 端口监听', value: 'udp' }, + { label: 'Kafka - Kafka 消费', value: 'kafka' }, + ], + default: 'beats', + }, + { + key: 'inputPort', + label: '监听端口', + type: 'number', + min: 1, + max: 65535, + default: 5044, + dependsOn: { key: 'inputType', valueIn: ['beats', 'tcp', 'udp'] }, + }, + { + key: 'inputPath', + label: '文件路径', + type: 'text', + default: '/var/log/*.log', + tip: '支持通配符,如 /var/log/*.log', + dependsOn: { key: 'inputType', value: 'file' }, + }, + { + key: 'inputTopics', + label: 'Kafka Topics', + type: 'text', + default: 'my-topic', + dependsOn: { key: 'inputType', value: 'kafka' }, + }, + { + key: 'inputKafkaBootstrap', + label: 'Kafka Bootstrap Servers', + type: 'text', + default: 'localhost:9092', + dependsOn: { key: 'inputType', value: 'kafka' }, + }, + ], + }, + { + title: '过滤配置', + fields: [ + { + key: 'filterGrok', + label: '启用 Grok 解析', + type: 'switch', + default: true, + tip: '使用 Grok 模式解析非结构化日志', + }, + { + key: 'grokPattern', + label: 'Grok 模式', + type: 'text', + default: '%{COMBINEDAPACHELOG}', + tip: '常用: COMBINEDAPACHELOG, SYSLOGLINE, NGINXACCESS', + dependsOn: { key: 'filterGrok', value: true }, + }, + { + key: 'filterGeoip', + label: '启用 GeoIP 解析', + type: 'switch', + default: false, + tip: '根据 IP 地址解析地理位置信息', + }, + { + key: 'geoipSource', + label: 'GeoIP 来源字段', + type: 'text', + default: 'client_ip', + dependsOn: { key: 'filterGeoip', value: true }, + }, + { + key: 'filterMutate', + label: '启用 Mutate 过滤', + type: 'switch', + default: false, + tip: '字段重命名、删除、替换等操作', + }, + { + key: 'mutateRemoveFields', + label: '移除字段', + type: 'text', + default: 'message,@version', + tip: '逗号分隔要删除的字段', + dependsOn: { key: 'filterMutate', value: true }, + }, + ], + }, + { + title: '输出配置', + fields: [ + { + key: 'outputType', + label: '输出类型', + type: 'select', + options: [ + { label: 'Elasticsearch (推荐)', value: 'elasticsearch' }, + { label: 'File - 输出到文件', value: 'file' }, + { label: 'Stdout - 标准输出 (调试)', value: 'stdout' }, + { label: 'Kafka - 发送到 Kafka', value: 'kafka' }, + ], + default: 'elasticsearch', + }, + { + key: 'outputHosts', + label: '目标地址', + type: 'text', + default: 'http://localhost:9200', + tip: '多个地址用逗号分隔', + }, + { + key: 'outputIndex', + label: '索引名称', + type: 'text', + default: 'logstash-%{+YYYY.MM.dd}', + dependsOn: { key: 'outputType', value: 'elasticsearch' }, + }, + { + key: 'outputFilePath', + label: '输出文件路径', + type: 'text', + default: '/var/log/output.log', + dependsOn: { key: 'outputType', value: 'file' }, + }, + ], + }, + { + title: '管道性能', + fields: [ + { + key: 'pipelineWorkers', + label: '管道工作线程数', + type: 'number', + min: 1, + max: 16, + default: 4, + tip: '建议设置为 CPU 核心数', + }, + { + key: 'pipelineBatchSize', + label: '批处理大小', + type: 'number', + min: 1, + max: 5000, + default: 125, + tip: '每次处理的事件数量', + }, + ], + }, + ], +} + +export function generateLogstashConf(config) { + const lines = [] + lines.push(`# Logstash 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // Input + lines.push(`# ======================== 输入 ========================`) + lines.push(`input {`) + if (config.inputType === 'beats') { + lines.push(` beats {`) + lines.push(` port => ${config.inputPort}`) + lines.push(` }`) + } else if (config.inputType === 'file') { + lines.push(` file {`) + lines.push(` path => "${config.inputPath}"`) + lines.push(` start_position => "beginning"`) + lines.push(` sincedb_path => "/dev/null"`) + lines.push(` }`) + } else if (config.inputType === 'syslog') { + lines.push(` syslog {`) + lines.push(` port => 514`) + lines.push(` type => "syslog"`) + lines.push(` }`) + } else if (config.inputType === 'tcp') { + lines.push(` tcp {`) + lines.push(` port => ${config.inputPort}`) + lines.push(` codec => json_lines`) + lines.push(` }`) + } else if (config.inputType === 'udp') { + lines.push(` udp {`) + lines.push(` port => ${config.inputPort}`) + lines.push(` codec => json_lines`) + lines.push(` }`) + } else if (config.inputType === 'kafka') { + lines.push(` kafka {`) + lines.push(` bootstrap_servers => "${config.inputKafkaBootstrap}"`) + lines.push(` topics => ["${config.inputTopics}"]`) + lines.push(` group_id => "logstash-group"`) + lines.push(` }`) + } + lines.push(`}`) + lines.push(``) + + // Filter + lines.push(`# ======================== 过滤 ========================`) + lines.push(`filter {`) + if (config.filterGrok) { + lines.push(` grok {`) + lines.push(` match => { "message" => "${config.grokPattern}" }`) + lines.push(` }`) + } + if (config.filterGeoip) { + lines.push(` geoip {`) + lines.push(` source => "${config.geoipSource}"`) + lines.push(` }`) + } + if (config.filterMutate) { + lines.push(` mutate {`) + const fields = config.mutateRemoveFields.split(',').map(f => `"${f.trim()}"`).join(', ') + lines.push(` remove_field => [${fields}]`) + lines.push(` }`) + } + lines.push(`}`) + lines.push(``) + + // Output + lines.push(`# ======================== 输出 ========================`) + lines.push(`output {`) + if (config.outputType === 'elasticsearch') { + lines.push(` elasticsearch {`) + lines.push(` hosts => ["${config.outputHosts}"]`) + lines.push(` index => "${config.outputIndex}"`) + lines.push(` }`) + } else if (config.outputType === 'file') { + lines.push(` file {`) + lines.push(` path => "${config.outputFilePath}"`) + lines.push(` }`) + } else if (config.outputType === 'stdout') { + lines.push(` stdout {`) + lines.push(` codec => rubydebug`) + lines.push(` }`) + } else if (config.outputType === 'kafka') { + lines.push(` kafka {`) + lines.push(` bootstrap_servers => "${config.outputHosts}"`) + lines.push(` topic_id => "logstash-output"`) + lines.push(` }`) + } + lines.push(`}`) + lines.push(``) + + // Pipeline settings + lines.push(`# ======================== 管道设置 ========================`) + lines.push(`# 在 config/jvm.options 或启动参数中设置:`) + lines.push(`# -Dpipeline.workers=${config.pipelineWorkers}`) + lines.push(`# -Dpipeline.batch.size=${config.pipelineBatchSize}`) + + return lines.join('\n') +} diff --git a/src/schemas/nacos.js b/src/schemas/nacos.js new file mode 100644 index 0000000..eb4cfee --- /dev/null +++ b/src/schemas/nacos.js @@ -0,0 +1,241 @@ +export const nacosSchema = { + id: 'nacos', + name: 'Nacos', + icon: 'Connection', + category: '服务治理', + description: '阿里巴巴开源的服务发现与配置管理平台', + format: 'properties', + fileName: 'application.properties', + groups: [ + { + title: '基础配置', + fields: [ + { + key: 'serverPort', + label: '服务端口', + type: 'number', + min: 1, + max: 65535, + default: 8848, + }, + { + key: 'contextPath', + label: '上下文路径', + type: 'text', + default: '/nacos', + }, + ], + }, + { + title: '数据源配置', + fields: [ + { + key: 'dataSourceType', + label: '数据源类型', + type: 'select', + options: [ + { label: 'Derby (内嵌,单机模式)', value: 'derby' }, + { label: 'MySQL (生产推荐)', value: 'mysql' }, + ], + default: 'derby', + }, + { + key: 'dbUrl', + label: '数据库连接地址', + type: 'text', + default: 'jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC', + dependsOn: { key: 'dataSourceType', value: 'mysql' }, + }, + { + key: 'dbUser', + label: '数据库用户名', + type: 'text', + default: 'root', + dependsOn: { key: 'dataSourceType', value: 'mysql' }, + }, + { + key: 'dbPassword', + label: '数据库密码', + type: 'text', + default: '', + placeholder: '请输入数据库密码', + dependsOn: { key: 'dataSourceType', value: 'mysql' }, + }, + ], + }, + { + title: '认证配置', + fields: [ + { + key: 'authEnable', + label: '开启认证', + type: 'switch', + default: false, + tip: '开启后需要 Token 访问 Nacos API', + }, + { + key: 'authPluginName', + label: '认证插件', + type: 'text', + default: 'com.alibaba.nacos.core.auth.NacosAuthPlugin', + dependsOn: { key: 'authEnable', value: true }, + }, + { + key: 'tokenSecretKey', + label: 'Token 密钥', + type: 'text', + default: '', + placeholder: '请输入自定义密钥(至少32字符)', + dependsOn: { key: 'authEnable', value: true }, + tip: '生产环境务必设置自定义密钥', + }, + { + key: 'tokenExpireSeconds', + label: 'Token 过期时间 (秒)', + type: 'number', + min: 60, + max: 86400, + default: 18000, + dependsOn: { key: 'authEnable', value: true }, + }, + ], + }, + { + title: '服务注册与发现', + fields: [ + { + key: 'namingPushTimeout', + label: '推送超时时间 (毫秒)', + type: 'number', + min: 1000, + max: 60000, + step: 1000, + default: 10000, + tip: '服务变更推送到客户端的超时时间', + }, + { + key: 'namingHeartbeatInterval', + label: '心跳间隔 (毫秒)', + type: 'number', + min: 1000, + max: 30000, + step: 1000, + default: 5000, + tip: '客户端向 Nacos 发送心跳的间隔', + }, + ], + }, + { + title: '集群配置', + fields: [ + { + key: 'clusterMode', + label: '集群模式', + type: 'switch', + default: false, + tip: '多节点部署时开启', + }, + { + key: 'clusterNodes', + label: '集群节点列表', + type: 'text', + default: '127.0.0.1:8848', + placeholder: 'ip1:port1,ip2:port2,ip3:port3', + dependsOn: { key: 'clusterMode', value: true }, + tip: '多个节点用逗号分隔', + }, + ], + }, + { + title: '日志配置', + fields: [ + { + key: 'logLevel', + label: '日志级别', + type: 'select', + options: [ + { label: 'INFO (默认)', value: 'INFO' }, + { label: 'WARN', value: 'WARN' }, + { label: 'DEBUG', value: 'DEBUG' }, + ], + default: 'INFO', + }, + ], + }, + ], +} + +export function generateNacosProperties(config) { + const lines = [] + lines.push(`# Nacos 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // 基础配置 + lines.push(`# ======================== 基础配置 ========================`) + lines.push(`server.port=${config.serverPort}`) + lines.push(`server.servlet.context-path=${config.contextPath}`) + lines.push(`server.tomcat.accesslog.enabled=true`) + lines.push(`server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D`) + lines.push(``) + + // 数据源配置 + lines.push(`# ======================== 数据源配置 ========================`) + lines.push(`spring.datasource.platform=${config.dataSourceType}`) + if (config.dataSourceType === 'derby') { + lines.push(`db.num=1`) + lines.push(`db.url.0=jdbc:derby://localhost:1527/nacos;create=true`) + lines.push(`db.user.0=nacos`) + lines.push(`db.password.0=nacos`) + } else { + lines.push(`db.num=1`) + lines.push(`db.url.0=${config.dbUrl}`) + lines.push(`db.user.0=${config.dbUser}`) + lines.push(`db.password.0=${config.dbPassword || ''}`) + } + lines.push(``) + + // 认证配置 + lines.push(`# ======================== 认证配置 ========================`) + lines.push(`nacos.core.auth.enabled=${config.authEnable}`) + if (config.authEnable) { + lines.push(`nacos.core.auth.plugin.type=${config.authPluginName}`) + if (config.tokenSecretKey) { + lines.push(`nacos.core.auth.default.token.secret.key=${config.tokenSecretKey}`) + } + lines.push(`nacos.core.auth.default.token.expire.seconds=${config.tokenExpireSeconds}`) + lines.push(`nacos.core.auth.server.identity.key=nacos`) + lines.push(`nacos.core.auth.server.identity.value=nacos`) + } + lines.push(``) + + // 服务注册与发现 + lines.push(`# ======================== 服务注册与发现 ========================`) + lines.push(`naming.push.timeout=${config.namingPushTimeout}`) + lines.push(`naming.heartbeat.interval=${config.namingHeartbeatInterval}`) + lines.push(`naming.clean.expired.instance.interval=5000`) + lines.push(``) + + // 集群配置 + lines.push(`# ======================== 集群配置 ========================`) + if (config.clusterMode) { + lines.push(`# 集群模式`) + const nodes = config.clusterNodes.split(',').map((n) => n.trim()) + lines.push(`nacos.cluster.member.list=${nodes.join(',')}`) + lines.push(`nacos.core.protocol.raft.grpc.server.enabled=true`) + } else { + lines.push(`# 单机模式`) + lines.push(`# nacos.cluster.member.list=ip1:port1,ip2:port2,ip3:port3`) + } + lines.push(``) + + // 日志配置 + lines.push(`# ======================== 日志配置 ========================`) + lines.push(`logging.level.root=${config.logLevel}`) + lines.push(`logging.level.com.alibaba.nacos=${config.logLevel}`) + lines.push(`logging.file.name=logs/nacos.log`) + lines.push(`logging.logback.rollingpolicy.max-file-size=10MB`) + lines.push(`logging.logback.rollingpolicy.max-history=30`) + + return lines.join('\n') +} diff --git a/src/schemas/oracle.js b/src/schemas/oracle.js new file mode 100644 index 0000000..3975757 --- /dev/null +++ b/src/schemas/oracle.js @@ -0,0 +1,239 @@ +export const oracleSchema = { + id: 'oracle', + name: 'Oracle', + icon: 'Coin', + category: '数据库', + description: 'Oracle 数据库初始化参数配置', + format: 'ora', + fileName: 'init.ora', + groups: [ + { + title: '数据库标识', + fields: [ + { + key: 'dbName', + label: '数据库名称', + type: 'text', + default: 'ORCL', + }, + { + key: 'dbDomain', + label: '数据库域名', + type: 'text', + default: 'localdomain', + }, + { + key: 'listenerPort', + label: '监听端口', + type: 'number', + min: 1, + max: 65535, + default: 1521, + }, + ], + }, + { + title: '内存配置', + fields: [ + { + key: 'sgaMaxSize', + label: 'SGA 最大大小', + type: 'select', + options: [ + { label: '1GB', value: '1GB' }, + { label: '2GB', value: '2GB' }, + { label: '4GB', value: '4GB' }, + { label: '8GB', value: '8GB' }, + { label: '16GB', value: '16GB' }, + ], + default: '2GB', + tip: '系统全局区,Oracle 核心内存结构', + }, + { + key: 'pgaAggregateTarget', + label: 'PGA 聚合目标', + type: 'select', + options: [ + { label: '256MB', value: '256MB' }, + { label: '512MB', value: '512MB' }, + { label: '1GB', value: '1GB' }, + { label: '2GB', value: '2GB' }, + ], + default: '512MB', + tip: '程序全局区,用于排序/哈希等操作', + }, + ], + }, + { + title: '进程与会话', + fields: [ + { + key: 'processes', + label: '最大进程数', + type: 'number', + min: 100, + max: 10000, + default: 500, + }, + { + key: 'sessions', + label: '最大会话数', + type: 'number', + min: 100, + max: 10000, + default: 600, + tip: '通常为 processes 的 1.1-1.2 倍', + }, + { + key: 'openCursors', + label: '最大打开游标数', + type: 'number', + min: 100, + max: 10000, + default: 300, + }, + ], + }, + { + title: '存储配置', + fields: [ + { + key: 'dbBlockSize', + label: '数据库块大小', + type: 'select', + options: [ + { label: '2048 (2KB)', value: '2048' }, + { label: '4096 (4KB)', value: '4096' }, + { label: '8192 (8KB, 推荐)', value: '8192' }, + { label: '16384 (16KB)', value: '16384' }, + ], + default: '8192', + }, + { + key: 'controlFileLocation', + label: '控制文件路径', + type: 'text', + default: '/u01/app/oracle/oradata/', + }, + { + key: 'diagnosticDest', + label: '诊断目录', + type: 'text', + default: '/u01/app/oracle', + }, + ], + }, + { + title: '字符集', + fields: [ + { + key: 'nlsCharacterSet', + label: 'NLS 字符集', + type: 'select', + options: [ + { label: 'AL32UTF8 (推荐,完整 Unicode)', value: 'AL32UTF8' }, + { label: 'UTF8', value: 'UTF8' }, + { label: 'ZHS16GBK (中文 GBK)', value: 'ZHS16GBK' }, + ], + default: 'AL32UTF8', + }, + ], + }, + { + title: '归档日志', + fields: [ + { + key: 'enableArchiveLog', + label: '开启归档日志', + type: 'switch', + default: false, + tip: '生产环境必须开启,支持时间点恢复', + }, + { + key: 'archiveLogDest', + label: '归档日志目录', + type: 'text', + default: '/u01/app/oracle/archive', + dependsOn: { key: 'enableArchiveLog', value: true }, + }, + ], + }, + { + title: '安全审计', + fields: [ + { + key: 'enableAudit', + label: '开启审计', + type: 'switch', + default: true, + }, + ], + }, + ], +} + +export function generateOracleConf(config) { + const lines = [] + lines.push(`# Oracle 初始化参数文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + lines.push(`# ======================== 数据库标识 ========================`) + lines.push(`db_name='${config.dbName}'`) + lines.push(`db_domain='${config.dbDomain}'`) + lines.push(`db_unique_name='${config.dbName}'`) + lines.push(`instance_name='${config.dbName}'`) + lines.push(``) + + lines.push(`# ======================== 内存配置 ========================`) + lines.push(`sga_max_size=${config.sgaMaxSize}`) + lines.push(`sga_target=${config.sgaMaxSize}`) + lines.push(`pga_aggregate_target=${config.pgaAggregateTarget}`) + lines.push(`memory_target=0`) + lines.push(``) + + lines.push(`# ======================== 进程与会话 ========================`) + lines.push(`processes=${config.processes}`) + lines.push(`sessions=${config.sessions}`) + lines.push(`open_cursors=${config.openCursors}`) + lines.push(``) + + lines.push(`# ======================== 存储配置 ========================`) + lines.push(`db_block_size=${config.dbBlockSize}`) + lines.push(`control_files='${config.controlFileLocation}/control01.ctl','${config.controlFileLocation}/control02.ctl'`) + lines.push(`diagnostic_dest='${config.diagnosticDest}'`) + lines.push(``) + + lines.push(`# ======================== 字符集 ========================`) + lines.push(`nls_language='AMERICAN'`) + lines.push(`nls_territory='AMERICA'`) + lines.push(`nls_characterset='${config.nlsCharacterSet}'`) + lines.push(``) + + lines.push(`# ======================== 网络配置 ========================`) + lines.push(`dispatchers='(PROTOCOL=TCP) (SERVICE=${config.dbName}XDB)'`) + lines.push(`local_listener='(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=${config.listenerPort}))'`) + lines.push(``) + + if (config.enableArchiveLog) { + lines.push(`# ======================== 归档日志 ========================`) + lines.push(`log_archive_dest_1='LOCATION=${config.archiveLogDest}'`) + lines.push(`log_archive_format='%t_%s_%r.arc'`) + lines.push(`log_archive_start=TRUE`) + lines.push(``) + } + + lines.push(`# ======================== 审计配置 ========================`) + lines.push(`audit_trail=${config.enableAudit ? 'DB' : 'NONE'}`) + if (config.enableAudit) { + lines.push(`audit_file_dest='${config.diagnosticDest}/admin/${config.dbName}/adump'`) + } + lines.push(``) + + lines.push(`# ======================== 兼容性 ========================`) + lines.push(`compatible='19.0.0'`) + lines.push(`undo_tablespace='UNDOTBS1'`) + lines.push(`undo_management='AUTO'`) + + return lines.join('\n') +} diff --git a/src/schemas/postgresql.js b/src/schemas/postgresql.js new file mode 100644 index 0000000..ab028db --- /dev/null +++ b/src/schemas/postgresql.js @@ -0,0 +1,229 @@ +export const postgresqlSchema = { + id: 'postgresql', + name: 'PostgreSQL', + icon: 'Coin', + category: '数据库', + description: '功能强大的开源关系型数据库', + format: 'conf', + fileName: 'postgresql.conf', + groups: [ + { + title: '基础配置', + fields: [ + { + key: 'port', + label: '监听端口', + type: 'number', + min: 1, + max: 65535, + default: 5432, + }, + { + key: 'maxConnections', + label: '最大连接数', + type: 'number', + min: 10, + max: 10000, + default: 100, + }, + ], + }, + { + title: '内存配置', + fields: [ + { + key: 'sharedBuffers', + label: '共享缓冲区', + type: 'select', + options: [ + { label: '128MB', value: '128MB' }, + { label: '256MB (推荐)', value: '256MB' }, + { label: '512MB', value: '512MB' }, + { label: '1GB', value: '1GB' }, + { label: '2GB', value: '2GB' }, + { label: '4GB', value: '4GB' }, + ], + default: '256MB', + tip: '建议设为服务器内存的 25%', + }, + { + key: 'effectiveCacheSize', + label: '有效缓存大小', + type: 'select', + options: [ + { label: '1GB', value: '1GB' }, + { label: '2GB', value: '2GB' }, + { label: '4GB', value: '4GB' }, + { label: '8GB', value: '8GB' }, + { label: '16GB', value: '16GB' }, + ], + default: '1GB', + tip: '建议设为服务器内存的 50-75%', + }, + { + key: 'workMem', + label: '工作内存', + type: 'select', + options: [ + { label: '4MB', value: '4MB' }, + { label: '16MB', value: '16MB' }, + { label: '32MB', value: '32MB' }, + { label: '64MB', value: '64MB' }, + ], + default: '4MB', + tip: '每个排序/哈希操作使用的内存', + }, + { + key: 'maintenanceWorkMem', + label: '维护工作内存', + type: 'select', + options: [ + { label: '64MB', value: '64MB' }, + { label: '128MB', value: '128MB' }, + { label: '256MB', value: '256MB' }, + { label: '512MB', value: '512MB' }, + ], + default: '64MB', + tip: '用于 VACUUM、CREATE INDEX 等操作', + }, + ], + }, + { + title: 'WAL 配置', + fields: [ + { + key: 'walLevel', + label: 'WAL 级别', + type: 'select', + options: [ + { label: 'replica - 支持复制和归档 (推荐)', value: 'replica' }, + { label: 'logical - 支持逻辑复制', value: 'logical' }, + { label: 'minimal - 最小化日志', value: 'minimal' }, + ], + default: 'replica', + }, + { + key: 'maxWalSize', + label: 'WAL 最大大小', + type: 'select', + options: [ + { label: '1GB', value: '1GB' }, + { label: '2GB', value: '2GB' }, + { label: '4GB', value: '4GB' }, + ], + default: '1GB', + }, + { + key: 'checkpointCompletionTarget', + label: 'Checkpoint 完成目标', + type: 'number', + min: 0, + max: 1, + step: 0.1, + default: 0.9, + tip: '0-1 之间,分散 checkpoint I/O', + }, + { + key: 'maxReplicationSlots', + label: '最大复制槽数', + type: 'number', + min: 0, + max: 10, + default: 4, + }, + { + key: 'maxWalSenders', + label: '最大 WAL 发送进程数', + type: 'number', + min: 0, + max: 10, + default: 3, + }, + ], + }, + { + title: '日志配置', + fields: [ + { + key: 'logMinDurationStatement', + label: '慢查询阈值', + type: 'number', + min: 0, + max: 60000, + default: 1000, + tip: 'ms, 0=记录所有语句', + }, + ], + }, + { + title: 'SSL 配置', + fields: [ + { + key: 'enableSsl', + label: '开启 SSL', + type: 'switch', + default: false, + }, + { + key: 'sslCertFile', + label: 'SSL 证书文件', + type: 'text', + default: '/etc/ssl/certs/server.crt', + dependsOn: { key: 'enableSsl', value: true }, + }, + { + key: 'sslKeyFile', + label: 'SSL 私钥文件', + type: 'text', + default: '/etc/ssl/private/server.key', + dependsOn: { key: 'enableSsl', value: true }, + }, + ], + }, + ], +} + +export function generatePostgresqlConf(config) { + const lines = [] + lines.push(`# PostgreSQL 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + lines.push(`# ======================== 连接配置 ========================`) + lines.push(`listen_addresses = '*'`) + lines.push(`port = ${config.port}`) + lines.push(`max_connections = ${config.maxConnections}`) + lines.push(``) + + lines.push(`# ======================== 内存配置 ========================`) + lines.push(`shared_buffers = ${config.sharedBuffers}`) + lines.push(`effective_cache_size = ${config.effectiveCacheSize}`) + lines.push(`work_mem = ${config.workMem}`) + lines.push(`maintenance_work_mem = ${config.maintenanceWorkMem}`) + lines.push(``) + + lines.push(`# ======================== WAL 配置 ========================`) + lines.push(`wal_level = ${config.walLevel}`) + lines.push(`max_wal_size = ${config.maxWalSize}`) + lines.push(`checkpoint_completion_target = ${config.checkpointCompletionTarget}`) + lines.push(`max_replication_slots = ${config.maxReplicationSlots}`) + lines.push(`max_wal_senders = ${config.maxWalSenders}`) + lines.push(``) + + lines.push(`# ======================== 日志配置 ========================`) + lines.push(`logging_collector = on`) + lines.push(`log_directory = 'log'`) + lines.push(`log_filename = 'postgresql-%Y-%m-%d.log'`) + lines.push(`log_min_duration_statement = ${config.logMinDurationStatement}`) + lines.push(``) + + if (config.enableSsl) { + lines.push(`# ======================== SSL 配置 ========================`) + lines.push(`ssl = on`) + lines.push(`ssl_cert_file = '${config.sslCertFile}'`) + lines.push(`ssl_key_file = '${config.sslKeyFile}'`) + lines.push(``) + } + + return lines.join('\n') +} diff --git a/src/schemas/prometheus.js b/src/schemas/prometheus.js new file mode 100644 index 0000000..f4de9a9 --- /dev/null +++ b/src/schemas/prometheus.js @@ -0,0 +1,245 @@ +export const prometheusSchema = { + id: 'prometheus', + name: 'Prometheus', + icon: 'TrendCharts', + category: '日志监控', + description: '开源监控与告警系统,时间序列数据库', + format: 'yml', + fileName: 'prometheus.yml', + groups: [ + { + title: '全局配置', + fields: [ + { + key: 'globalScrapeInterval', + label: '采集间隔 (秒)', + type: 'number', + min: 5, + max: 300, + default: 15, + tip: '全局数据采集频率', + }, + { + key: 'globalEvaluationInterval', + label: '规则评估间隔 (秒)', + type: 'number', + min: 5, + max: 300, + default: 15, + tip: '告警规则评估频率', + }, + { + key: 'retentionTime', + label: '数据保留时间', + type: 'text', + default: '15d', + tip: '如 15d、30d、1y', + }, + { + key: 'retentionSize', + label: '数据保留大小', + type: 'text', + default: '0', + tip: '0=不限制,如 10GB', + }, + ], + }, + { + title: '外部标签', + fields: [ + { + key: 'externalLabelsEnv', + label: '环境标签', + type: 'text', + default: 'production', + tip: '标识部署环境', + }, + { + key: 'externalLabelsCluster', + label: '集群标签', + type: 'text', + default: 'k8s-prod', + tip: '标识所属集群', + }, + ], + }, + { + title: 'Alertmanager', + fields: [ + { + key: 'enableAlertmanager', + label: '启用 Alertmanager', + type: 'switch', + default: false, + }, + { + key: 'alertmanagerTargets', + label: 'Alertmanager 地址', + type: 'text', + default: 'localhost:9093', + tip: '多个地址用逗号分隔', + dependsOn: { key: 'enableAlertmanager', value: true }, + }, + ], + }, + { + title: '采集任务', + fields: [ + { + key: 'scrapeJobName', + label: 'Prometheus Job 名称', + type: 'text', + default: 'prometheus', + }, + { + key: 'scrapeTarget', + label: 'Prometheus 自监控地址', + type: 'text', + default: 'localhost:9090', + }, + { + key: 'enableNodeExporter', + label: '启用 Node Exporter', + type: 'switch', + default: true, + tip: '采集主机指标(CPU、内存、磁盘等)', + }, + { + key: 'nodeExporterTarget', + label: 'Node Exporter 地址', + type: 'text', + default: 'localhost:9100', + dependsOn: { key: 'enableNodeExporter', value: true }, + }, + ], + }, + { + title: '远程读写', + fields: [ + { + key: 'enableRemoteWrite', + label: '启用 Remote Write', + type: 'switch', + default: false, + tip: '将数据写入远程存储', + }, + { + key: 'remoteWriteUrl', + label: 'Remote Write URL', + type: 'text', + default: 'http://localhost:8428/api/v1/write', + dependsOn: { key: 'enableRemoteWrite', value: true }, + }, + { + key: 'enableRemoteRead', + label: '启用 Remote Read', + type: 'switch', + default: false, + tip: '从远程存储读取数据', + }, + { + key: 'remoteReadUrl', + label: 'Remote Read URL', + type: 'text', + default: '', + dependsOn: { key: 'enableRemoteRead', value: true }, + }, + ], + }, + { + title: 'TLS 安全', + fields: [ + { + key: 'enableTls', + label: '启用 TLS', + type: 'switch', + default: false, + }, + ], + }, + ], +} + +export function generatePrometheusYml(config) { + const lines = [] + lines.push(`# Prometheus 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // Global + lines.push(`# ======================== 全局配置 ========================`) + lines.push(`global:`) + lines.push(` scrape_interval: ${config.globalScrapeInterval}s`) + lines.push(` evaluation_interval: ${config.globalEvaluationInterval}s`) + lines.push(` external_labels:`) + lines.push(` env: "${config.externalLabelsEnv}"`) + lines.push(` cluster: "${config.externalLabelsCluster}"`) + lines.push(``) + + // Alerting + if (config.enableAlertmanager) { + lines.push(`# ======================== Alertmanager ========================`) + lines.push(`alerting:`) + lines.push(` alertmanagers:`) + lines.push(` - static_configs:`) + lines.push(` - targets:`) + const targets = config.alertmanagerTargets.split(',').map(t => t.trim()) + targets.forEach(t => { + lines.push(` - '${t}'`) + }) + lines.push(``) + } + + // Rules + lines.push(`# ======================== 规则文件 ========================`) + lines.push(`rule_files:`) + lines.push(` - "rules/*.yml"`) + lines.push(``) + + // Scrape + lines.push(`# ======================== 采集任务 ========================`) + lines.push(`scrape_configs:`) + lines.push(``) + + // Prometheus self-monitoring + lines.push(` - job_name: '${config.scrapeJobName}'`) + lines.push(` static_configs:`) + lines.push(` - targets: ['${config.scrapeTarget}']`) + lines.push(``) + + // Node Exporter + if (config.enableNodeExporter) { + lines.push(` - job_name: 'node-exporter'`) + lines.push(` static_configs:`) + lines.push(` - targets: ['${config.nodeExporterTarget}']`) + lines.push(``) + } + + // Remote Write + if (config.enableRemoteWrite) { + lines.push(`# ======================== Remote Write ========================`) + lines.push(`remote_write:`) + lines.push(` - url: "${config.remoteWriteUrl}"`) + lines.push(``) + } + + // Remote Read + if (config.enableRemoteRead && config.remoteReadUrl) { + lines.push(`# ======================== Remote Read ========================`) + lines.push(`remote_read:`) + lines.push(` - url: "${config.remoteReadUrl}"`) + lines.push(``) + } + + // Storage (as comments, since these are usually CLI args) + lines.push(`# ======================== 存储设置 (命令行参数) ========================`) + lines.push(`# --storage.tsdb.retention.time=${config.retentionTime}`) + if (config.retentionSize !== '0') { + lines.push(`# --storage.tsdb.retention.size=${config.retentionSize}`) + } + if (config.enableTls) { + lines.push(`# --web.config.file=web.yml # 配置 TLS`) + } + + return lines.join('\n') +} diff --git a/src/schemas/rocketmq.js b/src/schemas/rocketmq.js new file mode 100644 index 0000000..0659277 --- /dev/null +++ b/src/schemas/rocketmq.js @@ -0,0 +1,197 @@ +export const rocketmqSchema = { + id: 'rocketmq', + name: 'RocketMQ', + icon: 'ChatDotRound', + category: '消息队列', + description: '阿里巴巴开源的分布式消息中间件', + format: 'conf', + fileName: 'broker.conf', + groups: [ + { + title: 'Broker 基础配置', + fields: [ + { + key: 'brokerName', + label: 'Broker 名称', + type: 'text', + default: 'broker-a', + }, + { + key: 'brokerId', + label: 'Broker ID', + type: 'number', + min: 0, + max: 10, + default: 0, + tip: '0 表示 Master,大于 0 表示 Slave', + }, + { + key: 'listenPort', + label: '监听端口', + type: 'number', + min: 1, + max: 65535, + default: 10911, + }, + { + key: 'namesrvAddr', + label: 'NameServer 地址', + type: 'text', + default: '127.0.0.1:9876', + tip: '多个用分号分隔', + }, + ], + }, + { + title: '存储配置', + fields: [ + { + key: 'storePathRootDir', + label: '存储根目录', + type: 'text', + default: '/home/rocketmq/store', + }, + { + key: 'mapedFileSizeCommitLog', + label: 'CommitLog 文件大小', + type: 'number', + min: 1048576, + max: 2147483647, + default: 1073741824, + tip: '1GB', + }, + { + key: 'deleteWhen', + label: '过期文件删除时间', + type: 'text', + default: '04', + tip: '凌晨4点清理', + }, + { + key: 'fileReservedTime', + label: '文件保留时间', + type: 'number', + min: 1, + max: 720, + default: 72, + tip: 'hours', + }, + ], + }, + { + title: 'Topic 配置', + fields: [ + { + key: 'defaultTopicQueueNums', + label: '默认 Topic 队列数', + type: 'number', + min: 1, + max: 64, + default: 8, + }, + { + key: 'autoCreateTopicEnable', + label: '自动创建 Topic', + type: 'switch', + default: true, + tip: '生产建议关闭', + }, + { + key: 'autoCreateSubscriptionGroup', + label: '自动创建订阅组', + type: 'switch', + default: true, + }, + ], + }, + { + title: '高可用配置', + fields: [ + { + key: 'brokerRole', + label: 'Broker 角色', + type: 'select', + options: [ + { label: 'ASYNC_MASTER - 异步复制 (默认)', value: 'ASYNC_MASTER' }, + { label: 'SYNC_MASTER - 同步双写', value: 'SYNC_MASTER' }, + { label: 'SLAVE - 从节点', value: 'SLAVE' }, + ], + default: 'ASYNC_MASTER', + }, + { + key: 'flushDiskType', + label: '刷盘策略', + type: 'select', + options: [ + { label: 'ASYNC_FLUSH - 异步刷盘 (性能高)', value: 'ASYNC_FLUSH' }, + { label: 'SYNC_FLUSH - 同步刷盘 (数据安全)', value: 'SYNC_FLUSH' }, + ], + default: 'ASYNC_FLUSH', + }, + ], + }, + { + title: '消息配置', + fields: [ + { + key: 'maxMessageSize', + label: '最大消息大小', + type: 'number', + min: 1024, + max: 16777216, + default: 4194304, + tip: '4MB', + }, + { + key: 'enablePropertyFilter', + label: '开启属性过滤', + type: 'switch', + default: false, + tip: '允许消费者使用 SQL92 过滤', + }, + ], + }, + ], +} + +export function generateRocketmqConf(config) { + const lines = [] + lines.push(`# RocketMQ Broker 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + lines.push(`# ======================== Broker 基础配置 ========================`) + lines.push(`brokerName=${config.brokerName}`) + lines.push(`brokerId=${config.brokerId}`) + lines.push(`listenPort=${config.listenPort}`) + lines.push(`namesrvAddr=${config.namesrvAddr}`) + lines.push(``) + + lines.push(`# ======================== 存储配置 ========================`) + lines.push(`storePathRootDir=${config.storePathRootDir}`) + lines.push(`storePathCommitLog=${config.storePathRootDir}/commitlog`) + lines.push(`storePathConsumeQueue=${config.storePathRootDir}/consumequeue`) + lines.push(`storePathIndex=${config.storePathRootDir}/index`) + lines.push(`mapedFileSizeCommitLog=${config.mapedFileSizeCommitLog}`) + lines.push(`deleteWhen=${config.deleteWhen}`) + lines.push(`fileReservedTime=${config.fileReservedTime}`) + lines.push(``) + + lines.push(`# ======================== Topic 配置 ========================`) + lines.push(`defaultTopicQueueNums=${config.defaultTopicQueueNums}`) + lines.push(`autoCreateTopicEnable=${config.autoCreateTopicEnable}`) + lines.push(`autoCreateSubscriptionGroup=${config.autoCreateSubscriptionGroup}`) + lines.push(``) + + lines.push(`# ======================== 高可用配置 ========================`) + lines.push(`brokerRole=${config.brokerRole}`) + lines.push(`flushDiskType=${config.flushDiskType}`) + lines.push(``) + + lines.push(`# ======================== 消息配置 ========================`) + lines.push(`maxMessageSize=${config.maxMessageSize}`) + lines.push(`enablePropertyFilter=${config.enablePropertyFilter}`) + lines.push(``) + + return lines.join('\n') +} diff --git a/src/schemas/syslog.js b/src/schemas/syslog.js new file mode 100644 index 0000000..65e4fc7 --- /dev/null +++ b/src/schemas/syslog.js @@ -0,0 +1,309 @@ +export const syslogSchema = { + id: 'syslog', + name: 'Syslog', + icon: 'Document', + category: '日志监控', + description: 'RSyslog 系统日志收集与转发服务', + format: 'conf', + fileName: 'rsyslog.conf', + groups: [ + { + title: '接收协议', + fields: [ + { + key: 'enableUdp', + label: '启用 UDP 接收', + type: 'switch', + default: true, + }, + { + key: 'udpPort', + label: 'UDP 端口', + type: 'number', + min: 1, + max: 65535, + default: 514, + dependsOn: { key: 'enableUdp', value: true }, + }, + { + key: 'enableTcp', + label: '启用 TCP 接收', + type: 'switch', + default: true, + }, + { + key: 'tcpPort', + label: 'TCP 端口', + type: 'number', + min: 1, + max: 65535, + default: 514, + dependsOn: { key: 'enableTcp', value: true }, + }, + { + key: 'enableRelp', + label: '启用 RELP 接收', + type: 'switch', + default: false, + tip: '可靠事件日志协议,保证日志不丢失', + }, + { + key: 'relpPort', + label: 'RELP 端口', + type: 'number', + min: 1, + max: 65535, + default: 2514, + dependsOn: { key: 'enableRelp', value: true }, + }, + ], + }, + { + title: '日志格式', + fields: [ + { + key: 'logFormat', + label: '日志格式', + type: 'select', + options: [ + { label: 'traditional - 传统格式', value: 'traditional' }, + { label: 'RFC5424 - 标准格式', value: 'RFC5424' }, + { label: 'RSYSLOG_FileFormat - 文件格式 (推荐)', value: 'RSYSLOG_FileFormat' }, + ], + default: 'RSYSLOG_FileFormat', + }, + { + key: 'enableHighPrecisionTimestamps', + label: '高精度时间戳', + type: 'switch', + default: true, + tip: '微秒级时间戳', + }, + ], + }, + { + title: '远程转发', + fields: [ + { + key: 'enableRemoteLogging', + label: '启用远程转发', + type: 'switch', + default: false, + tip: '将日志转发到远程服务器', + }, + { + key: 'remoteHost', + label: '远程主机', + type: 'text', + default: '192.168.1.100', + dependsOn: { key: 'enableRemoteLogging', value: true }, + }, + { + key: 'remotePort', + label: '远程端口', + type: 'number', + min: 1, + max: 65535, + default: 514, + dependsOn: { key: 'enableRemoteLogging', value: true }, + }, + { + key: 'remoteProtocol', + label: '远程协议', + type: 'select', + options: [ + { label: 'udp', value: 'udp' }, + { label: 'tcp', value: 'tcp' }, + { label: 'relp', value: 'relp' }, + ], + default: 'tcp', + dependsOn: { key: 'enableRemoteLogging', value: true }, + }, + ], + }, + { + title: '文件输出', + fields: [ + { + key: 'enableFileOutput', + label: '启用文件输出', + type: 'switch', + default: true, + }, + { + key: 'logDir', + label: '日志目录', + type: 'text', + default: '/var/log', + dependsOn: { key: 'enableFileOutput', value: true }, + }, + { + key: 'enablePerHostDir', + label: '按主机分目录', + type: 'switch', + default: false, + tip: '按主机名创建独立日志目录', + dependsOn: { key: 'enableFileOutput', value: true }, + }, + ], + }, + { + title: '速率限制', + fields: [ + { + key: 'enableRateLimiting', + label: '启用速率限制', + type: 'switch', + default: true, + tip: '防止日志风暴', + }, + { + key: 'rateLimitInterval', + label: '限制间隔 (秒)', + type: 'number', + min: 0, + max: 3600, + default: 0, + tip: '0=使用默认值', + dependsOn: { key: 'enableRateLimiting', value: true }, + }, + { + key: 'rateLimitBurst', + label: '突发上限', + type: 'number', + min: 1, + max: 1000000, + default: 10000, + dependsOn: { key: 'enableRateLimiting', value: true }, + }, + ], + }, + { + title: '日志源模块', + fields: [ + { + key: 'enableKernelLog', + label: '内核日志', + type: 'switch', + default: true, + }, + { + key: 'enableMailLog', + label: '邮件日志', + type: 'switch', + default: true, + }, + { + key: 'enableAuthLog', + label: '认证日志', + type: 'switch', + default: true, + }, + ], + }, + ], +} + +export function generateSyslogConf(config) { + const lines = [] + lines.push(`# RSyslog 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // Modules + lines.push(`# ======================== 模块加载 ========================`) + if (config.enableUdp) { + lines.push(`module(load="imudp")`) + } + if (config.enableTcp) { + lines.push(`module(load="imtcp")`) + } + if (config.enableRelp) { + lines.push(`module(load="imrelp")`) + } + if (config.enableKernelLog) { + lines.push(`module(load="imklog")`) + } + lines.push(``) + + // Global directives + lines.push(`# ======================== 全局设置 ========================`) + lines.push(`$WorkDirectory /var/lib/rsyslog`) + lines.push(`$ActionFileDefaultTemplate ${config.logFormat}`) + if (config.enableHighPrecisionTimestamps) { + lines.push(`$ActionFileDefaultTemplate RSYSLOG_FileFormat`) + } + lines.push(``) + + // Input listeners + lines.push(`# ======================== 接收配置 ========================`) + if (config.enableUdp) { + lines.push(`input(type="imudp" port="${config.udpPort}" ruleset="remote")`) + } + if (config.enableTcp) { + lines.push(`input(type="imtcp" port="${config.tcpPort}" ruleset="remote")`) + } + if (config.enableRelp) { + lines.push(`input(type="imrelp" port="${config.relpPort}" ruleset="remote")`) + } + lines.push(``) + + // Rate limiting + if (config.enableRateLimiting) { + lines.push(`# ======================== 速率限制 ========================`) + if (config.rateLimitInterval > 0) { + lines.push(`$SystemLogRateLimitInterval ${config.rateLimitInterval}`) + } + lines.push(`$SystemLogRateLimitBurst ${config.rateLimitBurst}`) + lines.push(``) + } + + // Log sources + lines.push(`# ======================== 日志源 ========================`) + lines.push(`# 系统默认日志`) + lines.push(`auth,authpriv.* ${config.enableFileOutput ? `${config.logDir}/auth.log` : '/dev/null'}`) + lines.push(`*.*;auth,authpriv.none ${config.enableFileOutput ? `${config.logDir}/syslog` : '/dev/null'}`) + if (config.enableKernelLog) { + lines.push(`kern.* ${config.enableFileOutput ? `${config.logDir}/kern.log` : '/dev/null'}`) + } + if (config.enableMailLog) { + lines.push(`mail.* ${config.enableFileOutput ? `${config.logDir}/mail.log` : '/dev/null'}`) + } + lines.push(`mail.err ${config.enableFileOutput ? `${config.logDir}/mail.err` : '/dev/null'}`) + lines.push(`cron.* ${config.enableFileOutput ? `${config.logDir}/cron.log` : '/dev/null'}`) + lines.push(``) + + // File output + if (config.enableFileOutput) { + lines.push(`# ======================== 文件输出模板 ========================`) + if (config.enablePerHostDir) { + lines.push(`template(name="perHostFile" type="string"`) + lines.push(` string="${config.logDir}/%HOSTNAME%/%PROGRAMNAME%.log")`) + lines.push(``) + lines.push(`ruleset(name="remote") {`) + lines.push(` action(type="omfile" dynaFile="perHostFile")`) + lines.push(`}`) + } else { + lines.push(`ruleset(name="remote") {`) + lines.push(` action(type="omfile" file="${config.logDir}/remote.log")`) + lines.push(`}`) + } + lines.push(``) + } + + // Remote forwarding + if (config.enableRemoteLogging) { + lines.push(`# ======================== 远程转发 ========================`) + if (config.remoteProtocol === 'relp') { + lines.push(`action(type="omrelp" target="${config.remoteHost}" port="${config.remotePort}")`) + } else if (config.remoteProtocol === 'tcp') { + lines.push(`action(type="omfwd" target="${config.remoteHost}" port="${config.remotePort}" protocol="tcp"`) + lines.push(` queue.type="linkedList" queue.filename="fwd_queue" queue.saveOnShutdown="on"`) + lines.push(` action.resumeRetryCount="-1")`) + } else { + lines.push(`action(type="omfwd" target="${config.remoteHost}" port="${config.remotePort}" protocol="udp")`) + } + } + + return lines.join('\n') +} diff --git a/src/schemas/zabbix.js b/src/schemas/zabbix.js new file mode 100644 index 0000000..2c9b087 --- /dev/null +++ b/src/schemas/zabbix.js @@ -0,0 +1,248 @@ +export const zabbixSchema = { + id: 'zabbix', + name: 'Zabbix', + icon: 'Monitor', + category: '日志监控', + description: '企业级开源监控解决方案', + format: 'conf', + fileName: 'zabbix_server.conf', + groups: [ + { + title: '基础配置', + fields: [ + { + key: 'listenPort', + label: '监听端口', + type: 'number', + min: 1, + max: 65535, + default: 10051, + }, + { + key: 'logType', + label: '日志输出方式', + type: 'select', + options: [ + { label: 'file - 输出到文件', value: 'file' }, + { label: 'console - 控制台输出', value: 'console' }, + { label: 'system - 系统日志', value: 'system' }, + ], + default: 'file', + }, + { + key: 'logFileSize', + label: '日志文件大小 (MB)', + type: 'number', + min: 1, + max: 1024, + default: 10, + tip: '日志轮转大小', + }, + ], + }, + { + title: '数据库配置', + fields: [ + { + key: 'dbHost', + label: '数据库主机', + type: 'text', + default: 'localhost', + }, + { + key: 'dbName', + label: '数据库名称', + type: 'text', + default: 'zabbix', + }, + { + key: 'dbUser', + label: '数据库用户', + type: 'text', + default: 'zabbix', + }, + { + key: 'dbPassword', + label: '数据库密码', + type: 'text', + default: 'zabbix', + }, + { + key: 'dbSocket', + label: '数据库 Socket', + type: 'text', + default: '/var/run/mysqld/mysqld.sock', + tip: '本地连接优先使用 Socket', + }, + ], + }, + { + title: '缓存配置', + fields: [ + { + key: 'cacheSize', + label: '配置缓存', + type: 'text', + default: '128M', + tip: '存储主机、监控项等配置数据', + }, + { + key: 'historyCacheSize', + label: '历史数据缓存', + type: 'text', + default: '64M', + }, + { + key: 'trendCacheSize', + label: '趋势数据缓存', + type: 'text', + default: '32M', + }, + { + key: 'valueCacheSize', + label: '值缓存', + type: 'text', + default: '32M', + tip: '缓存最近历史值,减少数据库查询', + }, + ], + }, + { + title: '进程配置', + fields: [ + { + key: 'startPollers', + label: 'Poller 进程数', + type: 'number', + min: 1, + max: 100, + default: 5, + tip: '常规数据采集进程', + }, + { + key: 'startPingers', + label: 'Pinger 进程数', + type: 'number', + min: 1, + max: 100, + default: 1, + tip: 'ICMP ping 检测进程', + }, + { + key: 'enableTrapper', + label: '启用 Trapper', + type: 'switch', + default: true, + tip: '接收主动发送的数据', + }, + { + key: 'trapperTimeout', + label: 'Trapper 超时 (秒)', + type: 'number', + min: 1, + max: 300, + default: 300, + dependsOn: { key: 'enableTrapper', value: true }, + }, + { + key: 'slowQueryThreshold', + label: '慢查询阈值 (秒)', + type: 'number', + min: 0, + max: 60, + default: 0, + tip: '0=关闭,记录超过此时间的数据库查询', + }, + ], + }, + { + title: '脚本与路径', + fields: [ + { + key: 'alertScriptsPath', + label: '告警脚本路径', + type: 'text', + default: '/usr/lib/zabbix/alertscripts', + }, + { + key: 'externalScripts', + label: '外部脚本路径', + type: 'text', + default: '/usr/lib/zabbix/externalscripts', + }, + ], + }, + { + title: '维护配置', + fields: [ + { + key: 'housekeepingFrequency', + label: '数据清理间隔 (小时)', + type: 'number', + min: 1, + max: 24, + default: 1, + tip: '过期历史数据清理频率', + }, + ], + }, + ], +} + +export function generateZabbixConf(config) { + const lines = [] + lines.push(`# Zabbix Server 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // 基础 + lines.push(`# ======================== 基础配置 ========================`) + lines.push(`ListenPort=${config.listenPort}`) + lines.push(`LogType=${config.logType}`) + lines.push(`LogFileSize=${config.logFileSize}`) + lines.push(``) + + // 数据库 + lines.push(`# ======================== 数据库配置 ========================`) + lines.push(`DBHost=${config.dbHost}`) + lines.push(`DBName=${config.dbName}`) + lines.push(`DBUser=${config.dbUser}`) + lines.push(`DBPassword=${config.dbPassword}`) + lines.push(`DBSocket=${config.dbSocket}`) + lines.push(``) + + // 缓存 + lines.push(`# ======================== 缓存配置 ========================`) + lines.push(`CacheSize=${config.cacheSize}`) + lines.push(`HistoryCacheSize=${config.historyCacheSize}`) + lines.push(`TrendCacheSize=${config.trendCacheSize}`) + lines.push(`ValueCacheSize=${config.valueCacheSize}`) + lines.push(``) + + // 进程 + lines.push(`# ======================== 进程配置 ========================`) + lines.push(`StartPollers=${config.startPollers}`) + lines.push(`StartPingers=${config.startPingers}`) + if (config.enableTrapper) { + lines.push(`StartTrappers=5`) + lines.push(`TrapperTimeout=${config.trapperTimeout}`) + } else { + lines.push(`StartTrappers=0`) + } + if (config.slowQueryThreshold > 0) { + lines.push(`SlowQueryThreshold=${config.slowQueryThreshold}`) + } + lines.push(``) + + // 脚本 + lines.push(`# ======================== 脚本与路径 ========================`) + lines.push(`AlertScriptsPath=${config.alertScriptsPath}`) + lines.push(`ExternalScripts=${config.externalScripts}`) + lines.push(``) + + // 维护 + lines.push(`# ======================== 维护配置 ========================`) + lines.push(`HousekeepingFrequency=${config.housekeepingFrequency}`) + + return lines.join('\n') +} diff --git a/src/schemas/zookeeper.js b/src/schemas/zookeeper.js new file mode 100644 index 0000000..d3ef79f --- /dev/null +++ b/src/schemas/zookeeper.js @@ -0,0 +1,215 @@ +export const zookeeperSchema = { + id: 'zookeeper', + name: 'ZooKeeper', + icon: 'Connection', + category: '分布式协调', + description: 'Apache 分布式协调服务', + format: 'cfg', + fileName: 'zoo.cfg', + groups: [ + { + title: '基础配置', + fields: [ + { + key: 'tickTime', + label: '心跳间隔 (毫秒)', + type: 'number', + min: 100, + max: 60000, + step: 100, + default: 2000, + tip: 'ZooKeeper 服务器之间或客户端与服务器之间的基本时间单元', + }, + { + key: 'initLimit', + label: '初始化同步限制', + type: 'number', + min: 1, + max: 100, + default: 10, + tip: 'Follower 连接并同步到 Leader 的最大 tick 数', + }, + { + key: 'syncLimit', + label: '同步限制', + type: 'number', + min: 1, + max: 100, + default: 5, + tip: 'Follower 与 Leader 之间的最大 tick 数', + }, + { + key: 'dataDir', + label: '数据目录', + type: 'text', + default: '/var/lib/zookeeper', + }, + { + key: 'dataLogDir', + label: '事务日志目录', + type: 'text', + default: '/var/lib/zookeeper/log', + tip: '建议使用独立磁盘提升性能', + }, + { + key: 'clientPort', + label: '客户端端口', + type: 'number', + min: 1, + max: 65535, + default: 2181, + }, + { + key: 'maxClientCnxns', + label: '最大客户端连接数', + type: 'number', + min: 1, + max: 10000, + default: 60, + tip: '单个 IP 最大连接数,0 表示不限制', + }, + ], + }, + { + title: '高级配置', + fields: [ + { + key: 'enable4lw', + label: '开启四字命令', + type: 'switch', + default: true, + tip: '允许 ruok、stat、mntr 等四字命令(运维监控用)', + }, + { + key: 'autopurgeSnapRetainCount', + label: '保留快照数量', + type: 'number', + min: 1, + max: 100, + default: 3, + tip: '自动清理时保留的快照文件数', + }, + { + key: 'autopurgePurgeInterval', + label: '自动清理间隔 (小时)', + type: 'number', + min: 0, + max: 168, + default: 0, + tip: '0 表示禁用自动清理', + }, + { + key: 'adminEnableServer', + label: '开启管理服务', + type: 'switch', + default: true, + tip: 'AdminServer 提供 HTTP API 用于管理', + }, + { + key: 'adminServerPort', + label: '管理服务端口', + type: 'number', + min: 1, + max: 65535, + default: 8080, + dependsOn: { key: 'adminEnableServer', value: true }, + }, + ], + }, + { + title: '集群配置', + fields: [ + { + key: 'enableCluster', + label: '集群模式', + type: 'switch', + default: false, + tip: '多节点部署时开启', + }, + { + key: 'clusterServers', + label: '集群节点列表', + type: 'text', + default: 'server.1=zk1:2888:3888\nserver.2=zk2:2888:3888\nserver.3=zk3:2888:3888', + placeholder: 'server.1=ip1:2888:3888\nserver.2=ip2:2888:3888', + dependsOn: { key: 'enableCluster', value: true }, + tip: '每行一个,格式:server.N=host:port:port', + }, + ], + }, + { + title: 'JVM 配置', + fields: [ + { + key: 'jvmHeap', + label: 'JVM 堆内存', + type: 'select', + options: [ + { label: '512M', value: '512M' }, + { label: '1G (默认)', value: '1G' }, + { label: '2G', value: '2G' }, + { label: '4G', value: '4G' }, + ], + default: '1G', + tip: '通过 JVMFLAGS 环境变量设置', + }, + ], + }, + ], +} + +export function generateZookeeperCfg(config) { + const lines = [] + lines.push(`# ZooKeeper 配置文件 - 由 ConfTemplate 生成`) + lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`) + lines.push(``) + + // 基础配置 + lines.push(`# ======================== 基础配置 ========================`) + lines.push(`tickTime=${config.tickTime}`) + lines.push(`initLimit=${config.initLimit}`) + lines.push(`syncLimit=${config.syncLimit}`) + lines.push(`dataDir=${config.dataDir}`) + lines.push(`dataLogDir=${config.dataLogDir}`) + lines.push(`clientPort=${config.clientPort}`) + lines.push(`maxClientCnxns=${config.maxClientCnxns}`) + lines.push(``) + + // 高级配置 + lines.push(`# ======================== 高级配置 ========================`) + if (config.enable4lw) { + lines.push(`4lw.commands.whitelist=*`) + } else { + lines.push(`# 4lw.commands.whitelist=*`) + } + lines.push(`autopurge.snapRetainCount=${config.autopurgeSnapRetainCount}`) + lines.push(`autopurge.purgeInterval=${config.autopurgePurgeInterval}`) + lines.push(``) + + if (config.adminEnableServer) { + lines.push(`# 管理服务`) + lines.push(`admin.enableServer=true`) + lines.push(`admin.serverPort=${config.adminServerPort}`) + } else { + lines.push(`admin.enableServer=false`) + } + lines.push(``) + + // 集群配置 + if (config.enableCluster) { + lines.push(`# ======================== 集群配置 ========================`) + const servers = config.clusterServers.split('\n').map((s) => s.trim()).filter(Boolean) + for (const server of servers) { + lines.push(server) + } + lines.push(``) + } + + // JVM 配置注释 + lines.push(`# ======================== JVM 配置 ========================`) + lines.push(`# 在 zkEnv.sh 或启动脚本中设置:`) + lines.push(`# export JVMFLAGS="-Xms${config.jvmHeap} -Xmx${config.jvmHeap} -XX:+UseG1GC -XX:MaxGCPauseMillis=200"`) + lines.push(`#`) + + return lines.join('\n') +}