How do I share variables/facts between Molecule Playbooks? - ansible

I'm trying to share a variable between my converge step and my cleanup step of my Molecule. Since both playbooks are being run on the same host, I figure I can use facts to cache the variable as a fact.
In converge.yml:
- name: Cache some variable
set_fact:
cacheable: yes
my_fact: "howdy, world"
In cleanup.yml:
- debug:
msg: "{{ my_fact }}"
and in my top-level ansible.cfg I specify:
[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/facts_cache
fact_caching_timeout = 7200
I first run molecule converge and then I run molecule cleanup I'm getting the error: (reformatted)
TASK [debug] *******************************************************************
fatal: [cluster-toolchain]: FAILED! => {"msg": "The task includes an option
with an undefined variable. The error was: 'my_fact' is undefined
The error appears to be in '{REDACTED}/cleanup.yml': line 5, column 7, but may be
elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:\n\n tasks:\n - debug:\n ^ here\n"}
I've got some guesses, like maybe Molecule doesn't see my top level ansible.cfg or something.
Anyway, I was hoping for some help here. Maybe there is a better way to share the variable in Molecule world.

Molecule is a tool to test Ansible roles. It is not targeted to execute Ansible playbooks. Usual command is ansible-playbook.
Molecule cannot not read your ansible.cfg with fact caching settings. If you want to make your commands working, add settings in molecule.yml:
provisioner:
name: ansible
config_options:
defaults:
gathering: smart
fact_caching: jsonfile
fact_caching_connection: /tmp/facts_cache
fact_caching_timeout: 7200
Then molecule converge followed by molecule cleanup gives:
PLAY [Cleanup] ************************************************************************************************************************
TASK [debug] **************************************************************************************************************************
ok: [vagrant-instance] => {
"msg": "howdy, world"
}

Related

Ansible: 'debug' task get's me error message 'ansible_lvm' is undefined

Im trying parted, lvg, lvol and filesystem modules on Ansible.
I have an error with a debug task:
- name: lvm debug
debug:
msg: "{{ ansible_lvm }}"
The error is:
fatal: [nfs_server]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible_lvm' is undefined\n\nThe error appears to be in ...
I thought ansible_lvm was gathered during facts gathering since I don't have gathering disabled.
My custom ansible.cfg (put in the playbook folder) is as follow:
[defaults]
host_key_checking= False
callbacks_enabled = profile_tasks
pipelining= True
Thank you
According ansible/lib/ansible/module_utils/facts/hardware/linux.py and Ansible Issue #17393
"if running as root and lvm utils are available"
you need to have high rights like root or become: true, as well LVM utils installed, otherwise
"gather_facts silently skips lvm facts if lvm pkg not installed"
Similar Q&A
Why is my logical volume not showing in the ansible_lvm variable?

How to use the listen_ports_facts module, ansible

Using ansible I want to check in which port tomcat is running, of course I think there are different ways to do it, but I found this ansible module
https://docs.ansible.com/ansible/latest/modules/listen_ports_facts_module.html
And I would like to use it, but according to the examples, I do not know how to use it.
I mean if I setup
gather_facts: true
And run the task
- name: List TCP ports
debug:
msg: "{{ ansible_facts.tcp_listen }}"
I got the error
TASK [discover-servers : List TCP ports] *******************************************************************************************************************************
task path: /home/A78252689/sap_bo/roles/discover-servers/tasks/tomcat_servers.yml:4
fatal: [2a00:da9:2:21ca:111:0:426:2]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'tcp_listen'\n\nThe error appears to be in '/home/A78252689/sap_bo/roles/discover-servers/tasks/tomcat_servers.yml': line 4, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: List TCP ports\n ^ here\n"}
If I set up the task exactly how it is in the example, I got an error in the first task Gather facts on listening ports
TASK [discover-servers : include_tasks] ********************************************************************************************************************************
task path: /home/A78252689/sap_bo/roles/discover-servers/tasks/main.yml:4
fatal: [2a00:da9:2:21ca:111:0:426:2]: FAILED! => {"reason": "no action detected in task. This often indicates a misspelled module name, or incorrect module path.\n\nThe error appears to be in '/home/A78252689/sap_bo/roles/discover-servers/tasks/tomcat_servers.yml': line 4, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Gather facts on listening ports\n ^ here\n"}
So, do you know how to use the module listen_ports_facts?
Thanks in advance for your kind support
The gather_facts stage of your playbook runs uses the setup module. It does not run listen_ports_facts, so if you don't run the module explicitly you won't have those facts available.
From the docs, the listen_ports_module creates the following facts:
tcp_listen
udp_listen
Using Ansible 2.9.2, the following works just fine:
---
- gather_facts: false
hosts: localhost
tasks:
- listen_ports_facts:
- debug:
msg: "{{ tcp_listen }}"
- debug:
msg: "{{ udp_listen }}"
If you're trying to run the listen_ports_facts module and you're getting the error "no action detected in task", it may be that you're running an older version of Ansible that doesn't have the listen_ports_facts module. It first showed up in version 2.9.

Ansible fileglob: unable to find ... in expected paths

I am trying to use ansible to delete all of the files within a directory while keeping the directory. To that end, I'm using the with_fileglob key on a task to get all of the files out of that directory as item variables. I have created a minimum example that shows my issue here:
Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
config.vm.provision :ansible do |ansible|
ansible.limit = "all"
ansible.playbook = "local.yml"
end
end
local.yml:
- name: Test
hosts: all
become: true
tasks:
- name: Test debug
debug:
msg: "{{ item }}"
with_fileglob:
- "/vagrant/*"
I expect to get a debug message for each file in the /vagrant directory - since this is the directory synced with the VM via Vagrant, I should get a message for the Vagrantfile, and for local.yml. Instead, I get the following confusing warning:
PLAY [Test] ********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [default]
TASK [Test debug] **************************************************************
[WARNING]: Unable to find '/vagrant' in expected paths (use -vvvvv to see
paths)
PLAY RECAP *********************************************************************
default : ok=1 changed=0 unreachable=0 failed=0
What expected paths are being referred to here? I have tried this with multiple fileglobs, and they all fail in this way, what am I missing?
Ansible lookup plugins are executed on local machine (where you launch Ansible), not remote one(s).
https://docs.ansible.com/ansible/latest/plugins/lookup.html
Lookup plugins allow Ansible to access data from outside sources. This
can include reading the filesystem in addition to contacting external
datastores and services. Like all templating, these plugins are
evaluated on the Ansible control machine, not on the target/remote.
Since fileglob only works on the local machine, I tested find als alternative and want to provide an example here. If we want to locate all *.jar files, this could be done like this:
- name: Find jar files
find:
paths: "{{ install_jar_path }}"
patterns: "*.jar"
register: jar_src_file
changed_when: False
jar_src_file is now an array. Every item has a property path.
- set_fact:
first_jar: "{{ jar_src_file.files[0].path }}"
This will give you the path of the first jar file for testing purpose. You could loop over the items using with_items for example if needed.

How to use passwords in encrypted vars-file (vault) in Ansible inventory?

I'm new to Ansible and struggle with Ansible vaults in combination with inventory files.
What I want to achieve is a playbook that updates three machines. Two of these machines require a password (for sudo) so I can become root.
So here's my playbook...
---
- name: update all hosts, make sure default software is installed
hosts:
- vhosts
- physical
vars_files:
- 'vars/main.yml'
tasks:
- name: Update apt cache
apt: update_cache=yes
- name: Upgrade packages
apt: upgrade=dist
... and this is my inventory (filename inventory) with passwords still in plain text:
[vhosts]
10.0.0.1 ansible_user=root
[physical]
10.0.0.200 ansible_user=xxx ansible_become=yes ansible_become_method=sudo ansible_become_pass=secretpassword1
10.0.0.201 ansible_user=yyy ansible_become=yes ansible_become_method=sudo ansible_become_pass=secretpassword2
This is working fine.
Of cause I do not want secretpassword1 or secretpassword2 in the inventory. So I created a vault (stored in file vars/main.yml that looks like that:
---
- vars:
pass1:secretpassword1
pass2:secretpassword2
And I changed the inventory file to this:
[vhosts]
10.0.0.1 ansible_user=root
[physical]
10.0.0.200 ansible_user=xxx ansible_become=yes ansible_become_method=sudo ansible_become_pass="{{ pass1 }}"
10.0.0.201 ansible_user=yyy ansible_become=yes ansible_become_method=sudo ansible_become_pass="{{ pass2 }}"
Now when I try to execute the goodness with ansible-playbook update.yml -i inventory --ask-vault-pass I receive following errors:
fatal: [10.0.0.200]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'pass1' is undefined\nexception type: <class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: 'pass1' is undefined"}
fatal: [10.0.0.201]: FAILED! => {"msg": "The field 'become_pass' has an invalid value, which includes an undefined variable. The error was: 'pass2' is undefined\nexception type: <class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: 'pass2' is undefined"}
It seems like I was unable to define my variables correctly. But I have absolutely no clue how to do so. If anyone could give me a hand I'd be super happy. Thanks.
Make your vault file look like this:
---
pass1: secretpassword1
pass2: secretpassword2
Your error:
You define variables in incorrect format inside YAML file.

Conditional role inclusion fails in Ansible

I want to run an Ansible role conditionally, i.e. only when some binary does NOT exist (which for me implies absence of some particular app installation).
Something like the pattern used here.
Using the following code in my playbook:
- hosts: my_host
tasks:
- name: check app existence
command: /opt/my_app/somebinary
register: myapp_exists
ignore_errors: yes
roles:
- { role: myconditional_role, when: myapp_exists|failed }
- another_role_to_be_included_either_way
Here is the output:
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [my_host ]
TASK [ myconditional_role : create temporary installation directory] ***********************
fatal: [my_host]: FAILED! => {"failed": true, "msg": "ERROR! The conditional check 'myapp_exists|failed' failed. The error was: ERROR! |failed expects a dictionary"}
Why is the conditional check failing?
Using ansible 2.0.0.2 on Ubuntu 16.04.01
btw: "create temporary installation directory" is the name of the first main task of the conditionally included role.
Tasks are executed after roles, so myapp_exists is undefined.
Use pre_tasks instead.
Also keep in mind that when is not actually a conditional role, it just attaches this when statement to every task in your role.

Resources