sample.csv:
table_name,column_name,prefix
segment_100,test1:null:string,x:y/1:z/1
segment_100,test2_name:null:string,p:q/1
segment_101,test3_name:null:string,foo
Ansible 剧本:
- hosts: localhost
tasks:
- name: Read CSV file
read_csv:
path: sample.csv
register: vms
- debug:
msg: "{{vms.list}}"
- name: Run shell command for each prefix
debug:
msg: "Running shell command for table -> {{item.0.table_name}} in column -> {{item.0.column_name}} for prefix -> {{item.1}}"
with_nested:
- "{{vms.list}}"
- "{{vms.list[0].prefix.split(':')}}"
注意: 我目前正在使用
"{{vms.list[0].prefix.split(':')"
加载列表中的第一项只是为了描述场景,但理想情况下它应该是每个表和列的循环。
输出:
TASK [Read CSV file] ******************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] **************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
{
"column_name": "test1:null:string",
"prefix": "x:y/1:z/1",
"table_name": "segment_100"
},
{
"column_name": "test2_name:null:string",
"prefix": "p:q/1",
"table_name": "segment_100"
},
{
"column_name": "test3_name:null:string",
"prefix": "foo",
"table_name": "segment_101"
}
]
}
TASK [Run shell command for each prefix] **********************************************************************************************************************************************************************
ok: [localhost] => (item=[{u'prefix': u'x:y/1:z/1', u'table_name': u'segment_100', u'column_name': u'test1:null:string'}, u'x']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> x"
}
ok: [localhost] => (item=[{u'prefix': u'x:y/1:z/1', u'table_name': u'segment_100', u'column_name': u'test1:null:string'}, u'y/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> y/1"
}
ok: [localhost] => (item=[{u'prefix': u'x:y/1:z/1', u'table_name': u'segment_100', u'column_name': u'test1:null:string'}, u'z/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> z/1"
}
ok: [localhost] => (item=[{u'prefix': u'p:q/1', u'table_name': u'segment_100', u'column_name': u'test2_name:null:string'}, u'x']) => {
"msg": "Running shell command for table -> segment_100 in column -> test2_name:null:string for prefix -> x"
}
ok: [localhost] => (item=[{u'prefix': u'p:q/1', u'table_name': u'segment_100', u'column_name': u'test2_name:null:string'}, u'y/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test2_name:null:string for prefix -> y/1"
}
ok: [localhost] => (item=[{u'prefix': u'p:q/1', u'table_name': u'segment_100', u'column_name': u'test2_name:null:string'}, u'z/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test2_name:null:string for prefix -> z/1"
}
ok: [localhost] => (item=[{u'prefix': u'foo', u'table_name': u'segment_101', u'column_name': u'test3_name:null:string'}, u'x']) => {
"msg": "Running shell command for table -> segment_101 in column -> test3_name:null:string for prefix -> x"
}
ok: [localhost] => (item=[{u'prefix': u'foo', u'table_name': u'segment_101', u'column_name': u'test3_name:null:string'}, u'y/1']) => {
"msg": "Running shell command for table -> segment_101 in column -> test3_name:null:string for prefix -> y/1"
}
ok: [localhost] => (item=[{u'prefix': u'foo', u'table_name': u'segment_101', u'column_name': u'test3_name:null:string'}, u'z/1']) => {
"msg": "Running shell command for table -> segment_101 in column -> test3_name:null:string for prefix -> z/1"
}
场景:
我需要为每个“前缀”值(用冒号分隔)运行一个shell脚本对应于每个“table_name”&“column_name”
期望的输出:
TASK [Run shell command for each prefix] **********************************************************************************************************************************************************************
ok: [localhost] => (item=[{u'prefix': u'x:y/1:z/1', u'table_name': u'segment_100', u'column_name': u'test1:null:string'}, u'x']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> x"
}
ok: [localhost] => (item=[{u'prefix': u'x:y/1:z/1', u'table_name': u'segment_100', u'column_name': u'test1:null:string'}, u'y/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> y/1"
}
ok: [localhost] => (item=[{u'prefix': u'x:y/1:z/1', u'table_name': u'segment_100', u'column_name': u'test1:null:string'}, u'z/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> z/1"
}
ok: [localhost] => (item=[{u'prefix': u'p:q/1', u'table_name': u'segment_100', u'column_name': u'test2_name:null:string'}, u'p']) => {
"msg": "Running shell command for table -> segment_100 in column -> test2_name:null:string for prefix -> p"
}
ok: [localhost] => (item=[{u'prefix': u'p:q/1', u'table_name': u'segment_100', u'column_name': u'test2_name:null:string'}, u'q/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test2_name:null:string for prefix -> q/1"
}
ok: [localhost] => (item=[{u'prefix': u'foo', u'table_name': u'segment_101', u'column_name': u'test3_name:null:string'}, u'foo']) => {
"msg": "Running shell command for table -> segment_101 in column -> test3_name:null:string for prefix -> foo"
}
基本上,我希望为 CSV 的每个行项目的每个 prefix 字符串(以冒号分隔)运行 shell 脚本。
注意:我目前使用的是以下Ansible版本
$ ansible --version
ansible 2.9.9
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/xyz/users/test/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, May 27 2022, 11:27:32)
前注:您使用的是过时且不受支持的 Ansible 版本,需要尽快升级。请参阅支持矩阵。我在下面给出的解决方案适用于最新版本的 ansible。我在这篇文章的底部给出了 ansible 2.9 的解决方法。
将冒号分隔的前缀转换为列表:
prefixes: "{{ ['prefix: '] | ansible.builtin.product(vms.list | map(attribute='prefix') | map('split', ':')) | map('join') | map('from_yaml') }}"
给予:
{
"prefixes": [
{
"prefix": [
"x",
"y/1",
"z/1"
]
},
{
"prefix": [
"p",
"q/1"
]
},
{
"prefix": [
"foo"
]
}
]
}
将它们与来自 csv 的初始列表相结合:
vms_data: "{{ vms.list | zip(prefixes) | map('combine') }}"
给:
{
"vms_data": [
{
"column_name": "test1:null:string",
"prefix": [
"x",
"y/1",
"z/1"
],
"table_name": "segment_100"
},
{
"column_name": "test2_name:null:string",
"prefix": [
"p",
"q/1"
],
"table_name": "segment_100"
},
{
"column_name": "test3_name:null:string",
"prefix": [
"foo"
],
"table_name": "segment_101"
}
]
}
使用
subelements
过滤器在该数据结构上循环。这是一个完整的剧本来测试:
---
- hosts: localhost
gather_facts: false
vars:
prefixes: "{{ ['prefix: '] | ansible.builtin.product(vms.list | map(attribute='prefix') | map('split', ':')) | map('join') | map('from_yaml') }}"
vms_data: "{{ vms.list | zip(prefixes) | map('combine') }}"
tasks:
- name: Read CSV file
ansible.builtin.read_csv:
path: sample.csv
register: vms
- name: Run shell command for each prefix
ansible.builtin.debug:
msg: "Running shell command for table -> {{ item.0.table_name }} in column -> {{ item.0.column_name }} for prefix -> {{ item.1 }}"
loop: "{{ vms_data | subelements('prefix') }}"
给出:
$ ansible-playbook csv_loop.yml
PLAY [localhost] ******************************************************************************************************************************************************************************************
TASK [Read CSV file] **************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Run shell command for each prefix] ******************************************************************************************************************************************************************
ok: [localhost] => (item=[{'table_name': 'segment_100', 'column_name': 'test1:null:string', 'prefix': ['x', 'y/1', 'z/1']}, 'x']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> x"
}
ok: [localhost] => (item=[{'table_name': 'segment_100', 'column_name': 'test1:null:string', 'prefix': ['x', 'y/1', 'z/1']}, 'y/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> y/1"
}
ok: [localhost] => (item=[{'table_name': 'segment_100', 'column_name': 'test1:null:string', 'prefix': ['x', 'y/1', 'z/1']}, 'z/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test1:null:string for prefix -> z/1"
}
ok: [localhost] => (item=[{'table_name': 'segment_100', 'column_name': 'test2_name:null:string', 'prefix': ['p', 'q/1']}, 'p']) => {
"msg": "Running shell command for table -> segment_100 in column -> test2_name:null:string for prefix -> p"
}
ok: [localhost] => (item=[{'table_name': 'segment_100', 'column_name': 'test2_name:null:string', 'prefix': ['p', 'q/1']}, 'q/1']) => {
"msg": "Running shell command for table -> segment_100 in column -> test2_name:null:string for prefix -> q/1"
}
ok: [localhost] => (item=[{'table_name': 'segment_101', 'column_name': 'test3_name:null:string', 'prefix': ['foo']}, 'foo']) => {
"msg": "Running shell command for table -> segment_101 in column -> test3_name:null:string for prefix -> foo"
}
PLAY RECAP ************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
过时 Ansible 版本的解决方法,其中过滤器
split
不存在,其中 list
是强制性的以从 map
中获取列表并且可能不完全支持 FQCN(完全限定的集合名称)<= Please upgrade to a 尽快支持的版本
---
- hosts: localhost
gather_facts: false
tasks:
- name: Read CSV file
read_csv:
path: sample.csv
register: vms
- name: Compute prefixes to perform combination
set_fact:
vms_data: >-
{{
vms_data | d([])
+
[item | combine({'prefix': item.prefix.split(':')})]
}}
loop: "{{ vms.list }}"
- name: Run shell command for each prefix
debug:
msg: "Running shell command for table -> {{ item.0.table_name }} in column -> {{ item.0.column_name }} for prefix -> {{ item.1 }}"
loop: "{{ vms_data | subelements('prefix') }}"
简化前缀列表
- debug:
msg: "{{ item.0.table_name }} {{ '%-22s' % (item.0.column_name) }} {{ item.1 }}"
with_subelements:
- "{{ vms.list|zip(prefixes)|map('combine') }}"
- prefix
vars:
prefixes: "{{ vms.list|
map(attribute='prefix')|
map('split', ':')|
map('community.general.dict_kv', 'prefix') }}"
给予
msg: segment_100 test1:null:string x
msg: segment_100 test1:null:string y/1
msg: segment_100 test1:null:string z/1
msg: segment_100 test2_name:null:string p
msg: segment_100 test2_name:null:string q/1
msg: segment_101 test3_name:null:string foo
完整的测试剧本示例
- hosts: localhost
tasks:
- read_csv:
path: /tmp/sample.csv
register: vms
- debug:
msg: "{{ item.0.table_name }} {{ '%-22s' % (item.0.column_name) }} {{ item.1 }}"
with_subelements:
- "{{ vms.list|zip(prefixes)|map('combine') }}"
- prefix
vars:
prefixes: "{{ vms.list|
map(attribute='prefix')|
map('split', ':')|
map('community.general.dict_kv', 'prefix') }}"