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

Я пытаюсь раздать сертификаты соответствующим хостам (просто приведу пример для задачи с закрытым ключом):

      - name: create certificate private key
  community.crypto.openssl_privatekey:
    path: "/root/client/{{ item }}.key"
    type: Ed25519
    backup: yes
    return_content: yes
  register: privatekey
  loop: "{{ ansible_play_hosts_all }}"
  when: "'prometheus1' in inventory_hostname"

Я могу вызвать переменную для других хостов следующим образом:

      {{ hostvars['prometheus1']['privatekey']['results'][0]['privatekey'] }}

Индекс указывает на определенный ключ, поэтому 0 будет первым хостом (prometheus1), 1 второй и так далее.

Я полагаю, что лучше всего использовать шаблоны, но я просто не знаю, как составить шаблон. Я думаюansible_play_hosts_allявляется ключом к решению, поскольку его индекс соответствует индексу закрытого ключа, например:ansible_play_hosts_all[2]-->hostvars['prometheus1']['privatekey']['results'][2]['privatekey']

Но логика была бы:

      for i in index of ansible_play_hosts_all
add the  hostvars['prometheus1']['privatekey']['results'][i]['privatekey']
if ansible_play_hosts_all[i] in inventory_hostname

Полагаю, что-то в этом роде :) Любая помощь будет очень признательна.


Обновлять

Может быть, что-то более точное:

      {% for i in ansible_play_hosts_all|length) %}
{{ hostvars['prometheus1']['privatekey']['results'][i]['privatekey'] }}
{% endfor %}

и к нему добавьте условие:

      {% if ansible_play_hosts_all[i] in inventory_hostname %}

3 ответа

Было бы проще использовать делегирование для создания ключей наprometheus1оставляя зарегистрированную переменную, связанную с правильным хостом. Тогда вы могли бы просто использоватьprivatekey.privatekeyв вашем шаблоне.

      - name: create certificate private key
  community.crypto.openssl_privatekey:
    path: /root/client/{{ inventory_hostname }}.key
    type: Ed25519
    backup: yes
    return_content: yes
  register: privatekey
  delegate_to: prometheus1

Если вы действительно хотите придерживаться текущей структуры, вы можете найти элемент списка, соответствующий текущему хосту, проверив значение в результате, которое содержитitemиз этой итерации цикла.

      {{ (hostvars['prometheus1']['privatekey']['results'] | selectattr('item', '==', inventory_hostname) | list | first).privatekey }}

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

      shell> cat hosts
prometheus1 ansible_host=localhost
test_11     ansible_host=10.1.0.61 ansible_user=admin 
test_12     ansible_host=10.1.0.62 ansible_user=admin
test_13     ansible_host=10.1.0.63 ansible_user=admin

книга пьес

      - hosts: all
  gather_facts: false
  tasks:
    - community.crypto.openssl_privatekey:
        path: "{{ playbook_dir }}/client/{{ item }}.key"
        type: Ed25519
        backup: yes
        return_content: yes
      register: privatekey
      loop: "{{ ansible_play_hosts_all|difference(['prometheus1']) }}"
      delegate_to: prometheus1
      run_once: true

    - set_fact:
        host_priv: "{{ privatekey.results|
                       json_query('[].{host: item,
                                       priv: privatekey}')|
                       items2dict(key_name='host', value_name='priv') }}"
      run_once: true

генерирует закрытые ключи для каждого хоста, кроме prometheus1 , сохраняет ключи в файлах и на основе зарегистрированных данных создает словарь хостов и их ключей

      shell> tree client/
client/
├── test_11.key
├── test_12.key
└── test_13.key
      ok: [prometheus1] => 
  host_priv:
    test_11: |-
      -----BEGIN PRIVATE KEY-----
      MC4CAQAwBQYDK2VwBCIEIM7/BtpiM1EZxrrwtuE2VdSdr++3J/yxm/BnabnMqL3e
      -----END PRIVATE KEY-----
    test_12: |-
      -----BEGIN PRIVATE KEY-----
      MC4CAQAwBQYDK2VwBCIEIPr8VV2RDOggNxo6vpBiXjSTzclJHFHaTVSxlFFVKoU1
      -----END PRIVATE KEY-----
    test_13: |-
      -----BEGIN PRIVATE KEY-----
      MC4CAQAwBQYDK2VwBCIEIJjp2knmccffeEGvTNaP2f+ijXkeLmu89cGgkqFi771/
      -----END PRIVATE KEY-----

Затем вы можете продолжить игру и скопировать ключи на хосты, например

          - name: copy private key
      copy:
        content: "{{ host_priv[inventory_hostname] }}"
        dest: /tmp/private.key
      when: inventory_hostname != 'prometheus1'
      become: true

Подберите пути в соответствии со своими потребностями, а также установите права собственности и разрешения.

Наконец я смог найти решение:

      {%  for i in range(ansible_play_hosts_all|length) %}
{% if ansible_play_hosts_all[i] in inventory_hostname -%}
{{ hostvars['prometheus1']['privatekey']['results'][i]['privatekey'] }}
{%- endif %}
{% endfor %}

Это работает так, как ожидалось. Я просматриваю длину ansible_play_hosts_all (чтобы узнать количество хостов, на которых выполняется роль) и внутри цикла добавляю условие, согласно которому индекс должен соответствовать имени хоста в инвентаре.

тот-%и%-в условных полосах if выводятся пробелы. Без них для каждого файла добавляется пустая строка (что, похоже, не беспокоит openssl в данном случае, но без нее, конечно, лучше)

Сама задача шаблона выглядит следующим образом:

      - name: copy certificate through templating
  template:
    src: certs.j2
    dest: "/root/{{ inventory_hostname }}.key"
Другие вопросы по тегам