この投稿では、次のAnsibleループモジュールについて説明します:with_items、with_nested、with_subelements、with_dict。
*が付いたこれらはすべてすでに非推奨であり、ループを使用することをお勧めします。
Chromaticでの私の役割の1つは、DevOpsチームのメンバーです。特に、これにはサーバーとクライアントのサーバーの操作が含まれます。つまり、サーバーとアプリケーションのプロビジョニング、構成、および展開のための一般的なツールであるAnsibleでの作業に多くの時間を費やすことになります。
簡単に言うと、Ansibleを実行しているマシンは、SSHを介して別のマシンでコマンドを実行します。これらのコマンドは、タスクと呼ばれるYAMLの小さなセクションを使用して宣言的に(オプションで)指定されます。これらのタスクは、ファイル、データベースなどの特定のコンポーネントでオプションを実行することに特化したAnsibleモジュールを呼び出します。
たとえば、次のタスクでは、Fileモジュール(ドキュメント、コード)を使用して、特定のディレクトリがまだ存在しない場合は作成し、正しく設定されていない場合はその属性を変更します。
- file:
path: /home/jenkins/.ssh
state: directory
owner: jenkins
group: jenkins
mode: 700
1つのタスクに関連する複数のタスクはロールにグループ化され、複数のロールをプレイブックにグループ化できます。その後、プレイブックを使用して、任意の数のサーバーで同時にまったく同じ構成手順を実行できます。
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プレイブックを作成しました。READMEの指示に従って、この投稿の例を実行するか、独自の例を試してください。ご質問やご意見がございましたら、@ chronousHQまでツイートしてください!