feat: 新增 MongoDB、Ansible、Ansible Playbook 三个组件
- MongoDB: WiredTiger 引擎、认证、TLS、副本集、Oplog、压缩算法 - Ansible: SSH 连接、Pipelining、Become 提权、Forks、日志、事实缓存 - Ansible Playbook: 变量、包管理、服务管理、文件复制、模板渲染、Shell、Handlers - 更新 README 组件矩阵与项目结构 - 更新 Schema 注册中心,新增自动化运维分类
This commit is contained in:
@@ -44,8 +44,11 @@
|
||||
| 代理与 Web | **NGINX** | `.conf` | HTTP/HTTPS 端口、域名、SSL 证书、反向代理、Gzip、CORS |
|
||||
| 缓存 | **Redis** | `.conf` | 单机/哨兵/集群模式、端口、内存限制、RDB/AOF 持久化、密码 |
|
||||
| 数据库 | **MySQL** | `.cnf` | 版本(5.7/8.0)、Buffer Pool 自动计算、字符集、慢查询、主从复制 |
|
||||
| 数据库 | **MongoDB** | `.conf` | 端口、WiredTiger 引擎、认证、TLS、副本集、Oplog、压缩算法 |
|
||||
| 云原生 | **K8s Deployment** | `.yaml` | 镜像、副本数、资源限制、健康检查、滚动更新策略 |
|
||||
| 云原生 | **K8s Service** | `.yaml` | ClusterIP/NodePort/LoadBalancer、端口映射、会话保持 |
|
||||
| 自动化运维 | **Ansible** | `.cfg` | SSH 连接、Pipelining、Become 提权、Forks 并发、日志、事实缓存 |
|
||||
| 自动化运维 | **Ansible Playbook** | `.yaml` | 变量、包管理、服务管理、文件复制、模板渲染、Shell 命令、Handlers |
|
||||
|
||||
---
|
||||
|
||||
@@ -105,8 +108,11 @@ conf-template/
|
||||
│ ├── nginx.js # NGINX Schema 定义 + 模板生成
|
||||
│ ├── redis.js # Redis Schema 定义 + 模板生成
|
||||
│ ├── mysql.js # MySQL Schema 定义 + 模板生成
|
||||
│ ├── mongodb.js # MongoDB Schema 定义 + 模板生成
|
||||
│ ├── k8s-deployment.js # K8s Deployment Schema + YAML 生成
|
||||
│ └── k8s-service.js # K8s Service Schema + YAML 生成
|
||||
│ ├── k8s-service.js # K8s Service Schema + YAML 生成
|
||||
│ ├── ansible.js # Ansible Schema + 配置生成
|
||||
│ └── ansible-playbook.js # Ansible Playbook Schema + YAML 生成
|
||||
└── dist/ # 生产构建产物(gitignore)
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,468 @@
|
||||
export const ansiblePlaybookSchema = {
|
||||
id: 'ansible-playbook',
|
||||
name: 'Ansible Playbook',
|
||||
icon: 'List',
|
||||
category: '自动化运维',
|
||||
description: 'Ansible 任务编排与自动化剧本',
|
||||
format: 'yaml',
|
||||
fileName: 'playbook.yaml',
|
||||
groups: [
|
||||
{
|
||||
title: 'Play 基本信息',
|
||||
fields: [
|
||||
{
|
||||
key: 'playName',
|
||||
label: 'Play 名称',
|
||||
type: 'text',
|
||||
placeholder: 'Configure web servers',
|
||||
default: 'My Playbook',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'hosts',
|
||||
label: '目标主机/组',
|
||||
type: 'text',
|
||||
placeholder: 'webservers 或 all',
|
||||
default: 'all',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'become',
|
||||
label: '使用 sudo 提权',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
key: 'gatherFacts',
|
||||
label: '收集主机信息',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '变量与环境',
|
||||
fields: [
|
||||
{
|
||||
key: 'enableVars',
|
||||
label: '定义变量',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'varAppPort',
|
||||
label: '应用端口 (app_port)',
|
||||
type: 'number',
|
||||
min: 1,
|
||||
max: 65535,
|
||||
default: 8080,
|
||||
dependsOn: { key: 'enableVars', value: true },
|
||||
},
|
||||
{
|
||||
key: 'varAppName',
|
||||
label: '应用名称 (app_name)',
|
||||
type: 'text',
|
||||
default: 'myapp',
|
||||
dependsOn: { key: 'enableVars', value: true },
|
||||
},
|
||||
{
|
||||
key: 'enableEnvironment',
|
||||
label: '设置环境变量',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'envHttpProxy',
|
||||
label: 'HTTP_PROXY',
|
||||
type: 'text',
|
||||
placeholder: 'http://proxy.example.com:8080',
|
||||
default: 'http://proxy.example.com:8080',
|
||||
dependsOn: { key: 'enableEnvironment', value: true },
|
||||
},
|
||||
{
|
||||
key: 'envHttpsProxy',
|
||||
label: 'HTTPS_PROXY',
|
||||
type: 'text',
|
||||
placeholder: 'http://proxy.example.com:8080',
|
||||
default: 'http://proxy.example.com:8080',
|
||||
dependsOn: { key: 'enableEnvironment', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '前置任务 (Pre Tasks)',
|
||||
fields: [
|
||||
{
|
||||
key: 'enablePretasks',
|
||||
label: '添加前置任务',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'pretaskUpdateCache',
|
||||
label: '更新包管理器缓存',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
dependsOn: { key: 'enablePretasks', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Tasks — 包管理',
|
||||
fields: [
|
||||
{
|
||||
key: 'taskInstallPackages',
|
||||
label: '安装软件包',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'packagesToInstall',
|
||||
label: '包名列表',
|
||||
type: 'text',
|
||||
placeholder: 'nginx, curl, vim (逗号分隔)',
|
||||
default: 'nginx, curl',
|
||||
dependsOn: { key: 'taskInstallPackages', value: true },
|
||||
tip: '多个包用逗号分隔',
|
||||
},
|
||||
{
|
||||
key: 'packageState',
|
||||
label: '安装状态',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'present - 确保已安装', value: 'present' },
|
||||
{ label: 'latest - 更新到最新版', value: 'latest' },
|
||||
{ label: 'absent - 卸载', value: 'absent' },
|
||||
],
|
||||
default: 'present',
|
||||
dependsOn: { key: 'taskInstallPackages', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Tasks — 服务管理',
|
||||
fields: [
|
||||
{
|
||||
key: 'taskManageService',
|
||||
label: '管理服务',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'serviceName',
|
||||
label: '服务名称',
|
||||
type: 'text',
|
||||
placeholder: 'nginx',
|
||||
default: 'nginx',
|
||||
dependsOn: { key: 'taskManageService', value: true },
|
||||
},
|
||||
{
|
||||
key: 'serviceState',
|
||||
label: '服务状态',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'started - 启动', value: 'started' },
|
||||
{ label: 'stopped - 停止', value: 'stopped' },
|
||||
{ label: 'restarted - 重启', value: 'restarted' },
|
||||
{ label: 'reloaded - 重载配置', value: 'reloaded' },
|
||||
],
|
||||
default: 'started',
|
||||
dependsOn: { key: 'taskManageService', value: true },
|
||||
},
|
||||
{
|
||||
key: 'serviceEnabled',
|
||||
label: '开机自启',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
dependsOn: { key: 'taskManageService', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Tasks — 文件管理',
|
||||
fields: [
|
||||
{
|
||||
key: 'taskCopyFile',
|
||||
label: '复制文件到远程',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'copySrc',
|
||||
label: '本地源文件路径',
|
||||
type: 'text',
|
||||
placeholder: './files/index.html',
|
||||
default: './files/index.html',
|
||||
dependsOn: { key: 'taskCopyFile', value: true },
|
||||
},
|
||||
{
|
||||
key: 'copyDest',
|
||||
label: '远程目标路径',
|
||||
type: 'text',
|
||||
placeholder: '/var/www/html/index.html',
|
||||
default: '/var/www/html/index.html',
|
||||
dependsOn: { key: 'taskCopyFile', value: true },
|
||||
},
|
||||
{
|
||||
key: 'taskCreateDir',
|
||||
label: '创建目录',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'dirPath',
|
||||
label: '目录路径',
|
||||
type: 'text',
|
||||
placeholder: '/var/www/myapp',
|
||||
default: '/var/www/myapp',
|
||||
dependsOn: { key: 'taskCreateDir', value: true },
|
||||
},
|
||||
{
|
||||
key: 'dirOwner',
|
||||
label: '目录所有者',
|
||||
type: 'text',
|
||||
default: 'www-data',
|
||||
dependsOn: { key: 'taskCreateDir', value: true },
|
||||
},
|
||||
{
|
||||
key: 'dirMode',
|
||||
label: '目录权限',
|
||||
type: 'text',
|
||||
default: '0755',
|
||||
dependsOn: { key: 'taskCreateDir', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Tasks — 模板渲染',
|
||||
fields: [
|
||||
{
|
||||
key: 'taskTemplate',
|
||||
label: '渲染 Jinja2 模板',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'templateSrc',
|
||||
label: '模板文件路径',
|
||||
type: 'text',
|
||||
placeholder: './templates/nginx.conf.j2',
|
||||
default: './templates/nginx.conf.j2',
|
||||
dependsOn: { key: 'taskTemplate', value: true },
|
||||
},
|
||||
{
|
||||
key: 'templateDest',
|
||||
label: '远程目标路径',
|
||||
type: 'text',
|
||||
placeholder: '/etc/nginx/nginx.conf',
|
||||
default: '/etc/nginx/nginx.conf',
|
||||
dependsOn: { key: 'taskTemplate', value: true },
|
||||
},
|
||||
{
|
||||
key: 'templateOwner',
|
||||
label: '文件所有者',
|
||||
type: 'text',
|
||||
default: 'root',
|
||||
dependsOn: { key: 'taskTemplate', value: true },
|
||||
},
|
||||
{
|
||||
key: 'templateMode',
|
||||
label: '文件权限',
|
||||
type: 'text',
|
||||
default: '0644',
|
||||
dependsOn: { key: 'taskTemplate', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Tasks — 执行命令',
|
||||
fields: [
|
||||
{
|
||||
key: 'taskShell',
|
||||
label: '执行 Shell 命令',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'shellCommand',
|
||||
label: '命令内容',
|
||||
type: 'text',
|
||||
placeholder: 'systemctl daemon-reload',
|
||||
default: 'systemctl daemon-reload',
|
||||
dependsOn: { key: 'taskShell', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '后置任务 (Post Tasks) 与处理器',
|
||||
fields: [
|
||||
{
|
||||
key: 'enableHandlers',
|
||||
label: '定义处理器 (Handlers)',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
tip: '由 notify 触发的任务,如重启服务',
|
||||
},
|
||||
{
|
||||
key: 'handlerName',
|
||||
label: '处理器名称',
|
||||
type: 'text',
|
||||
default: 'restart nginx',
|
||||
dependsOn: { key: 'enableHandlers', value: true },
|
||||
},
|
||||
{
|
||||
key: 'handlerService',
|
||||
label: '重启的服务',
|
||||
type: 'text',
|
||||
default: 'nginx',
|
||||
dependsOn: { key: 'enableHandlers', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export function generateAnsiblePlaybookYaml(config) {
|
||||
const indent = (str, n) => str.split('\n').map(l => ' '.repeat(n) + l).join('\n')
|
||||
const lines = []
|
||||
|
||||
lines.push(`# Ansible Playbook - 由 ConfTemplate 生成`)
|
||||
lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`)
|
||||
lines.push(`# 执行命令: ansible-playbook ${config.fileName || 'playbook.yaml'}`)
|
||||
lines.push(``)
|
||||
lines.push(`- name: ${config.playName}`)
|
||||
lines.push(` hosts: ${config.hosts}`)
|
||||
|
||||
if (config.become) {
|
||||
lines.push(` become: true`)
|
||||
}
|
||||
|
||||
lines.push(` gather_facts: ${config.gatherFacts ? 'true' : 'false'}`)
|
||||
|
||||
// 变量
|
||||
if (config.enableVars) {
|
||||
lines.push(``)
|
||||
lines.push(` vars:`)
|
||||
lines.push(` app_port: ${config.varAppPort}`)
|
||||
lines.push(` app_name: ${config.varAppName}`)
|
||||
}
|
||||
|
||||
// 环境变量
|
||||
if (config.enableEnvironment) {
|
||||
lines.push(``)
|
||||
lines.push(` environment:`)
|
||||
lines.push(` HTTP_PROXY: ${config.envHttpProxy}`)
|
||||
lines.push(` HTTPS_PROXY: ${config.envHttpsProxy}`)
|
||||
}
|
||||
|
||||
// 前置任务
|
||||
if (config.enablePretasks) {
|
||||
lines.push(``)
|
||||
lines.push(` pre_tasks:`)
|
||||
if (config.pretaskUpdateCache) {
|
||||
lines.push(` - name: Update apt cache`)
|
||||
lines.push(` apt:`)
|
||||
lines.push(` update_cache: yes`)
|
||||
lines.push(` cache_valid_time: 3600`)
|
||||
lines.push(` when: ansible_os_family == "Debian"`)
|
||||
lines.push(``)
|
||||
lines.push(` - name: Update yum cache`)
|
||||
lines.push(` yum:`)
|
||||
lines.push(` update_cache: yes`)
|
||||
lines.push(` when: ansible_os_family == "RedHat"`)
|
||||
}
|
||||
}
|
||||
|
||||
// 主任务
|
||||
lines.push(``)
|
||||
lines.push(` tasks:`)
|
||||
let taskNum = 0
|
||||
|
||||
// 安装包
|
||||
if (config.taskInstallPackages) {
|
||||
taskNum++
|
||||
const pkgs = config.packagesToInstall.split(',').map(s => s.trim()).filter(Boolean)
|
||||
lines.push(` - name: Install packages`)
|
||||
lines.push(` ansible.builtin.package:`)
|
||||
lines.push(` name:`)
|
||||
pkgs.forEach(p => lines.push(` - ${p}`))
|
||||
lines.push(` state: ${config.packageState}`)
|
||||
lines.push(``)
|
||||
}
|
||||
|
||||
// 文件复制
|
||||
if (config.taskCopyFile) {
|
||||
taskNum++
|
||||
lines.push(` - name: Copy file to remote host`)
|
||||
lines.push(` ansible.builtin.copy:`)
|
||||
lines.push(` src: ${config.copySrc}`)
|
||||
lines.push(` dest: ${config.copyDest}`)
|
||||
lines.push(` owner: root`)
|
||||
lines.push(` mode: '0644'`)
|
||||
|
||||
if (config.enableHandlers && config.handlerName) {
|
||||
lines.push(` notify: ${config.handlerName}`)
|
||||
}
|
||||
lines.push(``)
|
||||
}
|
||||
|
||||
// 创建目录
|
||||
if (config.taskCreateDir) {
|
||||
taskNum++
|
||||
lines.push(` - name: Create application directory`)
|
||||
lines.push(` ansible.builtin.file:`)
|
||||
lines.push(` path: ${config.dirPath}`)
|
||||
lines.push(` state: directory`)
|
||||
lines.push(` owner: ${config.dirOwner}`)
|
||||
lines.push(` mode: '${config.dirMode}'`)
|
||||
lines.push(``)
|
||||
}
|
||||
|
||||
// 模板渲染
|
||||
if (config.taskTemplate) {
|
||||
taskNum++
|
||||
lines.push(` - name: Deploy configuration from template`)
|
||||
lines.push(` ansible.builtin.template:`)
|
||||
lines.push(` src: ${config.templateSrc}`)
|
||||
lines.push(` dest: ${config.templateDest}`)
|
||||
lines.push(` owner: ${config.templateOwner}`)
|
||||
lines.push(` mode: '${config.templateMode}'`)
|
||||
|
||||
if (config.enableHandlers && config.handlerName) {
|
||||
lines.push(` notify: ${config.handlerName}`)
|
||||
}
|
||||
lines.push(``)
|
||||
}
|
||||
|
||||
// Shell 命令
|
||||
if (config.taskShell) {
|
||||
taskNum++
|
||||
lines.push(` - name: Execute shell command`)
|
||||
lines.push(` ansible.builtin.shell:`)
|
||||
lines.push(` cmd: ${config.shellCommand}`)
|
||||
lines.push(` changed_when: true`)
|
||||
lines.push(``)
|
||||
}
|
||||
|
||||
// 服务管理
|
||||
if (config.taskManageService) {
|
||||
taskNum++
|
||||
lines.push(` - name: Manage service ${config.serviceName}`)
|
||||
lines.push(` ansible.builtin.service:`)
|
||||
lines.push(` name: ${config.serviceName}`)
|
||||
lines.push(` state: ${config.serviceState}`)
|
||||
lines.push(` enabled: ${config.serviceEnabled ? 'true' : 'false'}`)
|
||||
lines.push(``)
|
||||
}
|
||||
|
||||
// 处理器
|
||||
if (config.enableHandlers && config.handlerName) {
|
||||
lines.push(` handlers:`)
|
||||
lines.push(` - name: ${config.handlerName}`)
|
||||
lines.push(` ansible.builtin.service:`)
|
||||
lines.push(` name: ${config.handlerService}`)
|
||||
lines.push(` state: restarted`)
|
||||
}
|
||||
|
||||
return lines.join('\n')
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
export const ansibleSchema = {
|
||||
id: 'ansible',
|
||||
name: 'Ansible',
|
||||
icon: 'Files',
|
||||
category: '自动化运维',
|
||||
description: '自动化配置管理与应用部署工具',
|
||||
format: 'cfg',
|
||||
fileName: 'ansible.cfg',
|
||||
groups: [
|
||||
{
|
||||
title: '基础配置',
|
||||
fields: [
|
||||
{
|
||||
key: 'inventory',
|
||||
label: 'Inventory 文件路径',
|
||||
type: 'text',
|
||||
default: '/etc/ansible/hosts',
|
||||
tip: '主机清单文件路径',
|
||||
},
|
||||
{
|
||||
key: 'remoteUser',
|
||||
label: '远程用户',
|
||||
type: 'text',
|
||||
placeholder: 'root',
|
||||
default: 'root',
|
||||
},
|
||||
{
|
||||
key: 'hostKeyChecking',
|
||||
label: 'SSH 主机密钥检查',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
tip: '首次连接是否检查主机密钥,测试环境建议关闭',
|
||||
},
|
||||
{
|
||||
key: 'retryFilesEnabled',
|
||||
label: '启用重试文件',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
tip: '失败时生成 .retry 文件',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'SSH 连接',
|
||||
fields: [
|
||||
{
|
||||
key: 'privateKeyFile',
|
||||
label: 'SSH 私钥路径',
|
||||
type: 'text',
|
||||
placeholder: '~/.ssh/id_rsa',
|
||||
default: '~/.ssh/id_rsa',
|
||||
},
|
||||
{
|
||||
key: 'sshPort',
|
||||
label: 'SSH 默认端口',
|
||||
type: 'number',
|
||||
min: 1,
|
||||
max: 65535,
|
||||
default: 22,
|
||||
},
|
||||
{
|
||||
key: 'timeout',
|
||||
label: '连接超时 (秒)',
|
||||
type: 'number',
|
||||
min: 5,
|
||||
max: 300,
|
||||
default: 30,
|
||||
},
|
||||
{
|
||||
key: 'pipelining',
|
||||
label: '开启 Pipelining',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
tip: '减少 SSH 连接次数,提升执行效率',
|
||||
},
|
||||
{
|
||||
key: 'sshArgs',
|
||||
label: 'SSH 额外参数',
|
||||
type: 'text',
|
||||
placeholder: '-o ControlMaster=auto -o ControlPersist=60s',
|
||||
default: '-o ControlMaster=auto -o ControlPersist=60s',
|
||||
tip: '控制 SSH 连接复用',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '权限提升 (Become)',
|
||||
fields: [
|
||||
{
|
||||
key: 'become',
|
||||
label: '默认开启提权',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
tip: '是否默认使用 sudo 提权',
|
||||
},
|
||||
{
|
||||
key: 'becomeMethod',
|
||||
label: '提权方式',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'sudo', value: 'sudo' },
|
||||
{ label: 'su', value: 'su' },
|
||||
{ label: 'pbrun', value: 'pbrun' },
|
||||
{ label: 'pfexec', value: 'pfexec' },
|
||||
],
|
||||
default: 'sudo',
|
||||
dependsOn: { key: 'become', value: true },
|
||||
},
|
||||
{
|
||||
key: 'becomeUser',
|
||||
label: '提权目标用户',
|
||||
type: 'text',
|
||||
default: 'root',
|
||||
dependsOn: { key: 'become', value: true },
|
||||
},
|
||||
{
|
||||
key: 'becomeAskPass',
|
||||
label: '询问提权密码',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
dependsOn: { key: 'become', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '执行控制',
|
||||
fields: [
|
||||
{
|
||||
key: 'forks',
|
||||
label: '并发进程数 (forks)',
|
||||
type: 'number',
|
||||
min: 1,
|
||||
max: 200,
|
||||
default: 20,
|
||||
tip: '同时操作的主机数量',
|
||||
},
|
||||
{
|
||||
key: 'pollInterval',
|
||||
label: '轮询间隔 (秒)',
|
||||
type: 'number',
|
||||
min: 1,
|
||||
max: 60,
|
||||
default: 15,
|
||||
},
|
||||
{
|
||||
key: 'timeoutTask',
|
||||
label: '任务超时 (秒)',
|
||||
type: 'number',
|
||||
min: 10,
|
||||
max: 3600,
|
||||
default: 300,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '日志与输出',
|
||||
fields: [
|
||||
{
|
||||
key: 'logPath',
|
||||
label: '日志文件路径',
|
||||
type: 'text',
|
||||
placeholder: '/var/log/ansible.log',
|
||||
default: '',
|
||||
tip: '留空表示不记录到文件',
|
||||
},
|
||||
{
|
||||
key: 'stdoutCallback',
|
||||
label: '输出回调插件',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'default - 默认格式', value: 'default' },
|
||||
{ label: 'yaml - YAML 格式 (推荐)', value: 'yaml' },
|
||||
{ label: 'json - JSON 格式', value: 'json' },
|
||||
{ label: 'minimal - 最小化输出', value: 'minimal' },
|
||||
{ label: 'dense - 密集输出', value: 'dense' },
|
||||
],
|
||||
default: 'yaml',
|
||||
},
|
||||
{
|
||||
key: 'displaySkippedHosts',
|
||||
label: '显示跳过的主机',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'displayOkHosts',
|
||||
label: '显示成功的主机',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '事实收集',
|
||||
fields: [
|
||||
{
|
||||
key: 'gathering',
|
||||
label: '事实收集策略',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'smart - 智能缓存 (推荐)', value: 'smart' },
|
||||
{ label: 'implicit - 每次收集', value: 'implicit' },
|
||||
{ label: 'explicit - 仅显式收集', value: 'explicit' },
|
||||
],
|
||||
default: 'smart',
|
||||
},
|
||||
{
|
||||
key: 'factCaching',
|
||||
label: '事实缓存方式',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'memory - 不缓存 (默认)', value: 'memory' },
|
||||
{ label: 'jsonfile - JSON 文件缓存', value: 'jsonfile' },
|
||||
{ label: 'redis - Redis 缓存', value: 'redis' },
|
||||
],
|
||||
default: 'memory',
|
||||
},
|
||||
{
|
||||
key: 'factCachingConnection',
|
||||
label: '缓存路径/连接',
|
||||
type: 'text',
|
||||
placeholder: '/tmp/ansible_facts_cache',
|
||||
default: '/tmp/ansible_facts_cache',
|
||||
dependsOn: { key: 'factCaching', value: 'jsonfile' },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export function generateAnsibleCfg(config) {
|
||||
const lines = []
|
||||
lines.push(`# Ansible 配置文件 - 由 ConfTemplate 生成`)
|
||||
lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`)
|
||||
lines.push(``)
|
||||
lines.push(`[defaults]`)
|
||||
lines.push(`inventory = ${config.inventory}`)
|
||||
lines.push(`remote_user = ${config.remoteUser}`)
|
||||
lines.push(`host_key_checking = ${config.hostKeyChecking ? 'True' : 'False'}`)
|
||||
lines.push(`retry_files_enabled = ${config.retryFilesEnabled ? 'True' : 'False'}`)
|
||||
lines.push(`forks = ${config.forks}`)
|
||||
lines.push(`poll_interval = ${config.pollInterval}`)
|
||||
lines.push(`timeout = ${config.timeoutTask}`)
|
||||
lines.push(`stdout_callback = ${config.stdoutCallback}`)
|
||||
lines.push(`display_skipped_hosts = ${config.displaySkippedHosts ? 'True' : 'False'}`)
|
||||
lines.push(`display_ok_hosts = ${config.displayOkHosts ? 'True' : 'False'}`)
|
||||
lines.push(`gathering = ${config.gathering}`)
|
||||
|
||||
if (config.factCaching !== 'memory') {
|
||||
lines.push(`fact_caching = ${config.factCaching}`)
|
||||
lines.push(`fact_caching_connection = ${config.factCachingConnection}`)
|
||||
lines.push(`fact_caching_timeout = 86400`)
|
||||
}
|
||||
|
||||
if (config.logPath) {
|
||||
lines.push(`log_path = ${config.logPath}`)
|
||||
}
|
||||
|
||||
lines.push(``)
|
||||
lines.push(`[ssh_connection]`)
|
||||
lines.push(`ssh_args = ${config.sshArgs}`)
|
||||
lines.push(`pipelining = ${config.pipelining ? 'True' : 'False'}`)
|
||||
lines.push(`control_path = /tmp/ansible-%%h-%%r`)
|
||||
lines.push(`timeout = ${config.timeout}`)
|
||||
|
||||
if (config.privateKeyFile) {
|
||||
lines.push(`private_key_file = ${config.privateKeyFile}`)
|
||||
}
|
||||
|
||||
if (config.become) {
|
||||
lines.push(``)
|
||||
lines.push(`[privilege_escalation]`)
|
||||
lines.push(`become = True`)
|
||||
lines.push(`become_method = ${config.becomeMethod}`)
|
||||
lines.push(`become_user = ${config.becomeUser}`)
|
||||
lines.push(`become_ask_pass = ${config.becomeAskPass ? 'True' : 'False'}`)
|
||||
}
|
||||
|
||||
lines.push(``)
|
||||
lines.push(`[inventory]`)
|
||||
lines.push(`enable_plugins = host_list, script, yaml, ini, auto`)
|
||||
|
||||
return lines.join('\n')
|
||||
}
|
||||
+16
-1
@@ -1,23 +1,32 @@
|
||||
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'
|
||||
|
||||
export const schemas = {
|
||||
nginx: nginxSchema,
|
||||
redis: redisSchema,
|
||||
mysql: mysqlSchema,
|
||||
mongodb: mongodbSchema,
|
||||
'k8s-deployment': k8sDeploymentSchema,
|
||||
'k8s-service': k8sServiceSchema,
|
||||
ansible: ansibleSchema,
|
||||
'ansible-playbook': ansiblePlaybookSchema,
|
||||
}
|
||||
|
||||
export const generators = {
|
||||
nginx: generateNginxConf,
|
||||
redis: generateRedisConf,
|
||||
mysql: generateMysqlConf,
|
||||
mongodb: generateMongodbConf,
|
||||
'k8s-deployment': generateK8sDeploymentYaml,
|
||||
'k8s-service': generateK8sServiceYaml,
|
||||
ansible: generateAnsibleCfg,
|
||||
'ansible-playbook': generateAnsiblePlaybookYaml,
|
||||
}
|
||||
|
||||
export const categories = [
|
||||
@@ -34,13 +43,18 @@ export const categories = [
|
||||
{
|
||||
name: '数据库',
|
||||
icon: 'Coin',
|
||||
items: ['mysql'],
|
||||
items: ['mysql', 'mongodb'],
|
||||
},
|
||||
{
|
||||
name: '云原生',
|
||||
icon: 'Box',
|
||||
items: ['k8s-deployment', 'k8s-service'],
|
||||
},
|
||||
{
|
||||
name: '自动化运维',
|
||||
icon: 'Files',
|
||||
items: ['ansible', 'ansible-playbook'],
|
||||
},
|
||||
]
|
||||
|
||||
export function getDefaultValues(schema) {
|
||||
@@ -57,6 +71,7 @@ export function getLanguage(format) {
|
||||
const map = {
|
||||
conf: 'ini',
|
||||
cnf: 'ini',
|
||||
cfg: 'ini',
|
||||
yaml: 'yaml',
|
||||
json: 'json',
|
||||
toml: 'toml',
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
export const mongodbSchema = {
|
||||
id: 'mongodb',
|
||||
name: 'MongoDB',
|
||||
icon: 'Coin',
|
||||
category: '数据库',
|
||||
description: '面向文档的 NoSQL 数据库',
|
||||
format: 'conf',
|
||||
fileName: 'mongod.conf',
|
||||
groups: [
|
||||
{
|
||||
title: '基础配置',
|
||||
fields: [
|
||||
{
|
||||
key: 'port',
|
||||
label: '监听端口',
|
||||
type: 'number',
|
||||
min: 1,
|
||||
max: 65535,
|
||||
default: 27017,
|
||||
},
|
||||
{
|
||||
key: 'bindIp',
|
||||
label: '绑定地址',
|
||||
type: 'text',
|
||||
default: '0.0.0.0',
|
||||
tip: '0.0.0.0 允许所有地址连接',
|
||||
},
|
||||
{
|
||||
key: 'dbPath',
|
||||
label: '数据目录',
|
||||
type: 'text',
|
||||
default: '/var/lib/mongodb',
|
||||
},
|
||||
{
|
||||
key: 'logPath',
|
||||
label: '日志文件路径',
|
||||
type: 'text',
|
||||
default: '/var/log/mongodb/mongod.log',
|
||||
},
|
||||
{
|
||||
key: 'fork',
|
||||
label: '守护进程模式',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '安全认证',
|
||||
fields: [
|
||||
{
|
||||
key: 'auth',
|
||||
label: '开启身份认证',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
tip: '生产环境必须开启',
|
||||
},
|
||||
{
|
||||
key: 'authorization',
|
||||
label: '授权模式',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'enabled - 基于角色的访问控制 (推荐)', value: 'enabled' },
|
||||
{ label: 'disabled - 无访问控制', value: 'disabled' },
|
||||
],
|
||||
default: 'enabled',
|
||||
dependsOn: { key: 'auth', value: true },
|
||||
},
|
||||
{
|
||||
key: 'enableTls',
|
||||
label: '开启 TLS/SSL',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'tlsCertFile',
|
||||
label: 'TLS 证书文件',
|
||||
type: 'text',
|
||||
placeholder: '/etc/ssl/mongodb.pem',
|
||||
default: '/etc/ssl/mongodb.pem',
|
||||
dependsOn: { key: 'enableTls', value: true },
|
||||
},
|
||||
{
|
||||
key: 'tlsKeyFile',
|
||||
label: 'TLS 私钥文件',
|
||||
type: 'text',
|
||||
placeholder: '/etc/ssl/mongodb-key.pem',
|
||||
default: '/etc/ssl/mongodb-key.pem',
|
||||
dependsOn: { key: 'enableTls', value: true },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '存储引擎',
|
||||
fields: [
|
||||
{
|
||||
key: 'engine',
|
||||
label: '存储引擎',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'WiredTiger (默认,推荐)', value: 'wiredTiger' },
|
||||
],
|
||||
default: 'wiredTiger',
|
||||
},
|
||||
{
|
||||
key: 'cacheSizeGB',
|
||||
label: 'WiredTiger 缓存大小 (GB)',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '自动 (物理内存的 50%)', value: '' },
|
||||
{ label: '1 GB', value: '1' },
|
||||
{ label: '2 GB', value: '2' },
|
||||
{ label: '4 GB', value: '4' },
|
||||
{ label: '8 GB', value: '8' },
|
||||
{ label: '16 GB', value: '16' },
|
||||
],
|
||||
default: '',
|
||||
tip: '默认为 (物理内存 - 1GB) 的 50%',
|
||||
},
|
||||
{
|
||||
key: 'journalEnabled',
|
||||
label: '开启 Journal 日志',
|
||||
type: 'switch',
|
||||
default: true,
|
||||
tip: '保证数据持久性,单节点必须开启',
|
||||
},
|
||||
{
|
||||
key: 'directoryPerDb',
|
||||
label: '每个数据库独立目录',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '网络与连接',
|
||||
fields: [
|
||||
{
|
||||
key: 'maxConns',
|
||||
label: '最大连接数',
|
||||
type: 'number',
|
||||
min: 10,
|
||||
max: 65536,
|
||||
default: 65536,
|
||||
},
|
||||
{
|
||||
key: 'ipv6',
|
||||
label: '启用 IPv6',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
key: 'httpInterface',
|
||||
label: '开启 HTTP 接口',
|
||||
type: 'switch',
|
||||
default: false,
|
||||
tip: '生产环境建议关闭',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '操作日志 (Oplog)',
|
||||
fields: [
|
||||
{
|
||||
key: 'oplogSizeMB',
|
||||
label: 'Oplog 大小 (MB)',
|
||||
type: 'number',
|
||||
min: 0,
|
||||
max: 102400,
|
||||
step: 512,
|
||||
default: 0,
|
||||
tip: '0 表示使用默认值(磁盘的 5%)',
|
||||
},
|
||||
{
|
||||
key: 'replSetName',
|
||||
label: '副本集名称',
|
||||
type: 'text',
|
||||
placeholder: '留空表示不启用副本集',
|
||||
default: '',
|
||||
tip: '设置后启用副本集模式',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '性能调优',
|
||||
fields: [
|
||||
{
|
||||
key: 'wiredTigerCollectionBlockCompressor',
|
||||
label: '压缩算法',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: 'snappy (默认,平衡)', value: 'snappy' },
|
||||
{ label: 'zlib (高压缩率)', value: 'zlib' },
|
||||
{ label: 'zstd (最佳压缩)', value: 'zstd' },
|
||||
{ label: 'none (不压缩)', value: 'none' },
|
||||
],
|
||||
default: 'snappy',
|
||||
},
|
||||
{
|
||||
key: 'profileLevel',
|
||||
label: 'Profiling 级别',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '0 - 关闭 (推荐生产)', value: '0' },
|
||||
{ label: '1 - 慢操作', value: '1' },
|
||||
{ label: '2 - 所有操作', value: '2' },
|
||||
],
|
||||
default: '0',
|
||||
tip: '性能分析,调试时开启',
|
||||
},
|
||||
{
|
||||
key: 'slowOpThresholdMs',
|
||||
label: '慢操作阈值 (毫秒)',
|
||||
type: 'number',
|
||||
min: 0,
|
||||
max: 60000,
|
||||
default: 100,
|
||||
dependsOn: { key: 'profileLevel', valueNotIn: ['0'] },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export function generateMongodbConf(config) {
|
||||
const lines = []
|
||||
lines.push(`# MongoDB 配置文件 - 由 ConfTemplate 生成`)
|
||||
lines.push(`# 生成时间: ${new Date().toLocaleString('zh-CN')}`)
|
||||
lines.push(``)
|
||||
lines.push(`# ======================== 系统日志 ========================`)
|
||||
lines.push(`systemLog:`)
|
||||
lines.push(` destination: file`)
|
||||
lines.push(` path: ${config.logPath}`)
|
||||
lines.push(` logAppend: true`)
|
||||
lines.push(``)
|
||||
lines.push(`# ======================== 存储 ========================`)
|
||||
lines.push(`storage:`)
|
||||
lines.push(` dbPath: ${config.dbPath}`)
|
||||
lines.push(` engine: ${config.engine}`)
|
||||
lines.push(` directoryPerDB: ${config.directoryPerDb}`)
|
||||
|
||||
if (config.journalEnabled) {
|
||||
lines.push(` journal:`)
|
||||
lines.push(` enabled: true`)
|
||||
}
|
||||
|
||||
if (config.cacheSizeGB) {
|
||||
lines.push(` wiredTiger:`)
|
||||
lines.push(` engineConfig:`)
|
||||
lines.push(` cacheSizeGB: ${config.cacheSizeGB}`)
|
||||
lines.push(` collectionConfig:`)
|
||||
lines.push(` blockCompressor: ${config.wiredTigerCollectionBlockCompressor}`)
|
||||
} else {
|
||||
lines.push(` wiredTiger:`)
|
||||
lines.push(` collectionConfig:`)
|
||||
lines.push(` blockCompressor: ${config.wiredTigerCollectionBlockCompressor}`)
|
||||
}
|
||||
|
||||
lines.push(``)
|
||||
lines.push(`# ======================== 网络 ========================`)
|
||||
lines.push(`net:`)
|
||||
lines.push(` port: ${config.port}`)
|
||||
lines.push(` bindIp: ${config.bindIp}`)
|
||||
lines.push(` maxIncomingConnections: ${config.maxConns}`)
|
||||
|
||||
if (config.ipv6) {
|
||||
lines.push(` ipv6: true`)
|
||||
}
|
||||
|
||||
if (config.httpInterface) {
|
||||
lines.push(` http:`)
|
||||
lines.push(` enabled: true`)
|
||||
}
|
||||
|
||||
if (config.enableTls) {
|
||||
lines.push(` tls:`)
|
||||
lines.push(` mode: requireTLS`)
|
||||
lines.push(` certificateKeyFile: ${config.tlsCertFile}`)
|
||||
}
|
||||
|
||||
lines.push(``)
|
||||
lines.push(`# ======================== 安全 ========================`)
|
||||
lines.push(`security:`)
|
||||
|
||||
if (config.auth) {
|
||||
lines.push(` authorization: ${config.authorization}`)
|
||||
} else {
|
||||
lines.push(` authorization: disabled`)
|
||||
}
|
||||
|
||||
if (config.replSetName) {
|
||||
lines.push(``)
|
||||
lines.push(`# ======================== 副本集 ========================`)
|
||||
lines.push(`replication:`)
|
||||
lines.push(` replSetName: ${config.replSetName}`)
|
||||
if (config.oplogSizeMB > 0) {
|
||||
lines.push(` oplogSizeMB: ${config.oplogSizeMB}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (config.profileLevel !== '0') {
|
||||
lines.push(``)
|
||||
lines.push(`# ======================== 操作日志 ========================`)
|
||||
lines.push(`operationProfiling:`)
|
||||
lines.push(` mode: ${parseInt(config.profileLevel) === 1 ? 'slowOp' : 'all'}`)
|
||||
lines.push(` slowOpThresholdMs: ${config.slowOpThresholdMs}`)
|
||||
}
|
||||
|
||||
lines.push(``)
|
||||
lines.push(`# ======================== 进程管理 ========================`)
|
||||
lines.push(`processManagement:`)
|
||||
lines.push(` fork: ${config.fork}`)
|
||||
lines.push(` pidFilePath: /var/run/mongodb/mongod.pid`)
|
||||
lines.push(` timeZoneInfo: /usr/share/zoneinfo`)
|
||||
|
||||
return lines.join('\n')
|
||||
}
|
||||
Reference in New Issue
Block a user