Ansible - accessing local environment variables - ansible

I wonder if there is a way for Ansible to access local environment variables.
The documentation references accessing variable on the target machine:
{{ lookup('env', 'SOMEVAR') }}
Is there a way to access environment variables on the source machine?

I have a Linux vm running on osx, and for me:
lookup('env', 'HOME') returns "/Users/Gonzalo" (the HOME variable from osx), while ansible_env.HOME returns "/root" (the HOME variable from the vm).
Worth to mention, that ansible_env.VAR fails if the variable does not exists, while lookup('env', 'VAR') does not fail.

Use ansible lookup:
- set_fact: env_var="{{ lookup('env','ENV_VAR') }}"

Those variables are in the management machine I suppose source machine in your case.
Check this: https://docs.ansible.com/ansible/devel/collections/ansible/builtin/env_lookup.html
Basically, if you just need to access existing variables, use the ‘env’ lookup plugin. For example, to access the value of the HOME environment variable on management machine:`
Now, if you need to access it in the remote machine you can just run your ansible script locally in the remote machine.
Or you could just the ansible facts variables. If it's not in the ansible facts you can just run a shell command to get it.

Use delegate_to to run it on any machine you want:
- name: get running ansible user
ansible.builtin.set_fact:
local_ansible_user: "{{ lookup('env', 'USER') }}"
delegate_to: localhost

Related

ansible the way to use consul_kv change between two versions

I need some help on using consul_kv module with ansible version since 2.8.x , maybe i missed something, but i took a look to the code of the module and i don't realy see changes between 2.7.x and 2.8.x that can explay the problem i got.
With ansible 2.7.x , when i try to get value from consul, i get consul host, port, path from my env vars and i execute my code like this:
# group_var/all
consul_path: "{{ lookup('env','ANSIBLE_CONSUL_PATH') }}"
consul_host: "{{ lookup('env','ANSIBLE_CONSUL_HOST') }}"
consul_port: "{{ lookup('env', 'ANSIBLE_CONSUL_PORT') }}"
- hosts: localhost
tasks:
- name: test ansible 2.8.5 with consul
debug:
msg: "{{ lookup('consul_kv', consul_path+'path/to/value' }}"
it works on 2.7.0 and i got my value, but doesn't work on 2.8.x , from those newer versions i need to specify host and port on each line which using lookup
msg: "{{ lookup('consul_kv', 'path/to/value', host='myconsulhost.com', port='80') }}"
Is there a way to continue to use env vars in ansible 2.8.x with this module ?
The fine manual says that the lookup now uses the $ANSIBLE_CONSUL_URL environment variable to determine the protocol, hostname, and port -- or (as you observed) using the inline kwargs to the lookup function. Those group_vars you mentioned no longer seem to be consulted
You'll also want to be careful as your group_vars/all (at least in this question, unknown if you are really doing it) has a trailing space in consul_path : which creates a variable named consul_path<space>

how to set different python interpreters for local and remote hosts

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

Refer to ansible inventory ip address [duplicate]

I'm setting up an Ansible playbook to set up a couple servers. There are a couple of tasks that I only want to run if the current host is my local dev host, named "local" in my hosts file. How can I do this? I can't find it anywhere in the documentation.
I've tried this when statement, but it fails because ansible_hostname resolves to the host name generated when the machine is created, not the one you define in your hosts file.
- name: Install this only for local dev machine
pip:
name: pyramid
when: ansible_hostname == "local"
The necessary variable is inventory_hostname.
- name: Install this only for local dev machine
pip:
name: pyramid
when: inventory_hostname == "local"
It is somewhat hidden in the documentation at the bottom of this section.
You can limit the scope of a playbook by changing the hosts header in its plays without relying on your special host label ‘local’ in your inventory. Localhost does not need a special line in inventories.
- name: run on all except local
hosts: all:!local
This is an alternative:
- name: Install this only for local dev machine
pip: name=pyramid
delegate_to: localhost

Ansible Host: how to get the value for $HOME variable?

I know about ansible_env.HOME variable, which allow us to retrieve the path for the home user for the VMs we are connecting using Ansible.
However I need to get the home path for the ansible host. That means, the machine which is running the ansible playbook. Is there a short variable to retrieve that information? I was hoping to avoid running a local command and storing the result in a variable.
You should be able to access it with a lookup plugin like so:
- debug: msg="{{ lookup('env','HOME') }}"
Lookup plugins run on the control machine not the remote systems.

How to get the host name of the current machine as defined in the Ansible hosts file?

I'm setting up an Ansible playbook to set up a couple servers. There are a couple of tasks that I only want to run if the current host is my local dev host, named "local" in my hosts file. How can I do this? I can't find it anywhere in the documentation.
I've tried this when statement, but it fails because ansible_hostname resolves to the host name generated when the machine is created, not the one you define in your hosts file.
- name: Install this only for local dev machine
pip:
name: pyramid
when: ansible_hostname == "local"
The necessary variable is inventory_hostname.
- name: Install this only for local dev machine
pip:
name: pyramid
when: inventory_hostname == "local"
It is somewhat hidden in the documentation at the bottom of this section.
You can limit the scope of a playbook by changing the hosts header in its plays without relying on your special host label ‘local’ in your inventory. Localhost does not need a special line in inventories.
- name: run on all except local
hosts: all:!local
This is an alternative:
- name: Install this only for local dev machine
pip: name=pyramid
delegate_to: localhost

Resources