объединение точек данных в файле на узле управления

#ansible

Вопрос:

У меня есть сценарий, в котором мне нужно проверить установки, версии и т. Д. В довольно большом кластере, собрать эти сведения и записать в файл на узле управления.Например java_version , elasticsearch_version и т. Д.

У меня есть динамический инвентарь ( ec2.py ), который я использую для сборника пьес. До сих пор я использовал blockinfile . Кажется, это нормально работает только для одного узла, который выполняется последним (я использую serial:1 по одному узлу за раз). Как вы, ребята, решаете эту проблему? может быть, нужно создать что — то вроде dictionary со всеми inventory_hostname и назначить эти точки данных?

Вот учебник, который напоминает (концептуально .. синтаксис может иметь проблемы, потому что это просто пример кода, чтобы дать больше контекста)

 ---
- name: collect all the data points
  hosts: tag_all_nodes
  serial: 1
  
  tasks:
  - name: ES version
    shell: 'dpkg -s elasticsearch | grep Version'
    register: es_version

  - name: java version
    shell: 'java -version'
    register: java_version

  - name: write these data points on control node
    blockinfile: 
      path: /path/to/myfile
      block: |
       details for machine {{ inventory_hostname }}
       1. Elasticsearch version {{ es_version }}
       2. Java version {{ java_version }}
    delegate_to: localhost
 

Давайте предположим, что если у меня есть 3 узла, я должен ожидать чего-то подобного

 details for machine node1
1. Elasticsearch version 7.12.0
2. Java version 1.8.0_181

details for machine node2
1. Elasticsearch version 7.12.0
2. Java version 1.8.0_181

details for machine node3
1. Elasticsearch version 7.12.0
2. Java version 1.8.0_181
 

но я вижу только

 details for machine node3
1. Elasticsearch version 7.12.0
2. Java version 1.8.0_181
 

что вполне понятно. Как я могу получить желаемый результат (информацию обо всех 3 узлах, а не только об одном последнем узле)?

Ответ №1:

Вы повторно используете одно и то же значение по умолчанию marker для своего blockinfile , поэтому оно перезаписывается при каждом запуске, оставляя только последнее, как вы видели.

Просто измените маркер на что-то конкретное для каждого узла. Поскольку ваш файл, похоже, не соответствует какому-либо определенному формату, вы даже можете использовать его, чтобы избавиться от первой вводной строки блока, например

  - name: write these data points on control node
    blockinfile: 
      path: /path/to/myfile
      marker: "{mark} details for machine {{ inventory_hostname }}"
      block: |
       1. Elasticsearch version {{ es_version }}
       2. Java version {{ java_version }}
    delegate_to: localhost

 

И результат должен быть:

 BEGIN details for machine node1
1. Elasticsearch version 7.12.0
2. Java version 1.8.0_181
END details for machine node1
BEGIN details for machine node2
1. Elasticsearch version 7.12.0
2. Java version 1.8.0_181
END details for machine node2
BEGIN details for machine node3
1. Elasticsearch version 7.12.0
2. Java version 1.8.0_181
END details for machine node3
 

Между тем более чистым подходом в этом случае может быть использование шаблона. Вам не нужно создавать какой-либо диктант, у вас уже есть доступная hostvars магическая переменная.

Шаблон templates/host_data_points.txt.j2

 {% for host in group['tag_all_nodes'] %}
details for machine {{ hostvars[host].inventory_hostname }}
1. Elasticsearch version {{ hostvars[host].es_version }}
2. Java version {{ hostvars[host].java_version }}

{% endfor %}
 

Затем удалите свою последнюю задачу в вышеприведенной игре и добавьте еще одну игру:

 #
# (your first play as above without last task goes here)  
#

- name: Write data points to file
  hosts: localhost
  gather_facts: false
  
  tasks:
    - name: Template the data to file
      template:
        src: host_data_points.txt.j2
        dest: /path/to/my_file
 

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

Комментарии:

1. Это здорово. Спасибо.