En esta parte, dejamos de hablar de lo simple y agradable y comenzamos a hablar de lo difícil. Variables en Ansible: alcance, precedencia, interpolación recursiva. Para aquellos que leen hasta el final, una pequeña ventaja: una tabla de prioridades simplificada para vivir. Partes anteriores: 1 , 2 .
Por lo general, una historia sobre variables en Ansible comienza con algo muy simple, lo que le da al lector la ilusión de que las variables en Ansible son como en cualquier otro lenguaje de programación. Mutable o no mutable, local y global. Esto no es verdad.
Esto no es verdad.
Ansible tiene un modelo de variable único (¿modelo de memoria?), Que debe aprenderse desde cero. Y empezaremos a considerarlo desde el lugar donde se utilizan los valores (normalmente se consideran variables de Ansible desde donde aparecen). ¿Por qué? Porque al decir en esta dirección, tenemos una gráfica dirigida, que es mucho más fácil de meter en la cabeza.
Nota: dije "valores" porque las "variables" son solo nombres de valores. Las variables tienen su propio mundo interior profundo, y sobre él en la segunda parte.
A lo largo de esta historia, usaré los términos "aparece" y / "se usa". Aparece: aquí es donde se estableció el valor. Y "hits" - este es el lugar donde el valor comienza a influir en el trabajo de Ansible, más precisamente, sus efectos secundarios - en el proceso real de ejecución de módulos en el sistema de destino. Si bien las variables se cambian de un lugar a otro en la sección vars
, los valores no "llegan" a ninguna parte y no afectan al mundo que los rodea.
Este es el primer pensamiento importante que debe recordar en su cabeza: mientras el valor no haya sido usado por algo que afecte al mundo que lo rodea, puede contener errores de sintaxis y referencias a variables inexistentes, etc., y esto no confundirá a nadie. Por qué, sigue leyendo.
Entonces, ¿dónde se utilizan los valores?
- .
- 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.