ansible_env.PATH, how is it set?

Hi Folks,

I’m a recent adoptee of Ansible and have found it to be a very productive alternative to both Chef and Puppet. Nicely done. I’m hoping to learn a little more about the fact system and how it works; I’m running a playbook on both CentOS 6.5 and RHEL 6.4 and found the value of ansible_env.PATH is quite different between them.

In the case of CentOS I seem to be getting everything from /etc/profile.d/*.sh by way of .bashrc

For RHEL, I’m getting a much more minimal path.

Any hints on where I can go to see how ansible_env.PATH is constructed?

I realize I have some levers to pull ( http://docs.ansible.com/playbooks_environment.html ), I’d just like to understand what is going on before I create (possibly unnecessary) workarounds.

Regards

Hmm…

The path the individual modules run in shouldn’t really be of consequence as nearly all executable invocations rely on finding the executables it needs in a specific search path.

Ultimately though, ansible is designed to ignore shell preferences unless you have in some way specified to force loading of a login shell, which seems a little unlikely that that’s the case. Though maybe it is?

We don’t like trusting the user environment because it can easily be inconsistent.

The environment keyword is there to force feed it specifics when needed, though if you are trying to run a specific binary, just pathing it may be easier too.

Hi Michael,

Thanks for the response, I’ll try and be a little more concrete about what I’m doing…

I’m installing an alternate ruby interpreter using RVM, but only if necessary. To check, I’m first running a command to check the
installed ruby version:

  • name: check ruby version
    command: ruby -v
    register: ruby_version
    ignore_errors: true

  • include: ruby_1_9_3.yml
    when: ruby_version.stdout.find(‘1.9.3’) == -1

If find the wrong ruby version, then I try and install a new one using RVM.

  • name: remove stock ruby + rubygems
    yum: name={{ item }} state=absent
    with_items:

  • ruby

  • rubygems

  • name: install ruby 1.9.3
    shell: \curl -sSL https://get.rvm.io | bash -s stable --ruby=1.9.3

This works, if I ssh to the host the new ruby interpreter is in my path, but a downside with RVM is it does a bunch of environment magic to make it all work. It puts a script in /etc/profile.d/rvm.sh which has about 70 lines to construct a new path based on the ruby it has installed. The high level instruction --ruby=1.9.3 ends up installing a non-deterministic (the latest) patchlevel:

part of the final path:

/usr/local/rvm/gems/ruby-1.9.3-p547/bin:/usr/local/rvm/gems/ruby-1.9.3-p547@global/bin:/usr/local/rvm/rubies/ruby-1.9.3-p547/bin:…

I could find a way to dig this out as a custom variable, but the funny thing is, on CentOS, the RVM supplied paths are in ansible_env.PATH. On RHEL, they aren’t.

The consequence is that the ruby -v command, and gem commands work on CentOS, on RHEL neither ruby nor gem are found.

I’m happy to do things the “ansible way”, perhaps what I need is a pointer on how best to proceed. To your question, I’m not doing anything special to try and use a particular shell / user environment.

Regards

The official RVM project shared a role in Galaxy which may be helpful:

https://galaxy.ansible.com/list#/roles/1087

Thanks. Unfortunately it only supports Ubuntu. What I ended up doing was:

  1. registering a variable the output of: /usr/local/rvm/bin/rvm current
  • name: get installed ruby
    command: /usr/local/rvm/bin/rvm current
    register: rvm_ruby_version
    changed_when: false
  1. creating a fact for the required path based on the output above.
  • name: create fact ruby_path
    set_fact: ruby_path={{ruby_gems_prefix}}{{rvm_ruby_version.stdout}}/bin:{{ruby_gems_prefix}}{{rvm_ruby_version.stdout}}@global/bin:{{ruby_path_prefix}}{{rvm_ruby_version.stdout}}/bin:{{ansible_env.PATH}}

note - this smells a little bad to me because I’m duplicating part of /etc/profile.d/rvm.sh

  1. supply the path to gem via environment.
  • name: install gems
    gem: name={{ item }} state=present user_install=no
    environment:
    PATH: “{{ruby_path}}”
    with_items:

Probably not idiomatic ansible(?), but at least it is robust across CentOS/RHEL/sudo/user environments.

Regards

I’m guessing the project would probably be interested in patches to make it more cross platform if you like!

I’d maybe ask a question on their github page for it.