Dieser Beitrag behandelt die folgenden Ansible-Schleifenmodule: with_items, with_nested, with_subelements, with_dict.
Alle diese mit * sind bereits veraltet und es wird empfohlen, loop zu verwenden.
Eine meiner Rollen bei Chromatic ist als Mitglied des DevOps-Teams. Dazu gehört unter anderem die Arbeit mit unseren Servern und den Servern unserer Kunden. Dies bedeutet wiederum, dass ich viel Zeit mit Ansible verbringe , einem beliebten Tool zum Bereitstellen, Konfigurieren und Bereitstellen von Servern und Anwendungen.
Einfach ausgedrückt, der Computer, auf dem Ansible ausgeführt wird, führt Befehle auf einem anderen Computer über SSH aus. Diese Befehle werden deklarativ (optional) in kleinen Abschnitten von YAML angegeben, die als Aufgaben bezeichnet werden. Diese AUFGABEN rufen Ansible-Module auf , die sich auf die Ausführung von Optionen für bestimmte Komponenten wie Dateien, Datenbanken usw. spezialisiert haben.
Die folgende Aufgabe verwendet beispielsweise das Dateimodul ( Dokumentation , Code ), um ein bestimmtes Verzeichnis zu erstellen, falls es noch nicht vorhanden ist, und ändert seine Attribute, wenn sie nicht bereits richtig festgelegt sind:
- file:
path: /home/jenkins/.ssh
state: directory
owner: jenkins
group: jenkins
mode: 700
Mehrere Aufgaben, die sich auf eine Aufgabe beziehen, sind in Rollen gruppiert, und mehrere Rollen können in Playbooks gruppiert werden. Sie können dann das Playbook verwenden, um genau dieselben Konfigurationsschritte auf einer beliebigen Anzahl von Servern gleichzeitig auszuführen.
Ist Ansible deklarativ?
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
, ). , , — — .
Hoffentlich hilft Ihnen dieser Beitrag dabei, meine anfänglichen Schwierigkeiten loszuwerden. Zu diesem Zweck habe ich eine virtuelle Vagrant- Maschine (Vagrant unterstützt nativ die Verwendung von Ansible für die Bereitstellung) und ein Ansible-Playbook erstellt, mit dem ich diese Beispiele erstellt und getestet habe. Folgen Sie einfach den Anweisungen in der README-Datei, um die Beispiele aus diesem Beitrag auszuführen, oder probieren Sie es selbst aus. Wenn Sie Fragen oder Kommentare haben, twittern Sie unter @chromaticHQ!