DEV Community

rndmh3ro
rndmh3ro

Posted on • Originally published at zufallsheld.de on

Interesting Uses of Ansible’s ternary filter

Some time ago I discovered an interesting use of the ternary-filter in Ansible. A ternary-filter in Ansible is a filter that takes three arguments: a condition, an value if the condition is true, and an alternative value if the condition is false.

<!-- PELICAN_END_SUMMARY --><!-- PELICAN_NO_JINJA -->

Here’s a simple example straight from Ansible’s documentation:

- name: service-foo, use systemd module unless upstart is present, then use old service module
  service:
    state: restarted
    enabled: yes
    use: "{{ (ansible_service_mgr == 'upstart') | ternary('service', 'systemd') }}"

Enter fullscreen mode Exit fullscreen mode

But there are many more interesting use cases for this filter and I decided to take a look what Ansible’s collection authors used it for.

Display command output only if verbosity is greater than 0.

This was the usage that initially got me interested in different use-cases for the filter.

Depending on what verbosity level you use when running a playbook (e.g. how many -v you add to the command), the command will run in quiet-mode (with the -quiet flag) or not.

- name: Validate configuration
  become: true
  become_user: "{{ consul_user }}"
  ansible.builtin.command: >
    {{ consul_binary }} validate {{ (ansible_verbosity == 0) | ternary("-quiet", "") }}
    {{ consul_config_path }}/config.json {{ consul_configd_path }}
  changed_when: false

Enter fullscreen mode Exit fullscreen mode

(Source)

Testing task idempotency in one run without molecule

This use of the ternary-filter is useful for testing task idempotency in one run.

First, the task-file test_create_scheduler.yml is imported without a variable set, so the task will change something. Then, the task-file is imported again, however this time with the variable test_proxysql_scheduler_check_idempotence set to true.

- name: "{{ role_name }} | test_create_scheduler | test create scheduler"
  import_tasks: test_create_scheduler.yml

- name: "{{ role_name }} | test_create_scheduler | test idempotence of create scheduler"
  import_tasks: test_create_scheduler.yml
  vars:
    test_proxysql_scheduler_check_idempotence: true

Enter fullscreen mode Exit fullscreen mode

When importing the test file test_create_scheduler.yml without the variable test_proxysql_scheduler_check_idempotence, the assert will check for status is changed, because the ternary-filter evaluated the variable test_proxysql_scheduler_check_idempotence as false.

- name: "{{ role_name }} | {{ current_test }} | check if create scheduler reported a change"
  assert:
    that:
      - "status is {{ test_proxysql_scheduler_check_idempotence|ternary('not changed', 'changed') }}"

Enter fullscreen mode Exit fullscreen mode

When importing the test file test_create_scheduler.yml with the variable test_proxysql_scheduler_check_idempotence, the assert will check for status is not changed, because the ternary-filter evaluated the variable test_proxysql_scheduler_check_idempotence as true.

(Source)

Do things based on regex searches

In Ansible you can chain filters using a pipe (|). This allows you to filter based on regex searches (which in hindsight is obvious that it works, but I never thought about that).

- name: "{{ role_name }} | {{ current_test }} | are we performing a delete"
  set_fact:
    test_delete: "{{ current_test | regex_search('^test_delete') | ternary(true, false) }}"

Enter fullscreen mode Exit fullscreen mode

(Source)

Handle older Python versions easily

In the following task, the cassandra-driver is installed. If the used (obsolete!) Python version starts with 2.7, pip should install the cassandra-driver in version 3.26.*. If a recent Python version is used, pip will install the latest version of the cassandra-driver.

- name: Install cassandra-driver
  pip:
    name: "cassandra-driver{{ ansible_python_version.startswith('2.7') | ternary('==3.26.*', '') }}"

Enter fullscreen mode Exit fullscreen mode

That’s definitely not the most elegant solution, but it works. (I’d probably have tried to install the correct cassandra-driver version according to the operating system and its Python version, wher eit should be installed)

(Source)

Comment line in template if var is defined

This task will add a line starting with ssl_ciphers, if the variable zabbix_web_ssl_cipher_suite is defined and not none. Otherwise it will add the same line but commented out.

{{ (zabbix_web_ssl_cipher_suite is defined and zabbix_web_ssl_cipher_suite is not none) | ternary('', '# ') }}ssl_ciphers {{ zabbix_web_ssl_cipher_suite | default('') }}

Enter fullscreen mode Exit fullscreen mode

(Source)

I used another way to add commented out lines in a template (see). I used the comment-filter:

{{ "HostKeyAlgorithms " ~ ssh_host_key_algorithms|join(',') if ssh_host_key_algorithms else "HostKeyAlgorithms" | comment }}

Enter fullscreen mode Exit fullscreen mode

Now that I see my own code, I could probably use the ternary-filter here, too!

{{ ssh_host_key_algorithms | ternary("HostKeyAlgorithms " ~ ssh_host_key_algorithms|join(','), "HostKeyAlgorithms" | comment) }}

Enter fullscreen mode Exit fullscreen mode

But I think I actually like the if-else syntax more.

Do you have any other interesting uses of the ternary-filter?

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit