I'm learning ansible awx and I have a situation that will come up that I want to address during testing so I'm looking for ideas and possible solutions.

The file structure is from here, Best Practices — Ansible Documentation > "Directory Structure".

To keep this question simple, I have a two playbooks and each playbook is supposed to run against a pre-configured Linux image that performs a role. One role is for desktops another role is for servers.

The amount of deployed desktops could be hundreds or thousands so I really need a simple solution that scales without much human interaction.

I imagine some desktop users will need to have custom changes. While the desktops uses 99% of the standard role configuration, they might need to have a specific background image or have their timezone set for their account as just an example or whatever else needs to be locked in on that desktop.

I don't want to create a playbook structure for each machine that steps outside of the standard configuration so is there a way to say, run the standard playbook but also run this other set of tasks but only against a host/group name matched in AWX after the standard playbook or even in the middle of a standard role task job?

Example might be in the tasks / main.yml can I include another yml file which is imported and run if a host matches an AWX group? This way the standard role is kept fairly clean which just imports another file that might import another file based off host matches which should match the group name in AWX?

Concept I'm thinking of, unsure if doable or something like it? All I would need to do is add a test in custom.yml and create a new file with the custom tasks for that host/group.

In tasks / main.yml

- name: install app

#end of tasks declarations
# At bottom of the file

include custom.yml

#file custom.yml
  host: user_machine_123
  import user_machine_123_custom_tasks.yml

#file user_machine_123_custom_tasks.yml
- name: install special app for user_machine_123

Including all exceptions into the playbook is not necessary, if the user may customize outside ansible. Also, beware having too large and complex of a playbook, you can have multiple playbooks.

That said, per group and per host values and actions are possible.

Define all values as variables to allow overrides. For example, at the role default level time zone is tz: UTC but in group_vars/desktop it can be tz: America/Chicago or whatever. In a common role you run on all hosts, use the timezone module:

 - timezone:
     name: "{{tz}}"

Optional per-host tasks are a bit trickier. Try a static include with the first_found lookup. First look up the most specific file name containing inventory_hostname, then a (possibly empty) defaults file.

- name: per host tasks
  include: "{{lookup('first_found', params)}}"
        - '{{inventory_hostname}}.yml'
        - default.yml
        - 'tasks'

If you find yourself reaching for this pattern, consider limiting its use. It only works on hosts already targeted by the play, and host specific behavior inside a tasks directory is not very intuitive.

A role is a more manageable unit to contain tasks and vars, and can be reused against any number of hosts. Have Ansible users contribute roles, which can be maintained separately from your play if you wish. Then map them to hosts in playbooks:

- name: Server common
  hosts: servers
  - common

- name: Web servers common
  hosts: web
  - webserver

- name: Widget inventory app
  hosts: widget
  - widgetapp

- name: special snowflake
  hosts: user123
  - custom123
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.