Я хочу добавить все имена хостов в список и передать его в другую игру с другой группой хостов (удаленный сервер), где он ищет файл с шаблоном. Я пробую сборник пьес 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. Есть предложения, как поступить?
Для файла инвентаризации 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 — это не Python».
Например, учитывая приведенный ниже инвентарь для тестирования
shell> cat hosts
[cisco_1]
host_a
nost_b
[cisco_2]
host_c
nost_d
[remote]
remote_x
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']
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
С помощью хостваров вы можете получить доступ к переменным, определенным для любого хоста в игре, в любой точке книги игр.
Вы можете видеть, что хосты не допускают только 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
- 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
- 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
- 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
Вау, в точку, спасибо большое. Это было действительно полезно, сэр.
Просто, понятно и эффективно. Спасибо. Работало как шарм. Любопытно, однако, что если бы я продолжил свой предыдущий подход, например, составил список и передал его в следующей игре, что я сделал не так? Ну, я начинаю с Ansible, так что это поможет узнать… вещи.