файл шаблона с возможностью получения разных частей переменных (через его индекс) для разных хостов
Я пытаюсь раздать сертификаты соответствующим хостам (просто приведу пример для задачи с закрытым ключом):
- 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"