Как передать список переменных в другую игру с разными хостами

Я хочу добавить все имена хостов в список и передать его в другую игру с другой группой хостов (удаленный сервер), где он ищет файл с шаблоном. Я пробую сборник пьес Ansible -

- name: Begin
  hosts: cisco
  tasks:
    - name: Initializing an empty list where I will try to append the hostnames
      set_fact:
        my_string: []

- name: Append info
  hosts: cisco
  gather_facts: no
  tasks:
    - name: Append hostname to list (appending is not working, not sure how to pass inventory_hostnames recursively)
      set_fact:
        my_string: "{{ my_strings + [inventory_hostname] }}"

- hosts: remoteserver
  tasks:
    - name: Find stored configuration file on remote server by passing value item from loop (Ansible can not find this variable my_string)
      find:
        paths: /Config/ansible-backups/
        patterns: "{{ item }}-config-*.txt"
      register: stored_configs
      loop: "{{ hostvars['cisco']['my_string'] }}"

Как видно, список my_string не работает должным образом, и я не могу передать его второй части. Я использую версию 2.10.17. Есть предложения, как поступить?

Введение в Ansible Roles
Введение в Ansible Roles
Ansible - это отличный инструмент управления конфигурацией, который можно использовать для автоматизации настройки или развертывания на большом...
1
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Для файла инвентаризации example.ini с содержимым

[inventory:children]
switches
servers

[switches]
one.example.com
two.example.com

[servers]
three.example.com
four.example.com

минимальный пример сборника пьес

---
- hosts: servers
  become: false
  gather_facts: false

  tasks:

    - name: On Remote Servers, passing value item from loop
      debug:
        msg: "{{ item }}-config-*.txt"
      loop: "{{ groups['switches'] }}"

позвонил через

ansible-playbook --inventory example.ini inventory.yml

приведет к выводу

TASK [On Remote Servers, pass value item from loop] *******
ok: [three.example.com] => (item=one.example.com) =>
  msg: one.example.com-config-*.txt
ok: [three.example.com] => (item=two.example.com) =>
  msg: two.example.com-config-*.txt
ok: [four.example.com] => (item=one.example.com) =>
  msg: one.example.com-config-*.txt
ok: [four.example.com] => (item=two.example.com) =>
  msg: two.example.com-config-*.txt

Просто, понятно и эффективно. Спасибо. Работало как шарм. Любопытно, однако, что если бы я продолжил свой предыдущий подход, например, составил список и передал его в следующей игре, что я сделал не так? Ну, я начинаю с Ansible, так что это поможет узнать… вещи.

mrin9san 26.08.2024 17:38

Хорошо, отлично, самый первый пункт «Ansible — это не Python».

mrin9san 27.08.2024 13:02

Например, учитывая приведенный ниже инвентарь для тестирования

shell> cat hosts
[cisco_1]
host_a
nost_b

[cisco_2]
host_c
nost_d

[remote]
remote_x
  • Взгляните на специальные переменные Ansible . Цитирую:

ansible_play_hosts_all: список всех хостов, на которые была нацелена игра.

ansible_play_name: имя текущего воспроизведения.

Проверьте специальные переменные

- name: Begin
  hosts: cisco_1
  tasks:
    - debug:
        msg: |
          ansible_play_name: {{ ansible_play_name }}
          ansible_play_hosts_all: {{ ansible_play_hosts_all }}
      run_once: true

- name: Append info
  hosts: cisco_2
  tasks:
    - debug:
        msg: |
          ansible_play_name: {{ ansible_play_name }}
          ansible_play_hosts_all: {{ ansible_play_hosts_all }}
      run_once: true

дает (в сокращении)

ok: [host_a] => 
  msg: |-
    ansible_play_name: Begin
    ansible_play_hosts_all: ['host_a', 'nost_b']

ok: [host_c] => 
  msg: |-
    ansible_play_name: Append info
    ansible_play_hosts_all: ['host_c', 'nost_d']
  • Взгляните на ключевые слова Ansible Playbook. Цитирую:

run_once: логическое значение, которое обходит цикл хоста, заставляя задачу попытаться выполниться на первом доступном хосте, а затем применить любые результаты и факты ко всем активным хостам в одном пакете.

Самая важная и полезная часть заключается в том, что это «применит любые результаты и факты ко всем активным хостам».

Пожалуйста, проверьте это

- name: Begin
  hosts: cisco_1
  tasks:
    - set_fact:
        my_hosts: "{{ my_hosts | d({}) | combine(this_hosts) }}"
      vars:
        this_hosts: "{{ {ansible_play_name: ansible_play_hosts_all} }}"
      run_once: true

- name: Append info
  hosts: cisco_2
  tasks:
    - set_fact:
        my_hosts: "{{ my_hosts | d({}) | combine(this_hosts) }}"
      vars:
        this_hosts: "{{ {ansible_play_name: ansible_play_hosts_all} }}"
      run_once: true

- hosts: remote
  tasks:
    - debug:
        var: hostvars[groups.cisco_1.0].my_hosts
    - debug:
        var: hostvars[groups.cisco_2.0].my_hosts

дает (в сокращении)

ok: [remote_x] => 
  hostvars[groups.cisco_1.0].my_hosts:
    Begin:
    - host_a
    - nost_b

ok: [remote_x] => 
  hostvars[groups.cisco_2.0].my_hosts:
    Append info:
    - host_c
    - nost_d
  • Взгляните на Информацию об Ansible: магические переменные . Цитирую:

С помощью хостваров вы можете получить доступ к переменным, определенным для любого хоста в игре, в любой точке книги игр.

Вы можете видеть, что хосты не допускают только my_hosts к своим играм. Используйте фильтр json_query и получите их все

  my_hosts: "{{ hostvars | json_query('*.my_hosts') }}" 

дает

  my_hosts:
  - Begin:
    - host_a
    - nost_b
  - Begin:
    - host_a
    - nost_b
  - Append info:
    - host_c
    - nost_d
  - Append info:
    - host_c
    - nost_d

Фильтровать уникальные предметы

  my_hosts: "{{ hostvars | json_query('*.my_hosts') | unique }}"

дает

  my_hosts:
  - Begin:
    - host_a
    - nost_b
  - Append info:
    - host_c
    - nost_d

Этот список предоставляет вам полную информацию о ведущих в пьесах. Если вы «хотите добавить все имена хостов в список», приведенное ниже объявление

  all_hosts: "{{ my_hosts | json_query('[].*') | flatten }}"

дает то, что ты хочешь

  all_hosts:
  - host_a
  - nost_b
  - host_c
  - nost_d

  • Example of a complete playbook for testing
- name: Begin
  hosts: cisco_1
  tasks:
    - set_fact:
        my_hosts: "{{ my_hosts | d({}) | combine(this_hosts) }}"
      vars:
        this_hosts: "{{ {ansible_play_name: ansible_play_hosts_all} }}"
      run_once: true

- name: Append info
  hosts: cisco_2
  tasks:
    - set_fact:
        my_hosts: "{{ my_hosts | d({}) | combine(this_hosts) }}"
      vars:
        this_hosts: "{{ {ansible_play_name: ansible_play_hosts_all} }}"
      run_once: true

- hosts: remote
  vars:
    my_hosts: "{{ hostvars | json_query('*.my_hosts') | unique }}"
    # my_hosts: "{{ hostvars | json_query('*.my_hosts') }}"
    all_hosts: "{{ my_hosts | json_query('[].*') | flatten }}"
  tasks:
    - debug:
        var: hostvars[groups.cisco_1.0].my_hosts
    - debug:
        var: hostvars[groups.cisco_2.0].my_hosts
    - debug:
        var: my_hosts
    - debug:
        var: all_hosts
  • The simplified playbook below gives the same result
- name: Begin
  hosts: cisco_1
  tasks:
    - set_fact:
        my_hosts: "{{ {ansible_play_name: ansible_play_hosts_all} }}"
      run_once: true

- name: Append info
  hosts: cisco_2
  tasks:
    - set_fact:
        my_hosts: "{{ {ansible_play_name: ansible_play_hosts_all} }}"
      run_once: true

- hosts: remote
  vars:
    all_hosts: "{{ hostvars | json_query('*.my_hosts[].*') | flatten | unique }}"
  tasks:
    - debug:
        var: all_hosts
  • This can be further simplified
- name: Begin
  hosts: cisco_1
  tasks:
    - set_fact:
        my_hosts: "{{ ansible_play_hosts_all }}"
      run_once: true

- name: Append info
  hosts: cisco_2
  tasks:
    - set_fact:
        my_hosts: "{{ ansible_play_hosts_all }}"
      run_once: true

- hosts: remote
  vars:
    all_hosts: "{{ hostvars | json_query('*.my_hosts') | flatten | unique }}"
  tasks:
    - debug:
        var: all_hosts

Вау, в точку, спасибо большое. Это было действительно полезно, сэр.

mrin9san 27.08.2024 13:05

Другие вопросы по теме