Dans cette partie, nous arrêtons de parler du simple et de l'agréable et commençons à parler du difficile. Variables dans Ansible: portée, priorité, interpolation récursive. Pour ceux qui lisent jusqu'au bout, un petit plus: une table de priorité simplifiée à vivre. Parties précédentes: 1 , 2 .
Habituellement, une histoire sur les variables dans Ansible commence par quelque chose de très simple, qui donne au lecteur l'illusion que les variables dans Ansible sont comme dans n'importe quel autre langage de programmation. Mutable ou non mutable, local et global. Ce n'est pas vrai.
Ce n'est pas vrai.
Ansible a un modèle de variable unique (modèle de mémoire?), Qui doit être appris à partir de zéro. Et nous commencerons à le considérer à partir de l'endroit où les valeurs sont utilisées (généralement les variables Ansible sont considérées à partir de là où elles apparaissent). Pourquoi? Parce qu'en disant dans cette direction, nous avons un graphe orienté, ce qui est beaucoup plus facile à mettre dans nos têtes.
Remarque - J'ai dit «valeurs» car les «variables» ne sont que des noms de valeurs. Les variables ont leur propre monde intérieur profond, et à ce sujet dans la deuxième partie.
Tout au long de cette histoire, j'utiliserai les termes «apparaît» et / «est utilisé». Apparaît - c'est là que la valeur a été définie. Et «frappe» - c'est le lieu où la valeur commence à influencer le travail d'Ansible, plus précisément ses effets secondaires - sur le processus réel d'exécution des modules dans le système cible. Pendant que les variables sont déplacées d'un endroit à l'autre dans la section vars
, les valeurs ne «vont» nulle part et n'affectent en aucune façon le monde environnant.
C'est la première pensée importante dont vous devez vous souvenir dans votre tête: tant que la valeur n'a pas été utilisée par quelque chose qui affecte le monde qui l'entoure, elle peut contenir des erreurs de syntaxe et des références à des variables inexistantes, etc., et cela ne déroutera personne. Pourquoi - lisez la suite.
Alors, où sont les valeurs utilisées?
- .
- copy: src=foo.conf dest=/etc/foo.conf
.foo.conf
/etc/foo.conf
— . . , , , . , jinja, / , (, , , , ). - ( action plugin) 'template' lookup plugin' template. ( lookup plugin , , ).
- play. play ( play) play. , jinja2
gather_facts
, play. —hosts
,remote_user
. - , . ,
ansible_host
,ansbile_user
,ansible_extra_ssh_args
,ansible_transport
.. .
, :
- name: Do not do this
file: path=hello.txt state=touch
loop: '{{ groups.all }}'
vars:
ansible_host: '{{ hostvars[item].ansible_host }}'
. "" ( , ).
?
-
ansible_host
( ){{ hostvars[item].ansible_host }}
. . yaml, . -
loop
.{{ groups.all }}
. — jinja. , . loop , , item " ". -
hello.txt
touch
. jinja, . -
file
ansible_host
ssh — . ,ansible_host
Jinja, . , (.. loop). , jinja item, (.. item - ). , . ? . , .
— . , , - . set_fact
, ( ), .
. , ( best practice) IP- :
allow_access: '{{ ansible_default_ipv4.address }}'
, setup ( gathering_facts), allow_access Jinja , — , .
Jinja
— Jinja ( ). , , (), ( ). : - . . - , . , . , ( , ..). , Jinja , .
:
- debug:
msg: '{{ message }}'
vars:
foo: 'foo'
foobar: '{{ foo + "bar" }}'
message: 'This is {{ foobar }}'
, 'msg' 'debug' ( , action plugin, ), {{ message }}
. ({{
}}
) message. This is {{foobar }}
. This is {{ foo + "bar" }}
. This is foobar
. , .. . msg debug.
, , , .
WTF, " ".
- hosts: localhost
tasks:
- debug: msg={{foo}}
vars:
foo: ''{{ foo + 1 }}'
vars:
foo: 1
play, "" foo . play, . debug? msg . , {{ foo + 1 }}
, {{ foo + 1 }} + 1
.. , .
:
- hosts: localhost
tasks:
- set_fact:
foo: '{{ foo + 1 }}'
- debug: msg={{foo}}
vars:
foo: 1
""? ? set_fact
- foo. foo, . , , foo ( 1) , foo . , .
, , . .
.
- hosts: localhost
vars:
foo: '{{ bar * 2 }}'
tasks:
- debug: var=foo
loop: [1,2,3]
vars:
bar: '{{ item + 10 }}'
vars play ( ). WTF , .
? 1, 2, 3. :
foo
'{{ bar * 2 }}'
bar
'{{ item + 10 }}'
. , vars ( play, ), ( ) , . . , "", - .
debug. foo {{ bar *2 }}
, {{ (item + 10) * 2 }}
. item ( loop') 22, 24, 26.
— , , , , .. scope/precedence ( ), , .
:
- hosts: localhost
vars:
foo: '{{ bar }}'
tasks:
- debug: var=foo
vars:
bar: 'one value'
- debug: var=foo
vars:
bar: 'another value'
. , , bar . Mystery solved.
Jinja
, (, jinja) . jinja. {{ }}
, {% if True %} "" {%endif %}
. . yaml .
- foo_module:
username: <
{% for user in myusers %}
{% if user.lower() in good and user.upper() in other %}
{{ user }}
{% endif %}
{% endfor %}
'content' file
. :
- name: Configure sfcapd systemd service
become: true
copy:
content: |
[Unit]
Description=sflow capture service
[Service]
Type=simple
ExecStart=/usr/bin/sfcapd sfcapd -w -T{{ sflow_extensions }} -p {{ sflow_port }} -B {{ sflow_buffer_size }} -l {{ sflow_data_path }} -b {{ sflow_host }}
Restart=always
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/sfcapd.service
notify:
- restart sfcapd
? 100500 . , . template
, copy
content
. , .
. .
- (, prometheus Go), . yaml- .
Ansible : safe unsafe. safe- — , . unsafe .
:
- debug:
msg: !unsafe'{{ inventory_hostname }}'
" ", {{ inventory_hostname }}
.
, .
— , ? , , : . , , ( ).
, , -, PHP .
.
---
- hosts: localhost
gather_facts: false
tasks:
- name: Case1
debug: var=item
loop: '{{ [1,2,3,4] }}'
- name: Case2
debug: var=item
loop: '{{ foo + bar }}'
- name: Case3
debug: var=item
loop: ' {{ [9,10] }}'
vars:
foo: '[5,6'
bar: '7,8]'
Case1 Jinja . , jinja2 , . , yaml'.
Case2 ( — , ) — , , - , . PHP.
Case3 — , .
Case2 Case3 — , . , , . ( ) json. , ( json').
Ansible:
- name: Case6, space at the end
debug: var=item
loop: '{{ [15, 16] }} '
- name: Case7, space at the start
debug: var=item
loop: ' {{ [15, 16] }}'
Case6 , loop ( ), Case7 , . ? . .
… . , , WTF' .
: , . 5 , , . ", ". , - — .
, : yaml, .
Scope ""
. -"", scope . :
- , inventory group_vars.
- play, play. ( , "play" — , ).
- task, .
- , . ( — ).
include_role
, include_role ( ), — include_role. , include .
Scope — scope scope:
---
- hosts: localhost
gather_facts: false
vars:
foo: 2
tasks:
- name: Case1
debug: var=foo
vars:
foo: 1
- name: Case2
debug: var=foo
play, foo=1, scope , foo scope play, foo 2. ( precedence ). "" "", ( ). "" — include_vars
, set_fact
, register
..
Variable precedence
. include_role
-"". , - scope, , . variable precedence ( — , ).
: , . , , http_port: 8088
, , http_port: 80
. -e
.. , , group_vars/
.
, , foo
inventory.yaml # [all:vars] foo=inventory
group_vars/all.yaml # foo: g_v_a
playbook.yaml
playbook.yaml
- debug: var=foo
?
… , variable precedence , , group_vars .
host_group_vars
( ) host_group_vars. , group vars host vars. , . group_vars/all.yaml , . playbook, playbook.
, , group_vars . , variable precedence (playbook), group_vars .
. group_vars , . , . , , , .. .
group_vars/other, group_vars/all, host_vars .. , .
, , — .
. precedence WTF, : ( ), hostvars .
- role/defaults — . , . pre/post tasks.
- group_vars/all — all
- group_vars/other_groups
- host_vars
- gather_facts: true (host_facts)
- play
- block
- task
- set_fact/register.
set_fact
, (.. play). - -e .
, ( ). "". .
: group_vars/all
group_vars/other_group.yaml
.
,
, . include' (, , ), , import include', add_host
, .. set_fact . , . jinja, . group_host_vars () play. , , .
Keep it clean, keep it simple.