Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible include_vars into dictionary

In my ansible playbook, I read a list of directories into a list. I then want to read a "config.yml" file from each of these directories and put their content into dictionary, so that I can reference the config-data via the directory name from that dictionary. The first part is no problem, but I cannot get the second part to work:

Step 1, load directories:

- name: Include directories
  include_vars:
  file: /main-config.yml
  name: config

Step 2, load configs from directories:

- name: load deploymentset configurations
  include_vars:
    file: /path/{{ item }}/config.yml
    name: "allconfs.{{ item }}"   ## << This is the problematic part 
  with_items:
    - "{{ config.dirs }}"

I tried different things like "allconfs['{{ item }}'], but none seemed to work. The playbook completed successfully, but the data was not in the dictionary. I also tried defining the outer dictionary beforehand, but that did not work either.

The config files themselves are very simple:

/main-config.yml:

dirs:
- dir1
- dir2
- dir3

/path/dir1/config.yml:

some_var: "some_val"
another_var: "another val"

I want to be able to then access the values of the config.yml files like this:

{{ allconfs.dir1.some_var }}

UPDATE to try Konstantins approach:

  - name: load deploymentset configurations
    include_vars:
      file: /repo/deploymentsets/{{ item }}/config.yml
      name: "default_config"
    with_items:
    - "{{ config.deploymentsets }}"
    register: default_configs


  - name: combine configs
    set_fact:
      default_configs: "{{ dict(default_configs.results | json_query('[].[item, ansible_facts.default_config]')) }}"

Error message:

fatal: [127.0.0.1]: FAILED! => {"failed": true, "msg": "Unexpected templating type error occurred on ({{ dict(default_configs.results | json_query('[].[item, ansible_facts.default_config]')) }}): <lambda>() takes exactly 0 arguments (1 given)"}

like image 701
feob Avatar asked Jul 24 '17 16:07

feob


2 Answers

Here is a piece of code from one of my projects with similar functionality:

- name: Load config defaults
  include_vars:
    file: "{{ item }}.yml"
    name: "default_config"
  with_items: "{{ config_files }}"
  register: default_configs
  tags:
    - configuration

- name: Combine configs into one dict
  # Здесь мы делаем словарь вида
  # default_configs:
  #   config_name_1: { default_config_object }
  #   config_name_2: { default_config_object }
  #   config_name_3: { default_config_object }
  #   ...
  set_fact:
    default_configs: "{{ dict(default_configs.results | json_query('[].[item, ansible_facts.default_config]')) }}"
  tags:
    - configuration

default_config is a dummy var to temporary load var data.
The trick is to use register: default_configs with include_vars and parse it with the following task stripping out unnecessary fields.

like image 74
Konstantin Suvorov Avatar answered Nov 09 '22 06:11

Konstantin Suvorov


AFAIK it isn't possible to create a single dictionary that encompasses multiple include_vars. From my testing it would create separate dictionaries for each included directory. Here's what you can do instead.

Remove allconfs. from your variable name.

- name: load deploymentset configurations
  include_vars:
    file: /path/{{ item }}/config.yml
    name: "{{ item }}"
  with_items:
    - "{{ config.dirs }}"

You can then either access variables directly with

debug:
  msg: "{{ dir1.some_var }}"
with_items: "{{ config.dirs }}"

Or if you need to loop through all variables in your included directories use this (hoisted from Ansible: how to construct a variable from another variable and then fetch it's value).

debug:
  msg: "{{ hostvars[inventory_hostname][item].some_var }}"
with_items: "{{ config.dirs }}"
like image 28
kfreezy Avatar answered Nov 09 '22 05:11

kfreezy