Location to keep Ansible custom modules - ansible

In the following directory structure I have to create a zip of "anisble" directory. The idea is to put everything inside the ansible directory like playbook, roles, inventory details and custom modules into a zip package and
its contents should not have any dependency on anything outside "ansible" directory.
<home>
|<user>
|__ansible
|_____playbook.yml
|_____inventory/
| |____myHosts
|
|_____library/
| |___my_Custom_module.py
|_roles
| |____role1
|____role2
I cannot use: "/home/$USER/.ansible/plugins/modules/" as this will make solution user specific and "/usr/share/ansible/plugins/modules/" is outside of the ansible directory and does need privileges(which user does not have)
Question:
Is there any possible place were my_custom_module.py can be placed so it will automatically get picked by ansible while running? This must be somewhere inside "ansible" directory.
If I do this before running the ansible playbook, it works but is there anyway to programmatically do it from ansible playbook before using the custom module ?
export ANSIBLE_LIBRARY=library/my_custom_module.py
Is there anyway I can provide the path of the custom module relative to "ansible" directory ? either in any conf file or env variable ? Note that I cannot use /etc ,/usr/ etc . Everything had to be inside ansible directory,
Is it even possible ?

You can create a file ansible.cfg inside of your ansible directory and then set the DEFAULT_MODULE_PATH variable (library) in that file:
[defaults]
library = ./library
More info can be found in the Ansible documentation for the Ansible configuration.
Here's what the documentation says about this setting:
Description: Colon separated paths in which Ansible will search for Modules.
Type: pathspec
Default: ~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
Ini Section: defaults
Ini Key: library
Environment: ANSIBLE_LIBRARY

Related

Ansible: bitwise oprations inside anisble playbook

I am trying to use bitwise operation inside my ansible playbooks. As sugegsted in this post (How to perform bitwise operations in Ansible?), I have created the .py file for "bitwise or" filter and placed under default filterplugin dir
/usr/share/ansible/plugins/filter
1)The ansible ansible.cfg file is edited to specify the filter plugin path.
filter_plugins = /usr/share/ansible/plugins/filter
2)Ansible version on controller node is: 3.6.10
But unfortunately playbook is not able to find the new defined filter. I am not sure if I am missing anything. Is there anything else I need to do?
Any help with this is appreciate.
The filter plugin I tried is working now. There was a small coding issue inside my filter python file, which was reported by playbook run logs on the console, that I didn't spot.
After carefully looking into the logs, I could fix the coding issue and, after that, the filter operation was found from the filter_plugin path that was specified in the ansible.cfg file.
filter_plugins = /usr/share/ansible/plugins/filter
There was no more setting needed apart from specifying the filter path in ansible.cfg.

Resolve Local Files by Playbook Directory?

I have the following Ansible role which simply does the following:
Create a temporary directory.
Download Goss, a server testing tool, into that temporary directory.
Upload a main Goss YAML file for the tests.
Upload additional directories for additional included tests.
Here are a couple places where I'm using it:
naftulikay.python-dev
naftulikay.ruby-dev
Specifically, these playbooks upload a local file adjacent to the playbook named goss.yml and a directory goss.d again adjacent to the playbook.
Unfortunately, it seems that Ansible logic has changed recently, causing my tests to not work as expected. My role ships with a default goss.yml, and it appears that when I set goss_file: goss.yml within my playbook, it uploads degoss/files/goss.yml instead of the Goss file adjacent to my playbook.
If I'm passing the name of a file to a role, is there a way to specify that Ansible should look up the file in the context of the playbook or the current working directory?
The actual role logic that is no longer working is this:
# deploy test files including the main and additional test files
- name: deploy test files
copy: src={{ item }} dest={{ degoss_test_root }} mode=0644 directory_mode=0755 setype=user_tmp_t
with_items: "{{ [goss_file] + goss_addtl_files + goss_addtl_dirs }}"
changed_when: degoss_changed_when
I am on Ansible 2.3.2.0 and I can reproduce this across distributions (namely CentOS 7, Ubuntu 14.04, and Ubuntu 16.04).
Ansible searches for relative paths in role's scope first, then in playbook's scope.
For example if you want to copy file test.txt in role r1, search order is this:
/path/to/playbook/roles/r1/files/test.txt
/path/to/playbook/roles/r1/test.txt
/path/to/playbook/roles/r1/tasks/files/test.txt
/path/to/playbook/roles/r1/tasks/test.txt
/path/to/playbook/files/test.txt
/path/to/playbook/test.txt
You can inspect your search_path order by calling ansible with ANSIBLE_DEBUG=1.
To answer your question, you have to options:
Use filename that doesn't exist within role's scope. Like:
goss_file: local_goss.yml
Supply absolute path. For example, you can use:
goss_file: '{{ playbook_dir }}/goss.yml'
Ansible doesn't apply search logic if the path is absolute.

Include stage environment in ansible

I want to deploy staging and production environment using ansible. All components are same for both staging and production except few configurations. So i created following files
group_vars
- all.yml
- production.yml
- staging.yml
Whenever i run ansible-playbook, it loads configuration from all.yml. But i also want to load either production.yml or staging.yml.
How do i include this configuration when run ansible playbook command?
This should actually work out of the box, given you have your hosts grouped in your inventory.
So let's say your inventory looks like this:
[production]
host.a
host.b
[staging]
host.c
host.d
And then you'd have the following yaml files, relative to your playbook:
group_vars/all
group_vars/production
group_vars/staging
The vars from all matching groups will be loaded. And of course additionally the all file.
Instead of files, the group names could also be directories and all included yaml files would then be loaded.
Update after discussion in comments:
So if your inventory for production looks like this:
[redisServers]
host.a
host.b
[apiServers]
host.c
host.d
[SQLServers]
host.e
host.f
Then you'd add another group production. To not repeat all the hostnames you can create a group of groups, like so:
[production:children]
redisServers
apiServers
SQLServers

Keep Ansible DRY: How to avoid repeating variables?

Recently just started using Ansible and I have run into a problem. In one of my YAML structures I have defined something like this:
---
# file: main.yml
#
# Jenkins variables for installation and configuration
jenkins:
debian:
# Debian repository containing Jenkins and the associated key for accessing the repository
repo: 'deb http://pkg.jenkins-ci.org/debian binary/'
repo_key: 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key'
# Dependencies needed for Jenkins to run properly
dependencies:
- 'openjdk-7-jdk'
- 'git-core'
- 'curl'
port: 8080
# Installation directory
home: '/opt/jenkins'
# Path to the location of the main Jenkins-cli binary
bin_path: '{{jenkins.home}}/jenkins-cli.jar'
# Path to the location of the Jenkins updates file
updates_path: '{{jenkins.home}}/updates_jenkins.json'
Ansible gives me an error like this from a specific task:
"recursive loop detected in template string:
{{jenkins.home}}/updates_jenkins.json"
I've narrowed it down to the problem being with the fact bin_path and updates_path both refer to 'home'. Is there a way around this? It kind of sucks that I would need to define '/opt/jenkins' multiple times.
As far as I know that this is a limitation of jinja2 variables. it was working with the old ${} and broke since 1.4. I am not sure if they fixed that in 1.5.
My temp solution would be removing home from the "jenkins"
---
# file: main.yml
#
# Jenkins variables for installation and configuration
# Installation directory
jenkins_home: '/opt/jenkins'
jenkins:
debian:
# Debian repository containing Jenkins and the associated key for accessing the repository
repo: 'deb http://pkg.jenkins-ci.org/debian binary/'
repo_key: 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key'
# Dependencies needed for Jenkins to run properly
dependencies:
- 'openjdk-7-jdk'
- 'git-core'
- 'curl'
port: 8080
# Path to the location of the main Jenkins-cli binary
bin_path: '{{jenkins_home}}/jenkins-cli.jar'
# Path to the location of the Jenkins updates file
updates_path: '{{jenkins_home}}/updates_jenkins.json'
This should do it:
bin_path: "{{ jenkins['home'] }}/jenkins-cli.jar"

Permanent Config File in Pylint

I've setup a custom configuration file for Pylint (name, conveniently, config). There has to be a way that I don't have to include --rcfile=config on every run. How can I set the config file permanently?
When you do not specify the --rcfile option, Pylint searches for a configuration file in the following order and uses the first one it finds:
pylintrc in the current working directory
If the current working directory is in a Python module, Pylint
searches up the hierarchy of Python modules until it finds a
pylintrc file. This allows you to specify coding standards on a
module-by-module basis. Of course, a directory is judged to be a
Python module if it contains an __init__.py file.
The file named by environment variable PYLINTRC
.pylintrc in your home directory, unless you have no home directory
or your home directory is /root
.pylintrc in the current working directory
/etc/pylintrc
Thus depending on the method you choose, Pylint can use a different configuration file based on the location of the code, the user or the machine.
Note that the configuration file only applies to Python files that are in modules. Thus, Pylint still uses its default rules when analyzing Python files in a directory with no __init__.py file.
For example, I have a bin/ directory containing command line applications. Ordinarily, this directory needs no __init__.py file because it is never imported. I had to add a bin/__init__.py file to get Pylint to analyze these Python files using my pylintrc file.
set the path to that file in the PYLINTRC environment variable, or rename the file $HOME/.pylintrc or /etc/pylintrc (the latter is probably only supported on *nix)
It can be done using .pre-commit-config.yaml. This snippet below need to be added to .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: pylint
name: pylint
entry: pylint
language: system
types: [python]
args: [
"-rn", # Only display messages
"-sn", # Don't display the score
"--rcfile=.pylintrc", # Link to your config file
"--load-plugins=pylint.extensions.docparams", # Load an extension
]

Resources