Conceptos básicos de Ansible, sin los cuales sus libros de jugadas son un montón de pasta, parte 3

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?



  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