【发布时间】:2019-11-04 22:27:32
【问题描述】:
我有一本包含多个角色、主机和组的剧本。我正在尝试开发一个可以在所有主机上运行的回滚功能。我目前的障碍是我看不到将角色、块或任务集委派给主机组的方法
- 我尝试在没有循环的情况下查找对组的委托,因此它可以在块上工作。
- 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 角色中的主机上执行(顺便说一句,执行来自下一个角色将在运行救援块时继续 - 尽管付出了所有努力,但任务数量相同),而我希望它改为在所有主机上运行。
【问题讨论】:
-
您是否考虑过第二次播放
- hosts: rollback-hosts,然后在rescue:块中使用add_host:来分配所有应该回滚到该组(否则为空)的主机?跨度> -
感谢您的回复,这对我来说是一个新想法!这里的问题是我使用
any_errors_fatal: true,第二次播放不会在第一次失败的任务中执行,如果我没有失败,第一次播放将继续。我的目标是在所有主机上成功执行任务,如果没有 - 然后失败并回滚。这就是我现在所拥有的:``` - 主机:所有 any_errors_fatal:true 任务:......救援: - 块: - set_fact:foo:“bar” - 失败:msg:“失败” - 主机:所有任务: -调试: var: foo ```
标签: ansible ansible-2.x