Допустим, я хотел бы запустить следующую задачу из ansible:
- name: dns-cloudflare | Request certificate
ansible.builtin.shell:
cmd: certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials {{ certbot_cloudflare_credentials_file }} \
--non-interactive \
--agree-tos \
--expand \
--email {{ certbot_email }} \
--domain {{ __domains }}
args:
executable: /bin/bash
creates: "{{ certbot_directory }}/{{ item.name }}/{{ item.name }}/cert.pem"
Я строю его из такого блока:
certbot_cert:
- name: test1.example.com
cn:
- test2-cn.example.com
post-hook: systemctl restart apache2
- name: test3.example.com
Я хочу добавить аргумент --post-hook к моей команде certbot в зависимости от того, item.post-hook
. И содержимое этого крючка не статично: все, что я туда ввожу, должно попасть в команду моего certbot, например --post-hook 'systemctl restart apache2'
Но когда я не определяю эту переменную, не должно быть пустого пост-хука, его вообще не должно быть в команде certbot.
Как я могу этого добиться?
Я поигрался с переменными и фильтрами, прочитал документацию, но не нашел подходящего способа обработки. Дублировать эту задачу несколько раз для каждого возможного необязательного аргумента не следует.
^-- github.com/geerlingguy/ansible-role-certbot
То, как вы написали значение cmd
, не сохраняет символы новой строки - это то, что вы хотите, поскольку это означает, что (а) вам не нужно экранировать (\
) конец строк, как вы это сделали в своем примере и (б) вы можете удобно использовать условные выражения jinja для подавления некоторых строк.
Так:
- hosts: localhost
gather_facts: false
vars:
certbot_cloudflare_credentials_file: creds.conf
certbot_email: [email protected]
__domains: example.com
certbot_directory: certs
certbot_cert:
- name: test1.example.com
cn:
- test2-cn.example.com
post-hook: systemctl restart apache2
- name: test3.example.com
tasks:
- name: dns-cloudflare | Request certificate
loop: "{{ certbot_cert }}"
ansible.builtin.shell:
cmd: certbot certonly
--dns-cloudflare
--dns-cloudflare-credentials "{{ certbot_cloudflare_credentials_file }}"
--non-interactive
--agree-tos
--expand
--email "{{ certbot_email }}"
--domain "{{ __domains }}"
{% if 'post-hook' in item %}
--post-hook "{{ item["post-hook"] }}"
{% endif %}
args:
executable: /bin/bash
creates: "{{ certbot_directory }}/{{ item.name }}/{{ item.name }}/cert.pem"
Для первого элемента в certbot_cert
это будет выполняться:
certbot certonly --dns-cloudflare --dns-cloudflare-credentials creds.conf --non-interactive --agree-tos --expand --email [email protected] --domain example.com --post-hook systemctl restart apache2
А для второй строки будет работать:
certbot certonly --dns-cloudflare --dns-cloudflare-credentials creds.conf --non-interactive --agree-tos --expand --email [email protected] --domain example.com
Наконец-то у меня появилось время протестировать всю роль, но когда я ее использую, я получаю следующую ошибку ` msg: |- Задача включает параметр с неопределенной переменной. Ошибка была: «объект dict» не имеет атрибута «post». Ошибка находится в «/opt/pscloud/ansible/roles/certbot/tasks/dns-cloudflare-without-cn.yaml»: строка 8, столбец 7, но может находиться и в другом месте файла в зависимости от конкретной синтаксической проблемы. Нарушающая строка выглядит так: - name: dns-cloudflare | Запросить сертификат ^ здесь` Можно ли использовать тире в имени переменной?
Тире не допускается в имени переменной, но оно вполне допустимо в ключе словаря. Показанный здесь сборник пьес работает так, как написано, без каких-либо ошибок в моей системе с Python 3.12.3 и Ansible 2.16.7.
Поскольку в команде оболочки могут быть пустые строки, если вы избегаете перевода строки, у вас может быть строка:
{{ "--post-hook '" ~ item['post-hook'] ~ "'" if item['post-hook'] is defined }} \
. Тем не менее, я был бы удивлен, если бы не существовало существующего модуля, который обеспечил бы вам интеграцию с cerbot, где вы, вероятно, могли бы сделать более простой post_hook: "{{ item['post-hook'] | default(omit) } }".