How to debug ansible variable precedence - debugging

I have a complex ansible setup which I want to refactor, with variables defined in various places / at various levels.
I am aware of the basic inheritance rules:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#ansible-variable-precedence
I would like to do a verbose debug run, that dumps all the variable key-value pairs to stdout or a file - as they would be effectively applied to my host or environments, but without actually applying any playbooks.
How can I do that with Ansible?
Also, how can I get Ansible to show which yaml files it sources in which order (e.g. what it has found where)

Related

Ansible inventory: aws_ec2 module -- Looking for an example of a working 'groups:' function

I have a dynamic ansible inventory which uses the aws_ec2 module. It works quite well, generally. However, there is one issue. I've tried several times to create groups using the 'groups:' keyword, and all attempts have failed. The documentation is a little sparse -- in fact here it is, in its entirety:
groups: (dictionary)
Default:{}
Add hosts to group based on Jinja2 conditionals.
I've tried a number of syntaxes, Jinja2, conditionals, declarations, and so far none have succeeded in creating a group named 'foo'. For awhile I thought maybe I need to pass a small code snibbet that returns true or false, and thus include or exclude the targeted hosts. This doesn't seem to be the case. I'm wondering if anyone here has used the 'groups:' keyword and gotten further than I have. I found very little while Googling. FWIW, I am using ansible 2.9.9 on Linux.
Some examples of things that don't work:
---
plugin: aws_ec2
### fails to create a group
groups:
foo: >-
tags.get('Name') if tags.get('Name') == 'foo-server'
### returns every host in the AWS account.
groups:
bar:
- "{{ tags.get('Name') == 'bar-server' }}"
Also, it is difficult to use ansible's debugging tools with this module.
Many, like the playbook debugger, seem not to work properly, though I find
them quite useful in other contexts. Any tips you might have for debugging
in this context would be warmly appreciated.
It looks like you were very close
As with many things ansible, the authoritative "documentation" is the source code. Specifically their use of the 'groups' option which calls _add_host_to_composed_groups wherein they feed the groups: dict into a Jinja2 evaluation context containing all the hostvars. The expression is plugged into {% if ... %} so you wouldn't want to include the {{ markers in your expression, just the "raw" jinja2 expression
groups:
foo: tags.get('Name') == 'foo-server'
Be forewarned that I don't have an environment handy to test that inventory script, but that's the theory

How to extend ansible playbooks to achieve complex conditions?

I understand that ansible is limited to being a configuration tool i.e., we create configurations in yaml files and python scripts does execution by looking at the configuration.
There are howevever a useful attribute when that will help in deciding which configuration to be done based on the condition mentioned in when and the order of the configurations is also done based on the order of the tasks,
variables and facts are available in achieving dynamic configurations.
However, my requirement involves complex loops and conditions and recursive processing which is either entirely not achievable in playbooks or multiple tasks need to be created with the conditions.
Few issues I find in using ansible playbooks are:
No if else structures
loops has very limited functionality
variable scopes does not work like in scripting languages
And the issue with recursive tasks is like for example:
start_installation.yml does installation of packages defined in a variable
The package has dependencies and the dependencies has dependencies i.e., recursive dependencies and installation should be done on the dependencies first recursively by calling start_installation.yml. However, this is creating problems with the variable scoping i.e., if a package_to_install is 'A' at the time of starting start_installation.yml for A, and if A has dependency 'B', then package_to_install will be set to 'B', at the time of starting start_installation.yml for B. Now, once installation of B is done, it can't do installation of A, as the variable scope is not local to the called function.
My question is mainly if it is a correct approach to use Ansible in doing these tasks or do I need to use a scripting language to do the required checks?
To answer your question:
" ... it is a correct approach to use Ansible in doing these tasks or do I need to use a scripting language to do the required checks?
Correct approach is to use package – Generic OS package manager. If this does not work create a Minimal, Complete, and Verifiable example

ansible - change precedence of role variables

I've created a role to install my apps.
This role needs specific variables defined in separate files in the vars dir of the role, depending of the app (here pdt_type), like that:
- name: Include pkg list of {{ pdt_type }}
include_vars:
file: "{{ pdt_type }}.yml"
It's working fine. But I'd like to be able to overload those variables of my role by the inventory ones. Or vars loaded by include_vars has a greater precedence of the inventory ones.
Do you know how I can do to change this behavior?
How I can defined default variables of a role based on a condition?
Thanks
I think you can't change the variable precedence in ansible and that's good.
A lot of folks may ask about how variables override another. Ultimately it’s Ansible’s philosophy that it’s better you know where to put a variable, and then you have to think about it a lot less. [...] There is only one Empire State Building. One Mona Lisa, etc. Figure out where to define a variable, and don’t make it complicated.
For defining variables on a condition see:
https://serverfault.com/questions/907164/ansible-conditionally-define-variables-in-vars-file-if-a-certain-condition-is-m
Conditionally define variable in Ansible
https://everythingshouldbevirtual.com/automation/ansible-using-set_facts-module/
For including variables conditionally from a file see:
https://docs.ansible.com/ansible/2.7/modules/include_vars_module.html

Retrieve hostname -f within YAML(yml)

I've got a config .cfg file that has the hostname hard coded in it. I'm trying to find a way for the hostname to be gotten locally (dynamically) by running a command similar to hostname -f to have it configure the variable in the .cfg, without running a script, like python, to write the config file ahead time. Is it possible to run a 'yum' command that gets the hostname to use in the YAML/yml file?
Thanks to Wikipedia, I think I found out why no one is helping me with this:
Wiki YAML -> Security
Security
YAML is purely a data representation language and thus has no executable commands. While validation and safe parsing is inherently possible in any data language, implementation is such a notorious pitfall that YAML's lack of an associated command language may be a relative security benefit.
However, YAML allows language-specific tags so that arbitrary local objects can be created by a parser that supports those tags. Any YAML parser that allows sophisticated object instantiation to be executed opens the potential for an injection attack. Perl parsers that allow loading of objects of arbitrary class create so-called "blessed" values. Using these values may trigger unexpected behavior, e.g. if the class uses overloaded operators. This may lead to execution of arbitrary Perl code.
The situation is similar for Python or Ruby parsers. According to the PyYAML documentation

Maven - dynamically creating a map, and referring to it

Our generic Maven build needs to pass on a number of properties to child processes.
Right now, we are providing these as environment variables, and reading them in individually as properties.
These properties are then substituted into a file to configure a test runtime, and provided to the Failsafe plugin as environment variables for the test run.
The above is fine, except for a couple of things:
The environment variable -> property map is manual - we need a property definition for every environment variable we want to pull in.
Specifying environment variables to Failsafe is again manual - we need a variable definition for every environment variable we want to pass on.
Right now, if we have 20 environment variables, we have 20 lines for each of these stages, and that's getting tedious quickly.
Is there a better way to do this?
My naive thoughts include (though I can't find a way to achieve it):
Define Maven properties dynamically, potentially based on a regex, from environment variables.
From Maven properties, automatically construct a list of environment variables, to be passed to Failsafe, again preferably via a regex.

Resources