I'm trying to create a playbook with Ansible (v 1.3.3) to install Pythonbrew system-wide on a Debian server following the instructions in the Pythonbrew readme file.
I am able to get Pythonbrew installed but I cannot install the specific version of Python that I want with it. I suspect the issue has to do with the shell environment Ansible is running under.
Here's my playbook script:
- name: Install and configure PythonBrew
hosts: dev
user: root
vars_files:
- vars.yml
gather_facts: false
tasks:
- name: Install PythonBrew Debian packages
apt: pkg=${item} state=installed update-cache=yes
with_items: ${pythonbrew_packages}
- name: Install PythonBrew system-wide
shell: curl -kL http://xrl.us/pythonbrewinstall | bash creates=/usr/local/pythonbrew executable=/bin/bash
- name: Update bashrc for PythonBrew
lineinfile:
dest=~/.bashrc
regexp='^'
line='[[ -s $HOME/.pythonbrew/etc/bashrc ]] && source $HOME/.pythonbrew/etc/bashrc'
state=present
create=True
- name: Install python binary
shell: pythonbrew install -v ${python_version} executable=/bin/bash
When I run this playbook, it fails with the following output
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 been tweaking things for the last hour or so to no avail. Does anybody have any suggestions for fixing this?
By peeking at the PythonBrew install script, I was able to figure this out. (And just in time for the deprecation of PythonBrew!)
Here's the playbook that installs PythonBrew without manual intervention. This may be of interest to anyone trying to script PythonBrew to install automatically.
vars.yml
#
# Python/PythonBrew Settings
# TODO: replace old-style Ansible ${vars} with jinja-style {{ vars }}
#
project_name: MY_PROJECT
python:
version: 2.7.3
pythonbrew:
root: /usr/local/pythonbrew
bashrc_path: $HOME/.pythonbrew/etc/bashrc
packages:
- curl
- zlib1g-dev
- libsqlite3-dev
- libssl-dev
- libxml2
- libxml2-dev
- libxslt1-dev
- libmysqlclient-dev
- libbz2-dev
pythonbrew.yml
---
#
# Install and Configure PythonBrew
#
- name: Install and configure PythonBrew
hosts: MY_HOST
user: root
vars_files:
- vars.yml
gather_facts: false
tasks:
- name: Install PythonBrew Debian packages
apt: pkg=${item} state=installed update-cache=yes
with_items: ${pythonbrew.packages}
- name: Install PythonBrew system-wide
shell: curl -kL http://xrl.us/pythonbrewinstall | bash
executable=/bin/bash
creates=${pythonbrew.root}
- name: Update bashrc for PythonBrew
lineinfile:
dest=/root/.bashrc
regexp='^'
line='[[ -s ${pythonbrew.bashrc_path} ]] && source ${pythonbrew.bashrc_path}'
state=present
create=True
# This step allows install to continue without new shell. Pulled from:
# https://github.com/utahta/pythonbrew/blob/master/pythonbrew/installer/pythonbrewinstaller.py#L91
- 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
Related
I need to use with_items loop to install apache2, sqlite3, and git in Ansible. I'm trying to use the below code but it seems like nothing is happening.
---
- hosts: all
sudo: yes
name: install apache2, sqlite3, git on remote server
tasks:
- name: Install list of packages
action: apt pkg={{item}} state=installed
with_items:
- apache2
- sqlite3
- git
you have to place the variable item inside the double quotes...
Try this code it'll work:
---
- name: install apache2, sqlite3, git on remote servers
hosts: all
become: true
tasks:
- name: Install packages
package:
name: "{{item}}"
state: present
loop:
- apache2
- sqlite3
- git
Try
---
- name: install apache2, sqlite3, git on remote servers
hosts: all
sudo: true
tasks:
- name: Install packages
package:
name: {{ item }}
state: present
loop:
- apache2
- sqlite3
- git
See package – Generic OS package manager
"This module actually calls the pertinent package modules for each system (apt, yum, etc)."
See apt – Manages apt-packages if you need apt specific attributes.
I am new to ansible and writing a playbook to install locustio with python3 on a Ubuntu 18.04. I don't know how to install locustio with pip3 in playbook. If use pip package, then it gives error to use older version of locust. ( use a pinned old locust version (pip/pip3 install locustio==0.13.5) . I would like to know how to install locust with pip3 or locust 0.13.5 version with pip?
- hosts: all
tasks:
- name: Create folder to keep the files
file:
path: /opt/locust
state: directory
mode: '0755'
become: yes
- name: Python installation
apt:
name: ['python3']
state: present
become: yes
- name: Pip installation
apt:
name: ['python3-pip']
state: present
become: yes
- name: pip install
apt:
name: ['python-pip']
state: present
become: yes
- name: Locust Installation
pip:
name: ['locustio']
state: present
become: yes
I haven't used Ansible, but looking at the docs there seems to be a executable parameter that you could set to pip3.
My Ansible server is communicating as root user with agent but I need to install ruby as different user i.e deploy. So I am trying to switch the user to deploy using 'become' to install ruby but I am facing issue. Its seems that when i am trying to switch the user and running the command its unable to use .bashrc file of deploy user. Below is my YML file
---
- hosts: test1
become: true
tasks:
- name: adding node.js repository
shell: curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
- name: adding yarn pubkey
shell: curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
- name: adding yarn repo
shell: echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
- name: update cache
apt: update_cache=true
- name: install all the below list of packages
apt: name={{ item }} update_cache=true
with_items:
- git-core
- curl
- zlib1g-dev
- build-essential
- libssl-dev
- libreadline-dev
- libyaml-dev
- libsqlite3-dev
- sqlite3
- libxml2-dev
- libxslt1-dev
- libcurl4-openssl-dev
- software-properties-common
- libffi-dev
- nodejs
- yarn
- name: change to deploy home directory
shell: cd
become: true
become_user: deploy
- name: getting repo from git
shell: git clone https://github.com/rbenv/rbenv.git ~/.rbenv
become: true
become_user: deploy
- name: copy path
shell: echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
become: true
become_user: deploy
- name: copy eval
shell: echo 'eval "$(rbenv init -)"' >> ~/.bashrc
become: true
become_user: deploy
- name: execute shell
shell: exec $SHELL
become: true
become_user: deploy
- name: ruby repo
shell: git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
become: true
become_user: deploy
- name: copy paths
shell: echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
become: true
become_user: deploy
- name: shell execute
shell: exec $SHELL
become: true
become_user: deploy
- name: install ruby
shell: rbenv install 2.4.4
become: true
become_user: deploy
- name: set global
shell: rbenv global 2.4.4
become: true
become_user: deploy
I am getting the below error:
TASK [install ruby] ***************
fatal: [host1]: FAILED! => {"changed": true, "cmd": "rbenv install
2.4.4", "delta": "0:00:00.003186", "end": "2018-09-25 15:43:23.224716", "msg": "non-zero return code", "rc": 127, "start":
"2018-09-25 15:43:23.221530", "stderr": "/bin/sh: 1: rbenv: not
found", "stderr_lines": ["/bin/sh: 1: rbenv: not found"], "stdout":
"", "stdout_lines": []}
But when I am providing the path manually in command for rbenv its working fine. As shown below:
- name: install ruby
shell: /home/deploy/.rbenv/bin/rbenv install 2.4.4
become: true
become_user: deploy
Can you please tell me why its behaving like this?
I need to install bundler also using gem. I am switching to user 'deploy' but its going to check the root user directory instead of deploy user and giving error. Please refer the below YML part for gem and error:
- name: install bundler
shell: gem install bundler
become: true
become_user: deploy
Below is the error for bundler:
TASK [install bundler] *********
fatal: [host1]: FAILED! => {"changed": true, "cmd": "gem install
bundler", "delta": "0:00:02.396195", "end": "2018-09-25
16:21:18.703899", "msg": "non-zero return code", "rc": 1, "start":
"2018-09-25 16:21:16.307704", "stderr": "ERROR: While executing gem
... (Gem::FilePermissionError)\n You don't have write permissions
for the /var/lib/gems/2.3.0 directory.", "stderr_lines": ["ERROR:
While executing gem ... (Gem::FilePermissionError)", " You don't
have write permissions for the /var/lib/gems/2.3.0 directory."],
"stdout": "", "stdout_lines": []}
Please help me to fix the issue.
Thanks.
That playbook does not do what you think it does, because every one of those tasks is effectively its own ssh connection. So, this:
- name: change to deploy home directory
shell: cd
become: true
become_user: deploy
- name: execute shell
shell: exec $SHELL
... is equivalent to ssh root#the-host "su deploy -c 'cd; exit'"; ssh root#the-host "su deploy -c 'exec $SHELL; exit'" and so forth.
You'll very like also want to move all of those tasks that run as deploy into their own playbook or role, and include them with those become: true and become: deploy at the include or role level to keep from repeating that text all over the tasks.
But even if you don't do that, the shortest path to success is to collapse all 10 of those steps into just one shell: | block to rescue your sanity and reinforce that they all need to happen in the same shell session
- name: install ruby using rbenv
become: true
become_user: deploy
shell: |
set -e # <-- stop running this script if something fails
cd $HOME
export ... # etc etc
args:
creates: /home/deploy/.rbenv/versions/2.4.4/bin/ruby
Optionally including that args: creates: business will give ansible a fighting chance to skip that step if it has already provisioned rbenv. You will, of course, likely want to update that to guard the step in a way that is more relevant to what you're trying to do.
I am trying to translate a shell script into Ansible.
Snippet of code that is confusing me:
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install msodbcsql mssql-tools
sudo apt-get install unixodbc-dev
What I have so far:
- name: Install SQL Server prerequisites
apt: name={{item}} state=present
update_cache: yes
with_items:
- msodbcsql
- mssql-tools
- unixodbc-dev
No idea where to tie in ACCEPT_EULA=Y.
This is an environment variable, so:
- name: Install SQL Server prerequisites
apt:
name: "{{item}}"
state: present
update_cache: yes
with_items:
- msodbcsql
- mssql-tools
- unixodbc-dev
environment:
ACCEPT_EULA: Y
And mind the indentation. It's really important in YAML.
I have a rather long task in my Ansible playbook that installs various packages using APT. This tasks takes a very long time on my laptop. Is there any way to get Ansible to "echo" which item it's installing as it iterates through the packages so I can get an idea of how much longer this task is going to take?
- name: install global packages
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600
become: True
become_user: root
with_items:
- git
- vim
- bash-completion
- bash-doc
- wput
- tree
- colordiff
- libjpeg62-turbo-dev
- libopenjpeg-dev
- zlib1g-dev
- libwebp-dev
- libffi-dev
- libncurses5-dev
- python-setuptools
- python-dev
- python-doc
- python-pip
- virtualenv
- virtualenvwrapper
- python-psycopg2
- postgresql-9.4
- postgresql-server-dev-9.4
- postgresql-contrib
- postgresql-doc-9.4
- postgresql-client
- postgresql-contrib-9.4
- postgresql-9.4-postgis-2.1
- postgis-doc
- postgis
- nginx
- supervisor
- redis-server
In general, Ansible actually does exactly that. It would output every item separately. Which under the hood means: It builds a python package, uploads it to the host(s) and executes it - for every item.
The apt and yum modules have been optimized for loops. Instead of looping over every item, Ansible builds a package that installs all loop items in one go.
Your command translates to something like this:
apt-get -y install git vim bash-completion bash-doc wput ...
So in this case, no, there is no way to output the separate steps to see where Ansible is. Because there are no separate steps.
The docs for the apt module is missing the note which is available in the yum module page:
When used with a loop of package names in a playbook, ansible optimizes the call to the yum module. Instead of calling the module with a single package each time through the loop, ansible calls the module once with all of the package names from the loop.
When you work with remote machines, this is actually a preferable behavior. This speeds up the play by a lot. If you run your playbook locally, of course there is not much benefit.
A simple workaround would be to simply not use the apt module but run a shell command.
- name: install global packages
shell: apt-get -y install {{ item }}
become: True
Find your ansible install directory using:
> python -c 'import ansible; print ansible.__file__'
/usr/local/lib/python2.7/dist-packages/ansible/__init__.pyc
Backup the <ansible_install>/runner/__init__.py file
/usr/local/lib/python2.7/dist-packages/ansible/runner/__init__.py
Edit the file, search for 'apt' and remove 'apt' from the list.
if len(items) and utils.is_list_of_strings(items) and self.module_name in [ 'apt', 'yum', 'pkgng' ]:
to
if len(items) and utils.is_list_of_strings(items) and self.module_name in [ 'yum', 'pkgng' ]:
Thats it!
When I want a bit more feedback on the playbook run I'll group packages together by their purpose. The cache_valid_time allows you to do this without the normal penalty of updating the repo cache each time. I find this improves readability and documentation as well.
- name: install global packages
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600
become: True
with_items:
- git
- vim
- bash-completion
- bash-doc
- wput
- tree
- colordiff
- libjpeg62-turbo-dev
- libopenjpeg-dev
- zlib1g-dev
- libwebp-dev
- libffi-dev
- libncurses5-dev
- name: install python and friends
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600
become: True
with_items:
- python-setuptools
- python-dev
- python-doc
- python-pip
- virtualenv
- virtualenvwrapper
- python-psycopg2
- name: install postgresql
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600
become: True
with_items:
- postgresql-9.4
- postgresql-server-dev-9.4
- postgresql-contrib
- postgresql-doc-9.4
- postgresql-client
- postgresql-contrib-9.4
- postgresql-9.4-postgis-2.1
- name: install postgis
apt: pkg={{ item }} update_cache=yes cache_valid_time=3600
become: True
with_items:
- postgis-doc
- postgis
- name: install nginx
apt: pkg=nginx update_cache=yes cache_valid_time=3600
become: True
- name: install supervisor
apt: pkg=supervisor update_cache=yes cache_valid_time=3600
become: True
- name: install redis
apt: pkg=redis-server update_cache=yes cache_valid_time=3600
become: True