We have been writing Ansible tasks wrong
Look at the following Ansible task:
- name: Prometheus Exporters - name: Extend caps for ping - File template: src: "roles/server/files{{ item }}" dest: "{{ item }}" owner: prometheus group: root mode: 0600 loop: - /etc/systemd/system/prometheus-blackbox-exporter.service.d/override.conf when: "'blackbox' in exporters" register: foo tags: config, monitoring notify: # - Reload systemd - Reload Blackbox Exporter
For a while I have been wishing to be able to write this like this:
class PrometheusExporters: def extend_caps_for_ping_File(self): if 'blackbox' in exporters: foo = [] for exporter in exporters: # tags: config, monitoring foo.append(template(f"roles/server/files{exporter}", exporter, 'prometheus', 'root', 0o600, notify=(reload_blackbox_exporter,)))
Notice that these are not 100% equivalent; the Python version uses exporter
as the loop_variable
,
but in the Ansible code I never set that because it's so cumbersome.
Why do I prefer that notation? Because:
- Even if Ansible aims to be a declarative language, it has many programming languages
features like
when
(if
),loop
(for
) andblock
/recover
(try
/except
). - Yes, the
register
equivalent I wrote there is not really nice, but alternatives are, I think, worse. - When using certain modules I almost always use the same params. Notice that a proper translation
would be
template(src=f"roles/server/files{exporter}", dest=exporter, owner='prometheus', group='root', mode=0o600)
, and that this is very close to the inline module invocation a.k.a. free form arguments1:template: src="roles/server/files{{ exporter }}" dest="{{ exporter }}" owner=prometheus group=root mode=0600
. - If the compiler would be clever enough, I could declare functions that would work as templates for tasks.
- As a programmer, this order makes more sense.
But I don't have to wait to have enough energy to write such compiler myself; I can more or less already change the order:
- name: Prometheus Exporters - name: Extend caps for ping - File when: "'blackbox' in exporters" loop: - /etc/systemd/system/prometheus-blackbox-exporter.service.d/override.conf register: foo template: src: "roles/server/files{{ item }}" dest: "{{ item }}" owner: prometheus group: root mode: 0600 notify: # - Reload systemd - Reload Blackbox Exporter tags: config, monitoring
Not 100% where I want it (setting loop_variable
is still ugly), but in my head it's easier to read.
I don't use free form arguments because it's not clear that I can split the line like I did on the
Python code.
-
Thanks oblikoamorale#ansible@libera.chat. ↩