在Ansible中创建动态列表的正确方法

问题描述 投票:6回答:2

我正在寻求建议。我有以下代码,动态创建一个列表,然后我可以在模板中使用。

这是我放在一起的测试代码的副本 - 对于实际角色,我刚刚将admins | regex_replace变量添加到j2模板中。

    ---

  - hosts: localhost
    gather_facts: false

    vars:
      # define empty admins var first so ansible doesn't complain
      admins:

      admin_accounts:
      - name: john
        uid: 1000
        group: sysadmin
        shell: /bin/bash
        comment: "Unix Administrator"
      - name: paul
        uid: 1001
        group: sysadmin
        shell: /bin/bash
        comment: "Unix Administrator"
      - name: george
        uid: 1002
        group: sysadmin
        shell: /bin/bash
        comment: "Unix Administrator"
      - name: ringo
        uid: 1003
        group: sysadmin
        shell: /bin/bash
        comment: "Unix Administrator"

    tasks:

      - name: build array of admin user names
        set_fact: admins="{{ admins}} {{ item.name }}"
        with_items: "{{ admin_accounts }}"

      # print out the fact piping through two jinja2 filters
      # careful with word wrapping
      - debug: msg={{ admins | regex_replace( '\s+',', ' ) | regex_replace`(',\s(.*)','\\1') }}`

这给了我以下内容:

    PLAY [localhost] ***************************************************************

TASK [build array of admin user names] *****************************************
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'john', u'uid': 1000})
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'paul', u'uid': 1001})
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'george', u'uid': 1002})
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'ringo', u'uid': 1003})

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "john, paul, george, ringo"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0

所以......我得到了我需要的东西,但我是否正确地走了?

Ansible版本是在Centos 7.2上运行的2.0.2.0。

提前致谢。


编辑:结果过滤器最终看起来像这样:

  - name: build list of admin user names
    set_fact:
      admin_list: "{{ admin_accounts | selectattr('state', 'equalto', 'present') | map(attribute='name') | join(', ') }}"
  - debug: msg={{ admin_list }}

在yaml中添加了另一个参数:

state: absent

根据需要,林戈被排除在外。

ansible ansible-playbook ansible-2.x
2个回答
9
投票

过滤器将在列表上运行,因此with_items真的很浪费,并且正则表达式的东西对于你正在做的事情非常迟钝。你真的想要一个逗号分隔的字符串,或者你只是想要一个从admin_accounts列表中提取的用户名列表?

如果您只想要列表,为什么不:

set_fact:
  admin_usernames: "{{ admin_accounts | map(attribute='name') | list }}"

...如果你真的想要以逗号分隔的列表作为扁平字符串,只需添加一个连接过滤器:

set_fact:
  admin_usernames: "{{ admin_accounts | map(attribute='name') | join(', ') }}"

但是,如果您的最终目标是模板,我建议在模板中执行此操作,因为这看起来与格式相关,而不是与逻辑相关(除非您只是简化Stack Overflow目的)...


1
投票

当需要添加前缀和后缀(并使所有内容成为列表)时,请查看:

  set_fact:
    extended_etcd_endpoints_list: "{{ groups['etcd'] | map('extract', hostvars, ['ansible_default_ipv4','address']) | map('regex_replace', '^(.*)$','https://\\1:2379') | list  }}"

做法是:获取组etcd中所有机器的列表,提取ipv4地址,添加前缀“https://”和后缀“:2379”。最后,所有内容都转换为列表。

© www.soinside.com 2019 - 2024. All rights reserved.