include another role's variables without running it's tasks?

I often need to access the default variables of another role. Currently I’m doing this via role dependencies, and passing a special variable to skip running a roles tasks. E.g.


:: my_role/meta/main.yml ::
dependencies:
- { role: other_role, skip_tasks: True }

:: other_role/tasks/tasks.yml ::
- { include: prepare.yml, tags: ['prepare'], when: skip_tasks is not defined or not skip_tasks }

This is nice because it accomplishes loading variables from other_role (default/main.yml, vars/main.yml) and is a well understood ansible convention… although it adds additional variable complexity (skip_tasks) and verbosity to the playbook output (all the skipped tasks are reported). As an alternative I am thinking about explicitly included the desired vars (if they are not already available). E.g.


:: my_role/tasks/main.yml ::

- name: gather variables
include_vars: "'/path/to/other_role/defaults/main.yml"
when: needed_var_from_other_role is not defined

Is this a recommended approach?

Alternatively I could probably stick all shared variables in a taskless common role that’s depended upon – although prefer the naturality of keeping the vars in their related role.

Thanks for your insight!

~ Brice

What you say is a “well understood ansible convention” I am having trouble processing.

I read most of your posts and think you are in general not getting the Zen of Ansible too much.

Keep things simple.

Don’t think about trying to read what some default value is. Just use the value that makes it through, knowing that the right value made it through.

The “skip_tasks” stuff, and other hacks should be shunned.

Once you get the bare minimum to automate application X, stop.

It’s not supposed to be a super-elegant software construct, or even a programming language. It’s a language for getting things done.

Thanks Michael.

In my example I have a backup role. It would like to know the path where the apache-role stores websites by default so that it can back them up. Lets say the apache role stores this variable as apache_sites_dir in its default/main.yml (and of course it can be specified as well in inentory vars).

So I currently have the backup role depending on the apache role to glean this variable (I thought conventional). I didn’t like this approach because it runs apache tasks – so I added the skip_task garbage.

Is explicitly loading apache’s agreeable in this situation? e.g.

:: backup/tasks/main.yml ::

  • name: detect apache sites location
    include_vars: “'path/apache/defaults/main.yml”

when: apache_sites_dir is not defined


or can you enlighten me upon a different approach.

Many Thanks,

~ Brice

In my example I have a backup role. It would like to know the path where the apache-role stores websites by default so that it can back them up. Lets say the apache role stores this variable as apache_sites_dir in its default/main.yml (and of course it can be specified as well in inentory vars).

I’m curious why you would do this (not because there is anything inherently wrong with it, but I’m wondering what your thinking is here).

My thoughts would be that you set up hostX as a backup client with a backup role and backup everything…(maybe excluding certain temporary directories)… Why do you want something explicitly different for web servers/web sites?

So I currently have the backup role depending on the apache role to glean this variable (I thought conventional). I didn’t like this approach because it runs apache tasks – so I added the skip_task garbage.

Is explicitly loading apache’s agreeable in this situation? e.g.

:: backup/tasks/main.yml ::

  • name: detect apache sites location
    include_vars: “'path/apache/defaults/main.yml”

when: apache_sites_dir is not defined

Rather than do this, IF I wanted something different (or explicit) about backing up web server files I would have a general purpose backup role (install some backup software, maybe provide some generic configuration) and have a role for installing the webserver software (or configuring a website or…) that sets up the software and then either modifies the backup software or (preferably) drops a configuration file in some included directory. If that isn’t possible (it all has to be in one file) then I would consider using the assemble module to create the configuration file from all of the pieces. (Otherwise on your next run the backup role would change the configuration file back and the webserver role would change it again.

You could still add a dependency but it would be the other way around. The web server role would “depend” on the backup role… (instead of confusing terminology like dependency call it “insist that it ran after”… :slight_smile:

Adam

In short – I am trying to avoid running 88 non-changing tasks to execute 2 changing ones. For instance; when I’m applying sites to a server, I don’t want to also apply apache, and whatever else apache depends on, and so forth – just to apply the sites. Here’s an example playbook;

https://github.com/iceburg-net/ansible-pcd/blob/master/iceburg-sites.yml

Apache was setup in a playbook I previously executed (as a dependency of the php role);

https://github.com/iceburg-net/ansible-pcd/blob/master/webservers.yml

… so, for instance, when I’m applying sites via the apache-site role, it’s really useful to know where to put SSL certificates. I define where to put ssl certificates in an upstream role (httpd) as httpd_ssl_dir. httpd_ssl_dir best belongs in the httpd role and not the apache_sites roles because OTHER ROLES may want to use it; and it’s the natural spot to look for it.

I know my organizational process differs from Michael and it’s made it very inefficient to me to work with ansible; but none-the-less it’s my favorite infrastructure automation tool && I believe my struggles have always been failure to clearly communicate my ideas. I think I’m closer now && I hope that I’ve created something respectable.

I believe elegance and simplicity are one in the same, and, in fact, dependent upon eachother.

~ Brice

“My thoughts would be that you set up hostX as a backup client with a backup role and backup everything…(maybe excluding certain temporary directories)… Why do you want something explicitly different for web servers/web sites?”

Agree.

I’d configure your backup tool to indicate what paths should be backed up.

Even if doing something as basic as rsync, rsync is very good at determining what files it needs to move.

Otherwise you are backing up only the things that ansible has known it changed, which doesn’t include things that the software could have changed by itself (databases) or users logging in.

Thus the backup process should probably be independent of the ansible playbook process – ansible will set up the backup to core, or cause it, but I’d venture it shouldn’t make decisions on what needs to be backed up conditionally based on what it changed, as that could miss things you might want to back up.

That's actually his initial question. Apache knows where to serve
sites from based on that role's (or groups) variables. Now his backup
tool needs to know which paths to backup. I've solved this similar
problem by including the role's vars in the backup playbook like he
suggested using include_vars.

“That’s actually his initial question.”

Just put it in the configuration file for the backup tool/script. No need to sprinkle this throughout the playbook IMHO.

It could even use variables to conditionally include things

{% if x in groups[‘webservers’] %}

{% endif %}
{% if x in groups[‘dbservers’] % }
{% endif %}

etc

My backup role ensures the backup tools and remote storage points (via the s3ql service role). It then registers backup tasks with cron, one of which is meant to backup sites. The site backup script executes rsync, passing a list of site files/paths to backup via the --files-from argument. This list is contained in a file “rsync_sites.inc”, and a variable named backup_rsync_sites_file in the backup role points to it.

When sites are applied to the server, and if backups are enabled for the site via the SITE_ENABLE_BACKUP flag, then lines are added to the backup_rsync_sites_file. The lines added can be passed explicitly, or are inferred by the site type (e.g. if a wordpress site, then .htaccess, wp-config.php, and wp-content/uploads are backed up).

Thus my role that applies sites needs to know the backup_rsync_sites_file variable, and that’s defined in the backup role. Similarly, it also needs to know where to store SSL certificates (if flagged as an SSL site), and this path is stored as httpd_ssl_dir in the httpd role. And so the roles are intralinked – and I’m thiking about using include_vars versus including the backup role as a dependency to glean these variables.

I’m sorry that I mentioned “ansible convention” in the OP. I meant that role dependencies are a convention, and that my skip_tasks hack was garbage, and wanted to discuss if include_vars for this was OK.

~ Brice

Is there a reason no to backup, say, /etc, /home, /srv and /var/www?

Maciej

Hey Maciej. That scenario (backing up entire directores) is totally supported as well via the backup role and feeding it a list of directories.

The reason I also support being explicit with site backups out of the box is two-fold;

  • site files are typically contained in distributed git repositories; and only server configurations and assets (e.g. CMS uploads) need be backed up

  • site applications often [and by default] produce a ton of temporary files inside the document root which have no business being part of the backup routine – I’ve had many a failed backup caused by attempting to rsync smarty cache files or magento var directories on remotely mounted storage/NFS.

Additionally, being explicit leads to smaller backup sizes that cost less and take less time to make.

~ Brice

For what it's worth, I simply follow this rule: if data needs to be
accessed from outside a role, then it should go in inventory somewhere
(e.g., group_vars/foo or group_vars/all/foo).

My 2¢.

For what it’s worth, I simply follow this rule: if data needs to be
accessed from outside a role, then it should go in inventory somewhere
(e.g., group_vars/foo or group_vars/all/foo).

My 2¢.

This is very good solution too (my nginx role also accounts for this). I would also provide sane default values whenever possible via role/defaults/main.yml to not force configuration upon user if not necessary.

Maciej

Yes -- I totally agree that setting these shared-between-roles variables in group_vars/all.yml is the way to go. And I also agree with Maciej in that you shouldn't force a user to configure things in their inventory vars if you can provide sensible values in role/defaults/main.yml -- which is what I've done and demonstrated -- and which is why I started this dang thread to begin with.

Setting the shared-between-roles variables in group_vars/all.yml is probably the way to go; as it avoids needing to depend on roles when all you need is a var from it, or the alternative of using include_vars, but it does force the user to add values to their inventory.

~ Brice

Right – that’s assuming the scope of the backup role. Simply; the backup role sets up a consistent backup mechanism and what paths to back up; and roles can tap into this to augment what gets backed up as well. It primarily does this by managing an rsync include file; but uses line_in_file vs templating/copying to ensure that outside (“software”?) changes don’t get overwritten.

In any case the intralinked site/backup role was just an example of a situation I had where one role needed to use a variable from another role; and I opened this thread to get an idea on how to best do so.

Thanks as always for the chastisement. Fear not, man … I won’t venture into the empire of Atilla DeHaan unless necessary bugs creep up :wink:

Never get involved in a land war in Asia.