bdb7d54505
- 新增SSH密钥库管理(集中托管私钥、自动指纹识别) - 新增模板中心(24个预置模板,7大分类,一键创建Playbook) - 新增文件分发功能(内容/文件双模式,权限设置) - 新增系统信息接口(版本/主机数/运行时间) - 主机支持密码/SSH密钥双认证方式 - 全新暗色玻璃拟态UI(侧边栏导航、SSE实时日志流) - 修复UpdateHost ID丢失bug - 添加.gitignore排除敏感数据
1659 lines
46 KiB
Go
1659 lines
46 KiB
Go
package services
|
||
|
||
// PlaybookTemplate Playbook模板定义
|
||
type PlaybookTemplate struct {
|
||
ID string `json:"id"`
|
||
Name string `json:"name"`
|
||
Category string `json:"category"`
|
||
Description string `json:"description"`
|
||
Icon string `json:"icon"`
|
||
Content string `json:"content"`
|
||
Tags []string `json:"tags"`
|
||
}
|
||
|
||
// TemplateCategory 模板分类
|
||
type TemplateCategory struct {
|
||
ID string `json:"id"`
|
||
Name string `json:"name"`
|
||
Icon string `json:"icon"`
|
||
Count int `json:"count"`
|
||
}
|
||
|
||
// GetTemplateCategories 获取所有模板分类
|
||
func GetTemplateCategories() []TemplateCategory {
|
||
cats := map[string]TemplateCategory{}
|
||
for _, t := range GetPlaybookTemplates() {
|
||
c, ok := cats[t.Category]
|
||
if !ok {
|
||
c = TemplateCategory{ID: t.Category, Name: categoryNames[t.Category], Icon: categoryIcons[t.Category]}
|
||
}
|
||
c.Count++
|
||
cats[t.Category] = c
|
||
}
|
||
var result []TemplateCategory
|
||
// 按固定顺序输出
|
||
order := []string{"system", "web", "database", "container", "devops", "security", "monitoring"}
|
||
for _, id := range order {
|
||
if c, ok := cats[id]; ok {
|
||
result = append(result, c)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
var categoryNames = map[string]string{
|
||
"system": "系统管理",
|
||
"web": "Web服务",
|
||
"database": "数据库",
|
||
"container": "容器化",
|
||
"devops": "DevOps",
|
||
"security": "安全加固",
|
||
"monitoring": "监控告警",
|
||
}
|
||
|
||
var categoryIcons = map[string]string{
|
||
"system": "🖥️",
|
||
"web": "🌐",
|
||
"database": "🗄️",
|
||
"container": "🐳",
|
||
"devops": "🔧",
|
||
"security": "🔒",
|
||
"monitoring": "📊",
|
||
}
|
||
|
||
// GetPlaybookTemplates 获取所有Playbook模板
|
||
func GetPlaybookTemplates() []PlaybookTemplate {
|
||
return []PlaybookTemplate{
|
||
// ===== 系统管理 =====
|
||
{
|
||
ID: "update-packages", Name: "系统包更新", Category: "system",
|
||
Description: "自动更新系统软件包,支持Debian/RedHat系列",
|
||
Icon: "📦", Tags: []string{"update", "apt", "yum"},
|
||
Content: `---
|
||
- name: 系统包更新
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
update_cache: yes
|
||
upgrade_type: dist # dist(完整升级) 或 safe(安全升级)
|
||
|
||
tasks:
|
||
- name: 更新apt缓存
|
||
apt:
|
||
update_cache: yes
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 升级所有包(Debian)
|
||
apt:
|
||
upgrade: "{{ upgrade_type }}"
|
||
autoremove: yes
|
||
autoclean: yes
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 更新yum缓存
|
||
yum:
|
||
update_cache: yes
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 升级所有包(RedHat)
|
||
yum:
|
||
name: "*"
|
||
state: latest
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 检查是否需要重启
|
||
stat:
|
||
path: /var/run/reboot-required
|
||
register: reboot_required
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 提示重启
|
||
debug:
|
||
msg: "⚠️ 系统需要重启以完成更新"
|
||
when: ansible_os_family == "Debian" and reboot_required.stat.exists
|
||
`,
|
||
},
|
||
{
|
||
ID: "check-system", Name: "系统信息采集", Category: "system",
|
||
Description: "采集操作系统、硬件、网络等详细信息",
|
||
Icon: "🔍", Tags: []string{"info", "facts", "inventory"},
|
||
Content: `---
|
||
- name: 系统信息采集
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
gather_facts: yes
|
||
|
||
tasks:
|
||
- name: 操作系统信息
|
||
debug:
|
||
msg: |
|
||
══════════ 系统信息 ══════════
|
||
主机名: {{ ansible_facts['hostname'] }}
|
||
系统: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }}
|
||
内核: {{ ansible_facts['kernel'] }}
|
||
架构: {{ ansible_facts['architecture'] }}
|
||
CPU: {{ ansible_facts['processor_vcpus'] }} vCPUs
|
||
内存: {{ (ansible_facts['memtotal_mb'] / 1024) | round(2) }} GB
|
||
IP: {{ ansible_facts['default_ipv4']['address'] | default('N/A') }}
|
||
═══════════════════════════════
|
||
|
||
- name: 磁盘使用
|
||
shell: df -h | grep -E '^/dev/'
|
||
register: disk_info
|
||
|
||
- name: 显示磁盘
|
||
debug:
|
||
msg: "{{ disk_info.stdout_lines }}"
|
||
|
||
- name: 运行时间
|
||
shell: uptime -p
|
||
register: uptime_info
|
||
|
||
- name: 显示运行时间
|
||
debug:
|
||
msg: "运行时间: {{ uptime_info.stdout }}"
|
||
`,
|
||
},
|
||
{
|
||
ID: "check-resources", Name: "资源监控检查", Category: "system",
|
||
Description: "检查CPU/内存/磁盘使用率,超阈值告警",
|
||
Icon: "📈", Tags: []string{"monitor", "cpu", "memory", "disk"},
|
||
Content: `---
|
||
- name: 资源监控检查
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
gather_facts: yes
|
||
vars:
|
||
warn_threshold: 80
|
||
crit_threshold: 90
|
||
|
||
tasks:
|
||
- name: 获取CPU使用率
|
||
shell: top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1
|
||
register: cpu_result
|
||
changed_when: false
|
||
|
||
- name: 获取内存使用率
|
||
shell: free | grep Mem | awk '{printf "%.0f", $3/$2*100}'
|
||
register: mem_result
|
||
changed_when: false
|
||
|
||
- name: 获取磁盘使用率
|
||
shell: df -h / | tail -1 | awk '{print $5}' | tr -d '%'
|
||
register: disk_result
|
||
changed_when: false
|
||
|
||
- name: 显示资源报告
|
||
debug:
|
||
msg: |
|
||
═══════ {{ inventory_hostname }} 资源报告 ═══════
|
||
CPU 使用率: {{ cpu_result.stdout }}%
|
||
内存使用率: {{ mem_result.stdout }}%
|
||
磁盘使用率: {{ disk_result.stdout }}%
|
||
告警阈值: {{ warn_threshold }}% / 严重: {{ crit_threshold }}%
|
||
═══════════════════════════════════════
|
||
|
||
- name: 严重告警
|
||
fail:
|
||
msg: "🚨 严重: {{ inventory_hostname }} 资源使用率超过 {{ crit_threshold }}%"
|
||
when: >
|
||
(cpu_result.stdout | int >= crit_threshold) or
|
||
(mem_result.stdout | int >= crit_threshold) or
|
||
(disk_result.stdout | int >= crit_threshold)
|
||
`,
|
||
},
|
||
{
|
||
ID: "log-cleanup", Name: "日志清理", Category: "system",
|
||
Description: "清理系统日志、临时文件,释放磁盘空间",
|
||
Icon: "🧹", Tags: []string{"cleanup", "log", "disk"},
|
||
Content: `---
|
||
- name: 日志清理
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
log_retention_days: 30
|
||
tmp_retention_days: 7
|
||
|
||
tasks:
|
||
- name: 清理journal日志
|
||
shell: journalctl --vacuum-time={{ log_retention_days }}d
|
||
register: journal_result
|
||
changed_when: "'Vacuuming' in journal_result.stdout"
|
||
|
||
- name: 清理旧日志文件
|
||
find:
|
||
paths: /var/log
|
||
patterns: "*.gz,*.old,*.[0-9]"
|
||
age: "{{ log_retention_days }}d"
|
||
register: old_logs
|
||
|
||
- name: 删除旧日志
|
||
file:
|
||
path: "{{ item.path }}"
|
||
state: absent
|
||
loop: "{{ old_logs.files }}"
|
||
|
||
- name: 清理临时文件
|
||
find:
|
||
paths: /tmp
|
||
age: "{{ tmp_retention_days }}d"
|
||
register: tmp_files
|
||
|
||
- name: 删除临时文件
|
||
file:
|
||
path: "{{ item.path }}"
|
||
state: absent
|
||
loop: "{{ tmp_files.files }}"
|
||
ignore_errors: yes
|
||
|
||
- name: 清理apt缓存
|
||
apt:
|
||
autoclean: yes
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 显示磁盘空间
|
||
shell: df -h /
|
||
register: disk_after
|
||
|
||
- name: 清理完成
|
||
debug:
|
||
msg: "{{ disk_after.stdout_lines }}"
|
||
`,
|
||
},
|
||
{
|
||
ID: "time-sync", Name: "时间同步(NTP)", Category: "system",
|
||
Description: "配置NTP时间同步,确保集群时间一致",
|
||
Icon: "⏰", Tags: []string{"ntp", "time", "chrony"},
|
||
Content: `---
|
||
- name: 时间同步配置
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
ntp_servers:
|
||
- ntp.aliyun.com
|
||
- ntp1.aliyun.com
|
||
- pool.ntp.org
|
||
|
||
tasks:
|
||
- name: 安装chrony
|
||
package:
|
||
name: chrony
|
||
state: present
|
||
|
||
- name: 配置NTP服务器
|
||
lineinfile:
|
||
path: /etc/chrony.conf
|
||
regexp: "^server "
|
||
line: "server {{ item }} iburst"
|
||
create: yes
|
||
loop: "{{ ntp_servers }}"
|
||
|
||
- name: 启动chrony
|
||
service:
|
||
name: chronyd
|
||
state: started
|
||
enabled: yes
|
||
|
||
- name: 验证时间同步
|
||
shell: chronyc tracking
|
||
register: chrony_status
|
||
changed_when: false
|
||
|
||
- name: 显示同步状态
|
||
debug:
|
||
msg: "{{ chrony_status.stdout_lines }}"
|
||
`,
|
||
},
|
||
|
||
// ===== Web服务 =====
|
||
{
|
||
ID: "deploy-nginx", Name: "部署Nginx", Category: "web",
|
||
Description: "安装配置Nginx,支持自定义站点和反向代理",
|
||
Icon: "🌐", Tags: []string{"nginx", "web", "proxy"},
|
||
Content: `---
|
||
- name: 部署Nginx
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
nginx_worker_processes: auto
|
||
nginx_worker_connections: 1024
|
||
server_name: localhost
|
||
listen_port: 80
|
||
proxy_pass: ""
|
||
root_dir: /var/www/html
|
||
|
||
tasks:
|
||
- name: 安装Nginx
|
||
package:
|
||
name: nginx
|
||
state: present
|
||
|
||
- name: 创建网站目录
|
||
file:
|
||
path: "{{ root_dir }}"
|
||
state: directory
|
||
owner: www-data
|
||
group: www-data
|
||
mode: '0755'
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 创建网站目录(RedHat)
|
||
file:
|
||
path: "{{ root_dir }}"
|
||
state: directory
|
||
owner: nginx
|
||
group: nginx
|
||
mode: '0755'
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 部署默认页面
|
||
copy:
|
||
content: |
|
||
<!DOCTYPE html>
|
||
<html><head><title>{{ server_name }}</title></head>
|
||
<body><h1>Deployed by Ansible Deploy</h1>
|
||
<p>Server: {{ inventory_hostname }}</p></body></html>
|
||
dest: "{{ root_dir }}/index.html"
|
||
when: proxy_pass == ""
|
||
|
||
- name: 配置Nginx站点
|
||
copy:
|
||
content: |
|
||
server {
|
||
listen {{ listen_port }};
|
||
server_name {{ server_name }};
|
||
{% if proxy_pass != "" %}
|
||
location / {
|
||
proxy_pass {{ proxy_pass }};
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
}
|
||
{% else %}
|
||
root {{ root_dir }};
|
||
index index.html;
|
||
location / {
|
||
try_files $uri $uri/ =404;
|
||
}
|
||
{% endif %}
|
||
}
|
||
dest: /etc/nginx/conf.d/{{ server_name }}.conf
|
||
notify: Reload Nginx
|
||
|
||
- name: 启动Nginx
|
||
service:
|
||
name: nginx
|
||
state: started
|
||
enabled: yes
|
||
|
||
handlers:
|
||
- name: Reload Nginx
|
||
service:
|
||
name: nginx
|
||
state: reloaded
|
||
`,
|
||
},
|
||
{
|
||
ID: "deploy-apache", Name: "部署Apache", Category: "web",
|
||
Description: "安装配置Apache HTTP Server",
|
||
Icon: "🪶", Tags: []string{"apache", "httpd", "web"},
|
||
Content: `---
|
||
- name: 部署Apache
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
server_name: localhost
|
||
listen_port: 80
|
||
document_root: /var/www/html
|
||
|
||
tasks:
|
||
- name: 安装Apache(Debian)
|
||
apt:
|
||
name: apache2
|
||
state: present
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装Apache(RedHat)
|
||
yum:
|
||
name: httpd
|
||
state: present
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 创建网站目录
|
||
file:
|
||
path: "{{ document_root }}"
|
||
state: directory
|
||
mode: '0755'
|
||
|
||
- name: 部署测试页面
|
||
copy:
|
||
content: "<h1>Apache on {{ inventory_hostname }}</h1>"
|
||
dest: "{{ document_root }}/index.html"
|
||
|
||
- name: 启动Apache(Debian)
|
||
service:
|
||
name: apache2
|
||
state: started
|
||
enabled: yes
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 启动Apache(RedHat)
|
||
service:
|
||
name: httpd
|
||
state: started
|
||
enabled: yes
|
||
when: ansible_os_family == "RedHat"
|
||
`,
|
||
},
|
||
|
||
// ===== 数据库 =====
|
||
{
|
||
ID: "deploy-mysql", Name: "部署MySQL", Category: "database",
|
||
Description: "安装MySQL/MariaDB,配置root密码和基础优化",
|
||
Icon: "🐬", Tags: []string{"mysql", "mariadb", "database"},
|
||
Content: `---
|
||
- name: 部署MySQL
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
mysql_root_password: "ChangeMe@2024"
|
||
mysql_port: 3306
|
||
mysql_max_connections: 500
|
||
mysql_datadir: /var/lib/mysql
|
||
|
||
tasks:
|
||
- name: 安装MySQL(Debian)
|
||
apt:
|
||
name:
|
||
- mysql-server
|
||
- mysql-client
|
||
- python3-pymysql
|
||
state: present
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装MariaDB(RedHat)
|
||
yum:
|
||
name:
|
||
- mariadb-server
|
||
- mariadb
|
||
- python3-PyMySQL
|
||
state: present
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 启动MySQL
|
||
service:
|
||
name: "{{ 'mysql' if ansible_os_family == 'Debian' else 'mariadb' }}"
|
||
state: started
|
||
enabled: yes
|
||
|
||
- name: 设置root密码
|
||
shell: |
|
||
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '{{ mysql_root_password }}'; FLUSH PRIVILEGES;"
|
||
ignore_errors: yes
|
||
no_log: true
|
||
|
||
- name: 优化配置
|
||
copy:
|
||
content: |
|
||
[mysqld]
|
||
port = {{ mysql_port }}
|
||
max_connections = {{ mysql_max_connections }}
|
||
datadir = {{ mysql_datadir }}
|
||
innodb_buffer_pool_size = 256M
|
||
character-set-server = utf8mb4
|
||
collation-server = utf8mb4_unicode_ci
|
||
slow_query_log = 1
|
||
slow_query_log_file = /var/log/mysql/slow.log
|
||
long_query_time = 2
|
||
dest: /etc/mysql/conf.d/optimize.cnf
|
||
when: ansible_os_family == "Debian"
|
||
notify: Restart MySQL
|
||
|
||
- name: 验证MySQL
|
||
shell: mysql -u root -p{{ mysql_root_password }} -e "SELECT VERSION();"
|
||
register: mysql_version
|
||
changed_when: false
|
||
no_log: true
|
||
|
||
- name: 显示版本
|
||
debug:
|
||
msg: "MySQL版本: {{ mysql_version.stdout_lines[-1] | default('unknown') }}"
|
||
|
||
handlers:
|
||
- name: Restart MySQL
|
||
service:
|
||
name: "{{ 'mysql' if ansible_os_family == 'Debian' else 'mariadb' }}"
|
||
state: restarted
|
||
`,
|
||
},
|
||
{
|
||
ID: "deploy-redis", Name: "部署Redis", Category: "database",
|
||
Description: "安装Redis,配置密码、内存限制和持久化",
|
||
Icon: "🔴", Tags: []string{"redis", "cache", "database"},
|
||
Content: `---
|
||
- name: 部署Redis
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
redis_port: 6379
|
||
redis_password: "ChangeMe@2024"
|
||
redis_maxmemory: "512mb"
|
||
redis_maxmemory_policy: allkeys-lru
|
||
redis_bind: "0.0.0.0"
|
||
|
||
tasks:
|
||
- name: 安装Redis
|
||
package:
|
||
name: redis-server
|
||
state: present
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装Redis(RedHat)
|
||
yum:
|
||
name: redis
|
||
state: present
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 配置Redis
|
||
lineinfile:
|
||
path: /etc/redis/redis.conf
|
||
regexp: "{{ item.regexp }}"
|
||
line: "{{ item.line }}"
|
||
loop:
|
||
- { regexp: '^bind ', line: 'bind {{ redis_bind }}' }
|
||
- { regexp: '^port ', line: 'port {{ redis_port }}' }
|
||
- { regexp: '^requirepass ', line: 'requirepass {{ redis_password }}' }
|
||
- { regexp: '^maxmemory ', line: 'maxmemory {{ redis_maxmemory }}' }
|
||
- { regexp: '^maxmemory-policy ', line: 'maxmemory-policy {{ redis_maxmemory_policy }}' }
|
||
notify: Restart Redis
|
||
|
||
- name: 启动Redis
|
||
service:
|
||
name: "{{ 'redis-server' if ansible_os_family == 'Debian' else 'redis' }}"
|
||
state: started
|
||
enabled: yes
|
||
|
||
- name: 验证Redis
|
||
shell: redis-cli -a {{ redis_password }} ping
|
||
register: redis_ping
|
||
changed_when: false
|
||
no_log: true
|
||
|
||
- name: 显示状态
|
||
debug:
|
||
msg: "Redis状态: {{ redis_ping.stdout }}"
|
||
|
||
handlers:
|
||
- name: Restart Redis
|
||
service:
|
||
name: "{{ 'redis-server' if ansible_os_family == 'Debian' else 'redis' }}"
|
||
state: restarted
|
||
`,
|
||
},
|
||
{
|
||
ID: "deploy-postgresql", Name: "部署PostgreSQL", Category: "database",
|
||
Description: "安装PostgreSQL,配置用户和基础优化",
|
||
Icon: "🐘", Tags: []string{"postgresql", "postgres", "database"},
|
||
Content: `---
|
||
- name: 部署PostgreSQL
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
postgres_version: "15"
|
||
postgres_password: "ChangeMe@2024"
|
||
postgres_port: 5432
|
||
postgres_max_connections: 200
|
||
|
||
tasks:
|
||
- name: 安装PostgreSQL(Debian)
|
||
apt:
|
||
name:
|
||
- postgresql
|
||
- postgresql-contrib
|
||
- python3-psycopg2
|
||
state: present
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装PostgreSQL(RedHat)
|
||
yum:
|
||
name:
|
||
- postgresql-server
|
||
- postgresql-contrib
|
||
- python3-psycopg2
|
||
state: present
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 初始化数据库(RedHat)
|
||
shell: postgresql-setup --initdb
|
||
when: ansible_os_family == "RedHat"
|
||
ignore_errors: yes
|
||
|
||
- name: 启动PostgreSQL
|
||
service:
|
||
name: postgresql
|
||
state: started
|
||
enabled: yes
|
||
|
||
- name: 设置postgres密码
|
||
become_user: postgres
|
||
shell: psql -c "ALTER USER postgres PASSWORD '{{ postgres_password }}';"
|
||
no_log: true
|
||
|
||
- name: 验证安装
|
||
become_user: postgres
|
||
shell: psql -c "SELECT version();"
|
||
register: pg_version
|
||
changed_when: false
|
||
|
||
- name: 显示版本
|
||
debug:
|
||
msg: "{{ pg_version.stdout_lines[0] | default('PostgreSQL installed') }}"
|
||
`,
|
||
},
|
||
|
||
// ===== 容器化 =====
|
||
{
|
||
ID: "deploy-docker", Name: "部署Docker", Category: "container",
|
||
Description: "安装Docker CE + Docker Compose,配置镜像加速",
|
||
Icon: "🐳", Tags: []string{"docker", "container", "compose"},
|
||
Content: `---
|
||
- name: 部署Docker
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
docker_mirror: "https://mirror.ccs.tencentyun.com"
|
||
docker_data_root: /var/lib/docker
|
||
docker_log_max_size: "100m"
|
||
docker_log_max_file: "3"
|
||
|
||
tasks:
|
||
- name: 安装依赖(Debian)
|
||
apt:
|
||
name:
|
||
- apt-transport-https
|
||
- ca-certificates
|
||
- curl
|
||
- gnupg
|
||
- lsb-release
|
||
state: present
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 添加Docker GPG密钥
|
||
shell: |
|
||
curl -fsSL https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||
when: ansible_os_family == "Debian"
|
||
ignore_errors: yes
|
||
|
||
- name: 添加Docker仓库
|
||
shell: |
|
||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable" > /etc/apt/sources.list.d/docker.list
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装Docker(Debian)
|
||
apt:
|
||
name:
|
||
- docker-ce
|
||
- docker-ce-cli
|
||
- containerd.io
|
||
- docker-compose-plugin
|
||
state: present
|
||
update_cache: yes
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装Docker(RedHat)
|
||
yum:
|
||
name:
|
||
- docker
|
||
- docker-compose-plugin
|
||
state: present
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 配置Docker
|
||
copy:
|
||
content: |
|
||
{
|
||
"data-root": "{{ docker_data_root }}",
|
||
"registry-mirrors": ["{{ docker_mirror }}"],
|
||
"log-driver": "json-file",
|
||
"log-opts": {
|
||
"max-size": "{{ docker_log_max_size }}",
|
||
"max-file": "{{ docker_log_max_file }}"
|
||
},
|
||
"storage-driver": "overlay2",
|
||
"live-restore": true
|
||
}
|
||
dest: /etc/docker/daemon.json
|
||
notify: Restart Docker
|
||
|
||
- name: 启动Docker
|
||
service:
|
||
name: docker
|
||
state: started
|
||
enabled: yes
|
||
|
||
- name: 添加用户到docker组
|
||
user:
|
||
name: "{{ ansible_user }}"
|
||
groups: docker
|
||
append: yes
|
||
ignore_errors: yes
|
||
|
||
- name: 验证Docker
|
||
shell: docker version --format '{{.Server.Version}}'
|
||
register: docker_ver
|
||
changed_when: false
|
||
|
||
- name: 显示版本
|
||
debug:
|
||
msg: "Docker版本: {{ docker_ver.stdout }}"
|
||
|
||
handlers:
|
||
- name: Restart Docker
|
||
service:
|
||
name: docker
|
||
state: restarted
|
||
`,
|
||
},
|
||
{
|
||
ID: "deploy-portainer", Name: "部署Portainer", Category: "container",
|
||
Description: "部署Portainer CE容器管理面板",
|
||
Icon: "🎛️", Tags: []string{"portainer", "docker", "ui"},
|
||
Content: `---
|
||
- name: 部署Portainer
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
portainer_port: 9443
|
||
portainer_data: /opt/portainer
|
||
|
||
tasks:
|
||
- name: 创建数据目录
|
||
file:
|
||
path: "{{ portainer_data }}"
|
||
state: directory
|
||
|
||
- name: 拉取并启动Portainer
|
||
shell: |
|
||
docker volume create portainer_data
|
||
docker run -d \
|
||
-p 8000:8000 \
|
||
-p {{ portainer_port }}:9443 \
|
||
--name portainer \
|
||
--restart=always \
|
||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||
-v portainer_data:/data \
|
||
portainer/portainer-ce:latest
|
||
register: portainer_result
|
||
ignore_errors: yes
|
||
|
||
- name: 显示访问地址
|
||
debug:
|
||
msg: "Portainer已部署: https://{{ ansible_host | default(inventory_hostname) }}:{{ portainer_port }}"
|
||
`,
|
||
},
|
||
|
||
// ===== DevOps =====
|
||
{
|
||
ID: "deploy-nodejs", Name: "部署Node.js", Category: "devops",
|
||
Description: "安装Node.js + PM2进程管理器",
|
||
Icon: "💚", Tags: []string{"nodejs", "npm", "pm2"},
|
||
Content: `---
|
||
- name: 部署Node.js
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
node_version: "20"
|
||
install_pm2: true
|
||
|
||
tasks:
|
||
- name: 安装NodeSource仓库
|
||
shell: |
|
||
curl -fsSL https://deb.nodesource.com/setup_{{ node_version }}.x | bash -
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装Node.js(Debian)
|
||
apt:
|
||
name: nodejs
|
||
state: present
|
||
update_cache: yes
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装Node.js(RedHat)
|
||
yum:
|
||
name: nodejs
|
||
state: present
|
||
when: ansible_os_family == "RedHat"
|
||
|
||
- name: 安装PM2
|
||
npm:
|
||
name: pm2
|
||
global: yes
|
||
when: install_pm2
|
||
|
||
- name: 设置PM2开机启动
|
||
shell: pm2 startup systemd -u {{ ansible_user }} --hp /home/{{ ansible_user }}
|
||
when: install_pm2
|
||
ignore_errors: yes
|
||
|
||
- name: 验证安装
|
||
shell: node --version && npm --version
|
||
register: node_ver
|
||
changed_when: false
|
||
|
||
- name: 显示版本
|
||
debug:
|
||
msg: "{{ node_ver.stdout_lines }}"
|
||
`,
|
||
},
|
||
{
|
||
ID: "deploy-python-app", Name: "部署Python应用", Category: "devops",
|
||
Description: "配置Python环境 + Gunicorn + Systemd服务",
|
||
Icon: "🐍", Tags: []string{"python", "gunicorn", "flask", "django"},
|
||
Content: `---
|
||
- name: 部署Python应用
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
app_name: myapp
|
||
app_dir: /opt/myapp
|
||
python_version: python3
|
||
venv_dir: /opt/myapp/venv
|
||
gunicorn_port: 8000
|
||
gunicorn_workers: 4
|
||
app_user: www-data
|
||
|
||
tasks:
|
||
- name: 安装Python和依赖
|
||
package:
|
||
name:
|
||
- "{{ python_version }}"
|
||
- "{{ python_version }}-venv"
|
||
- python3-pip
|
||
state: present
|
||
|
||
- name: 创建应用目录
|
||
file:
|
||
path: "{{ app_dir }}"
|
||
state: directory
|
||
owner: "{{ app_user }}"
|
||
mode: '0755'
|
||
|
||
- name: 创建虚拟环境
|
||
shell: "{{ python_version }} -m venv {{ venv_dir }}"
|
||
args:
|
||
creates: "{{ venv_dir }}/bin/activate"
|
||
|
||
- name: 安装Gunicorn
|
||
pip:
|
||
name: gunicorn
|
||
virtualenv: "{{ venv_dir }}"
|
||
|
||
- name: 创建Systemd服务
|
||
copy:
|
||
content: |
|
||
[Unit]
|
||
Description={{ app_name }} Gunicorn Service
|
||
After=network.target
|
||
|
||
[Service]
|
||
User={{ app_user }}
|
||
WorkingDirectory={{ app_dir }}
|
||
ExecStart={{ venv_dir }}/bin/gunicorn --workers {{ gunicorn_workers }} --bind 0.0.0.0:{{ gunicorn_port }} app:app
|
||
Restart=always
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
dest: /etc/systemd/system/{{ app_name }}.service
|
||
notify: Restart App
|
||
|
||
- name: 启动服务
|
||
systemd:
|
||
name: "{{ app_name }}"
|
||
state: started
|
||
enabled: yes
|
||
daemon_reload: yes
|
||
|
||
handlers:
|
||
- name: Restart App
|
||
systemd:
|
||
name: "{{ app_name }}"
|
||
state: restarted
|
||
daemon_reload: yes
|
||
`,
|
||
},
|
||
{
|
||
ID: "backup-data", Name: "数据备份", Category: "devops",
|
||
Description: "定时备份指定目录到本地或远程",
|
||
Icon: "💾", Tags: []string{"backup", "cron", "archive"},
|
||
Content: `---
|
||
- name: 数据备份
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
backup_source: /data
|
||
backup_dest: /backup
|
||
backup_retention_days: 7
|
||
backup_hour: "2"
|
||
backup_minute: "0"
|
||
|
||
tasks:
|
||
- name: 创建备份目录
|
||
file:
|
||
path: "{{ backup_dest }}"
|
||
state: directory
|
||
mode: '0700'
|
||
|
||
- name: 创建备份脚本
|
||
copy:
|
||
content: |
|
||
#!/bin/bash
|
||
DATE=$(date +%Y%m%d_%H%M%S)
|
||
BACKUP_FILE="{{ backup_dest }}/backup_${DATE}.tar.gz"
|
||
tar -czf "$BACKUP_FILE" {{ backup_source }} 2>/dev/null
|
||
find {{ backup_dest }} -name "backup_*.tar.gz" -mtime +{{ backup_retention_days }} -delete
|
||
echo "Backup completed: $BACKUP_FILE"
|
||
dest: /usr/local/bin/backup.sh
|
||
mode: '0755'
|
||
|
||
- name: 配置定时任务
|
||
cron:
|
||
name: "daily-backup"
|
||
hour: "{{ backup_hour }}"
|
||
minute: "{{ backup_minute }}"
|
||
job: "/usr/local/bin/backup.sh >> /var/log/backup.log 2>&1"
|
||
|
||
- name: 立即执行一次备份
|
||
shell: /usr/local/bin/backup.sh
|
||
register: backup_result
|
||
|
||
- name: 备份结果
|
||
debug:
|
||
msg: "{{ backup_result.stdout }}"
|
||
`,
|
||
},
|
||
|
||
// ===== 安全加固 =====
|
||
{
|
||
ID: "security-hardening", Name: "安全加固", Category: "security",
|
||
Description: "SSH加固、防火墙配置、禁用root远程登录",
|
||
Icon: "🔒", Tags: []string{"security", "ssh", "firewall", "hardening"},
|
||
Content: `---
|
||
- name: 安全加固
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
ssh_port: 22
|
||
disable_root_login: true
|
||
enable_firewall: true
|
||
allowed_ssh_users: []
|
||
|
||
tasks:
|
||
- name: 修改SSH端口
|
||
lineinfile:
|
||
path: /etc/ssh/sshd_config
|
||
regexp: "^#?Port "
|
||
line: "Port {{ ssh_port }}"
|
||
notify: Restart SSH
|
||
|
||
- name: 禁用root登录
|
||
lineinfile:
|
||
path: /etc/ssh/sshd_config
|
||
regexp: "^#?PermitRootLogin "
|
||
line: "PermitRootLogin no"
|
||
when: disable_root_login
|
||
notify: Restart SSH
|
||
|
||
- name: 禁用密码认证(仅密钥)
|
||
lineinfile:
|
||
path: /etc/ssh/sshd_config
|
||
regexp: "^#?PasswordAuthentication "
|
||
line: "PasswordAuthentication no"
|
||
notify: Restart SSH
|
||
|
||
- name: 设置SSH超时
|
||
lineinfile:
|
||
path: /etc/ssh/sshd_config
|
||
regexp: "^#?ClientAliveInterval "
|
||
line: "ClientAliveInterval 300"
|
||
notify: Restart SSH
|
||
|
||
- name: 安装UFW(Debian)
|
||
apt:
|
||
name: ufw
|
||
state: present
|
||
when: ansible_os_family == "Debian" and enable_firewall
|
||
|
||
- name: 配置UFW规则
|
||
shell: |
|
||
ufw allow {{ ssh_port }}/tcp
|
||
ufw allow 80/tcp
|
||
ufw allow 443/tcp
|
||
ufw --force enable
|
||
when: ansible_os_family == "Debian" and enable_firewall
|
||
|
||
- name: 安装fail2ban
|
||
package:
|
||
name: fail2ban
|
||
state: present
|
||
ignore_errors: yes
|
||
|
||
- name: 启动fail2ban
|
||
service:
|
||
name: fail2ban
|
||
state: started
|
||
enabled: yes
|
||
ignore_errors: yes
|
||
|
||
- name: 加固完成
|
||
debug:
|
||
msg: "✅ 安全加固完成 - SSH端口: {{ ssh_port }}, Root登录: {{ '禁用' if disable_root_login else '允许' }}"
|
||
|
||
handlers:
|
||
- name: Restart SSH
|
||
service:
|
||
name: "{{ 'ssh' if ansible_os_family == 'Debian' else 'sshd' }}"
|
||
state: restarted
|
||
`,
|
||
},
|
||
{
|
||
ID: "ssl-cert", Name: "SSL证书部署", Category: "security",
|
||
Description: "使用Certbot自动申请Let's Encrypt证书",
|
||
Icon: "📜", Tags: []string{"ssl", "https", "certbot", "letsencrypt"},
|
||
Content: `---
|
||
- name: SSL证书部署
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
domain: example.com
|
||
email: admin@example.com
|
||
webroot: /var/www/html
|
||
|
||
tasks:
|
||
- name: 安装Certbot
|
||
package:
|
||
name:
|
||
- certbot
|
||
- python3-certbot-nginx
|
||
state: present
|
||
|
||
- name: 申请证书
|
||
shell: |
|
||
certbot certonly --webroot -w {{ webroot }} \
|
||
-d {{ domain }} \
|
||
--email {{ email }} \
|
||
--agree-tos --non-interactive
|
||
args:
|
||
creates: /etc/letsencrypt/live/{{ domain }}/fullchain.pem
|
||
|
||
- name: 配置自动续期
|
||
cron:
|
||
name: "certbot-renew"
|
||
hour: "3"
|
||
minute: "30"
|
||
job: "certbot renew --quiet --post-hook 'systemctl reload nginx'"
|
||
|
||
- name: 证书信息
|
||
shell: openssl x509 -in /etc/letsencrypt/live/{{ domain }}/fullchain.pem -noout -dates
|
||
register: cert_info
|
||
changed_when: false
|
||
ignore_errors: yes
|
||
|
||
- name: 显示证书
|
||
debug:
|
||
msg: "{{ cert_info.stdout_lines | default(['证书已申请']) }}"
|
||
`,
|
||
},
|
||
|
||
// ===== 监控告警 =====
|
||
{
|
||
ID: "deploy-node-exporter", Name: "部署Node Exporter", Category: "monitoring",
|
||
Description: "部署Prometheus Node Exporter采集主机指标",
|
||
Icon: "📡", Tags: []string{"prometheus", "monitoring", "exporter"},
|
||
Content: `---
|
||
- name: 部署Node Exporter
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
exporter_version: "1.7.0"
|
||
exporter_port: 9100
|
||
|
||
tasks:
|
||
- name: 创建用户
|
||
user:
|
||
name: node_exporter
|
||
system: yes
|
||
shell: /usr/sbin/nologin
|
||
create_home: no
|
||
|
||
- name: 下载Node Exporter
|
||
get_url:
|
||
url: "https://github.com/prometheus/node_exporter/releases/download/v{{ exporter_version }}/node_exporter-{{ exporter_version }}.linux-amd64.tar.gz"
|
||
dest: /tmp/node_exporter.tar.gz
|
||
|
||
- name: 解压
|
||
unarchive:
|
||
src: /tmp/node_exporter.tar.gz
|
||
dest: /tmp
|
||
remote_src: yes
|
||
|
||
- name: 安装二进制
|
||
copy:
|
||
src: "/tmp/node_exporter-{{ exporter_version }}.linux-amd64/node_exporter"
|
||
dest: /usr/local/bin/node_exporter
|
||
mode: '0755'
|
||
remote_src: yes
|
||
|
||
- name: 创建Systemd服务
|
||
copy:
|
||
content: |
|
||
[Unit]
|
||
Description=Node Exporter
|
||
After=network.target
|
||
|
||
[Service]
|
||
User=node_exporter
|
||
ExecStart=/usr/local/bin/node_exporter --web.listen-address=:{{ exporter_port }}
|
||
Restart=always
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
dest: /etc/systemd/system/node_exporter.service
|
||
|
||
- name: 启动服务
|
||
systemd:
|
||
name: node_exporter
|
||
state: started
|
||
enabled: yes
|
||
daemon_reload: yes
|
||
|
||
- name: 验证
|
||
shell: curl -s http://localhost:{{ exporter_port }}/metrics | head -5
|
||
register: metrics
|
||
changed_when: false
|
||
|
||
- name: 显示状态
|
||
debug:
|
||
msg: "Node Exporter运行在端口 {{ exporter_port }}"
|
||
`,
|
||
},
|
||
{
|
||
ID: "deploy-grafana", Name: "部署Grafana", Category: "monitoring",
|
||
Description: "部署Grafana可视化监控面板",
|
||
Icon: "📊", Tags: []string{"grafana", "dashboard", "visualization"},
|
||
Content: `---
|
||
- name: 部署Grafana
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
grafana_port: 3000
|
||
grafana_admin_password: "admin123"
|
||
|
||
tasks:
|
||
- name: 安装依赖
|
||
apt:
|
||
name:
|
||
- apt-transport-https
|
||
- software-properties-common
|
||
state: present
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 添加Grafana仓库
|
||
shell: |
|
||
curl -fsSL https://apt.grafana.com/gpg.key | gpg --dearmor -o /usr/share/keyrings/grafana.gpg
|
||
echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://apt.grafana.com stable main" > /etc/apt/sources.list.d/grafana.list
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 安装Grafana
|
||
apt:
|
||
name: grafana
|
||
state: present
|
||
update_cache: yes
|
||
when: ansible_os_family == "Debian"
|
||
|
||
- name: 配置端口
|
||
lineinfile:
|
||
path: /etc/grafana/grafana.ini
|
||
regexp: "^;?http_port"
|
||
line: "http_port = {{ grafana_port }}"
|
||
|
||
- name: 启动Grafana
|
||
service:
|
||
name: grafana-server
|
||
state: started
|
||
enabled: yes
|
||
|
||
- name: 显示访问信息
|
||
debug:
|
||
msg: "Grafana: http://{{ ansible_host | default(inventory_hostname) }}:{{ grafana_port }} (admin/{{ grafana_admin_password }})"
|
||
`,
|
||
},
|
||
|
||
// ===== 系统管理(新增) =====
|
||
{
|
||
ID: "host-connectivity", Name: "主机连通性测试", Category: "system",
|
||
Description: "批量检测主机SSH连通性、DNS解析、端口可达性",
|
||
Icon: "🔗", Tags: []string{"ping", "connectivity", "network", "check"},
|
||
Content: `---
|
||
- name: 主机连通性测试
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
gather_facts: no
|
||
|
||
tasks:
|
||
- name: Ansible Ping 测试
|
||
ping:
|
||
register: ping_result
|
||
ignore_errors: yes
|
||
|
||
- name: 检测SSH端口
|
||
wait_for:
|
||
host: "{{ ansible_host | default(inventory_hostname) }}"
|
||
port: "{{ ansible_port | default(22) }}"
|
||
timeout: 5
|
||
delegate_to: localhost
|
||
register: ssh_port
|
||
ignore_errors: yes
|
||
|
||
- name: 检测DNS解析
|
||
shell: nslookup {{ inventory_hostname }} 2>/dev/null || host {{ inventory_hostname }} 2>/dev/null || echo "DNS解析失败"
|
||
delegate_to: localhost
|
||
register: dns_result
|
||
changed_when: false
|
||
ignore_errors: yes
|
||
|
||
- name: 检测常用端口
|
||
wait_for:
|
||
host: "{{ ansible_host | default(inventory_hostname) }}"
|
||
port: "{{ item }}"
|
||
timeout: 3
|
||
delegate_to: localhost
|
||
loop: [80, 443]
|
||
register: port_scan
|
||
ignore_errors: yes
|
||
|
||
- name: 输出连通性报告
|
||
debug:
|
||
msg: |
|
||
═══════ {{ inventory_hostname }} 连通性报告 ═══════
|
||
SSH Ping: {{ '✅ 成功' if ping_result is succeeded else '❌ 失败' }}
|
||
SSH 端口: {{ '✅ 开放' if ssh_port is succeeded else '❌ 不可达' }}
|
||
DNS 解析: {{ dns_result.stdout | default('N/A') }}
|
||
HTTP(80): {{ '✅ 开放' if port_scan.results[0] is succeeded else '❌ 关闭' }}
|
||
HTTPS(443): {{ '✅ 开放' if port_scan.results[1] is succeeded else '❌ 关闭' }}
|
||
═══════════════════════════════════════
|
||
`,
|
||
},
|
||
{
|
||
ID: "ubuntu-multi-ip", Name: "Ubuntu 22.04 多IP配置", Category: "system",
|
||
Description: "通过Netplan为Ubuntu 22.04配置多IP地址(主IP+辅助IP)",
|
||
Icon: "🌐", Tags: []string{"ubuntu", "netplan", "network", "multi-ip"},
|
||
Content: `---
|
||
- name: Ubuntu 22.04 多IP地址配置
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
# 主网卡名称(根据实际修改)
|
||
primary_nic: ens192
|
||
# 主IP配置
|
||
primary_ip: "192.168.1.100/24"
|
||
primary_gateway: "192.168.1.1"
|
||
primary_dns:
|
||
- 223.5.5.5
|
||
- 119.29.29.29
|
||
# 辅助IP列表(可添加多个)
|
||
secondary_ips:
|
||
- "192.168.1.101/24"
|
||
- "10.0.0.100/16"
|
||
|
||
tasks:
|
||
- name: 确认系统版本
|
||
assert:
|
||
that:
|
||
- ansible_distribution == "Ubuntu"
|
||
- ansible_distribution_version is version('22.04', '>=')
|
||
fail_msg: "此模板仅适用于 Ubuntu 22.04+"
|
||
success_msg: "系统版本: {{ ansible_distribution }} {{ ansible_distribution_version }}"
|
||
|
||
- name: 备份现有Netplan配置
|
||
shell: |
|
||
mkdir -p /etc/netplan/backup
|
||
cp /etc/netplan/*.yaml /etc/netplan/backup/ 2>/dev/null || true
|
||
args:
|
||
creates: /etc/netplan/backup
|
||
|
||
- name: 生成Netplan配置
|
||
copy:
|
||
content: |
|
||
network:
|
||
version: 2
|
||
ethernets:
|
||
{{ primary_nic }}:
|
||
addresses:
|
||
- {{ primary_ip }}
|
||
{% for ip in secondary_ips %}
|
||
- {{ ip }}
|
||
{% endfor %}
|
||
routes:
|
||
- to: default
|
||
via: {{ primary_gateway }}
|
||
nameservers:
|
||
addresses:
|
||
{% for dns in primary_dns %}
|
||
- {{ dns }}
|
||
{% endfor %}
|
||
dest: /etc/netplan/01-multi-ip.yaml
|
||
mode: '0600'
|
||
register: netplan_config
|
||
|
||
- name: 验证Netplan配置语法
|
||
shell: netplan try --timeout=10
|
||
environment:
|
||
NETPLAN_TRY_TIMEOUT: "10"
|
||
ignore_errors: yes
|
||
register: netplan_try
|
||
|
||
- name: 应用Netplan配置
|
||
shell: netplan apply
|
||
when: netplan_config is changed
|
||
|
||
- name: 等待网络恢复
|
||
wait_for:
|
||
host: "{{ primary_ip | ansible.utils.ipaddr('address') }}"
|
||
port: 22
|
||
timeout: 30
|
||
delegate_to: localhost
|
||
when: netplan_config is changed
|
||
ignore_errors: yes
|
||
|
||
- name: 验证IP配置
|
||
shell: ip addr show {{ primary_nic }} | grep "inet "
|
||
register: ip_verify
|
||
changed_when: false
|
||
|
||
- name: 显示配置结果
|
||
debug:
|
||
msg: |
|
||
═══════ 多IP配置完成 ═══════
|
||
网卡: {{ primary_nic }}
|
||
主IP: {{ primary_ip }}
|
||
网关: {{ primary_gateway }}
|
||
辅助IP:
|
||
{% for ip in secondary_ips %}
|
||
- {{ ip }}
|
||
{% endfor %}
|
||
当前IP列表:
|
||
{{ ip_verify.stdout }}
|
||
═══════════════════════════
|
||
`,
|
||
},
|
||
{
|
||
ID: "ipmitool-bmc", Name: "IPMI配置BMC地址", Category: "system",
|
||
Description: "使用ipmitool配置服务器BMC/IPMI管理口IP地址",
|
||
Icon: "🔧", Tags: []string{"ipmi", "bmc", "ipmitool", "hardware"},
|
||
Content: `---
|
||
- name: IPMI配置BMC地址
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
# BMC网络配置
|
||
bmc_ip: "10.10.10.100"
|
||
bmc_netmask: "255.255.255.0"
|
||
bmc_gateway: "10.10.10.1"
|
||
# BMC用户配置
|
||
bmc_user: "admin"
|
||
bmc_password: "Admin@123"
|
||
bmc_channel: 1
|
||
# 是否启用DHCP(设为true则忽略上面的静态IP配置)
|
||
bmc_dhcp: false
|
||
|
||
tasks:
|
||
- name: 安装ipmitool
|
||
package:
|
||
name: ipmitool
|
||
state: present
|
||
|
||
- name: 加载IPMI内核模块
|
||
modprobe:
|
||
name: "{{ item }}"
|
||
state: present
|
||
loop:
|
||
- ipmi_devintf
|
||
- ipmi_si
|
||
ignore_errors: yes
|
||
|
||
- name: 查看当前BMC配置
|
||
shell: ipmitool lan print {{ bmc_channel }}
|
||
register: bmc_current
|
||
changed_when: false
|
||
ignore_errors: yes
|
||
|
||
- name: 显示当前BMC信息
|
||
debug:
|
||
msg: "{{ bmc_current.stdout_lines | default(['无法读取BMC信息']) }}"
|
||
|
||
- name: 设置BMC为静态IP
|
||
shell: ipmitool lan set {{ bmc_channel }} ipsrc static
|
||
when: not bmc_dhcp
|
||
|
||
- name: 配置BMC IP地址
|
||
shell: ipmitool lan set {{ bmc_channel }} ipaddr {{ bmc_ip }}
|
||
when: not bmc_dhcp
|
||
|
||
- name: 配置BMC子网掩码
|
||
shell: ipmitool lan set {{ bmc_channel }} netmask {{ bmc_netmask }}
|
||
when: not bmc_dhcp
|
||
|
||
- name: 配置BMC默认网关
|
||
shell: ipmitool lan set {{ bmc_channel }} defgw ipaddr {{ bmc_gateway }}
|
||
when: not bmc_dhcp
|
||
|
||
- name: 设置BMC为DHCP模式
|
||
shell: ipmitool lan set {{ bmc_channel }} ipsrc dhcp
|
||
when: bmc_dhcp
|
||
|
||
- name: 配置BMC用户密码
|
||
shell: |
|
||
ipmitool user set name {{ bmc_channel }} 2 {{ bmc_user }} 2>/dev/null || true
|
||
ipmitool user set password 2 {{ bmc_password }}
|
||
ipmitool user enable 2
|
||
ipmitool channel setaccess {{ bmc_channel }} 2 privilege=4
|
||
no_log: true
|
||
ignore_errors: yes
|
||
|
||
- name: 验证BMC配置
|
||
shell: ipmitool lan print {{ bmc_channel }}
|
||
register: bmc_verify
|
||
changed_when: false
|
||
|
||
- name: 显示最终配置
|
||
debug:
|
||
msg: |
|
||
═══════ BMC配置完成 ═══════
|
||
模式: {{ 'DHCP' if bmc_dhcp else '静态IP' }}
|
||
IP: {{ bmc_ip }}
|
||
掩码: {{ bmc_netmask }}
|
||
网关: {{ bmc_gateway }}
|
||
用户: {{ bmc_user }}
|
||
═══════════════════════════
|
||
{{ bmc_verify.stdout }}
|
||
`,
|
||
},
|
||
{
|
||
ID: "apt-install", Name: "APT软件安装", Category: "system",
|
||
Description: "通过apt批量安装/卸载软件包,支持指定版本和仓库",
|
||
Icon: "📦", Tags: []string{"apt", "install", "package", "debian"},
|
||
Content: `---
|
||
- name: APT软件安装
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
# 要安装的软件包列表
|
||
packages_install:
|
||
- vim
|
||
- curl
|
||
- wget
|
||
- htop
|
||
- net-tools
|
||
- tree
|
||
- unzip
|
||
- git
|
||
# 要卸载的软件包列表
|
||
packages_remove: []
|
||
# 是否更新缓存
|
||
update_cache: yes
|
||
# 是否自动清理
|
||
autoremove: yes
|
||
# 安装推荐包
|
||
install_recommends: no
|
||
# 指定版本(可选,格式: "package=version")
|
||
# 例: packages_install: ["nginx=1.18.0-0ubuntu1"]
|
||
|
||
tasks:
|
||
- name: 确认Debian系统
|
||
assert:
|
||
that: ansible_os_family == "Debian"
|
||
fail_msg: "此模板仅适用于 Debian/Ubuntu 系统"
|
||
|
||
- name: 更新APT缓存
|
||
apt:
|
||
update_cache: yes
|
||
cache_valid_time: 3600
|
||
when: update_cache
|
||
|
||
- name: 安装软件包
|
||
apt:
|
||
name: "{{ packages_install }}"
|
||
state: present
|
||
install_recommends: "{{ install_recommends }}"
|
||
register: install_result
|
||
when: packages_install | length > 0
|
||
|
||
- name: 卸载软件包
|
||
apt:
|
||
name: "{{ packages_remove }}"
|
||
state: absent
|
||
purge: yes
|
||
when: packages_remove | length > 0
|
||
|
||
- name: 自动清理
|
||
apt:
|
||
autoremove: yes
|
||
autoclean: yes
|
||
when: autoremove
|
||
|
||
- name: 验证安装结果
|
||
shell: dpkg -l {{ packages_install | join(' ') }} 2>/dev/null | grep "^ii" | awk '{print $2, $3}'
|
||
register: verify_result
|
||
changed_when: false
|
||
when: packages_install | length > 0
|
||
|
||
- name: 显示安装报告
|
||
debug:
|
||
msg: |
|
||
═══════ APT安装报告 ═══════
|
||
已安装: {{ packages_install | length }} 个包
|
||
已卸载: {{ packages_remove | length }} 个包
|
||
变更: {{ install_result.changed | default(false) }}
|
||
{% if verify_result is defined and verify_result.stdout_lines is defined %}
|
||
已确认:
|
||
{% for line in verify_result.stdout_lines %}
|
||
✓ {{ line }}
|
||
{% endfor %}
|
||
{% endif %}
|
||
═══════════════════════════
|
||
`,
|
||
},
|
||
{
|
||
ID: "dpkg-install", Name: "DPKG软件安装", Category: "system",
|
||
Description: "通过dpkg安装本地.deb包,支持URL下载和依赖修复",
|
||
Icon: "📥", Tags: []string{"dpkg", "deb", "install", "offline"},
|
||
Content: `---
|
||
- name: DPKG软件安装
|
||
hosts: "{{ target_hosts | default('all') }}"
|
||
become: yes
|
||
vars:
|
||
# 本地deb包路径列表(服务器上的路径)
|
||
local_deb_files: []
|
||
# 远程URL列表(会自动下载后安装)
|
||
remote_deb_urls: []
|
||
# 下载临时目录
|
||
download_dir: /tmp/dpkg_install
|
||
# 安装后是否修复依赖
|
||
fix_dependencies: yes
|
||
# 是否保留下载的deb文件
|
||
keep_deb_files: no
|
||
|
||
tasks:
|
||
- name: 确认Debian系统
|
||
assert:
|
||
that: ansible_os_family == "Debian"
|
||
fail_msg: "此模板仅适用于 Debian/Ubuntu 系统"
|
||
|
||
- name: 创建下载目录
|
||
file:
|
||
path: "{{ download_dir }}"
|
||
state: directory
|
||
mode: '0755'
|
||
when: remote_deb_urls | length > 0
|
||
|
||
- name: 下载远程deb包
|
||
get_url:
|
||
url: "{{ item }}"
|
||
dest: "{{ download_dir }}/{{ item | basename }}"
|
||
mode: '0644'
|
||
loop: "{{ remote_deb_urls }}"
|
||
register: download_result
|
||
when: remote_deb_urls | length > 0
|
||
|
||
- name: 安装本地deb包
|
||
apt:
|
||
deb: "{{ item }}"
|
||
state: present
|
||
loop: "{{ local_deb_files }}"
|
||
register: local_install
|
||
when: local_deb_files | length > 0
|
||
|
||
- name: 安装下载的deb包
|
||
apt:
|
||
deb: "{{ download_dir }}/{{ item | basename }}"
|
||
state: present
|
||
loop: "{{ remote_deb_urls }}"
|
||
register: remote_install
|
||
when: remote_deb_urls | length > 0
|
||
|
||
- name: 修复依赖关系
|
||
apt:
|
||
update_cache: yes
|
||
force_apt_get: yes
|
||
shell: apt-get install -f -y
|
||
when: fix_dependencies
|
||
ignore_errors: yes
|
||
|
||
- name: 清理下载文件
|
||
file:
|
||
path: "{{ download_dir }}"
|
||
state: absent
|
||
when: not keep_deb_files and remote_deb_urls | length > 0
|
||
|
||
- name: 显示安装报告
|
||
debug:
|
||
msg: |
|
||
═══════ DPKG安装报告 ═══════
|
||
本地包: {{ local_deb_files | length }} 个
|
||
远程包: {{ remote_deb_urls | length }} 个
|
||
{% if local_deb_files | length > 0 %}
|
||
本地安装:
|
||
{% for f in local_deb_files %}
|
||
✓ {{ f }}
|
||
{% endfor %}
|
||
{% endif %}
|
||
{% if remote_deb_urls | length > 0 %}
|
||
远程安装:
|
||
{% for u in remote_deb_urls %}
|
||
✓ {{ u | basename }}
|
||
{% endfor %}
|
||
{% endif %}
|
||
依赖修复: {{ '是' if fix_dependencies else '否' }}
|
||
═══════════════════════════
|
||
`,
|
||
},
|
||
}
|
||
}
|