Writing config files
That's an amazingly boring title for something that simply could be seen as magic. Sometimes with Ansible you'd really want to write out files without actually defining the contents. Vague ? :) Yeah i'd guess.
As an example for a configuration file lets assume that using Ansible combined with a Jinja template you would have something like this:
# Jinja template
set_default = {{ template_set_default }}
change_color = {{ some_variable }}
All the above variables would have to be set ( when not using defined and other logic ), but what if you have multiple files with different content.
Well, that was the challenge for today :)
Writing the role
Since i havent reached my caffeine high yet, lets create a role named arwain
simply an acronymn for 'Ansible Role Without An Interesting Name'.
ansible-galaxy init --offline roles/adhoc/arwain
Variables
I'll be testing/working on seenine
. Lets define some variables to work with. Preferably in inventory/host_vars/seenine
arwain_variables:
testing_myfile1.txt:
INI_main: true
entry1: 'yes'
using_color: 'no'
testing_myfile2.txt:
text: 'no'
hold_camera: 'maybe'
Tasks
In this particular example looking at the variables i'd like to see files written to (and i'll append /tmp/ to it) /tmp/testing/myfile1.txt
and myfile2.txt
, Will test if a variable starts with INI
to encapsulate it with '[]'. And use the rest as file contents. Obviously when all this works we can write any type of file or add more magic.
roles/adhoc/arwain/tasks/main.yml
---
# tasks file for roles/adhoc/arwain
- name: Create list of keys as dir/filenames
set_fact:
l_filenames: "{{ arwain_variables.keys() | list }}"
- name: Include tasks for writing multiple templates
include_tasks: write_template.yml
with_items: "{{ l_filenames }}"
loop_control:
loop_var: d_filename
roles/adhoc/arwain/tasks/write_template.yml
---
- name: Create fact with variables per file
set_fact:
my_items: "{{ arwain_variables[d_filename] }}"
- name: Create directory
file:
path: "/tmp/{{ d_filename.split('_')[0] }}"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: 0750
state: directory
- name: Write template
template:
src: templates/write_template.j2
dest: "/tmp/{{ d_filename|replace('_','/') }}"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: 0644
Template(s)
And for the template file roles/adhoc/arwain/templates/write_template.j2
{{ ansible_managed | comment }}
{% for entry in my_items %}
{% if entry.startswith('INI') %}
[{{ entry.split('_')[1] }}]
{% else %}
{{ entry }} = {{ my_items[entry] }}
{% endif %}
{% endfor %}
Tests
Change the roles/adhoc/arwain/tests/tests.yml
file to match your test environment.
---
- hosts: 'seenine*'
remote_user: ansible
become: no
gather_facts: no
roles:
- roles/adhoc/arwain
Lets put it to the test
ansible-playbook roles/adhoc/arwain/tests/test.yml
That seems to work, lets check the contents of a file:
cat /tmp/testing/myfile1.txt
#
# Okairi.nl - This file is managed by Ansible.
#
[main]
entry1 = yes
using_color = no
And file 2:
#
# Okairi.nl - This file is managed by Ansible.
#
text = no
hold_camera = maybe
And thats it :)