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') }