Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Templating YAML with ansible

I need to template a configuration file, which itself has YAML format. What is a good practice to do it?

Final file looks like this:

development:
  adapter: mysql2
  database: tracks
  # set this if you are storing utf8 in your mysql database to handle strings
  # like "Réné". Not needed for sqlite. For PostgreSQL use encoding: unicode
  # encoding: utf8
  host: localhost
  username: root
  password: qwerty

Most of these variables should be defined and some need non-default values. And it's YAML both in vars and in the template. So I have to repeat almost the same structure at least twice: in the template and in the vars file.

A real problem is with the optional parameters. To set the right encoding (or none) I have to write something like:

# tasks/configure.yml
- include: {tracks_database}.yml

# variables/mysql2.yml
tracks_database_encoding: utf8

# templates/site.yml
development:
  database: "{{ tracks_database }}"
  {% if tracks_database_use_utf8 %}
  encoding: "{{ tracks_database_encoding }}"
  {% endif %} 
  • This looks quite ugly and breaks the YAML formatting.
  • Lots of repeated code

So I've considered another way: to store the configuration as it is in a variable and just write it to the config through a jijna filter.

# group_vars/tracks.yml
tracks_database_settings:
  development:
    name: tracks
    adapter: mysql2
    host: localhost
    encoding: utf8
    username: root
    password: qwerty

# templates/site.yml
{{ tracks_database_settings | to_nice_yaml }}

But there are negative effects:

  • Comments are lost
  • If I need to override just several variables, I have to copy the whole structure. (hash_behaviour=merge is not an option).
  • Can not preset variables for different db types and include them.
  • Elements in the dictionary get rearranged (sorted).

Is there any better way of templating YAML files? The perfect solution would be something like:

{{ tracks_database_default_settings_with_comments |
  with overriden values from group_vars/host_vars/whatever |
  with preset values from db-specific file |
  to_nice_yaml_with_comments }}

I'm currently looking at combining hashes/dictionaries, but I still have no idea how/where to define the combined dictionaries.


UPD: by now I managed to do this:

{{ tracks_database_defaults | combine(tracks_database_override, recursive=True) | to_nice_yaml }}

But it looks really unusual for ansible. And still inconvenient.

like image 879
Nick Volynkin Avatar asked Apr 29 '16 09:04

Nick Volynkin


1 Answers

According to current variable management behavior and your requirements:

  • hash_behaviour=merge is not an option
  • don't repeat yourself inside var and template files

You picked the best option.

Also, note that combine(..., recursive=True) filter and hash_behaviour=merge use the same merge_hash function.
So, it will simply replace nested scalars or arrays.

like image 151
Artem Gromov Avatar answered Sep 28 '22 11:09

Artem Gromov