Installing Pythonbrew

I’m trying to move the fabric-based deployment process for one of our Python projects over to Ansible. In our current process, the provisioning stage is done manually. I’ve read a few tutorials and managed to migrate the first couple steps of the provisioning stage. But I’m stuck on getting Pythonbrew installed.

I suspect the problem has to do with the bash environment for the user, similar to the question posed here: .bashrc not being sourced

When I install Pythonbrew manually, I follow the steps here on the project page and then log out of my terminal and log back in.

This is the error I’m getting:

failed: [devserver] => {“changed”: true, “cmd”: "pythonbrew install -v 2.7.3 ", “delta”: “0:00:00.016639”, “end”: “2013-10-11 15:21:40.989677”, “rc”: 127, “start”: “2013-10-11 15:21:40.973038”} stderr: /bin/bash: pythonbrew: command not found

I’ve posted a question to StackOverflow that includes my playbook script:

http://stackoverflow.com/q/19328252/1093087

Can anyone identify my problem or point me to an online guide for successfully installing Pythonbrew?

Thanks,
Tom

Where is pythonbrew being installed? It would seem like you either need to add it to your PATH or to run the command through the full path to the executable.

It looks like Pythonbrew gets installed to:

/usr/local/pythonbrew/bin/pythonbrew

This is my task, replacing pythonbrew with the full path:

  • name: Install python binary
    shell: /usr/local/pythonbrew/bin/pythonbrew install -v ${python_version} executable=/bin/bash

When I try running the playbook again, I no longer get the command not found error. I get this result:

changed: [sna9devibbtmp] => {“changed”: true, “cmd”: "/usr/local/pythonbrew/bin/pythonbrew install -v 2.7.3 ", “delta”: “0:00:00.099058”, “end”: “2013-10-15 10:13:15.766443”, “rc”: 0, “start”: “2013-10-15 10:13:15.667385”, “stderr”: “\u001b[31mERROR: Unknown python version: Python-2.7.3\n\u001b[0m”, “stdout”: “”}

When I ssh into the server as root (same user as in playbook) and run the same command, I don’t get the error. All I can figure is some contextual shell information is missing for the user when the playbook runs. I hoped the executable=/bin/bash flag would handle that but it doesn’t look like it.

So I whittled away at this and believe I finally got it figured out. A question persists.

As I suspected, solving the problem required getting the bash environment in the right state. I was able to install pythonbrew manually without logging out and in again (as is usually advised) by applying the equivalent of the following tasks:

  • name: Source pythonbrew bashrc file
    shell: export PYTHONBREW_ROOT=${pythonbrew.root}; source ${pythonbrew.root}/etc/bashrc
    executable=/bin/bash

  • name: Install python binary
    shell: pythonbrew install ${python.version}
    executable=/bin/bash

  • name: Switch to python version
    shell: pythonbrew switch ${python.version}
    executable=/bin/bash

This did not work in my playbook. Apparently the shell state does not persist between tasks. Is that expected behavior?

Appending the export and source command to each step solved the problem:

  • name: Install python binary
    shell: export PYTHONBREW_ROOT=${pythonbrew.root}; source ${pythonbrew.root}/etc/bashrc; pythonbrew install ${python.version}
    executable=/bin/bash

  • name: Switch to python version
    shell: export PYTHONBREW_ROOT=${pythonbrew.root}; source ${pythonbrew.root}/etc/bashrc; pythonbrew switch ${python.version}
    executable=/bin/bash

Is there a more elegant way to do this? Something more like the first example?

Not sure, but can you use ansible’s ‘environment’.

http://www.ansibleworks.com/docs/playbooks_environment.html

Nope, it’s not a persistent shell between tasks.

Like Romeo suggested, the environment keyword is a good option.

Thank you Romeo and Michael for the pointing me to the environment keyword. Looking at the docs on it, however, it’s not clear to me how I would apply it to my case:

http://www.ansibleworks.com/docs/playbooks_environment.html

My impression from the docs is that the environment keyword functions something like a task-specific alternative to vars. It’s not clicking for me.

Perhaps someone with some experience using the environment keyword could demonstrate how to use it with the following code sample so as to eliminate the redundant export PYTHONBREW_ROOT=${pythonbrew.root}; source ${pythonbrew.root}/etc/bashrc; commands:

  • name: Install python binary
    shell: export PYTHONBREW_ROOT=${pythonbrew.root}; source ${pythonbrew.root}/etc/bashrc; pythonbrew install ${python.version}
    executable=/bin/bash

  • name: Switch to python version
    shell: export PYTHONBREW_ROOT=${pythonbrew.root}; source ${pythonbrew.root}/etc/bashrc; pythonbrew switch ${python.version}
    executable=/bin/bash