使用Chef和Ansible对哈希|映射数据的多重循环进行比较
以下是使用Chef和Ansible展示按照哈希映射结构进行嵌套循环的示例。
厨师的例子
菜谱
node.default['var_test']['a']['aa']['aaa'] = 'AAA'
node.default['var_test']['a']['aa']['aab'] = 'AAB'
node.default['var_test']['a']['ab']['aba'] = 'ABA'
node.default['var_test']['b']['ba']['baa'] = 'BAA'
node.default['var_test']['c']['ca']['caa'] = 'CAA'
node.default['var_test']['c']['cb']['cba'] = 'CBA'
node['var_test'].each do |key1, val1|
val1.each do |key2, val2|
val2.each do |key3, val3|
log "key1:#{key1} key2:#{key2} key3:#{key3} val:#{val3}"
end
end
end
可以使用.each对哈希进行简洁的多重循环描述。
此外,属性可以使用以下方式或通过传递JSON进行描述。
node.default['var_test'] = {
'a' => {
'aa' => {
'aaa' => 'AAA',
'aab' => 'AAB',
},
...
执行结果
$ kitchen conv
-----> Starting Kitchen (v1.21.2)
-----> Converging <chef-loop-centos-7>...
Preparing files for transfer
Preparing dna.json
Resolving cookbook dependencies with Berkshelf 7.0.2...
Removing non-cookbook files before transfer
Preparing validation.pem
Preparing client.rb
-----> Chef Omnibus installation detected (install only if missing)
Transferring files to <chef-loop-centos-7>
Starting Chef Client, version 14.3.37
resolving cookbooks for run list: ["chef_loop::default"]
Synchronizing Cookbooks:
- chef_loop (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 6 resources
Recipe: chef_loop::default
* log[key1:a key2:aa key3:aaa val:AAA] action write
* log[key1:a key2:aa key3:aab val:AAB] action write
* log[key1:a key2:ab key3:aba val:AAA] action write
* log[key1:b key2:ba key3:baa val:BAA] action write
* log[key1:c key2:ca key3:caa val:CAA] action write
* log[key1:c key2:cb key3:cba val:CBA] action write
Running handlers:
Running handlers complete
Chef Client finished, 6/6 resources updated in 01 seconds
Downloading files from <chef-loop-centos-7>
Finished converging <chef-loop-centos-7> (0m7.12s).
-----> Kitchen is finished. (0m10.56s)
在Chef中,通过在循环中逐层处理结构化数据,可以实现简洁的执行,并且保持执行顺序和数据顺序的一致。我认为这样可以获得可读性、易维护性、可移植性和抽象化等优点。
Ansible的例子
Ansible的playbook并非编程语言,而是通过使用数据结构来强行实现逻辑,因此在需要逻辑的情况下,描述非常难读。
剧本
---
- hosts: all
vars:
var_test:
a:
aa:
aaa: AAA
aab: AAB
ab:
aba: ABA
b:
ba:
baa: BAA
c:
ca:
caa: CAA
cb:
cba: CBA
tasks:
- name: "loop0"
include: loop1.yml
with_dict : "{{ vars.var_test }}"
数据具有与Chef示例相同的结构体
对于哈希|映射,可以使用with_dict进行循环,但无法指定块内容,必须使用include将循环内容分解到另一个文件中(在这种情况下是loop1.yml)。
因此,可读性和可维护性较低。
参考:想要在Ansible块单位循环,但由于无法实现而需要变通方法。
---
- name: loop1
include: loop2.yml
with_dict: "{{ item.value }}"
loop_control:
loop_var: item1
为了进一步循环,需要进一步分割文件。(在这里使用loop2.yml)
需要注意的是,如果简单地创建第二个循环,会导致指定内容为”item”的关键字重复,因此使用了别名”item1″。
---
- name: loop2
debug: msg="key1:{{ item.key }} key2:{{ item1.key }} key3:{{ item2.key }} val:{{ item2.value }}"
with_dict: "{{ item1.value }}"
loop_control:
loop_var: item2
在循环结束时,执行处理部分的代码。
为避免关键词重复,使用了别名item2。
执行结果
$ kitchen conv
-----> Starting Kitchen (v1.21.2)
-----> Converging <ansible-loop-centos-7>...
Preparing files for transfer
*************** AnsiblePush install_command ***************
Ansible push config validated
Transferring files to <ansible-loop-centos-7>
*************** AnsiblePush run ***************
PLAY [all] ******************************************************************************************
TASK [Gathering Facts] ******************************************************************************
ok: [ansible-loop-centos-7]
TASK [loop0] ****************************************************************************************
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop1.yml for ansible-loop-centos-7
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop1.yml for ansible-loop-centos-7
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop1.yml for ansible-loop-centos-7
TASK [loop1] ****************************************************************************************
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop2.yml for ansible-loop-centos-7
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop2.yml for ansible-loop-centos-7
TASK [loop2] ****************************************************************************************
ok: [ansible-loop-centos-7] => (item={'value': u'AAA', 'key': u'aaa'}) => {
"msg": "key1:a key2:aa key3:aaa val:AAA"
}
ok: [ansible-loop-centos-7] => (item={'value': u'AAB', 'key': u'aab'}) => {
"msg": "key1:a key2:aa key3:aab val:AAB"
}
TASK [loop2] ****************************************************************************************
ok: [ansible-loop-centos-7] => (item={'value': u'ABA', 'key': u'aba'}) => {
"msg": "key1:a key2:ab key3:aba val:ABA"
}
TASK [loop1] ****************************************************************************************
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop2.yml for ansible-loop-centos-7
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop2.yml for ansible-loop-centos-7
TASK [loop2] ****************************************************************************************
ok: [ansible-loop-centos-7] => (item={'value': u'CBA', 'key': u'cba'}) => {
"msg": "key1:c key2:cb key3:cba val:CBA"
}
TASK [loop2] ****************************************************************************************
ok: [ansible-loop-centos-7] => (item={'value': u'CAA', 'key': u'caa'}) => {
"msg": "key1:c key2:ca key3:caa val:CAA"
}
TASK [loop1] ****************************************************************************************
included: /Users/aa220269/repo/repo-test/cookbooks/ansible_loop/recipes/loop2.yml for ansible-loop-centos-7
TASK [loop2] ****************************************************************************************
ok: [ansible-loop-centos-7] => (item={'value': u'BAA', 'key': u'baa'}) => {
"msg": "key1:b key2:ba key3:baa val:BAA"
}
PLAY RECAP ******************************************************************************************
ansible-loop-centos-7 : ok=14 changed=0 unreachable=0 failed=0
*************** AnsiblePush end run *******************
Downloading files from <ansible-loop-centos-7>
Finished converging <ansible-loop-centos-7> (0m5.49s).
-----> Kitchen is finished. (0m8.37s)
日志很难读且缺乏可维护性。
执行顺序没有得到保障。