有人可以帮助我构建嵌套循环吗?
我正在创建简单的备份角色,它将为备份准备客户端服务器,它还将准备备份服务器。备份服务器将在定义的时间从客户端下载备份。我想为每个客户端定义不同的时间和不同的文件夹(通过 host_vars)。
我的工作流程:
备份服务器
客户
备份服务器
我有这个角色的第一个版本,它被应用于服务器的客户端组。备份服务器是在 delegate_to:
语句的帮助下配置的。但是在备份服务器上创建 cron 文件存在问题,因为存在诸如“竞争条件”之类的东西。当 playbook 完成时,备份的服务器 cron 文件中只有一个随机条目。但我希望所有客户端服务器都应该有条目。我试图打开问题 https://github.com/ansible/ansible/issues/74189 - 我得到了答案,我应该更改对此问题的访问权限。
我的第二次尝试是重写 ansible 角色。然后我可以将它应用于备份服务器而不是客户端组。现在我在客户端服务器组上使用 delegate_to:
。
备份服务器上(简化的)预期 cron 作业的示例:
0 0 * * * backup -include /home --include /var/www --include /srv --exclude '**' backup.lab.local::/ /home/backup/srv1.lab.local
# -> similar entry for srv2
# -> similar entry for srv3
我的场景:
# hosts file
[backup_servers]
backup.lab.local
[testing_servers]
srv1.lab.local
srv2.lab.local
srv3.lab.local
host_vars 文件示例:
# host_vars/srv1.lab.local
backup_folders:
- /home
- /var/www
- /srv
我坚持在备份服务器上创建 cron 条目的任务。我需要循环 groups['testing_servers']
并且在这个循环中我需要创建另一个 hostvars[<each_host_from_group>]['backup_folder']
循环。
请问怎么做?
答案 0 :(得分:1)
我不会遍历 backup_folder
,我会 join
这些值。
假设您正确循环 groups['testing_servers']
主机,例如
0 0 * * * backup {{ ([''] + hostvars[item]['backup_folder']) | join(' --include ') }} --exclude '**' backup.lab.local::/ /home/backup/{{ item }}
会给:
0 0 * * * backup --include /home --include /var/www --include /srv --exclude '**' backup.lab.local::/ /home/backup/srv1.lab.local
注意:这个奇怪的结构:([''] + hostvars[item]['backup_folder'])
是为了在列表的开头创建一个空元素,使其以 --include
开头,否则你会有
... backup /home --include /var/www --include /srv --exclude '**' ...
## ^--- missing "--include " here
答案 1 :(得分:0)
关于提到的 GitHub 问题,您可以使用 throttle: 1
(documentation)
即您的 cron 剧本应包含:
tasks:
- name: "Set backup cron job"
ansible.builtin.cron:
name: "Backup cron job for {{ inventory_hostname }}"
user: root
minute: "{{ backup_minute }}"
hour: "{{ backup_hour }}"
day: "{{ backup_day }}"
month: "{{ backup_month }}"
weekday: "{{ backup_weekday }}"
job: "rdiff-backup --create-full-path --remote-schema \"ssh -C -i /home/backup/.ssh/id_rsa -p {{ ansible_port | default(22) }} -o 'StrictHostKeyChecking no' \\%s rdiff-backup --server\" --include /path/to/dir --exclude '**' {{ ansible_host }}::/ /home/backup/{{ inventory_hostname }}"
delegate_to: deb10.lab.local
throttle: 1 # <--------- THIS IS THE IMPORTANT LINE
你提到的使用嵌套循环的另一种方式可以通过在 Ansible 中使用嵌套循环来完成,或者通过预先构建嵌套结构,然后对其进行迭代:
您可以按照文档所述在循环中构建循环,方法是将一个任务用作带有 include_tasks
模块的外循环,以及一个带有重命名的循环控制变量 (loop_var
) 的循环。
如文档中的示例所示,您需要将其分成两个文件:
# main.yml tasks file
- include_tasks: inner.yml
loop:
- 1
- 2
- 3
loop_control:
loop_var: outer_item
和
# inner.yml tasks file
- name: Print outer and inner items
ansible.builtin.debug:
msg: "outer item={{ outer_item }} inner item={{ item }}"
loop:
- a
- b
- c
使用产品过滤器创建列表列表:
['alice', 'bob'] |product(['clientdb', 'employeedb', 'providerdb'])|list
创造
[('alice', 'clientdb'), ('alice', 'employeedb'), ('alice', 'providerdb'), ('bob', 'clientdb'), ('bob', 'employeedb'), ('bob', 'providerdb')]
例如文档状态中的示例,您可以使用类似于以下的代码:
- name: Give users access to multiple databases
community.mysql.mysql_user:
name: "{{ item[0] }}"
priv: "{{ item[1] }}.*:ALL"
append_privs: yes
password: "foo"
loop: "{{ ['alice', 'bob'] |product(['clientdb', 'employeedb', 'providerdb'])|list }}"