如何使用ansible循环重复任务
通常,我们希望执行单个任务,但使用该单个任务迭代一组数据。例如,我们可能不希望创建一个用户帐户,而是希望创建10个。或者我们可能希望在一个系统中安装15个软件包。可能性是无穷无尽的,但重点仍然是你不想写10个单独的Ansible任务来创建10个用户帐户。幸运的是,Ansible支持在数据集上循环,以确保我们可以使用严格定义的代码执行大规模操作。在本节中,我们将探讨如何在Ansible剧本中实际使用循环。
在简单循环上迭代
这是一个非常简单的剧本,我们只是在一个项目循环中迭代,并回显单个项目。要访问循环中的单个数据,我们使用item
-- - name: Working with loop module hosts: localhost gather_facts: false tasks: - name: Echo the value command: echo "{{ item }}" loop: - 1 - 2 - 3 - 4 - 5
让我们来执行这个剧本:
[ansible@controller ~]$ ansible-playbook loop-iterate.yml PLAY [Working with loop module] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ** TASK [Echo the value] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** changed: [localhost] => (item=1) changed: [localhost] => (item=2) changed: [localhost] => (item=3) changed: [localhost] => (item=4) changed: [localhost] => (item=5) PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
因此,playbook整齐地打印了所有5个项目,而无需花费太多精力来编写playbook,或者将相同的内容写5次以迭代每个值。
寄存器输出到变量
当我们使用"register"捕获任何命令的输出时,可以对循环输出执行类似的操作。唯一的区别是,结果现在将存储在一个字典中,循环的每次迭代都有一个字典条目,而不仅仅是一组结果。
例如,在现有的playbook中,我减少了项目的数量以缩短输出,然后我将输出存储到"loopresult"变量中。然后我们将打印"loopresult"变量的内容:
-- - name: Working with loop module hosts: localhost gather_facts: false tasks: - name: Echo the value command: echo "{{ item }}" loop: - 1 - 2 - 3 register: loopresult - name: print the results from loop debug: var: loopresult
让我们执行剧本并观察结果:
[ansible@controller ~]$ ansible-playbook loop-iterate.yml PLAY [Working with loop module] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ** TASK [Echo the value] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** changed: [localhost] => (item=1) changed: [localhost] => (item=2) changed: [localhost] => (item=3) TASK [print the results from loop] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** ok: [localhost] => { "loopresult": { "changed": true, "msg": "All items completed", "results": [ { "ansible_loop_var": "item", "changed": true, "cmd": [ "echo", "1" ], "delta": "0:00:00.003420", "end": "2017-09-25 12:42:46.060420", "failed": false, "invocation": { "module_args": { "_raw_params": "echo \"1\"", "_uses_shell": false, "argv": null, "chdir": null, "creates": null, "executable": null, "removes": null, "stdin": null, "stdin_add_newline": true, "strip_empty_ends": true, "warn": true } }, "item": 1, "rc": 0, "start": "2017-09-25 12:42:46.057000", "stderr": "", "stderr_lines": [], "stdout": "1", "stdout_lines": [ "1" ] }, { "ansible_loop_var": "item", "changed": true, "cmd": [ "echo", "2" ], "delta": "0:00:00.003135", "end": "2017-09-25 12:42:46.288099", "failed": false, "invocation": { "module_args": { "_raw_params": "echo \"2\"", "_uses_shell": false, "argv": null, "chdir": null, "creates": null, "executable": null, "removes": null, "stdin": null, "stdin_add_newline": true, "strip_empty_ends": true, "warn": true } }, "item": 2, "rc": 0, "start": "2017-09-25 12:42:46.284964", "stderr": "", "stderr_lines": [], "stdout": "2", "stdout_lines": [ "2" ] }, { "ansible_loop_var": "item", "changed": true, "cmd": [ "echo", "3" ], "delta": "0:00:00.002974", "end": "2017-09-25 12:42:46.526784", "failed": false, "invocation": { "module_args": { "_raw_params": "echo \"3\"", "_uses_shell": false, "argv": null, "chdir": null, "creates": null, "executable": null, "removes": null, "stdin": null, "stdin_add_newline": true, "strip_empty_ends": true, "warn": true } }, "item": 3, "rc": 0, "start": "2017-09-25 12:42:46.523810", "stderr": "", "stderr_lines": [], "stdout": "3", "stdout_lines": [ "3" ] } ] } } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
迭代哈希表
对于那些熟悉编程语言的人来说,哈希的概念并不是什么新鲜事。对于不熟悉的人来说,散列只是一组由键标识的数据点。散列中可以有多个键,每个键都有一个关联的值。
让我们看一个哈希的基本示例,以更好地了解这种独特但流行的数据结构的工作原理:
Key: Value FName: hynman LName: Prasad Location: India
从这个表中,我们可以看到键只是一个标识符,键表示的值可以是存储在值表中与该特定键关联的任何字符串或者数据段。
其中:我创建了一个具有哈希值的playbook,其中包含3个关键元素,即"fname"、"lname"和"location",这些元素可以与"item"一起用于循环。
-- - name: Working with loop module hosts: localhost gather_facts: false tasks: - name: Iterate over hashes debug: msg: - "Hello '{{ item.fname }}', nice to meet you" - "Your last name as per our record is '{{ item.lname }}'" - "Your country of residence is '{{ item.location }}'" loop: - { fname: 'hynman', lname: 'prasad', location: 'India' } - { fname: 'amit', lname: 'kumar', location: 'Argentina' } - { fname: 'rahul', lname: 'sharma', location: 'Canada' } - { fname: 'vivek', lname: 'mittal', location: 'Brazil' } - { fname: 'anurag', lname: 'keshav', location: 'Japan' }
让我们来执行这个剧本:
[ansible@controller ~]$ ansible-playbook loop-iterate.yml PLAY [Working with loop module] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ** TASK [Iterate over hashes] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** ok: [localhost] => (item={'fname': 'hynman', 'lname': 'prasad', 'location': 'India'}) => { "msg": [ "Hello 'hynman', nice to meet you", "Your last name as per our record is 'prasad'", "Your country of residence is 'India'" ] } ok: [localhost] => (item={'fname': 'amit', 'lname': 'kumar', 'location': 'Argentina'}) => { "msg": [ "Hello 'amit', nice to meet you", "Your last name as per our record is 'kumar'", "Your country of residence is 'Argentina'" ] } ok: [localhost] => (item={'fname': 'rahul', 'lname': 'sharma', 'location': 'Canada'}) => { "msg": [ "Hello 'rahul', nice to meet you", "Your last name as per our record is 'sharma'", "Your country of residence is 'Canada'" ] } ok: [localhost] => (item={'fname': 'vivek', 'lname': 'mittal', 'location': 'Brazil'}) => { "msg": [ "Hello 'vivek', nice to meet you", "Your last name as per our record is 'mittal'", "Your country of residence is 'Brazil'" ] } ok: [localhost] => (item={'fname': 'anurag', 'lname': 'keshav', 'location': 'Japan'}) => { "msg": [ "Hello 'anurag', nice to meet you", "Your last name as per our record is 'keshav'", "Your country of residence is 'Japan'" ] } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
所以我们有一个有组织的输出,包含散列中的所有值。
迭代字典
字典是一个无序的、可变的和索引的集合。在Python中,字典是用花括号编写的,它们有键和值。下面我们以最简单的形式获取数据,例如YAML格式的键值对,其中键值由冒号分隔。在y冒号后面加一个空格来区分键和值是很重要的
Fruit: Apple Vegetable: Carrot Liquid: Water Meat: Chicken
这里的键是"水果"、"蔬菜"、"液体"、"肉",而相应的值是"苹果"、"胡萝卜"、"水"和"鸡肉"`
要在Ansible中循环使用"dict2items"。其中:我写了一个简单的剧本,它使用项.键
从键和项目.价值
从值访问内容。
-- - name: Working with loop module hosts: localhost gather_facts: false tasks: - name: Iterate over dictionary debug: msg: - "The {{ item.key }} of your car is {{ item.value }}" loop: "{{ my_car | dict2items }}" vars: my_car: Color: Blue Model: Corvette Transition: Manual Price: ,000
让我们检查一下这个游戏的输出:
[ansible@controller ~]$ ansible-playbook loop-iterate.yml PLAY [Working with loop module] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ** TASK [Iterate over hashes] ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** ok: [localhost] => (item={'key': 'Color', 'value': 'Blue'}) => { "msg": [ "The Color of your car is Blue" ] } ok: [localhost] => (item={'key': 'Model', 'value': 'Corvette'}) => { "msg": [ "The Model of your car is Corvette" ] } ok: [localhost] => (item={'key': 'Transition', 'value': 'Manual'}) => { "msg": [ "The Transition of your car is Manual" ] } ok: [localhost] => (item={'key': 'Price', 'value': ',000'}) => { "msg": [ "The Price of your car is ,000" ] } PLAY RECAP ** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** *** localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
因此,我们的playbook通过遍历dictionary的键值对成功地执行了。