我有如下数据:
nova_flavors:
- disk: 10
name: m1.tiny
properties:
disk_read_bytes_sec: 12500000
disk_read_iops_sec: 1000
disk_write_bytes_sec: 3125000
disk_write_iops_sec: 250
vif_inbound_average: 2500
vif_inbound_burst: 3750000
vif_inbound_peak: 12500
vif_outbound_average: 2500
vif_outbound_burst: 3750000
vif_outbound_peak: 12500
ram: 1
- disk: 10
name: m1.small
properties:
disk_read_bytes_sec: 25000000
disk_read_iops_sec: 2000
disk_write_bytes_sec: 6250000
disk_write_iops_sec: 500
vif_inbound_average: 5000
vif_inbound_burst: 7500000
vif_inbound_peak: 25000
vif_outbound_average: 5000
vif_outbound_burst: 7500000
vif_outbound_peak: 25000
ram: 2
我需要以下 Python 循环的 Ansible 等效版本:
for flavor in nova_flavors:
for propname, propval in flavor['properties'].items():
# do something with (flavor['name'], propname, propval)
我希望我能做到这一点:
- debug:
msg: "{{ item }}"
with_subelements:
- "{{ nova_flavors }}"
- "properties"
但这样做会失败,因为properties
这是字典,而不是列表。你也不能这样做:
- debug:
msg: "{{ item }}"
with_subelements:
- "{{ nova_flavors }}"
- "properties.items()"
有什么指点吗?
答案1
好吧,我可以建议一个半黑客解决方案,其中您使用 set_fact 几次来构建您可能使用的字典列表?
- hosts: localhost
vars:
nova_flavors:
- disk: 10
name: m1.tiny
properties:
disk_read_bytes_sec: 12500000
disk_read_iops_sec: 1000
disk_write_bytes_sec: 3125000
ram: 1
- disk: 10
name: m1.small
properties:
vif_outbound_burst: 7500000
vif_outbound_peak: 25000
ram: 2
tasks:
- set_fact:
aslist: |
[
{% for item in nova_flavors %}
{% for prop in item.properties.keys() %}
{{ '{' }} 'name':'{{ item.name }}','propname':'{{ prop }}','propvalue':{{item.properties[prop]}} {{ '}' }},
{% endfor %}
{% endfor %}
]
- debug:
var: aslist
结果。
TASK [debug] *******************************************************************
ok: [localhost] => {
"aslist": [
{
"name": "m1.tiny",
"propname": "disk_write_bytes_sec",
"propvalue": 3125000
},
{
"name": "m1.tiny",
"propname": "disk_read_iops_sec",
"propvalue": 1000
},
{
"name": "m1.tiny",
"propname": "disk_read_bytes_sec",
"propvalue": 12500000
},
{
"name": "m1.small",
"propname": "vif_outbound_peak",
"propvalue": 25000
},
{
"name": "m1.small",
"propname": "vif_outbound_burst",
"propvalue": 7500000
}
]
}
PLAY RECAP *********************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
我相信这将使您能够轻松地循环构造列表并设置每个属性。
答案2
如果我忽略“我想先检查值”部分,我可以通过模板来解决这个问题,如下所示:
- name: set flavor properties:
command: >-
openstack flavor set
{%for prop in item.properties.items()%}--property
{{prop.0}}={{prop.1}} {%endfor %} {{ item.name }}
loop: "{{ nova_flavors }}"
这可行,但很丑陋,并且会导致
changed
每次运行剧本时一切都如此。我可以在将数据传递给 ansible 之前对其进行处理,以便properties
键是列表列表而不是字典列表,如下所示:
- disk: 10
name: m1.tiny
properties:
- [disk_read_bytes_sec, 12500000]
- [disk_read_iops_sec, 1000]
- [disk_write_bytes_sec, 3125000]
- [disk_write_iops_sec, 250]
- [vif_inbound_average, 2500]
- [vif_inbound_burst, 3750000]
- [vif_inbound_peak, 12500]
- [vif_outbound_average, 2500]
- [vif_outbound_burst, 3750000]
- [vif_outbound_peak, 12500]
ram: 1
vcpus: 1
- disk: 10
name: m1.small
properties:
- [disk_read_bytes_sec: 25000000]
- [disk_read_iops_sec: 2000]
- [disk_write_bytes_sec: 6250000]
- [disk_write_iops_sec: 500]
- [vif_inbound_average: 5000]
- [vif_inbound_burst: 7500000]
- [vif_inbound_peak: 25000]
- [vif_outbound_average: 5000]
- [vif_outbound_burst: 7500000]
- [vif_outbound_peak: 25000]
ram: 2
vcpus: 1
但读写起来不太直观......而且它实际上是.items()
手动重新实现该方法。