Princípios básicos ansiosos, sem os quais seus manuais são um monte de massa, parte 3

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?



  1. . - copy: src=foo.conf dest=/etc/foo.conf. foo.conf /etc/foo.conf — . . , , , . , jinja, / , (, , , , ).
  2. ( action plugin) 'template' lookup plugin' template. ( lookup plugin , , ).
  3. play. play ( play) play. , jinja2 gather_facts, play. — hosts, remote_user .
  4. , . , 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 }}'


. "" ( , ).



?



  1. ansible_host ( ) {{ hostvars[item].ansible_host }}. . yaml, .
  2. loop. {{ groups.all }}. — jinja. , . loop , , item " ".
  3. hello.txt touch. jinja, .
  4. 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 . :



  1. , inventory group_vars.
  2. play, play. ( , "play" — , ).
  3. task, .
  4. , . ( — ).


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



( ) 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 .





, , WTF'.



  • 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.




All Articles