我有一个包含多个角色、主持人和组的剧本。我正在尝试开发一个回滚功能,该功能将在所有主机上运行。我目前的障碍是,我认为无法将角色、块或任务集委派给主机组
- 我尝试在没有循环的情况下查找分组委托,因此它可以在一个块上工作。
- import_role不接受循环
- include_role不接受delegate_to
- 与import_tasks/include_tasks相同
这是我现在作为剧本文件(缩短版本)的内容
- hosts: all
any_errors_fatal: true
vars_prompt:
- name: "remote_user_p"
prompt: "Remote user running the playbook"
default: "root"
private: no
- name: "service_user_p"
prompt: "Specify user to run non-root tasks"
default: "user"
private: no
tasks:
- set_fact:
playbook_type: "upgrade"
- import_role:
name: 0_pre_check
run_once: true
remote_user: "{{ remote_user_p }}"
become_user: "{{ service_user_p }}"
become_method: su
become: yes
- block:
- import_role:
name: 1_os
- import_role:
name: 2_mysql
when: inventory_hostname in groups['mysql'] | default("")
- import_role:
name: 3_web
when: inventory_hostname in groups['web'] | default("")
...
rescue:
- block:
- name: run rollback
import_tasks: ../common/roles/5_rollback/tasks/rollback.yml
remote_user: "{{ remote_user }}"
become_user: "{{ service_user }}"
become_method: su
become: yes
这是来自 rollback.yml 的一些示例代码:
- block:
- name: rollback symlinks to config dir
file:
src: "{{ current_config_path }}"
dest: "{{ install_dir }}/static/cfg"
owner: "{{ service_user }}"
group: "{{ service_user_primary_group }}"
state: link
when: current_new_configs | default("N") == "Y"
delegate_to: "{{ item }}"
with_items:
- "{{ ansible_play_hosts }}"
- block:
- name: return config files
shell: test -f '{{ item.1.current_ver_file_path }}' && cp -p {{ item.1.current_ver_file_path }} {{ item.1.old_config_location }}
args:
warn: false
register: return_config_files
failed_when: return_config_files.rc >= 2
when:
- roolback_moved_cfg | default('N') == "Y"
- inventory_hostname in groups[item.0.group]
- item.1.old_config_location != ""
- item.1.current_ver_file_path != ""
with_subelements:
- "{{ config_files }}"
- files
become_user: root
become_method: sudo
become: yes
- name: systemctl daemon-reload
shell: systemctl daemon-reload
failed_when: false
when: root_rights == "Y"
args:
warn: false
delegate_to: "{{ item }}"
with_items:
- "{{ ansible_play_hosts }}"
when: root_rights == "Y"
become_user: root
become_method: sudo
become: yes
- fail:
msg: "Upgrade failed. Symbolic links were set to the previous version. Fix the issues and try again. If you wish to cancel the upgrade, restore the database backup manually."
如您所见,现在我通过引入来使用蹩脚的解决方法
delegate_to: "{{ item }}"
with_items:
- "{{ ansible_play_hosts }}"
每次任务后。
这里有两个问题: 1.任务return config files
后我不能使用相同的方法,因为它已经使用了一个循环 2.这通常是蹩脚的代码重复,我讨厌它
为什么我需要它:例如,如果 playbook 执行失败mysql
角色中的某个地方,则rescue
块将仅在该mysql
角色的主机上执行(顺便说一句,下一个角色的任务的执行将在运行救援块时继续 - 尽管付出了所有努力,但仍有相同数量的任务),而我希望它运行所有主机。
我终于能够通过一个丑陋的黑客来解决这个问题。用过的戏剧而不仅仅是角色——现在有 10 多部戏剧。不要评判我,我花了很多精力试图让它变得漂亮):
示例播放后跟检查 - 与其他所有游戏相同。
- hosts: mysql
any_errors_fatal: true
tasks:
- block:
- import_role:
name: 2_mysql
when: not rollback | default(false)
rescue:
- block:
- name: set fact for rollback
set_fact:
rollback: "yes"
delegate_to: "{{ item }}"
delegate_facts: true
with_items: "{{ groups['all'] }}"
- hosts: all
any_errors_fatal: true
tasks:
- name: run rollback
import_tasks: ../common/roles/5_rollback/tasks/rollback.yml
when: rollback | default(false)
include_role
不接受
delegate_to
事实上,确实如此。
使用ansible内核2.8:
- name: "call my/role with host '{{ansible_hostname}}' for hosts in '{{ansible_play_hosts}}'"
include_role:
name: my/role
apply:
delegate_to: "{{current_host}}"
with_items: "{{ansible_play_hosts}}"
loop_control:
loop_var: current_host
对于 ansible-core 2.5 到 2.7,请参阅 George Shuklinansible/ansible
issue 35398 中提到的 "2.5:delegate_to,include_role with loops">
- name: "call my/role with host '{{ansible_hostname}}' for items in '{{ansible_play_hosts}}'"
include_tasks: loop.yml
with_items: "{{ansible_play_hosts}}"
loop_control:
loop_var: current_host
loop.yml
其自己的文件中的另一个任务:
- name: "Import my/role for '{{current_host}}'"
import_role: name=my/role
delegate_to: "{{current_host}}"
因此,在两个文件(使用 ansible 核心 2.7)或一个文件 (2.8)中,您可以使所有角色及其任务在委派服务器上运行。