defaults files per os and release

63 views
Skip to first unread message

Mike Ray

unread,
Mar 28, 2017, 12:33:29 PM3/28/17
to Ansible Project
In the current Ansible setup, you can have 1 file in defaults (i.e. defaults/main.yml) and it is used for all hosts that run that task, no matter what the host.

In our use case, we have found it would be highly advantageous to be able to have os-specific and release-specific defaults files. For instance, some applications change directives between releases -- using a directive in a release that doesn't support it, in the best case just issues a warning (which is not ideal), but in the far more likely case, breaks something.

We cannot use include_vars as this completely ruins precedence: http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

To illustrate, here is an example/outline of our setup:

    file structure:
        - inventory/production/host_vars/mail-server-1
        - inventory/production/group_vars/mail-servers
        - roles/servers/mail-server
        - roles/postfix
        - mail-server.yml

    mail-server.yml:
        roles:
            - roles/servers/mail-server

    roles/servers/mail-server/meta/main.yml:
        dependencies:
            - { role: postfix }


    summary: What the above is trying to illustrate, is that we have our re-usable building blocks in "roles" and server-specific setups in "roles/servers", e.g. the "mail-server" role runs through postfix as meta, and then runs through its own tasks. This gives us the flexibility to:
    - set host-specific vars in the inventory host_vars variables (e.g. relayhost="")
    - set vars common to particular groupings of mail servers in inventory group_vars variables (e.g. relay_domains=domain.foo)
    - set vars common to mail-servers in general in roles/servers/mail-server/vars (e.g. content-filter=smtp-amavis:[127.0.0.1]:10024)
    - set vars for everything that runs the postfix role (e.g. heloname="{{ ansible_hostname }}")

If for example, we were to use include_vars to try to include variables specific to CentOS, it would be the highest precedence and override host specific settings with generic CentOS stuff.



Our current working solution is to do a large amount of "union-ing" in the defaults file based on variables, i.e. to get the proper postfix configuration options trusty v. xenial:
    postfix_configuration_options: "{{ postfix_common_configuration_options | union( (ansible_distribution_release=='xenial') | ternary(postfix_xenial_configuration_options,[]) ) | union( (ansible_distribution_release=='trusty') | ternary(postfix_trusty_configuration_options,[]) ) }}"

This is not ideal for a number of reasons:
    - unless you already know what it does, it can take some time to figure out
    - it gets messier and messier the more distributions you support
    - it'll get slower to run the more distributions are supported

But is still useful as you can have a common template for everything then:
main.cf.j2:
    # {{ ansible_managed }}
    {% for item in postfix_configuration_options %}
    {% if item.option is defined and item.value is defined %}
    {% if item.comment is defined %}
    {{ item.comment }}
    {% endif %}
    {{ item.option }} = {{ item.value }}
    {% endif %}
    {% endfor %}




What we had planned on doing was using the meta structure to include specific roles with particular defaults based on os and release, e.g.:

    - mail-server.yml:
        roles:
            - meta/postfix

    - meta/postfix/meta/main.yml:
        dependencies:
          - { role: os/CentOS/postfix, when: ansible_distribution == 'CentOS' }
          - { role: releases/trusty/postfix, when: ansible_distribution_release == 'trusty' }
          - { role: releases/xenial/postfix, when: ansible_distribution_release == 'xenial' }
          - { role: postfix }

    - release/trusty/postfix/defaults/main.yml:
        postfix_configuration_options:
            postscreen_dnsbl_ttl

    - release/trusty
        postfix_configuration_options:
            address_verify_pending_request_limit
        
And then in the aforementioned main.cf.j2, xenial hosts would define "address_verify_pending_request_limit" (which is not a thing available in the postfix release for trusty) and trusty hosts would define "postscreen_dnsbl_ttl" (which is not a thing available in the postfix release for xenial).

While it works for that case, I've found that even when a meta role is skipped, the defaults file is still read, so for situations where you had the same directive, but wanted different values based on os/release, it would not work (i.e. in the following example, "biff" would always be set to "yes"):

    - release/trusty/postfix/defaults/main.yml:
        postfix_configuration_options:
            biff = no

    - release/trusty
        postfix_configuration_options:
            biff = yes



Does anyone have any ideas for how to have a defaults file per os/release like I want? Does anyone have alternative suggestions on setups such that I would not need/want this anymore?

Laurent Hoss

unread,
Jun 13, 2019, 11:07:02 AM6/13/19
to Ansible Project
I've got the same issue (in various roles) and still cannot foresee a good enough fix exists (or planned)

- An earlier post with the same question:

- Please upvote your favorite solution, in the proposals I gathered in following post:

Wawrzek Niewodniczanski

unread,
Jun 23, 2019, 5:01:42 AM6/23/19
to ansible...@googlegroups.com
Hi,

Have you tried include_vars:
https://docs.ansible.com/ansible/latest/modules/include_vars_module.html

It has such example:

- name: Load a variable file based on the OS type, or a default if not
found. Using free-form to specify the file.
include_vars: "{{ lookup('first_found', possible_files) }}"
vars:
possible_files:
- "{{ ansible_distribution }}.yaml"
- "{{ ansible_os_family }}.yaml"
- default.yaml
> --
> You received this message because you are subscribed to the Google Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
> To post to this group, send email to ansible...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/188121b2-963a-4840-a65b-f05d1a97bcf1%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Dr Wawrzyniec Niewodniczański or Wawrzek for short
PhD in Quantum Chemistry & MSc in Molecular Engineering
WWW: http://wawrzek.name E-MAIL: jo...@wawrzek.name
Linux User #177124
Reply all
Reply to author
Forward
0 new messages