Ansible - 如何引用当前在另一个循环中循环的项目

问题描述 投票:0回答:1

我有一个看起来像的变量(现实更长):

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没有发生循环。

loops ansible nested-loops
1个回答
1
投票

在使用子元素过滤器之前,您可以使用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 }}"
© www.soinside.com 2019 - 2024. All rights reserved.