Ansible: Can I force include: to use another path - ansible

I have the following problem. I'm keeping two separate Ansible project directories for two different technologies. Imagine you have a nice Ansible setup and want to pull an Ansible project and use some of your established structure without integrating it completely.
The first statement does what I want. It gives a fq path.
debug: msg="{{lynx_ansible}}/roles/centos_common/centos_{{jdk_provider}}.yml"
include: "{{lynx_ansible}}/roles/centos_common/centos_{{jdk_provider}}.yml"
The include adds a path to the ansible-project root dir and doesn't expand the variables. Is there a way to do this?

Try $lynx_ansible rather than {{ lynx_ansible }}. Include doesn't seem to support jinja2 syntax.

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.

Avoid path redundancy in Gitlab CI include

To improve the structure of my Gitlab CI file I include some specific files, like for example
include:
- '/ci/config/linux.yml'
- '/ci/config/windows.yml'
# ... more includes
To avoid the error-prone redundancy of the path I thought to put it into a variable, like:
variables:
CI_CONFIG_DIR: '/ci/config'
include:
- '${CI_CONFIG_DIR}/linux.yml' # ERROR: "Local file `${CI_CONFIG_DIR}/linux.yml` does not exist!"
- '${CI_CONFIG_DIR}/windows.yml'
# ... more includes
But this does not work. Gitlab CI claims that ${CI_CONFIG_DIR}/linux.yml does not exist, although the documentation says that variables in include paths are allowed, see https://docs.gitlab.com/ee/ci/variables/where_variables_can_be_used.html#gitlab-ciyml-file.
What also didn't work was to include a file /ci/config/main.yml and from that include the specific configurations without paths:
# /ci/config/main.yml
include:
- 'linux.yml' # ERROR: "Local file `linux.yml` does not exist!"
- 'windows.yml'
# ... more includes
How can I make this work or is there an alternative to define the path in only one place without making it too complicated?
This does not seem to be implemented at the moment, and there is an open issue at the moment in the backlog.
Also, with the documentation saying that you could use variables within include sections, those are only for predefined variables.
See if GitLab 14.2 (August 2021) can help:
Use CI/CD variables in include statements in .gitlab-ci.yml
You can now use variables as part of include statements in .gitlab-ci.yml files.
These variables can be instance, group, or project CI/CD variables.
This improvement provides you with more flexibility to define pipelines.
You can copy the same .gitlab-ci.yml file to multiple projects and use variables to alter its behavior.
This allows for less duplication in the .gitlab-ci.yml file and reduces the need for complicated per-project configuration.
See Documentation and Issue.

Are there any vars that Ansible can merge?

Today I noticed that Ansible won't merge vars.
For example when I have something like
---
lvm_roles:
postgresql:
size: '10g'
path: '/var/lib/postgresql'
And in another place I have for example
---
lvm_roles:
sonarqube:
size: '10g'
path: '/opt/sonarqube'
Ansible won't merge these facts. I am not sure about precedence but I think the first one wins. Without errors or warnings. IMHO a dangerous feature for a configuration management tool.
Are there any vars that Ansible can merge? Lists and hash won't work. Is there a workaround of some sort for this?
This is a significant shortcoming of Ansible. Because "facts" can be dependent on what you are provisioning. The inability to merge "facts" make it necessary to hard code and duplicate the stuff that you wan't to be configurable.
For example when I create one file with
lvm_roles:
postgresql:
size: '10g'
path: '{{ postgresql_home }}'
sonarqube:
size: '10g'
path: '{{ sonar_home }}'
This will not work because sonar_home is not defined on de postgresql node. On the the sonarqube node, postgresql_home is not defined. The ability to flexibly use vars is greatly impacted if merging is not possible.
Extract of a default ansible.cfg file:
# if inventory variables overlap, does the higher precedence one win
# or are hash values merged together? The default is 'replace' but
# this can also be set to 'merge'.
#hash_behaviour = replace
You can therefore change this behavior by setting hash_behaviour = merge.
I would not change that on a system wide basis as it might break other projects/roles that would rely on a default behavior. You can distribute the ansible.cfg at the root of your specific project that really needs this.
Meanwhile, as #dgw pointed out with a specific example, I've always been able to keep the default behavior by carefully choosing where to place my variables (group or host in inventory, included file, playbook...) and eventually merge them myself if needed.

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.

Have ansible role retrieve its files from external location as part of its own role

So one thing we've encountered in our project is that we do not want to store our large files in our git repo for our ansible roles because it slows down cloning (and git limits files to 100 mb anyways).
What we've done is store our files in a separate internal location, where our files can sit statically and have no size restrictions. Our roles are written so that they first pull these static files to their local files folder and then continue like normal.
i.e.
roles/foo/tasks/main.yml
- name: Create role's files directory
file:
path: "{{roles_files_directory}}"
state: directory
- name: Copy static foo to local
get_url:
url: "{{foo_static_gz}}"
dest: "{{roles_files_directory}}/{{foo_gz}}"
#....Do rest of the tasks...
roles/foo/vars/main.yml
roles_files_directory: "/some/path/roles/foo/files"
foo_static_gz: "https://internal.foo.tar.gz"
foo_gz: "foo.tar.gz"
The main thing I don't find really sound is the hard coded path to the role's files directory. I preferably would like to dynamically look up the path when running ansible, but I haven't been able to find documentation on that. The issue can arise because different users may check roles to a different root paths. Does anyone know how to dynamically know the role path, or have some other pattern that solves the overall problem?
Edit:
I discovered there's actually a {{playbook_dir}} variable that would return "/some/path", which might be dynamic enough in this case. Still isn't safe against the situation where the role name might change, but that's a way rarer occurrence and can be handled through version control.
What about passing values from the command line?
---
- hosts: '{{ hosts }}'
remote_user: '{{ user }}'
tasks:
- ...
ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"
http://docs.ansible.com/playbooks_variables.html#passing-variables-on-the-command-line
I just want to add another possible solution: you can try to add custom "facter".
Here is a link to official documentation: http://docs.ansible.com/setup_module.html
And I found this article that might be useful: http://serverascode.com/2015/01/27/ansible-custom-facts.html

Resources