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

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.

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!

Ansible script - error with pexpect module

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]

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.

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

Using puppet module straight from a cloned repo

I'm trying to use puppet module in a vagrant setup. In a worked around the problem I tried to solve in this stackoverflow question.
I cloned the puppet module repo (apt module and nodejs module) into a sub folder
set the puppet module path in the vagrantfile
And include the puppet modules and call them in the puppet manifest file for example:
class { 'apt':
}
include apt
class{ 'apt':} -> apt::builddep { ["python-imaging","python-lxml"]:
require => Class['apt']
}
I wonder, maybe there is an install/build step I'm missing when I just git clone the repo? is this even possible to do?
The error message:
←[0;37mdebug: importing '/tmp/vagrant-puppet/modules-0/apt/manifests/init.pp' in
environment production←[0m
←[0;37mdebug: Automatically imported apt from apt into production←[0m
←[0;37mdebug: importing '/tmp/vagrant-puppet/modules-0/apt/manifests/params.pp'
in environment production←[0m
←[0;37mdebug: Automatically imported apt::params from apt/params into production
←[0m
←[0;37mdebug: importing '/tmp/vagrant-puppet/modules-0/apt/manifests/update.pp'
in environment production←[0m
←[0;37mdebug: Automatically imported apt::update from apt/update into production
←[0m
Unknown function validate_bool at /tmp/vagrant-puppet/modules-0/apt/manifests/in
it.pp:36 on node precise32
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
cd /tmp/vagrant-puppet/manifests && puppet apply --verbose --debug --modulepath
'/etc/puppet/modules:/tmp/vagrant-puppet/modules-0' default.pp --detailed-exitco
des || [ $? -eq 2 ]
You are missing the stdlib module, which is a dependency at least of the apt module, and which provides, among other things, the validate_bool function Puppet can't find.
You can find the stdlib module here:
https://github.com/puppetlabs/puppetlabs-stdlib
Use the Puppet module installation tool rather than just cloning a single repo.
http://docs.puppetlabs.com/puppet/latest/reference/modules_installing.html
or better yet use librarian-puppet.

Resources