Nesta parte, paramos de falar sobre o simples e o agradável e passamos a falar sobre o difícil. Variáveis em Ansible: escopo, precedência, interpolação recursiva. Para quem leu até o fim, um pequeno bônus: uma tabela de prioridades simplificada para conviver. Partes anteriores: 1 , 2 .
Normalmente, uma história sobre variáveis no Ansible começa com algo muito simples, o que dá ao leitor a ilusão de que as variáveis no Ansible são como em qualquer outra linguagem de programação. Mutável ou não mutável, local e global. Isso não é verdade.
Isso não é verdade.
O Ansible tem um modelo de variável único (modelo de memória?), Que deve ser aprendido do zero. E começaremos a considerá-lo a partir do local onde os valores são usados (normalmente as variáveis Ansible são consideradas de onde aparecem). Por quê? Porque quando falamos nessa direção, temos um gráfico direcionado, que é muito mais fácil de colocar na cabeça.
Nota - Eu disse "valores" porque "variáveis" são apenas nomes para valores. As variáveis têm seu próprio mundo interior profundo, e sobre isso na segunda parte.
Ao longo desta história, usarei os termos "aparece" e / "é usado". Aparece - aqui é onde o valor foi definido. E “acertos” - é aqui que o valor passa a influenciar o trabalho da Ansible, mais precisamente, seus efeitos colaterais - no processo real de execução dos módulos no sistema alvo. Enquanto as variáveis estão sendo deslocadas de um lugar para outro na seção vars
, os valores não "chegam" a lugar nenhum e não afetam o mundo circundante de forma alguma.
Este é o primeiro pensamento importante que você precisa lembrar em sua cabeça: contanto que o valor não tenha sido usado por algo que afete o mundo ao seu redor, ele pode conter quaisquer erros de sintaxe e referências a variáveis inexistentes, etc., e isso não confundirá ninguém. Por que assim - continue a ler.
Então, onde são usados os 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.