在Ansible中创建动态列表的正确方法 [英] Correct way to create dynamic lists in Ansible
问题描述
我正在寻找建议.我有以下代码可以动态创建一个列表,以后可以在模板中使用它.
I'm looking for advice. I have the following code that creates a list dynamically that I can then later use in a template.
这是我编写的测试代码的副本-对于实际角色,我只是将admins | regex_replace变量添加到j2模板中.
This is a copy of the test code I put together - for the actual role I just added the admins|regex_replace variable into the j2 template.
---
- 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
所以...我得到了我所需要的,但是我是否正以正确的方式去做?
So...I get what I need, but am I going about it the right way?
Ansible版本是在Centos 7.2上运行的2.0.2.0.
Ansible version is 2.0.2.0 running on Centos 7.2.
谢谢.
最终的过滤器最终看起来像这样:
The resultant filter ended up looking like this:
- 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添加了另一个参数:
Having added another parameter to the yaml:
state: absent
Ringo根据需要被排除在外.
Ringo was left out, as desired.
推荐答案
过滤器将对列表进行操作,因此with_items确实很浪费,而regex东西对于您正在做的事情相当晦涩.您是否真的要用逗号分隔的字符串,还是只需要从admin_accounts
列表中提取的用户名列表?
Filters will operate on lists, so the with_items is really wasteful, and the regex stuff is pretty obtuse for what you're doing. Do you really want a comma-separated string, or do you just want a list of the usernames extracted from the admin_accounts
list?
如果您只想要列表,为什么不呢?
If you just want the list, why not:
set_fact:
admin_usernames: "{{ admin_accounts | map(attribute='name') | list }}"
...,如果您确实希望将逗号分隔的列表作为纯字符串,只需添加一个连接过滤器即可:
... and if you really want the comma-separated list as a flat string, just add a join filter:
set_fact:
admin_usernames: "{{ admin_accounts | map(attribute='name') | join(', ') }}"
但是,如果最终目标是模板,则建议在模板内执行此操作,因为这看起来与格式相关,而与逻辑相关(除非您只是出于堆栈溢出的目的而简化).
If your ultimate target is a template, though, I'd suggest doing this inside the template, since this looks pretty formatting-related as opposed to logic-related (unless you're just simplifying for Stack Overflow purposes)...
这篇关于在Ansible中创建动态列表的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!