I'm just getting started with ansible, and I'm trying to get it to work with the linode module from OSX Yosemite. I'm using brew-installed Python, and pip-installed ansible. So I have done the following:
$ brew install python
$ PYCURL_SSL_LIBRARY=nss pip install pycurl
$ CFLAGS=-Qunused-arguments CPPFLAGS=-Qunused-arguments pip install ansible
To test:
$ which python
/usr/local/bin/python
$ python --version
Python 2.7.9
$ which ansible
/usr/local/bin/ansible
$ ansible --version
ansible 1.8.2
configured module search path = None
When I run my playbook I get:
failed=True msg='pycurl required for this module'
So somehow ansible is not seeing the pycurl library.
Here is the playbook:
---
- hosts: 127.0.0.1
connection: local
gather_facts: no
tasks:
- name: "provision a server"
local_action:
module: linode
api_key: FOO
name: linode-test1
plan: 1
datacenter: 1
distribution: 99
password: 'superSecureRootPassword'
ssh_pub_key: ssh-rsa FOO
swap: 768
wait: yes
wait_timeout: 600
state: present
It's happening on ubuntu as well, finally figured out the solution. You need to explicity pass path to python executable
Change Ansible hosts file from
[local]
localhost
to
[local]
localhost ansible_python_interpreter=/usr/local/bin/python
or to your virtual environment python path.
I was able to fix this on OS X El Capitan 10.11.6 by editing hosts:
[local]
localhost ansible_python_interpreter=/usr/local/bin/python
You may then need additional Python dependencies:
pip install pycurl
pip install linode-python
Related
With this playbook
---
- name: ReadJsonfile
hosts: localhost
tasks:
- name: Display the JSON file content
shell: "cat config.json"
register: result
- name: save the Json data to a Variable as a Fact
set_fact:
jsondata: "{{ result.stdout | from_json }}"
- name: setDomainName
set_fact:
domain_name: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: '[].domain[].name'
There are two users on my Linux server: user1 and user2
python3.8, pip, ansible-core, ansible-base & jmespath were installed.
I login with user1 and the above playbook runs fine
ansible-playbook test.yml
However, when I login with user2 and run the same I get the below error
TASK [setDomainName]
****************************************************************************************** Monday 21 March 2022 01:16:40 -0500 (0:00:00.140) 0:00:04.221
********** fatal: [localhost]: FAILED! => {"msg": "template error while templating string: No filter named 'json_query'.. String: {{
jsondata | json_query(jmesquery) }}"}
Note: When run with user1 the playbook works fine. The error is when run with user2 only.
Is there something wrong with the way I setup things with user2?
Below are the details for user2
[user2#myhost Migrator]$ ansible --version
ansible [core 2.12.3]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/user2/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/user2/.local/lib/python3.8/site-packages/ansible
ansible collection location = /home/user2/.ansible/collections:/usr/share/ansible/collections
executable location = /bin/ansible
python version = 3.8.12 (default, Mar 21 2022, 00:59:19) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
jinja version = 3.0.3
libyaml = True
[user2#myhost Migrator]$ ansible-playbook --version
ansible-playbook [core 2.12.3]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/user2/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/user2/.local/lib/python3.8/site-packages/ansible
ansible collection location = /home/user2/.ansible/collections:/usr/share/ansible/collections
executable location = /bin/ansible-playbook
python version = 3.8.12 (default, Mar 21 2022, 00:59:19) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
jinja version = 3.0.3
libyaml = True
[user2#myhost Migrator]$ pip --version
bash: pip: command not found
[user2#myhost Migrator]$ pip3 --version
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
pip 21.3.1 from /home/user2/.local/lib/python3.6/site-packages/pip (python 3.6)
[user2#myhost Migrator]$ pip3 install jmespath
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: jmespath in /usr/local/lib/python3.6/site-packages (0.10.0)
[user2#myhost Migrator]$
[user2#myhost Migrator]$ python3.8 --version
Python 3.8.12
JmesPath was installed as below:
$ sudo pip3.8 install jmespath
Collecting jmespath
Downloading jmespath-1.0.0-py3-none-any.whl (23 kB)
Installing collected packages: jmespath
Successfully installed jmespath-1.0.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
Can you please suggest a solution to the issue?
Because you did install Ansible with the pip packages ansible-core & ansible-base, you don't have the collection community.general, which this filter is part of.
You have multiple options:
Install the missing collection, when logged in with the problematic user:
ansible-galaxy collection install community.general
Install the full Ansible package:
pip uninstall ansible-core ansible-base
pip install ansible
Reinstall the collection in the shared folder, with the option -p
ansible-galaxy collection install community.general \
-p /usr/share/ansible/collections
I'm learning Vagrant and Ansible, I'm trying to setup a local development environment for a basic flask app in ubuntu20.04 with Nginx.
my vagrantfile looks like this:
Vagrant.configure("2") do |config|
config.vm.define :ubuntuserver do | ubuntuserver |
ubuntuserver.vm.box = "bento/ubuntu-20.04"
ubuntuserver.vm.hostname = "ubuntuserver"
ubuntuserver.vm.provision :ansible do | ansible |
ansible.playbook = "development.yml"
end
ubuntuserver.vm.network "private_network", ip:"10.11.1.105"
ubuntuserver.vm.network "forwarded_port", guest: 80, host: 8080
ubuntuserver.vm.network "public_network", bridge: "en1: Wi-Fi (AirPort)"
ubuntuserver.vm.provider :virtualbox do |vb|
vb.memory = "1024"
end
ubuntuserver.vm.synced_folder "./shared", "/var/www"
end
end
my ansible-playbook like so:
-
name: local env
hosts: ubuntuserver
tasks:
- name: update and upgrade apt packages
become: yes
apt:
upgrade: yes
update_cache: yes
- name: install software properties common
apt:
name: software-properties-common
state: present
- name: install nginx
become: yes
apt:
name: nginx
state: present
update_cache: yes
- name: ufw allow http
become: yes
community.general.ufw:
rule: allow
name: "Nginx HTTP"
- name: installing packages for python env
become: yes
apt:
name:
- python3-pip
- python3-dev
- build-essential
- libssl-dev
- libffi-dev
- python3-setuptools
- python3-venv
update_cache: yes
- name: Create app directory if it does not exist
ansible.builtin.file:
path: /var/www/app
state: directory
mode: '0774'
- name: Install virtualenv via pip
become: yes
pip:
name: virtualenv
executable: pip3
- name: Set python virual env
command:
cmd: virtualenv /var/www/app/ -p python3
creates: "/var/www/app/"
- name: Install requirements
pip:
requirements: /var/www/requirements.txt
virtualenv: /var/www/app/appenv
virtualenv_python: python3
My playbook fails at the next task with error:
- name: Activate /var/www/app/appenv
become: yes
command: source /var/www/app/appenv/bin/activate
fatal: [ubuntuserver]: FAILED! => {"changed": false, "cmd": "source /var/www/app/appenv/bin/activate", "msg": "[Errno 2] No such file or directory: b'source'", "rc": 2}
Rest of the playbook
- name: ufw allow 5000
become: yes
community.general.ufw:
rule: allow
to_port: 5000
- name: Run app
command: python3 /var/www/app/appenv/app.py
From what I understand from this thread, The "source" command must be used from inside the vagrant machine. (I tried solutions from the thread but couldn't get it to work)
If I ssh into the vagrant machine and execute the three last commands of my playbook manually:
source /var/www/app/appenv/bin/activate
sudo ufw allow 5000
python3 /var/www/app/appenv/app.py
my basic flask app is running on port 5000 at the IP set in the vagrantfile 10.11.1.105
My questions are:
How can I get the playbook to work and not have to ssh into the machine to accomplish the same?
Is my approach even correct, knowing that my end goal is to replicate in the vagrant machine a similar environment to what would be the production environment and develop the flask app from my local machine in the synced folder?
to give a maximum of information, if one wants to reproduce this.
I also have a shared/app/appenv/app.py file containing the basic flask app
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "<h1 style='color:blue'>Hello There!</h1>"
if __name__ == "__main__":
app.run(host='0.0.0.0')
and shared/requirements.txt file
wheel
uwsgi
flask
This question was coming from a misconception about python venv.
I thought that in order to install packages inside the virtual env it had to be activated.
for example:
source env/bin/activate
pip install package_name
I understood later that I can install packages in the venv without activating it by doing:
env/bin/pip install package_name
So the solution with ansible is not to activate the venv to install packages but instead
- name: "Install python packages with the local instance of pip"
shell: "{{virtualenv_path}}/bin/pip3 install package_name"
become: no
or better even with the pip module and the packages in a requirements.txt file:
- name: Install project requirements in venv
pip:
requirements: '{{project_path}}/requirements.txt'
virtualenv: '{{virtualenv_path}}'
virtualenv_python: python3
I wrote this article for a Linux computer with Python 3.x. In this scenario, this is your Ansible development machine. First, verify the installed Python version and path:
# check Python version
$ python3 -V
Python 3.6.8
$ which python3
/usr/bin/python3
I recommend setting up a directory for the virtual environment:
$ mkdir python-venv
$ cd !$
Create a new virtual environment
$ python3 -m venv ansible2.9
$ ls
ansible2.9
activate python venv
$ source ansible2.9/bin/activate
(ansible2.9)$ python3 -V
Python 3.6.8
upgrade pip
(ansible2.9)$ python3 -m pip install --upgrade pip
Install Ansible in a virtual environment
(ansible2.9)$ python3 -m pip install ansible==2.9
(ansible2.9)$ which ansible
~/python-venv/ansible2.9/bin/ansible
Verify your new installation:
(ansible2.9)$ ansible --version
ansible 2.9.0
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/devops/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/devops/python-venv/ansible2.9/lib64/python3.6/site-packages/ansible
executable location = /home/devops/python-venv/ansible2.9/bin/ansible
python version = 3.6.8 (default, Jan 09 2021, 10:57:11) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
Install Ansible roles or collections
(ansible2.9)$ ansible-galaxy collection install \
kubernetes.core:==1.2.1 -p collections
Deactivate a Python virtual environment
(ansible2.9)$ deactivate
Create another Python virtual environment for Ansible 3.0
$ python3 -m venv ansible3.0
$ ls -1
ansible2.9
ansible3.0
$ source ansible3.0/bin/activate
(ansible3.0)$ which python
~/python-venv/ansible3.0/bin/python
(ansible3.0)$ python3 -m pip install --upgrade pip
(ansible3.0)$ python3 -m pip install ansible==3.0
I am trying to run an Ansible script that invokes the 'expect' module (see end of the message).
When I run it, I get error:
The pexpect python module is required
Yet, the pip task for installing pexpect runs without error.
What am I doing wrong?
Thx.
Alain Désilets
=== Playbook content ===
---
- name: Run Anaconda shell
hosts: all
vars:
conda_home: "~/anaconda2-NEW"
conda_inst_sh_path: /path/to/Anaconda2-2018.12-MacOSX-x86_64.sh
tasks:
- name: install pexpect
pip:
name: pexpect
become: yes
become_user: root
- name: Run anaconda installation script
expect:
command: "sh {{conda_inst_sh_path}}"
responses:
(?i)password: "MySekretPa$$word"
become: yes
become_user: root
As the Ansible documentation of the expect module states:
The below requirements are needed on the host that executes this module.
python >= 2.6
pexpect >= 3.3
You need to install pexpect in a minimum version of 3.3 besides python >= 2.6 on the target system, that means that you have to install pexpect and python on every system, that is defined under hosts: all.
How to install ansible on a RHEL 6.8 machine which doesn't have access to Internet?
I'd propose to use raw: module. Copy rpm (scp) to server, and run rpm -i.
Raw module does not use a usual ansible workflow and do things 'directly'. Here my code to install python if it's not present on server, I think you can adopt it for rpm for ansible too.
- hosts: all
gather_facts: no
tasks:
- name: Remember sever key and install python
raw: test -x /usr/bin/python || sudo apt-get update && sudo apt-get -y install python
changed_when: True
I'm very new to Vagrant and Ansible, somehow I managed to setup Vagrant and have a box running but when i try to provision it with Ansible then I get error.ImportError: No module named yum
My playbook looks like below :-
---
- hosts: default
connection: local
sudo: true
tasks:
- name: install apache
yum: name=httpd state=latest
I'm using Ubuntu as my host machine and have Vagrant 1.8.5 and latest version of Ansible on it.Can somebody please suggest where I'm mistaking. Thanks in advance.
With
connection: local
you are running the playbook on your host which is Ubuntu.
And that's why it doesn't find yum.