Background: I had a lineinfile module that was using regexp and line to ensure I have correct lines inside of my config files. This works perfectly but there is an issue that I did not think of, other people adding in the same line in the config file with a different setting. Ansible lineinfile only changes the last instance; In order to fix this, I created a function to handle all of the duplicates, so we only have one instance of that line in the file. I know that templating the files would be fast/optimal, but I am not allowed to do that... Below is the working code; inside of the roles/duplicate_checker/tasks/main.yml, I want to basically check to see if the line inside of the config_path is the same as the variable I am passing through (config_line).
What I want to be able to do: All I want is to be able to skip the last task in roles/duplicate_checker/tasks/main.yml if the line that I am tyring to change is the same as in the file.
roles/kyle/tasks/main.yml:
---
- name: Lineinfile handler
include_role:
name: "roles/duplicate_checker"
loop: "{{ lineinfile_facts }}"
vars:
config_name: "{{ item.name }}"
config_path: "{{ item.path }}"
config_regexp: '{{ item.regexp }}'
config_line: "{{ item.line }}"
config_stigid: "{{ item.stigid }}"
when: item.when
- name: Notify handlers with assert
assert: { that: true, quiet: true }
changed_when: True
when: True
notify:
- dconf_update
- ssh_restart
- auditd_restart
roles/kyle/defaults/main.yml:
lineinfile_facts:
- name: 'Banner'
stigid: 'V-230225'
path: '/etc/ssh/sshd_config'
regexp: '^\s*(?i)banner\s+'
line: 'banner /etc/issue'
when: True and "'openssh-server' in packages"
# I have like over 150 of these
roles/duplicate_checker/tasks/main.yml:
---
# This takes 4 seconds
- name: "{{ config_stigid }} Get the count of occurences in {{ config_path }}"
lineinfile:
path: "{{ config_path }}"
regexp: "{{ config_regexp }}"
state: absent
check_mode: true
changed_when: false
register: dupes
# This should be skipped most of the time, so I am not worried about this
- name: "{{ config_stigid }} Remove all occurences from {{ config_path }} if the count is greater than one"
replace:
path: "{{ config_path }}"
regexp: "{{ config_regexp }}"
when:
- dupes.found is defined
- dupes.found > 1
# This takes 4 seconds, but I want to be able to skip it if the line in the file and the line in my variables, config_line are the exact same
- name: "{{ config_stigid }} {{ config_name }}"
lineinfile:
path: "{{ config_path }}"
line: "{{ config_line }}"
regexp: "{{ config_regexp }}"
create: true
What I tried: I tried to use ansible builtin lookups inside of the when condition of the task below but after a ton of errors I figured out that this only searches on the control node and I want it to search on the host.
- name: "{{ config_stigid }} {{ config_name }}"
lineinfile:
path: "{{ config_path }}"
line: "{{ config_line }}"
regexp: "{{ config_regexp }}"
create: true
when: "{{ config_line not in lookup('file', config_path) }}"