Ansible中如何对instance_name字符串两次拆分以生成目标主机组
问题:Ansible Playbook处理带连字符的instance_name生成主机组失败
原Playbook在instance_name为APP1,APP2这类无连字符格式时,可正常生成预期主机组列表。但当instance_name变为APP1-brazil,APP2-Chile这类带连字符的格式时,需要先按逗号拆分每个元素,再提取每个元素连字符前的部分,尝试两种写法均失败,现求可行解决方案。
调用命令
ansible-playbook -i /web/aes/admin/playbooks/updated.hosts /web/aes/admin/playbooks/split.yml -e ENV=qa -e NODE=cluster -e instance_name=APP1-brazil,APP2-Chile
原可用Playbook
--- - hosts: "{{ [ENV] | product(instance_name.split(',')) | product([NODE]) | product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}" user: wladmin gather_facts: no vars: ansible_host_key_checking: false ansible_ssh_extra_args: -o StrictHostKeyChecking=no -o ConnectionAttempts=20
错误尝试及结果
错误写法1
- hosts: "{{ [ENV] | product(instance_name.split(',') | split('-')[0]) | product([NODE]) | product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}"
报错信息:
ERROR! template error while templating string: expected token ',', got '['. String: {{ [ENV] | product(instance_name.split(',') | split('-')[0]) | product([NODE]) | product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}
原因:split(',')返回的是列表,无法直接链式调用split('-'),必须用map处理列表中的每个元素。
错误写法2
- hosts: "{{ [ENV] | product(instance_name.split(',')[0].split('-')[0]) | product([NODE]) | product(['wladmin_mmsplit'])|map('flatten')|map('join', '_') }}"
错误输出:
PLAY [['qa_A_cluster_wladmin_mmsplit', 'qa_P_cluster_wladmin_mmsplit', 'qa_P_cluster_wladmin_mmsplit', 'qa_1_cluster_wladmin_mmsplit']]
原因:仅提取了第一个拆分元素的连字符前部分,且将该字符串的每个字符单独拆分参与了product运算,导致生成错误的主机组。
预期输出
PLAY [['qa_APP1_cluster_wladmin_mmsplit', 'qa_APP2_cluster_wladmin_mmsplit']]
可行解决方案
使用map过滤器遍历拆分后的每个instance元素,依次处理连字符拆分并提取首部分,修改后的Playbook如下:
--- - hosts: "{{ [ENV] | product(instance_name.split(',') | map('split', '-') | map('first')) | product([NODE]) | product(['wladmin_mmsplit']) | map('flatten') | map('join', '_') }}" user: wladmin gather_facts: no vars: ansible_host_key_checking: false ansible_ssh_extra_args: -o StrictHostKeyChecking=no -o ConnectionAttempts=20
逻辑说明:
instance_name.split(','):将输入字符串按逗号拆分为列表['APP1-brazil', 'APP2-Chile']map('split', '-'):遍历列表中每个元素,按连字符拆分,得到[['APP1','brazil'], ['APP2','Chile']]map('first'):提取每个子列表的第一个元素,得到目标列表['APP1','APP2']- 后续的
product、flatten、join逻辑与原Playbook一致,最终生成符合预期的主机组名称。
内容的提问来源于stack exchange,提问作者Ashar
相关产品推荐
相关产品推荐

