Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ANSIBLE_PYTHON_INTERPRETER env variable. #6345

Closed
alimony opened this Issue Mar 8, 2014 · 21 comments

Comments

Projects
None yet
10 participants
@alimony
Copy link
Contributor

commented Mar 8, 2014

Issue Type:

Feature Idea

Ansible Version:

ansible 1.6 (devel da2126e) last updated 2014/03/04 20:54:15 (GMT +200)

Environment:

N/A

Summary:

At the moment, there is no env variable equivalent of the ansible_python_interpreter setting.

If I use a python at some other path than /usr/bin/python I need to set this config variable.

But if I already have an ansible.cfg under source control, I can't do it in there, since people will share that file and they may need some other python path than me.

And combining several config files is not supported.

So, how would I solve this?

Having a corresponding env variable (as with many other settings) would solve this nicely, but from what I gather from a bit of googling, that env variable is deliberately not available. How come?

Steps To Reproduce:

I would ideally want to do this:

export ANSIBLE_PYTHON_INTERPRETER=/some/special/python
Expected Results:

That the ansible_python_interpreter setting is available as an env var setting as well.

Actual Results:

It is not :)

@alimony

This comment has been minimized.

Copy link
Contributor Author

commented Mar 8, 2014

Another solution to the same problem would be to have #!/usr/bin/env python instead of #!/usr/bin/python everywhere. But it seems this have been requested many times, with the ansible_python_interpreter setting as most common answer. But this might not work in all cases, as stated in this issue.

@bcoca

This comment has been minimized.

Copy link
Member

commented Mar 8, 2014

It is not just ansible_python_interpreter, this facility works for ruby
(ansible_ruby_interpreter), perl, bash, etc.

Using env is not a universal solution either too many distros and OSs have
multiple pythons sometimes python == v2 sometimes v3, hell, sometimes even
the env binary is in a different location.

@alimony

This comment has been minimized.

Copy link
Contributor Author

commented Mar 8, 2014

I'm not sure I follow. Is there a ansible_ruby_interpreter config variable? I can't find it references anywhere in code…?

In any case, /usr/bin/env is much more portable than /usr/bin/python, which is also why the latter is a python script best practice.

@bcoca

This comment has been minimized.

Copy link
Member

commented Mar 8, 2014

The logic is 'ansible_*_interpreter', so ruby, perl, any script executable
works. There used to be a reference that this was the case when using
python as a example (mostly cause all core modules use it).

/usr/bin/python is not used for portability, it is used so you can control
substitution with the mechanism detailed above.

@alimony

This comment has been minimized.

Copy link
Contributor Author

commented Mar 8, 2014

The change would then be to change all occurrences so that they can still be substituted, while providing additional portability when running ansible in e.g. a virtual environment. I understand that this may be a large change with many side effects, but would still be useful.

@bcoca

This comment has been minimized.

Copy link
Member

commented Mar 8, 2014

I don't see why a change is needed, using the variable setting already
ensures portability to any environment.

@alimony

This comment has been minimized.

Copy link
Contributor Author

commented Mar 8, 2014

See my original comment. If you can't use the configuration file for this setting, because you want to share it in a project, there is no way to do it. Am I missing something?

@bcoca

This comment has been minimized.

Copy link
Member

commented Mar 8, 2014

normally you set it as a group var or host variable, you can even set it on
the command line -e 'ansible_python_interpreter=/opt/bin/python2'

@alimony

This comment has been minimized.

Copy link
Contributor Author

commented Mar 8, 2014

But how can I put it in a variable if I share the inventory with others? I may want to use /usr/local/bin/python as value, and some other collaborator wants /opt/bin/python, and so on.

@bcoca

This comment has been minimized.

Copy link
Member

commented Mar 8, 2014

you can put variables in the inventory, since these are host/group specific
I doubt 2 people will want to use different values as only 1 of them should
work.

@alimony

This comment has been minimized.

Copy link
Contributor Author

commented Mar 8, 2014

In my specific case, I need the dopy python module for the digital_ocean module to work. Since I've installed python through Homebrew, it lives in /usr/local/bin/python and running pip install dopy will install it in /usr/local/lib/python2.7/site-packages.

When I run Ansible, it will not have that last path available, since Ansible always uses /usr/bin/python unless ansible_python_interpreter is set. Now, if I want to set this variable in a shared repo, I would have to set it to a value that works for me, i.e. ansible_python_interpreter = /usr/local/bin/python

Now, the next person who uses this repository and configuration will have the same interpreter path. But if that person has python at /opt/bin/python and pip installs packages in /opt/lib/python2.7/site-packages, the dopy package will not be found since Ansible is looking in the wrong place.

How would you solve this situation?

@mpdehaan

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2014

What Brian said about this applying to all languages applies, and this is introduced to be able to manage systems where you are simultaneously talking to two systems with different interpreter paths. Thus, setting it globally defeats that purpose.

If you do need to assign it globally, it can be assigned at the group_vars/all level.

@mpdehaan mpdehaan closed this Mar 9, 2014

@alimony

This comment has been minimized.

Copy link
Contributor Author

commented Mar 9, 2014

For anyone reading this, I solved this based on the suggestion by @mpdehaan, using a host var:

---
- hosts: all
  vars:
    ansible_python_interpreter: "/usr/bin/env python"
@etrikp

This comment has been minimized.

Copy link

commented Jun 6, 2014

This is closed but I don't believe that the creator of this issue was understood properly. I am running into the same issue. There is no desire to set an environment variable on a remote host. The use case here is for a development host/jump host. So lets say the scope is restricted to the implicit localhost (the feature that was added in 1.5).

As an example, I am creating instances on OpenStack via the nova module, which is run on localhost. In order to make this work properly with my MacPorts version of python I need to explicitly define localhost in an inventory, then add the ansible_python_interpreter variable to the inventory entry, or follow one of the other suggestions that is essentially the same thing, explicitly defining variables for localhost.

This is an issue when you are working with others as the explicit definition for localhost that I have made in the inventory, may not be what their localhost looks like.

So the proposal is as follows, the environment variable ANSIBLE_PYTHON_INTEPRETER (or any language) would only take precedence in the localhost scope.

- hosts: localhost
  vars:
    ansible_python_interpreter: "/usr/bin/env python"

Otherwise it would be ignored. Its sane to defer to local environment variables to make sure a program has the proper information about how the local environment is configured.

I can also see this working fine for remote hosts as long as its reading from the local environment, i.e. pushing out an environment variable thats set on my machine to a bunch of other machines that are likely configured different makes no sense, but that is not what this discussion is intended to be about.

@darKoram

This comment has been minimized.

Copy link

commented Jun 10, 2014

We also just came across it when running against localhost with sudo.

We do have use cases for many users sharing the same hostfile. For us, it is an entire devteam using a vagrant setup with ansible as the provisioner. We can have all devs using a single private ip with
private_network: 192.168.x.y in the Vagrantfile.

We share a single ansible tree and a single hosts file for vagrant with
localhost ansible_python_interpreter=$LOCAL_ANSIBLE_PYTHON_INTERPRETER ansible_connection=local

in a .ansiblerc file we have
export LOCAL_ANSIBLE_PYTHON_INTERPRETER=which python

This works fine for regular tasks, but for sudo tasks the LOCAL_ANSIBLE_PYTHON_INTERPRETER evaluates to null as it is not in the root env. This causes a Permission denied error as the python interpreter vanishes and the ansible module is not executable.

We develop on mac so there isn't even a /root to place a config file in.

I believe setting an ANSIBLE_PYTHON_INTERPRETER var in .ansible.cfg would solve both these issues. It should only apply to the local machine, but it should apply to all users of localhost.

+1 for setting an env variable for this.

@dvdplm

This comment has been minimized.

Copy link

commented Oct 22, 2014

The objections to adding an env var do not convince. Not using #!/usr/bin/env python is surprising and poorly explained (or at least I didn't get it).

@cewood

This comment has been minimized.

Copy link

commented Sep 8, 2015

It's hard to believe there is still no support for this functionality. @alimony is completely correct, having to set this variable via inventory/group_vars/extra_vars just won't cut it, there are far too many use cases where this breaks portability. To name just a few:

  1. Shared repository amongst multiple people with different operating enviroments (OSX, Arch, Gentoo, Windows, etc)
  2. Shared external tooling such as Vagrant, Makefiles, etc, that is expecting fixed input

Is anyone interested in working on this?

@copumpkin

This comment has been minimized.

Copy link

commented Dec 2, 2015

👍 on this. @bcoca any chance of getting this re-examined?

@dominikborkowski

This comment has been minimized.

Copy link

commented Feb 9, 2016

This issue becomes a slight nuisance when working with official docker containers from the 'python' tag, as in entries from https://hub.docker.com/_/python/.

When trying to use the docker connector from ansible 2.0 on those containers, one will encounter this error:

$ docker run -td --name ansible_test python:2 /bin/sh
$ ansible all -i ansible_test, -c docker -m command -a 'uptime'
python_test | FAILED | rc=0 >>
MODULE FAILURE

# we create a symbolic link:

$ docker exec -it ansible_test /bin/ln -sf /usr/local/bin/python /usr/bin/python
$ ansible all -i ansible_test, -c docker -m command -a 'uptime'
ansible_test | SUCCESS | rc=0 >>
 15:09:13 up 11:51,  0 users,  load average: 0.07, 0.04, 0.05
@abadger

This comment has been minimized.

Copy link
Member

commented Feb 9, 2016

There will not be an environment variable for python interpreter added to ansible. There are ways to enable all the use cases that people are asking for by setting ansible_python_interpreter in one manner or another.

@dominikborkowski Your issue with docker sounds like it is the primary use case for ansible_python_interpreter. On the docker containers, python is installed into /usr/local/bin/ instead of into /usr/bin/ because of that, for your docker containers you need to tell ansible that the python executable resides somewhere other than /usr/bin/python. You do this using ansible_python_interpreter in an inventory file:

[docker_python_hosts]
docker1
docker2

[docker_python_hosts:vars]
ansible_python_interpreter=/usr/local/bin/python

For everyone who wants to have multiple python interpreters on the same host with different users using different ones there's various methods which may suit your needs in various ways. The one closest to setting an env var is to set ansible_python_interpreter on the command line as bcoca mentioned: #6345 (comment)

$ ansible docker1 -m ping -e 'ansible_python_interpreter=/usr/local/bin/python'

If you want to set that in a shell login file so that it applies to all of your hosts (like setting an environment variable in a shell login file would do) use alias to always add that to the ansible and ansible-playbook commands:

alias ansible='ansible -e "ansible_python_interpreter=/usr/local/bin/python"'
alias ansible-playbook='ansible-playbook -e "ansible_python_interpreter=/usr/local/bin/python"'

Something similar can also be done in inventory with inventory names per-user like this:

[user_host_aliases]
abadger-shared ansible_host=shared1 ansible_python_interpreter=/home/badger/bin/python
toshio-shared ansible_host=shared1 ansible_python_interpreter=/home/toshio/bin/python

I'm going to be locking this issue as the environment variable is probably never going to happen. If you need help getting an alternative to work, feel free to stop by the mailing list or IRC and someone will be happy to try and get an example working for you. I'll paste the mailing list information below.

List Information

Hi!

Thanks very much for your interest in Ansible. It sincerely means a lot to us.

This appears to be a user question, and we'd like to direct these kinds of things to either the mailing list or the IRC channel.

If you can stop by there, we'd appreciate it. This allows us to keep the issue tracker for bugs, pull requests, RFEs and the like.

Thank you once again and we look forward to seeing you on the list or IRC. Thanks!

@ansible ansible locked and limited conversation to collaborators Feb 9, 2016

@abadger

This comment has been minimized.

Copy link
Member

commented Feb 9, 2016

On IRC there was a little bit of discussion about a related issue. I'll add the information here in case it's helpful.

Sometimes people don't want to hardcode a specific python path for the remote machine, instead relying on the python interpreter that's found first in the remote machine's PATH. ansible_python_interpreter can be used to address that case as well if you have the env program installed in a reliable location. here's how you can do that in an inventory file:

[vars:all]
ansible_python_interpreter="/usr/bin/env python"

ansible will then create module scripts with the shebang line of #! /usr/bin/env python

If you have to do this at the command line that is also possible:

$ ansible -m ping -i 'rhel6-test,' '*' -e 'ansible_python_interpreter="/usr/bin/env python"'

Note that we had to nest our quotes so that the embedded space in the variable's value was handled correctly (the single quotes are processed by the shell and then the double quotes are handled by ansible's key=value parser).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.