How to dynamically load var files and combine them into one variable using ansible - variables

I want to dynamically include var files in ansible. Dynamically means, that the user can provide a list as an extra-var, that list will be transformed into an array and defines the files to load. This is possible so far. What makes it hard is the fact that those files shall result in a single object holding the information.
This works and loads all the files in the folder and creates a variable (projects) out of the values specified there:
- name: Load project-specific Configuration
include_vars:
name: projects
dir: "{{project_vars_dir}}"
extensions:
- yml
To reach my goal and give the ability to specify which files to load, I tried the following:
- name: Load project-specific Configuration (requested projects only)
include_vars:
name: projects
file: "{{project_vars_dir}}/{{item}}.yml"
with_items: "{{projectlist.split(',') | list}}"
I can now call my playbook and specify --extra-vars like so: --extra-vars projectlist=projectA,projectB
Loading these files works, but the last file always overwrites the projects variable. How can I combine it?
Many thanks in advance

This is a somewhat complex loop so you'll need 2 files and the include_tasks module:
In tasks.yml you put:
- include_vars:
name: file_vars
file: "{{ item }}"
- set_fact:
all_vars: "{{ file_vars | combine(all_vars | default({})) }}"
In playbook.yml you put:
- hosts: all
tasks:
- include_tasks: tasks.yaml
loop: "{{projectlist.split(',') | list}}"
Ansible is not meant to be used as a programming language so complex loops are hard to write elegantly. Ideally you should look for built-in modules which handle your use case (which isn't the case here, as far as I know), write your own custom module or look into prepackaged roles written by someone else.

Related

no-changed-when lint warning araise in the ansible playbook

I have been creating a role in Ansible and when I run my gitci pipeline, i get a warning message as
"no-changed-when: Commands should not change things if nothing needs doing"
I have tried to use changed_when: false on the task file. When I try to deploy the image build, I get the permission error or status doesn't show properly.
In the example below, I am just copying the files from one directory to another.
Let me know how to use the shell module here.
E.g.
- name: Copy the configuration files to the Helm Directory
shell: "cp {{ files_dir_path }}/*.xml {{ roles_dir_path }}/{{ image.docker_tag }}/files/helm- chart/"
I am a little late to the party, but for those, that stumble upon this:
Ansible wants to be idempotent, so it needs to be able to verify if a change is necessary. In your example Ansible has to blindly run a command, without being able to check if that is even necessary. This is what the warning wants to tell you.
You can solve this, by giving Ansible a file, that will be present, only after the command ran. That way Ansible will skip the task the next time around.
- name: Copy the configuration files to the Helm Directory
shell: "cp {{ files_dir_path }}/*.xml {{ roles_dir_path }}/{{ image.docker_tag }}/files/helm- chart/"
args:
creates: "{{ roles_dir_path }}/{{ image.docker_tag }}/files/helm- chart/*.xml"
See e.g., the command module documentation for further reference.

How to run the same playbooks and inventories with or without a jumphost?

I have few playbooks and inventories and I need to run them from 2 different locations.
One that requires a jumphost and one that doesn't.
I have defined the jumphost in my inventory but when trying to run the playbook on the local one (no jumphost required) will fail.
Is there a way to load the SSH related vars based on ansible hostname?
If you just need to run things on the local host.. you can do that with specific tasks:
try local_action.. e.g.:
- name: copy file
local_action:
module: copy
src: stfile
dest: /path/to/testfile
or you can use delegate_to:
- name: copy a file
delegate_to: localhost
copy:
src: testfile
dest: /path/to/testfile
Edit: OK it seems I misread your question. Your question seems to be that you are running playbooks off two different hosts, one works and one fails, and so you need some logic that will select different variables for you based on the host?
You can include logic in the tasks using the when conditional like so :
- name: get ansible hostname
local_action:
module: shell
cmd: hostname
register: hostname_output
- shell: echo '{{variablefornonjumpbox}}'
when: hostname_output.stdout.find('jumpbox') != -1"
If you need to change the SSH target and details based on the hostname, you can use special variables like the ones at the bottom of this page:
https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html
Hopefully that helps.. If not I will need some clarification on the variables you are using and the errors you see.

Ansible - update variable in vars_file and call it again in a playbook doesn't work

Please see my playbook below. I call 2 executions on different hosts in 1 playbook.
The first execution changes some variables in a vars file which would be used in next execution (create new backup folder and update its name to another vars file)
The second execution try to use 2 vars file to do backup tasks (using roles). The issue I met here is the vars file value were loaded with old value not the updated. Seem all defined vars files were loaded before tasks executed on all hosts, and update during running task doesn't effect.
I can separate this playbook into 2 playbooks and all work well as expected but I'm trying to combine 1 playbook. Do anyone can show me how to reload vars file in correctly executing tasks/roles ? I exactly want the second execution load the updated vars file before running roles.
## backup playbook
---
- hosts: ftpserver01
gather_facts: no
ignore_errors: yes
vars_files:
- ./vars_files/lab1.yml
- ./vars_files/global_vars.yml
roles:
- create_define_backup_folder
# this role will create new backup folder and update its name in ./vars_files/global_vars.yml
- hosts: terminal02
become: yes
become_method: su
gather_facts: no
ignore_errors: yes
vars_files:
- ./vars_files/lab1.yml
- ./vars_files/global_vars.yml
roles:
- backup_feature01
- backup_feature02
Expect: using updated global_vars.yml while running tasks on hosts terminal02
Actual result: all tasks on terminal02 using old value not the updated value of global_vars.yml vars_files
Use include_vars and include_role in the 2nd play
- hosts: terminal02
become: yes
become_method: su
gather_facts: no
ignore_errors: yes
tasks:
- include_vars:
file: ./vars_files/lab1.yml
- include_vars:
file: ./vars_files/global_vars.yml
- include_role:
name: backup_feature01
- include_role:
name: backup_feature02

Ansible :- list sub directories in a dir & use each dir name as a variable.

I want to list all sub-directories in a parent directory then use each directory name a seperate variable in ansible for further action.
Keep in mind, that it is in general not possible to use file names as Ansible variables. A file name can contain characters, which are illegal in a variable name.
Also keep in mind, that a file could have the same name as an already defined variable. It is better to prefix the variable to avoid collisions.
The following example filters for valid file names and prefixes the variable names.
---
- hosts: test1
tasks:
- find:
path: /etc
file_type: file
use_regex: yes
patterns: "^[a-zA-Z0-9_]+$"
recurse: no
register: files
- set_fact:
"my_{{ item | basename }}": "{{ item }}"
with_items: "{{ files.files | map(attribute='path') | list }}"
- debug: var=my_passwd
- debug: var=my_hosts

ansible playbooks get which variable file by default if not defined

I have a devop directory containing ansible's varible directroy , plabooks and inventory directory
The directory looks like this
|groups_vars
-all.yml
-development.yml
-staging.yml
|inventroy
- staging
- development
configure.yml
deploy.yml
configure.yml and deploy.yml contains task that are applied to either staging or development machines using variable in groups_vars
Know if i call ansible-playbook command with staging inventory. How will it know which variable file to use. The varfile task in not added to configure.yml and deploy.yml
By the way am using an example from the company i work and the example is working I just want to know the magic that is happening it is using the right variable file though the var file is not incuded in the configure.yml nor deploy.yml
Ansible uses a few conventions to load vars files:
group_vars/[group]
host_vars/[host]
So if you have an inventory file that looks like this:
[staging]
some-host.name.com
Then These files will be included (optional extension .yml or .yaml also):
/group_vars/all
/group_vars/staging
/host_vars/some-host.name.com
I think this is the "magic" you are referring to.
You can find more on the subject here: http://docs.ansible.com/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable
And here: http://docs.ansible.com/playbooks_best_practices.html