我有一个看起来像的变量(现实更长):
deploy_dirs:
conf:
base: '/etc/projects/'
subs:
apache: '/httpd'
modsec: '/modsec'
php: '/php'
haproxy: '/haproxy'
varnish: '/varnish'
logs:
base: '/var/log/projects/'
subs:
apache: '/httpd'
modsec: '/modsec'
php: '/php'
haproxy: '/haproxy'
varnish: '/varnish'
然后我有一个看起来像这样的任务:
- debug:
msg: '{{ item.0.value.base }}SOME-OTHER-VAR{{ item.1 }}'
loop: '{{ deploy_dirs | dict2items | subelements("value.subs") }}'
我希望输出:
/etc/projects/SOME-OTHER-VAR/httpd
/etc/projects/SOME-OTHER-VAR/modsec
/etc/projects/SOME-OTHER-VAR/php
/etc/projects/SOME-OTHER-VAR/haproxy
/etc/projects/SOME-OTHER-VAR/varnish
/var/log/projects/SOME-OTHER-VAR/httpd
/var/log/projects/SOME-OTHER-VAR/modsec
/var/log/projects/SOME-OTHER-VAR/php
/var/log/projects/SOME-OTHER-VAR/haproxy
/var/log/projects/SOME-OTHER-VAR/varnish
这些变量在我的剧本的各个地方重复使用,结构对我来说很有意义,而且看起来很简单。
我已经尝试将subelements()
滤波器更改为product()
滤波器(with_nested
等效),但它似乎无法以与subelements()
滤波器相同的方式引用早期循环中的变量。
显然上面的问题是subelements()
需要一个列表,而不是字典。我无法将"value.subs"
参数转换为列表,因为我找不到像这样嵌套过滤器的方法..?
有没有人对如何使这个工作有任何想法?
谢谢!
更新:如果我也有:
www:
base: '/srv/www/projects/'
subs: {}
而我只想输出:
/srv/www/projects/SOME-OTHER-VAR
你知道我如何摆动subs
位以使其运行并产生预期的结果吗?目前它只是跳过它。即,www
没有发生循环。
在使用子元素过滤器之前,您可以使用json_query在列表中转换subs
dict。
- debug:
msg: "{{ item.0.base }}SOME-OTHER-VAR{{ item.1 }}"
loop: >-
{{
deploy_dirs
| json_query('*[].{base: base, subs: subs.*}')
| subelements('subs')
}}
看看jmespath documentation的语法。当您的数据结构变得复杂时,json_query非常方便。
这个解决方案不会循环使用空subs
元素的元素,比如示例中的'www'
映射条目,并且我没有“干净简单”的方法在单个任务中执行此操作。您可以轻松地使用空subs => deploy_dirs | json_query("* | [?!subs]")
循环遍历元素的第二个任务
我猜你的最终目标不是将调试消息写入屏幕。如果您真的需要单个结构来完成最终任务(例如创建目录),您可以使用set_fact和上述技术填充var,然后使用它来实现您的实际任务
- name: Get all elements with subs to loop over
set_fact:
my_var: >-
{{
deploy_dirs
| json_query('*[].{base: base, subs: subs.*}')
| subelements('subs')
}}
- name: Add entries with empty item1 for elements with empty subs
set_fact:
my_var: >-
{{
my_var
+
[[item, '']]
}}
loop: >-
{{ deploy_dirs | json_query("* | [?!subs]") }}
- name: This will be replaced with a real task
debug:
msg: "{{ item.0.base }}SOME-OTHER-VAR{{ item.1 }}"
loop: "{{ my_var }}"