I've been looking into attempting to get ansible to use python3 on remote targets, in order to run playbooks against them, however, simply running a playbook against a target with python3 installed fails with the error message:
"/bin/sh: 1: /usr/bin/python: not found\r\n"
Looking for answers to this online only seem to discuss configuring ansible on the host to use python3 rather than the remote. Is it possible to configure the remote to use python3 rather than 2?
You can set the ansible_python_interpreter variable to tell Ansible which version of Python to use. You can set this globally, as C. Dodds has suggested in their answer, but it generally makes more sense to set this as a per-host inventory variable. E.g., using a YAML inventory:
all:
hosts:
myhost:
ansible_python_interpreter: /usr/bin/python3
Or using an ini-style inventory:
myhost ansible_python_interpreter=/usr/bin/python3
And of course you can set this per-hostgroup if you have several hosts that require the same configuration.
This is discussed in the Ansible documentation.
Adding the argument "-e 'ansible_python_interpreter=/usr/bin/python3'" was the solution to this:
ansible-playbook sample-playbook.yml -e 'ansible_python_interpreter=/usr/bin/python3'
Related
Use-Case:
Playbook 1
when we first connect to a remote host/s, the remote host will already have some python version installed - the auto-discovery feature will find it
now we install ansible-docker on the remote host
from this time on: the ansible-docker docs suggest to use ansible_python_interpreter=/usr/bin/env python-docker
Playbook 2
We connect to the same host/s again, but now we must use the /usr/bin/env python-docker python interpreter
What is the best way to do this?
Currently we set ansible_python_interpreter on the playbook level of Playbook 2:
---
- name: DaqMon app
vars:
- ansible_python_interpreter: "{{ '/usr/bin/env python-docker' }}"
This works, but this will also change the python interpreter of the local actions. And thus the local actions will fail, because (python-docker does not exist locally).
the current workaround is to explicitly specify the ansible_python_interpreter on every local-action which is tedious and error-prone
Questions:
the ideal solution is, if we could add '/usr/bin/env python-docker' as fallback to interpreter-python-fallback - but I think this is not possible
is there a way to set the python interpreter only for the remote hosts - and keep the default for the localhost?
or is it possible to explicitly override the python interpreter for the local host?
You should set the ansible_python_interpreter on the host level.
So yes, it's possible to explicitly set the interpreter for localhost in your inventory.
localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python
And I assume that you could also use set_fact on hostvars[<host>].ansible_python_interpreter on your localhost or docker host.
There is a brillant article about set_fact on hostvars ! ;-P
Thanks to the other useful answers I found an easy solution:
on the playbook level we set the python interpreter to /usr/bin/env python-docker
then we use a set_fact task to override the interpreter for localhost only
we must also delegate the facts
we can use the magic ansible_playbook_python variable, which refers to the python interpreter that was used on the (local) Ansible host to start the playbook: see Ansible docs
Here are the important parts at the start of Playbook 2:
---
- name: Playbook 2
vars:
- ansible_python_interpreter: "{{ '/usr/bin/env python-docker' }}"
...
tasks:
- set_fact:
ansible_python_interpreter: '{{ ansible_playbook_python }}'
delegate_to: localhost
delegate_facts: true
Try to use set_fact for ansible_python_interpreter at host level in the first playbook.
Globally, use the interpreter_python key in the [defaults] section of the ansible.cfg file.
interpreter_python = auto_silent
I need to know if it's possible to call / execute ansible playbooks from the target machine. I think i saw a vendor do it or at least something similar. they downloaded a script and it did ran the playbook.
if this is possible how would it be done?
my goal is to run ansible as a centralized server in aws to perform tasks in mulitple environments. most are behind firewalls, any reccomendations/thoughts would be appreciated.
Sure. If your host will install Ansible on target and feed it with all the playbooks the you can run it as any other executable. Should you do that is another story but technically there's no obstacle.
You can run ansible and ansible playbook as you would any other binary on the target's $PATH, so any tool that facilitates running remote commands would work.
Because you are in AWS, one way might be to use AWS System's Manager.
If you wanted to use Ansible itself to do this you could use the shell or command modules:
- hosts: target
become: false
gather_facts: false
tasks:
- name: ansible in ansible
command: ansible --version
- name: ansible-playbook in ansible
command: ansible-playbook --version
Though, as with any situation where you reach for the shell or command modules, you have to be vigilant to maintain playbook idempotency yourself.
If you're requirement is just the ability to execute Ansible commands remotely, you might look into AWX which is the upstream project for Red Hat's Ansible Tower. It wraps ansible in a nice user interface to allow you to trigger Ansible playbooks remotely and with nice-to-haves like RBAC.
If you're ok with executing tasks remotely over ssh take a look at Sparrowdo it has out of the box facilities to run bash scripts ( read ansible executable ) remotely from one master host to another. Or you can even use it to install all the ansible dependencies or whatever you need to do for your scope.
When I try running this Ansible command - ansible testserver -m ping it works just fine, but when I try this command - ansible webservers -m ping I get the following error - ERROR! Specified hosts options do not match any hosts.
My host file looks like this -
[webservers]
testserver ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
What could be the problem? Why can ansible recognize the host in question and not the host group?
I've tried changing the file to make sure ansible is reading from this file specifically, and made sure this is the case, so this is not a problem of reading configurations from another file I am not aware of.
I've also tried using the solutions specified in Why Ansible skips hosts group and does nothing but it seems like a different problem with a different solution.
EDIT - added my anisble.cfg file, to point out I've already made all the vagrant specific configurations.
[defaults]
inventory = ./ansible_hosts
roles_path = ./ansible_roles
remote_user = vagrant
private_key_file = .vagrant/machine/default/virtualbox/private_key
host_key_checking = False
I think you are working with the vagrant and you need to ping like this:
ansible -i your-inventory-file webservers -m ping -u vagrant -k
Why your ping fail prevously:
ansible try to connect to vagrant machine using local login user and it doesn't exist on the vagrant machine
it also need password for the vagrant user which is also vagrant.
Hope that help you.
production (inventory file):
#main ansible_host=54.293.2785.210 ansible_port=22 ansible_ssh_user=ubuntu
54.293.2785.210 ansible_ssh_user=ubuntu
Running an ad-hoc command: ansible all -i production -a "hostname" Works!
But when I uncomment the first line and comment the second:
ansible main -i production -a "hostname" -vvvv
Gives the following error:
main | FAILED => SSH Error: ssh: Could not resolve hostname main: Name or service not known
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
Why is this not working?
ansible_host is the new (>=2.0) syntax.
Before that is was simply ansible_ssh_host but this has been deprecated in the more recent versions of Ansible (>=2.0):
Ansible 2.0 has deprecated the “ssh” from ansible_ssh_user, ansible_ssh_host, and ansible_ssh_port to become ansible_user, ansible_host, and ansible_port. If you are using a version of Ansible prior to 2.0, you should continue using the older style variables (ansible_ssh_*). These shorter variables are ignored, without warning, in older versions of Ansible.
If you're using an earlier version of Ansible then ansible_ssh_host should work for you.
I'm new to configuration management tool.
I want to use Ansible.
I'd like to set proxy to several GNU/Linux Debian (in fact several Raspbian).
I'd like to append
export http_proxy=http://cache.domain.com:3128
to /home/pi/.bashrc
I also want to append
Acquire::http::Proxy "http://cache.domain.com:3128";
to /etc/apt.conf
I want to set DNS to IP X1.X2.X3.X4 creating a
/etc/resol.conf file with
nameserver X1.X2.X3.X4
What playbook file should I write ? How should I apply this playbook to my servers ?
Start by learning a bit about Ansible basics and familiarize yourself with playbooks. Basically you ensure you can SSH in to your Raspian machines (using keys) and that the user Ansible invokes on these machines can run sudo. (That's the hard bit.)
The easy bit is creating the playbook for the tasks at hand, and there are plenty of pointers to example playbooks in the documentation.
If you really want to add a line to a file or two, use the lineinfile module, although I strongly recommend you create templates for the files you want to push to your machines and use those with the template module. (lineinfile can get quite messy.)
I second jpmens. This is a very basic problem in Ansible, and a very good way to get started using the docs, tutorials and example playbooks.
However, if you're stuck or in a hurry, you can solve this like this (everything takes place on the "ansible master") :
Create a roles structure like this :
cd your_playbooks_directory
mkdir -p roles/pi/{templates,tasks,vars}
Now create roles/pi/tasks/main.yml :
- name: Adds resolv.conf
template: src=resolv.conf.j2 dest=/etc/resolv.conf mode=0644
- name: Adds proxy env setting to pi user
lineinfile: dest=~pi/.bashrc regexp="^export http_proxy" insertafter=EOF line="export http_proxy={{ http_proxy }}"
Then roles/pi/templates/resolv.conf.j2 :
nameserver {{ dns_server }}
then roles/pi/vars/main.yml :
dns_server: 8.8.8.8
http_proxy: http://cache.domain.com:3128
Now make a top-level playbook to apply roles, at your playbook root, and call it site.yml :
- hosts : raspberries
roles:
- { role: pi }
You can apply your playbook using :
ansible-playbook site.yml
assuming your machines are in the raspberries group.
Good luck.