Mike Williams
Mike Williams

Reputation: 85

Ansible, module_defaults and package module

So I'm trying to write roles and plays for our environment that are as OS agnostic as possible.
We use RHEL, Debian, Gentoo, and FreeBSD.

Gentoo needs getbinpkg, which I can make the default for all calls to community.general.portage with module_defaults.
But I can, and do, install some packages on the other 3 systems by setting variables and just calling package.

Both of the following plays work for Gentoo, but both fail on Debian etc due to the unknown option getbinpkg in the first example and trying to specifically use portage on systems that don't have portage in the second example.

- hosts: localhost
  module_defaults:
    package:
      getbinpkg: yes
  tasks:
    - package:
        name: {{ packages }}

- hosts: localhost
  module_defaults:
    community.general.portage:
      getbinpkg: yes
  tasks:
    - community.general.portage:
        name: {{ packages }}

Is there any way to pass module_defaults "through" the package module to the portage module?

I did try when on module_defaults to restrict setting the defaults, interestingly it was completely ignored.

- hosts: localhost
  module_defaults:
    package:
      getbinpkg: yes
    when: ansible_facts['distribution'] == 'Gentoo'
  tasks:
    - package:
        name: {{ packages }}

I really don't want to mess with EMERGE_DEFAULT_OPTS.

Upvotes: 1

Views: 1266

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68064

Q: "How to load distribution-specific module defaults?"

Update

Unfortunately, the solution described below doesn't work anymore. For some reason, the keys of the dictionary module_defaults must be static. The play below fails with the error

ERROR! The field 'module_defaults' is supposed to be a dictionary or list of dictionaries, the keys of which must be static action, module, or group names. Only the values may contain templates. For example: {'ping': "{{ ping_defaults }}"}

See details, workaround, and solution.


A: The variable ansible_distribution, and other setup facts, are not available when a playbook starts. You can see the first task in a playbook "Gathering Facts" when not disabled. The solution is to collect the facts and declare a dictionary with module defaults in the first play, and use them in the rest of the playbook. For example

shell> cat pb.yml
- hosts: test_01
  gather_subset: min
  tasks:
    - debug:
        var: ansible_distribution
    - set_fact:
        my_module_defaults:
          Ubuntu:
            debug:
              msg: "Ubuntu"
          FreeBSD:
            debug:
              msg: "FreeBSD"

- hosts: test_01
  gather_facts: false
  module_defaults: "{{ my_module_defaults[ansible_distribution] }}" 
  tasks:
    - debug:

gives

shell> ansible-playbook pb.yml

PLAY [test_01] ****

TASK [Gathering Facts] ****
ok: [test_01]

TASK [debug] ****
ok: [test_01] => 
  ansible_distribution: FreeBSD

TASK [set_fact] ****
ok: [test_01]

PLAY [test_01] ****

TASK [debug] ****
ok: [test_01] => 
  msg: FreeBSD

PLAY RECAP ****
test_01: ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Upvotes: 3

Related Questions