Ansible script - error with pexpect module - ansible

I am writing ansible script to install universal forwarder but stuck using pexpect module.
Error I am getting:
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ModuleNotFoundError: No module named 'pexpect'
fatal: [Server-a]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (pexpect) on **** Python /usr/bin/python3. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"}
I tried many workarounds like passing python interpreter in the command line while running ansible script.
Tried with both python versions 2.7 and 3.
I also see that pexpect is installed: pexpect-2.3-py2.7.egg-info

Since the pexpect Python module is needed on the nodes in a version greater or equal to 3.3 and that there is a pip module to install python dependancies, what you could do is to write the pip task needed to upgrade your nodes dependancies to the right version on pexpect.
Something like:
- pip:
name: pexpect>=3.3
- name: This is just an expect demo
expect:
command: read -p 'What is the answer to life, the universe and everything?'
responses:
(?i)answer: 42
Those two would then yield:
TASK [pip] *******************************************************************
changed: [localhost]
TASK [This is just an expect demo] *******************************************
changed: [localhost]

Related

Install another version of existing package with a supplied deb file using ansible

I want to upgrade certain linux packages on my machines using ansible apt module and provided debian files, but not able to do so. To describe, I've used perl-base package as example below.
I am trying to install a specific version of perl-base(perl-base_5.26.1-6ubuntu0.5_amd64) on a linux system with already installed perl-base_5.26.1-6ubuntu0.3_amd64.
When I do it manually using apt it suggests removal of some conflicting packages, but proceeds without error, which is also the desired outcome.
root#logger:/home/ubuntu# apt install /home/deb_pkgs/perl-base_5.26.1-6ubuntu0.5_amd64.deb
Reading package lists... Done
Building dependency tree
Reading state information... Done
Note, selecting 'perl-base' instead of '/home/deb_pkgs/perl-base_5.26.1-6ubuntu0.5_amd64.deb'
Suggested packages:
perl
The following packages will be REMOVED:
lm-sensors perl
The following packages will be upgraded:
perl-base
1 upgraded, 0 newly installed, 2 to remove and 0 not upgraded.
Need to get 0 B/1,391 kB of archives.
After this operation, 962 kB disk space will be freed.
Do you want to continue? [Y/n]
But when I try to do the same using ansible, it fails citing the break in dependency of the perl packages.
TASK [deb-pkg-install : Install deb files] **********************************************************************************************************************************************************
failed: [ubuntu] (item=perl-base) => changed=false
ansible_loop_var: item
item: perl-base
msg: Breaks existing package 'perl' dependency perl-base (= 5.26.1-6ubuntu0.3)
My task currently looks like this,
- name: Install deb files
apt:
deb: "/home/deb_pkgs/{{ deb_files[item].file_name }}"
install_recommends: no
when: not ansible_check_mode
register: install_output
loop: "{{ required_debs }}"
I have solved it by adding another task which removes the packages suggested by apt, but I think there might be more elegant solution than this. I have gone through documentation of builtin.module.apt but couldn't find any suitable parameter to add.
Any input appreaciated! Thanks!

Fast idempotent Ansible apt deb url

It looks like like command apt install https://github.com/jgraph/drawio-desktop/releases/download/v12.9.3/draw.io-amd64-12.9.3.deb could take long time each time when is invoked even if the package is installed already. It is literally downloads the package each time.
And yes, with ansible is idempotent, with status changed: no.
- name: Install a drawio-desktop .deb package
apt:
deb: https://github.com/jgraph/drawio-desktop/releases/download/v12.9.3/draw.io-amd64-12.9.3.deb
when: ansible_facts['lsb']['id'] == "Ubuntu"
tags:
- debug
- not-macos
Is there any short way to skip download if package installed ?
Ideally will be to say in name that I want to install draw.io if not installed from deb: url else consider things installed.
- name: Install a drawio-desktop .deb package
apt:
name: draw.io
deb: https://github.com/jgraph/drawio-desktop/releases/download/v12.9.3/draw.io-amd64-12.9.3.deb
but is not working like that
TASK [desktop : Install a drawio-desktop .deb package] *********
fatal: [tuxedo]: FAILED! => {"changed": false, "msg": "parameters are mutually exclusive: deb|package|upgrade"}
Any suggestion on a lighter solution to speed up the task?
The behavior seems to be intended according the parameter deb
Ansible will attempt to download deb before installing.
and the current source of apt.py.
So you may have a look into the module package_facts
- name: Gather Package Facts
package_facts:
manager: apt # default ["auto"]
as well a Conditional Example of
when: "ansible_facts['lsb']['id'] == 'Ubuntu' and 'draw.io' not in ansible_facts.packages"
Credits to
How to get the installed apt packages with Ansible?
Further Q&A
Ansible: Do task if apt package is missing
An other approach might be to have the latest package always internally (cached) available and provide a .list file for the native package manager, pointing to the internal repository URL (file share).
By doing this, you could then just use
- name: Install a drawio-desktop .deb package
apt:
name: draw.io
state: latest
without further checks. This will address required updates too.

Ansible is not picking up installed hvac module after installing on mac OS

My ansible play uses hashivault_read. I installed this module on my mac. When I try to execute the playbook, this task errors out saying No module named hvac. When I see pip list I can find this module on my mac.
Did anyone face this issue before on mac? If someone has a resolution to this please comment.
Ansible Properties
ansible-playbook 2.8.0
config file = /Users/mdhoke/ansible.cfg
configured module search path = [u'/Users/mdhoke/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /Library/Python/2.7/site-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 2.7.10 (default, Feb 22 2019, 21:55:15) [GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.37.14)]
I assume ansible is trying to find hvac module under /Library/Python/2.7/site-packages/ansible which is not present but hashivault_read is present.
hvac module is present under /Library/Python/2.7/site-packages.
Error I am getting:
fatal: [vault]: FAILED! => {"changed": false, "module_stderr": "Shared connection to vault closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/mdhoke/.ansible/tmp/ansible-tmp-1567120470.9-210430890667193/AnsiballZ_hashivault_read.py\", line 114, in <module>\r\n _ansiballz_main()\r\n File \"/home/mdhoke/.ansible/tmp/ansible-tmp-1567120470.9-210430890667193/AnsiballZ_hashivault_read.py\", line 106, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/home/mdhoke/.ansible/tmp/ansible-tmp-1567120470.9-210430890667193/AnsiballZ_hashivault_read.py\", line 49, in invoke_module\r\n imp.load_module('__main__', mod, module, MOD_DESC)\r\n File \"/tmp/ansible_hashivault_read_payload_kE0iQk/__main__.py\", line 3, in <module>\r\n File \"/tmp/ansible_hashivault_read_payload_kE0iQk/ansible_hashivault_read_payload.zip/ansible/module_utils/hashivault.py\", line 4, in <module>\r\n
ImportError: No module named hvac\r\n",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
I managed to solve this issue for myself yesterday. I assume you are running ansible locally from your mac and connecting to the remote server (vault). If so, you will need to install hvac on the vault server too.
the following code snippet will suffice
- name: install hvac pip package
become: yes
become_method: sudo
pip:
name: hvac
state: present
obviously for the above play to work, you will need python-pip installed on the vault server too and in order to install that, you will need to enable epel-release. The below coe will take care of those dependencies.
- name: enable epel-relase and install pip
become: yes
become_method: sudo
yum:
name: "{{ item }}"
state: present
with_items:
- epel-release
- python-pip
Actually hashivault_read module is expected to be executed on a local machine. So delegating it to local machine solved my issue.

I have copied the ansible "copy" module to the project but the copied module does not work

I have developed the ansible modules.
I have copied the ansible's copy module's source code copy.py to the project's root directory as c_copy.py("c_copy" module), and execute the task used the "c_copy" module. As a result, I can't understand but the task have failed although the task used the "copy" module have suceeeded.
It seems that the "c_copy" module can't find files in the role's files directory.
So, please tell me why "c_copy" module does not work at well.
To ask your help, I have created the github repository.
https://github.com/suzuki-shunsuke/ansible-module-test-example
You can check my source code and reproduce my problem.
Requirements to reproduce
Python 2.7.12(pyenv)
pip
Vagrant(My Vagrant version is 1.8.6)
Setup
$ git clone https://github.com/suzuki-shunsuke/ansible-module-test-example
$ cd ansible-module-test-example
$ pyenv install 2.7.12
$ pip install --upgrade pip
$ pip install --upgrade virtualenv
$ virtualenv env
$ source env/bin/activate
$ cp env/lib/python2.7/site-packages/ansible/modules/core/files/copy.py c_copy.py
Test
$ vagrant up --provision-with=ansible
ansible.cfg
[defaults]
library = .
tasks/main.yml
- name: run the copy module
copy:
src: test.txt
dest: /tmp/test.txt
- name: run the clone of the copy module
c_copy:
src: test.txt
dest: /tmp/c_test.txt
Result
TASK [copy : run the copy module] **********************************************
changed: [default]
TASK [copy : run the clone of the copy module] *********************************
fatal: [default]: FAILED! => {"changed": false, "failed": true, "msg": "Source test.txt not found"}
Some modules are wrapped with action plugins.
Here is one for copy module.
So when you call copy, Ansible executes action plugin copy, which in turn calls copy module.
When there is no action plugin, module with the same name called directly.
If you look into copy action plugin code, you'll notice a bunch of file handling stuff, that your c_copy module omits.
Try to duplicate action plugin code and test your setup again.

How to fix ansible problems at fact gathering time?

When gathering facts, provisioning fails for the first host with the error you see below.
PLAY [surveylab] ************************************************************
GATHERING FACTS *************************************************************
failed: [192.168.56.101] => {"cmd": "/usr/bin/facter --puppet --json", "failed": true, "rc": 2}
msg: [Errno 2] No such file or directory
ok: [192.168.56.102]
This problem can be fixed by doing:
ln -sf /usr/bin/ruby1.9.1 /usr/bin/ruby
Which I want to do as a pre_task in my playbook like this:
pre_tasks:
- name: symlink expected ruby bin from versioned bin
command: ln -sf /usr/bin/ruby1.9.1 /usr/bin/ruby
It doesn't work, the error still shows. The obvious explanation is that when the facts are gathered, the problem still exists... but how are such things done?
you could try to write a separate playbook that just sets the link - there you would have to disable the gathering of the facts:
- name: 'some playbook'
gather_facts: no
might work.
Make sure the facter package is installed on the target machine(s). For example, on RHEL/CentOS:
sudo yum install facter

Resources