actually i'm getting into Ansible and writing my first ever playbook, which does some general setup on my linux servers when i got them.
I am trying to get a Jinja2 template to apply, but only if the file does not exist or is different from the content in the Jinja2 template. If the content of the file is the same, the task should be skipped.
I got this behavior of skipping already for setting the timezone:
- name: Check current Timezone
command: timedatectl show --property=Timezone --value
register: timezone_output
changed_when: false
- name: Configure Timezone
command: timedatectl set-timezone {{ timezone }}
when: timezone_output.stdout != timezone
But i cant get this for comparing files. I already tried this - but the checksums are not equal although the content of the files are the same:
---
- name: Calculate checksum of Jinja2 template
set_fact:
template_content: "{{ lookup('file', 'templates/sshd_config.j2') }}"
- name: Display checksum template
debug:
var: template_content | md5
- name: Calculate checksum of remote file
command: md5sum /etc/ssh/sshd_config.d/initial.conf
register: md5sum_output
changed_when: false
check_mode: no
- set_fact:
remote_file_checksum: "{{ md5sum_output.stdout.split()[0] }}"
- name: Display checksum
debug:
var: remote_file_checksum
- name: Update SSH configuration
template:
src: sshd_config.j2
dest: /etc/ssh/sshd_config.d/initial.conf
notify: Reload SSH Service
Since I will have quite a few roles that will apply templates, it is important for me to skip the tasks if the content of the file is already correct to have a better evaluation later.
The comment by Zeitounator is all you need to use the module template successfully. Let me explain why you see different checksums.
Short answer: Instead of the lookup plugin file use template.
Details: Given the template
shell> cat sshd_config.j2
Port: {{ sshd_Port }}
AddressFamily: {{ sshd_AddressFamily }}
ListenAddress: {{ sshd_ListenAddress4 }}
ListenAddress: {{ sshd_ListenAddress6 }}
and the variables
sshd_Port: 22
sshd_AddressFamily: any
sshd_ListenAddress4: 0.0.0.0
sshd_ListenAddress6: '::'
the below task
- template:
src: sshd_config.j2
dest: /tmp/sshd_config
gives
shell> cat /tmp/sshd_config
Port: 22
AddressFamily: any
ListenAddress: 0.0.0.0
ListenAddress: ::
You get the same result using the template lookup
- debug:
msg: "{{ lookup('template', 'sshd_config.j2') }}"
gives
msg:
Port: 22
AddressFamily: any
ListenAddress: 0.0.0.0
ListenAddress: ::
However, when you use the file lookup
- debug:
msg: "{{ lookup('file', 'sshd_config.j2') }}"
the variables won't be expanded
msg:
Port: {{ sshd_Port }}
AddressFamily: {{ sshd_AddressFamily }}
ListenAddress: {{ sshd_ListenAddress4 }}
ListenAddress: {{ sshd_ListenAddress6 }}
- hosts: localhost
vars:
sshd_Port: 22
sshd_AddressFamily: any
sshd_ListenAddress4: 0.0.0.0
sshd_ListenAddress6: '::'
tasks:
- debug:
msg: "{{ lookup('template', 'sshd_config.j2') }}"
- debug:
msg: "{{ lookup('file', 'sshd_config.j2') }}"
- template:
src: sshd_config.j2
dest: /tmp/sshd_config
There is one more problem if you want to compare the checksums
- debug:
msg: |
{{ lookup('template', 'sshd_config.j2')|md5 }}
{{ lookup('file', '/tmp/sshd_config')|md5 }}
{{ lookup('file', 'sshd_config.j2')|md5 }}
gives
msg: |-
2ee29dc15e27ef8169fc557ea6e52263
bfa2cb3f7cda847038b2591a6e07bbff
6a91ff2707d18b5f397a03c8e6433b4e
The checksums of the first two items should be equal. Unfortunately, the template lookup adds an empty line to the result but the module template, when creating the file, removes this empty line. If you want to get the same checksums remove the last empty line from the result of the template lookup
- debug:
msg: |
{{ tmpl|md5 }}
{{ lookup('file', '/tmp/sshd_config')|md5 }}
{{ lookup('file', 'sshd_config.j2')|md5 }}
vars:
tmpl: "{{ lookup('template', 'sshd_config.j2').splitlines()|join('\n') }}"
gives
msg: |-
bfa2cb3f7cda847038b2591a6e07bbff
bfa2cb3f7cda847038b2591a6e07bbff
6a91ff2707d18b5f397a03c8e6433b4e