需求:
在一个服务器添加多个canal_instance.
笨办法定义一个var
ha_group_name: mgr_dev1
master_address: 172.18.12.211:3307
journal_name:
master_position:
master_timestamp:
master_gtid:
tsdb_mysql_host: 172.18.12.211
tsdb_mysql_port: 3311
tsdb_mysql_db: canal_mgr_dev1
多次执行playbook
想换一个办法, 定义一个var, 是一个列表, 循环这个列表
canal_instances:
- ha_group_name: mgr_dev1
master_address: 172.18.12.211:3307
journal_name:
master_position:
master_timestamp:
master_gtid:
tsdb_mysql_host: 172.18.12.211
tsdb_mysql_port: 3311
tsdb_mysql_db: canal_mgr_dev1
- ha_group_name: mgr_dev2
master_address: 172.18.12.211:3307
journal_name:
master_position:
master_timestamp:
master_gtid:
tsdb_mysql_host: 172.18.12.211
tsdb_mysql_port: 3311
tsdb_mysql_db: canal_mgr_dev2
传统的循环是每个task 使用 with_items自己循环自己的, 我这里是希望多个task公用一个循环
使用include_task, with_Items 和 loop_control
main.yaml
---
- include_tasks: add_canal_instance/tasks/add_instance.yaml
with_items:
- "{{ canal_instances }}"
loop_control:
loop_var: instance
add_instance.yaml
---
# tasks file for add_instance
- name: 创建目录
file:
path: "/usr/local/canal/conf/{{ instance.ha_group_name }}"
state: directory
mode: 0755
recurse: true
register: is_dir_exist
- set_fact: ha_group_name={{ instance.ha_group_name }}
- set_fact: master_address={{ instance.master_address }}
- set_fact: journal_name={{ instance.journal_name }}
- set_fact: master_position={{ instance.master_position }}
- set_fact: master_timestamp={{ instance.master_timestamp }}
- set_fact: master_gtid={{ instance.master_gtid }}
- set_fact: tsdb_mysql_host={{ instance.tsdb_mysql_host }}
- set_fact: tsdb_mysql_port={{ instance.tsdb_mysql_port }}
- set_fact: tsdb_mysql_db={{ instance.tsdb_mysql_db }}
- name: 生成canal.properties
template:
src: instance.properties.j2
dest: "/usr/local/canal/conf/{{ instance.ha_group_name }}/instance.properties"
mode: 0755
when:
- is_dir_exist is changed
模板文件
instance.properties.j2
canal.instance.master.address={{ master_address }}
canal.instance.master.journal.name={{ journal_name }}
canal.instance.master.position={{ master_position }}
canal.instance.master.timestamp={{ master_timestamp }}
canal.instance.master.gtid={{ master_gtid }}
...
关于 loop_control
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
New in version 2.1.
In 2.0 you are again able to use loops and task includes (but not playbook includes). This adds the ability to loop over the set of tasks in one shot. Ansible by default sets the loop variable item
for each loop, which causes these nested loops to overwrite the value of item
from the “outer” loops. As of Ansible 2.1, the loop_control
option can be used to specify the name of the variable to be used for the loop:
set_fact 改进版
写那么多set_fact感觉不够优雅
一开始以为可以写词instance.0=instance.1, 然后报错dict object has no element 0
说明字典没有元素0
就想取key value, 但是我的key是不固定的
翻文档https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html 发现dict2items
这个filter
于是点进去看
它正好可以把我这种不固定的key弄成一个包含 key value 的列表
用debug测了下没有问题
- debug:
msg: "key={{ item.key }} value={{ item.value }}"
loop: "{{ instance|dict2items }}"
于是写成这样
- set_fact: {{ item.key }}={{ item.value }}
loop: "{{ instance|dict2items }}"
结果报错
google一下 搜索 “set_fact item.key”
https://stackoverflow.com/questions/38143647/set-fact-with-dynamic-key-name-in-ansible/38144157
发现应该这样写
- set_fact: {"{{ item.key }}":"{{ item.value }}"}
loop: "{{ instance|dict2items }}"
loop 和 with_item的区别
https://stackoverflow.com/questions/50456997/ansible-with-items-vs-loop