这篇文章涵盖了以下Ansible循环模块:with_items,with_nested,with_subelements,with_dict。
所有带*的字符串已被弃用,建议使用循环。
我在Chromatic的职责之一是作为DevOps团队的成员。除其他外,这包括使用我们的服务器和客户的服务器。反过来,这意味着我花了大量时间与Ansible(一种用于配置,配置和部署服务器和应用程序的流行工具)一起工作。
简而言之,运行Ansible的计算机通过SSH在另一台计算机上运行命令。这些命令是使用称为任务的YAML的小部分以声明方式(可选)指定的。这些任务调用Ansible模块,这些模块专门用于在某些组件(例如文件,数据库等)上执行选项。
例如,以下任务使用文件模块(document,code)创建一个特定目录(如果尚不存在),并修改其属性(如果尚未正确设置):
- file:
path: /home/jenkins/.ssh
state: directory
owner: jenkins
group: jenkins
mode: 700
与一个任务相关的多个任务按角色分组,而多个角色可以在剧本中分组。然后,您可以使用剧本在任意数量的服务器上同时执行完全相同的配置步骤。
Ansible是声明性的吗?
TASKS Ansible , , TASKS. , , , . , Ansible Copy, . Ansible , :
- name: Copy SSH config file into Alice’s .ssh directory.
copy:
src: files/config
dest: /home/alice/.ssh/config
owner: alice
group: alice
mode: 0600
, , bash, scp
, chown
chmod. Ansible , .
, , — , , .
, Ansible, — TASKS . , Ansible , , — PHP, .
, Ansible. Loops , «loops _ + lookup(), ». (Lookups) — Ansible, « Ansible », Loops Ansible Github, .
Ansible « », , . Ansible, , , .
Ansible
TASKS, , , , , ( : , , , , !)
:
, :
alice
,bob
,carol
dan
.
, :
.ssh/
loops
.
, . , alice :
/home/alice/
├── .ssh/
├── bob/
├── carol/
├── dan/
└── loops/
1. WITH_ITEMS
Ansible , chuck
, :
- name: Remove user ‘Chuck’ from the system.
user:
name: chuck
state: absent
remove: yes
— , Chuck
Craig
— with_items
. with_items ( ), ( ):
- name: Remove users ‘Chuck’ and ‘Craig’ from the system.
user:
name: "{{ item }}"
state: absent
remove: yes
with_items:
- chuck
- craig
, with_items , alice
bob
:
users_with_items:
- name: "alice"
personal_directories:
- "bob"
- "carol"
- "dan"
- name: "bob"
personal_directories:
- "alice"
- "carol"
- "dan"
TASKS
- name: "Loop 1: create users using 'with_items'."
user:
name: "{{ item.name }}"
with_items: "{{ users_with_items }}"
Ansible User users_with_items. , , , , personal_directories ( , personal_directories — ).
Ansible ( Ansible ): TASKS , . , , personal_directories
TASKS (. . User, File).
with_items
, PHP:
<?php
foreach ($users_with_items as $user) {
// Do something with $user...
}
, , :
• item.name
.
• with_items
, .
, Ansible item
, item.property
.
/home/
├── alice/
└── bob/
2: , WITH_NESTED
: 2 , 1. chown failed: failed to look up user
, users_with_items
1, , common_directories
, , . , ( PHP), -, :
<?php
foreach ($users_with_items as $user) {
foreach ($common_directories as $directory) {
// Create $directory for $user...
}
}
Ansible with_nested
. with_nested
, :
users_with_items:
- name: "alice"
personal_directories:
- "bob"
- "carol"
- "dan"
- name: "bob"
personal_directories:
- "alice"
- "carol"
- "dan"
common_directories:
- ".ssh"
- "loops
TASKS
# Note that this does not set correct permissions on /home/{{ item.x.name }}/.ssh!
- name: "Loop 2: create common users' directories using 'with_nested'."
file:
dest: "/home/{{ item.0.name }}/{{ item.1 }}"
owner: "{{ item.0.name }}"
group: "{{ item.0.name }}"
state: directory
with_nested:
- "{{ users_with_items }}"
- "{{ common_directories }}"
, with_nested , item.0
( users_with_items
) item.1
( common_directories
) . , , /home/alice/.ssh
.
/home/
├── alice/
│ ├── .ssh/
│ └── loops/
└── bob/
├── .ssh/
└── loops/
3: , WITH_SUBELEMENTS
: 3 , 1. chown failed: failed to look up user
with_subelements
, users_with_items
1. PHP :
<?php
foreach ($users_with_items as $user) {
foreach ($user['personal_directories'] as $directory) {
// Create $directory for $user...
}
}
, $users_with_items
$user['personal_directories']
.
users_with_items:
- name: "alice"
personal_directories:
- "bob"
- "carol"
- "dan"
- name: "bob"
personal_directories:
- "alice"
- "carol"
- "dan"
TASKS
- name: "Loop 3: create personal users' directories using 'with_subelements'."
file:
dest: "/home/{{ item.0.name }}/{{ item.1 }}"
owner: "{{ item.0.name }}"
group: "{{ item.0.name }}"
state: directory
with_subelements:
- "{{ users_with_items }}"
- personal_directories
with_subelements
, with_nested
, , , — personal_directories. 2, ( ) /home/alice/bob
.
/home/
├── alice/
│ ├── .ssh/
│ ├── bob/
│ ├── carol/
│ ├── dan/
│ └── loops/
└── bob/
├── .ssh/
├── alice/
├── carol/
├── dan/
└── loops/
4: WITH_DICT
3 , alice
bob
, , , carol
dan
. users_with_dict
Ansible with_dict
.
, (dict
dictionary
— Python ); with_dict
, . , Ansible, PHP :
<?php
foreach ($users_with_dict as $user => $properties) {
// Create a user named $user...
}
users_with_dict:
carol:
common_directories: "{{ common_directories }}"
dan:
common_directories: "{{ common_directories }}"
TASKS
- name: "Loop 4: create users using 'with_dict'."
user:
name: "{{ item.key }}"
with_dict: "{{ users_with_dict }}"
with_dict
. , , , dict
with_dict
(, , with_dict
).
/home/
├── alice/
│ ├── .ssh/
│ ├── bob/
│ ├── carol/
│ ├── dan/
│ └── loops/
├── bob/
│ ├── .ssh/
│ ├── alice/
│ ├── carol/
│ ├── dan/
│ └── loops/
├── carol/
└── dan/
5: ,
users_with_dict
, Ansible, -. alice
, bob
, carol
dan
, with_nested
/home/
. , , , TASKS:
- Ansible
- Ansible
- Jinja2 ()
- Jinja2 ()
common_directories:
- ".ssh"
- "loops"
TASKS
- name: "Get list of extant users."
shell: "find * -type d -prune | sort"
args:
chdir: "/home"
register: "home_directories"
changed_when: false
- name: "Loop 5: create personal user directories if they don't exist."
file:
dest: "/home/{{ item.0 }}/{{ item.1 }}"
owner: "{{ item.0 }}"
group: "{{ item.0 }}"
state: directory
with_nested:
- "{{ home_directories.stdout_lines }}"
- "{{ home_directories.stdout_lines | union(common_directories) }}"
when: "'{{ item.0 }}' != '{{ item.1 }}'"
TASKS: shell
find
, file .
/home
find \ -type d -prune | sort
( shell
) , /home
, , , .
home_directories
register: "home_directories"
. , , :
"stdout_lines": [
"alice",
"bob",
"carol",
"dan",
],
( ) with_nested
, :
-
with_nested
:
- "{{ home_directories.stdout_lines | union(common_directories) }}"
,
when
TASKS:
when: "'{{ item.0 }}' != '{{ item.1 }}'"
. with_nested
Jinja2 TASKS ( home_directories.stdout_lines
). Jinja:
- (
home_directories.stdout_lines
) - (
|
) - , (
union (common_directories)
)
, home_directories.stdout_lines
common_directories
:
item:
- .ssh
- alice
- bob
- carol
- dan
- loops
, with_nested
home_directories.stdout_lines
( with_nested
) , .
, — , , , ! (, /home/alice/alice
, /home/bob/bob
. .) Ansible — when
— :
when: "'{{ item.0 }}' != '{{ item.1 }}'"
, home_directories.stdout_lines
home_directories.stdout_lines
( Ansible Loops, «… when
with_items
( ), when »). PHP , , :
<?php
$users = ['alice', 'bob', 'carol', 'dan'];
$common_directories = ['.ssh', 'loops'];
$directories = $user + $common_directories;
foreach ($users as $user) {
foreach ($directories as $directory) {
if ($directory != $user) {
// Create the directory…
}
}
}
, , .
/home/
├── alice/
│ ├── .ssh/
│ ├── bob/
│ ├── carol/
│ ├── dan/
│ └── loops/
├── bob/
│ ├── .ssh/
│ ├── alice/
│ ├── carol/
│ ├── dan/
│ └── loops/
├── carol/
│ ├── .ssh/
│ ├── alice/
│ ├── bob/
│ ├── dan/
│ └── loops/
└── dan/
├── .ssh/
├── alice/
├── bob/
├── carol/
└── loops/
Ansible . ( Ansible), , (with_nested
? with_subitems
?) .
, , TASKS, ( , array_filter
, array_reduce
, array_map
, ). , , — — .
希望这篇文章能对您有所帮助。为此,我构建了一个Vagrant虚拟机(Vagrant本机支持使用Ansible进行配置)和一本用于创建和测试这些示例的Ansible剧本。只需按照自述文件中的说明运行本文中的示例,或尝试自己的示例。如果您有任何疑问或意见,请通过@色散HQ发推!