如何使用 jinja2 输出作为 ansible 指令而不是字符链?

How to use the jinja2 output as an ansible directive instead of a chain of characters?

我目前正在显示一些带有 'extract' 的变量:

- name: Display hostvars over conditionnal
  hosts: all

  tasks:   
        - debug: 
            msg: "{{
              ansible_play_hosts
              | map('extract', hostvars, inventory_hostname)
              |selectattr('ansible_distribution', 'regex', 'Rocky|CentOS' )
              |selectattr('ansible_distribution_major_version', '==', '8' )
              |flatten
            }}"

结果是符合这些条件的名称列表:

TASK [debug] 
ok: [ancolie-lba] => {
    "msg": [
        "vm703-dev"
    ]
}

现在我想用 jinja2 ansible_facts.j2

模板化这个显示
{{'{{'}}
ansible_play_hosts
|map('extract', hostvars)
{% for condition in conditions %}
|selectattr('{{condition.attribute}}', '{{condition.verb}}', '{{condition.text}}' )
{% endfor %}
|flatten
{{'}}'}}

以便像下面这样使用 jinja2 输出文件:

        - block:
            - name: generate a conf
              template: 
                src: ansible_facts.j2
                dest: /tmp/ansible_facts
            - debug:
                msg: "{{lookup('file', '/tmp/ansible_facts')}}"
          tags: template
          delegate_to: localhost
          vars:
            conditions:
              - attribute: 'ansible_distribution'
                verb: 'regex'
                text: 'Rocky|CentOS'
              - attribute: 'ansible_distribution_major_version'
                verb: '=='
                text: '8'

但 ansible 似乎将查找输出解释为链字符,而不是像最初那样执行过滤器:

返回的内容:

    "msg": "{{ansible_play_hosts|map('extract', hostvars, os)|selectattr('ansible_distribution', 'regex', 'Rocky|CentOS' )|selectattr('ansible_distribution_major_version', '==', '8' )|flatten}}"

预期结果:

TASK [debug] *********************************************************************************************************************************************************************************
ok: [ancolie-lba] => {
    "msg": [
        "vm703-dev"
    ]
}

如何使用 jinja2 输出作为 ansible 指令而不是字符链?

您似乎在尝试生成 Jinja 模板作为模板的结果,然后以某种方式诱导 Ansible re-do 它认为已经完成的模板。这在技术上可能可以实现,但正在与 Ansible 的 Jinja 集成作斗争而不是与之合作。

只要您至少有 Jinja 2.10(为了 namespace() 支持),您就可以以相当直接的方式完成此操作,而无需 double-templating。它也可能在旧版本上可行,但会更痛苦。

test.j2:

{% set ns = namespace(result=(ansible_play_hosts | map('extract', hostvars))) %}
{% for condition in conditions %}
{% set ns.result = ns.result | selectattr(condition.attribute, condition.verb, condition.text) %}
{% endfor %}
{{ ns.result | map(attribute='inventory_hostname') | to_nice_yaml }}

test.yml:

- hosts: all
  tasks:
    - debug:
        msg: "{{ lookup('template', 'test.j2') | from_yaml }}"
      run_once: true
      vars:
        conditions:
          - attribute: ansible_facts.hostname
            verb: match
            text: pe

输出:

PLAY [all] ************************************************************************

TASK [Gathering Facts] ************************************************************ok: [rotten-rusalka.authz-relay.x.mail.umich.edu]
ok: [persistent-servitor.relay-egress.x.mail.umich.edu]
ok: [bounteous-abumiguchi.mx.x.mail.umich.edu]
ok: [worthy-yithian.vdc-relay.x.mail.umich.edu]
ok: [commutual-chthonian.syslog.x.mail.umich.edu]
ok: [yern-elderthing.authz-static.x.mail.umich.edu]
ok: [diligent-griffin.authn-relay.x.mail.umich.edu]
ok: [dauntless-ratthing.dnsbl.x.mail.umich.edu]
ok: [powerful-yithian.covid-relay.x.mail.umich.edu]
ok: [legible-sansei.egress.x.mail.umich.edu]
ok: [dominant-shantak.dnsbl.x.mail.umich.edu]
ok: [trustworthy-dhole.jail.x.mail.umich.edu]
ok: [rose-dobyoshi.mx.x.mail.umich.edu]
ok: [pear-kaichigo.mx.x.mail.umich.edu]
ok: [pandora.x.mail.umich.edu]
ok: [queenly-kuzunoha.egress.x.mail.umich.edu]

TASK [debug] *********************************************************************$
ok: [worthy-yithian.vdc-relay.x.mail.umich.edu] => {
    "msg": [
        "persistent-servitor.relay-egress.x.mail.umich.edu",
        "pear-kaichigo.mx.x.mail.umich.edu"
    ]
}