who i can remplace multiple line in a cfg - ansible

I would like some help to be able to replace several lines in a cfg file with the ansible module lineinfile
- name: "[MODIFY /etc/zabbix/zabbix.agentd.conf]
lineinfile:
path: /etc/zabbix/zabbix.agentd.conf]
insertafter: "{{ item}}"
with_items:
- line 99
- line 77
line: "{{ item }}"
with_items:
- set number
- :colorschem murphy
become: yes
become_method: sudo

A: It's not possible to use two loops (with_items) in one task.
Put the configuration data into one loop. Try the task below
- name: MODIFY /etc/zabbix/zabbix.agentd.conf
lineinfile:
path: /etc/zabbix/zabbix.agentd.conf
line: "{{ item.line }}"
insertafter: "{{ item.after }}"
loop:
- line: 'line 99'
after: 'set number'
- line: 'line 77'
after: 'colorschem murphy'
become: yes
become_method: sudo
Q: I want replaces line 99 by set number
A: Use replace module.
- name: MODIFY /etc/zabbix/zabbix.agentd.conf
replace:
path: /etc/zabbix/zabbix.agentd.conf
regexp: "{{ item.regexp }}"
replace: "{{ item.replace }}"
loop:
- regexp: 'line 99'
replace: 'set number'
become: yes
become_method: sudo
(not tested)

This might be a good time to use templates:
- name: MODIFY /etc/zabbix/zabbix.agentd.conf
template:
src: template/zabbix.agentd.conf.j2
dest: /etc/zabbix/zabbix.agentd.conf
The file zabbix.agentd.conf.j2 should be a copy of the file you want to copy at the dest path. Your variable goes in the j2 file and can be change at each interaction.
Example:
vi zabbix.agentd.conf.j2
line 1 my file
line 2
line 3
.
.
line 99 {{ set number }}

Related

ansible playbook inline to add multiple lines

i got following pb to add multiple lines to chrony.conf
- name: add line
lineinfile:
backup: no
backrefs: no
state: present
path: "{{ file_path }}"
insertafter: "{{ line.replace_with }}"
line: "{{ line.line_to_add }}"
with_items:
- { search: "{{ line.replace_with }}", add: "{{ line.line_to_add }}" }
in my vars files I got it like this
line:
line_to_add:
- "server ntp1.domain.com iburst"
- "server ntp2.domain.com iburst"
- "server ntp3.domain.com iburst"
but the change put all 3 ntp servers in one line instead of 3.
any idea?
when i change my yml to
- name: add line
lineinfile:
backup: no
backrefs: no
state: present
path: "{{ file_path }}"
#regexp: '^(\s*)[#]?{{ item.search }}(: )*'
insertafter: "{{ line.replace_with }}"
line: "{{ item }}"
create: true
loop: "{{ line.line_to_add }}"
with_items:
- { search: "{{ line.replace_with }}", add: "{{ line.line_to_add }}" }
I get suplicate loop in task: items
You can use loop for this to iterate each line in the line.line_to_add variable. I also assumed that you have another line.replace_with variable.
- name: Example of multiple lines
hosts: localhost
gather_facts: no
vars:
line:
line_to_add:
- "server ntp1.domain.com iburst"
- "server ntp2.domain.com iburst"
- "server ntp3.domain.com iburst"
replace_with:
- test_line
tasks:
- name: add line
lineinfile:
backup: no
backrefs: no
state: present
path: test_file
insertafter: "{{ line.replace_with }}"
line: "{{ item }}"
create: true
loop: "{{ line.line_to_add }}"
Gives:
server ntp1.domain.com iburst
server ntp2.domain.com iburst
server ntp3.domain.com iburst

How to add multiple lines in all files present in a directory using Ansible

In Ansible script, First I'm using find_module to find all files in a directory, and then I'm using set_fact to mention all commands that I want to add in all files and then I am using lineinfile module to add multiple lines in all the files, but it is adding all commands in list format ['line1','line2','line3'] instead of this I want these lines to be added one after another in all files.
Below mentioned is the script
tasks:
- name: finding all files present in something directory
find:
paths: /etc/something.d/
file_type: file
patterns: '*.d'
register: c1
become: true
- set_fact:
lines:
- "line1"
- "line2"
- "line3"
- lineinfile:
path: "{{ item.path }}"
line: "{{ lines}}"
state: present
create: yes
backup: yes
register: c2
become: true
with_items: "{{ c1.files }}"
- debug:
var: c1
- debug:
var: c2
This works for me:
tasks:
- name: finding all files present in something directory
find:
paths: /etc/something.d/
file_type: file
patterns: '*.d'
register: c1
become: true
- blockinfile:
path: "{{ item.path }}"
state: present
create: yes
backup: yes
block: |
line1
line1
line1
register: c2
become: true
with_items: "{{ c1.files }}"
- debug:
var: c1
- debug:
var: c2
So... the old way, which I prefer, is with_nested:
set_fact:
lines:
- line1
- line2
- line3
lineinfile:
...
...
with_nested:
- "{{ c1.files }}"
- "{{ lines }}"
The new way, and I have no idea what escapee from a Ph.D. CS program came up with this, is to combine the lists:
set_fact:
lines:
- line1
- line2
- line3
lineinfile:
...
...
loop: "{{ c1.files | product | lines | list }}"
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#with-nested-with-cartesian
If all the lines are together, you might want to look at blockinfile.
I was able to add multiple lines in all files present in a directory by using below mentioned ansible script, However the problem now is all lines are getting duplicated, if I run this script again, Please suggest any way so that lines won't get duplicated in all files
tasks:
- name: finding all files present in something directory
find:
paths: /etc/something.d/
file_type: file
patterns: '*.d'
register: c1
become: true
- set_fact:
lines:
- "line1"
- "line2"
- "line3"
- lineinfile:
path: "{{ item.path }}"
line: "{{ lines[0]+'\n'+lines[1]+'\n'+lines[2]+'\n'}}"
state: present
create: yes
backup: yes
register: c2
become: true
with_items: "{{ c1.files }}"
- debug:
var: c1
- debug:
var: c2

Use Ansible to ensure a file exists, ignoring any extra lines

I'm trying to update the sssd.conf file on about 200 servers with a standardized configuration file, however, there is one possible exception to the standard. Most servers will have a config that looks like this:
[domain/domainname.local]
id_provider = ad
access_provider = simple
simple_allow_groups = unixsystemsadmins, datacenteradmins, sysengineeringadmins, webgroup
default_shell = /bin/bash
fallback_homedir = /export/home/%u
debug_level = 0
ldap_id_mapping = false
case_sensitive = false
cache_credentials = true
dyndns_update = true
dyndns_refresh_interval = 43200
dyndns_update_ptr = true
dyndns_ttl = 3600
ad_use_ldaps = True
[sssd]
services = nss, pam
config_file_version = 2
domains = domainname.local
[nss]
[pam]
However, on some servers, there's an additional line after simple_allow_groups called simple_allow_users, and each server that has this line has it configured for specific users to be allowed to connect without being a member of an LDAP group.
My objective is to replace the sssd.conf file on all servers, but not to remove this simple_allow_users line, if it exists. I looked into lineinfile and blockinfile, but neither of these seems to really handle this exception. I'm thinking I'm going to have to check the file for the existance of the line, store it to a variable, push the new file, and then add the line back, using the variable afterwards, but I'm not entirely sure if this is the best way to handle it. Any suggestions on the best way to accomplish what I'm looking to do?
Thanks!
I would do the following
See if the simple_allow_users exists in the current sssd.conf file
Change your model configuration to add the current value of the line simple_allow_users is exists
overwrite the sssd.conf file with the new content
You can use jinja2 conditional to achieve step 2 https://jinja2docs.readthedocs.io/
I beleive the above tasks will solve what you need, just remember to test on a simngle host and backup the original file just for good measure ;-)
- shell:
grep 'simple_allow_users' {{ sssd_conf_path }}
vars:
sssd_conf_path: /etc/sssd.conf
register: grep_result
- set_fact:
configuration_template: |
[domain/domainname.local]
id_provider = ad
access_provider = simple
simple_allow_groups = unixsystemsadmins, datacenteradmins, sysengineeringadmins, webgroup
{% if 'simple_allow_users' in grep_result.stdout %}
{{ grep_result.stdout.rstrip() }}
{% endif %}
default_shell = /bin/bash
..... Rest of your config file
- copy:
content: "{{ configuration_template }}"
dest: "{{ sssd_conf_path }}"
vars:
sssd_conf_path: /etc/sssd.conf
I used Zeitounator's tip, along with this question Only check whether a line present in a file (ansible)
This is what I came up with:
*as it turns out, the simple_allow_groups are being changed after the systems are deployed (thanks for telling the admins about that, you guys... /snark for the people messing with my config files)
---
- name: Get Remote SSSD Config
become: true
slurp:
src: /etc/sssd/sssd.conf
register: slurpsssd
- name: Set simple_allow_users if exists
set_fact:
simpleallowusers: "{{ linetomatch }}"
loop: "{{ file_lines }}"
loop_control:
loop_var: linetomatch
vars:
- decode_content: "{{ slurpsssd['content'] | b64decode }}"
- file_lines: "{{ decode_content.split('\n') }}"
when: '"simple_allow_users" in linetomatch'
- name: Set simple_allow_groups
set_fact:
simpleallowgroups: "{{ linetomatch }}"
loop: "{{ file_lines }}"
loop_control:
loop_var: linetomatch
vars:
- decode_content: "{{ slurpsssd['content'] | b64decode }}"
- file_lines: "{{ decode_content.split('\n') }}"
when: '"simple_allow_groups" in linetomatch'
- name: Install SSSD Config
copy:
src: etc/sssd/sssd.conf
dest: /etc/sssd/sssd.conf
owner: root
group: root
mode: 0600
backup: yes
become: true
- name: Add simple_allow_users back to file if it existed
lineinfile:
path: /etc/sssd/sssd.conf
line: "{{ simpleallowusers }}"
insertafter: "^simple_allow_groups"
when: simpleallowusers is defined
become: true
- name: Replace simple allow groups with existing values
lineinfile:
path: /etc/sssd/sssd.conf
line: "{{ simpleallowgroups }}"
regexp: "^simple_allow_groups"
backrefs: true
when: simpleallowgroups is defined
become: true

Remove the users from /etc/ssh/sshd_config with Ansible

I am trying to remove users added to the AllowGroups line in the /etc/ssh/sshd_conf file using the following after the comments from #imjoseangel.
The current line is
AllowGroups devops1 devops2 devops3 user01 user02 user03
The desired line is
AllowGroups devops1 devops2 user02 user03
The play is
name: Remove User from AllowGroups (opening dash removed)
replace:
regexp: "(^AllowGroups)\\s.*"
backup: True
path: /etc/ssh/sshd_config.bak
replace: "\\1 {{ item }} "
with_items:
- devops3
- user01
After the play is complete I am getting the following
"AllowGroups user01"
The whole is replaced by last user in the "item".
This solution worked.
tasks:
- name: Remove User from AllowGroup and AllowUsers
replace:
regexp: "{{ item }}"
backup: True
path: /etc/ssh/sshd_config.bak
replace: "\b"
with_items:
- devops1
- user03

Ansible - replace particular string in multiple files if file exists

I can replace a string in the file if the file exists in a directory.
Similarly, I want to replace the string in another 25 files (test2.conf .. test25.conf) if the files exist in the same directory. Using with_items I can able to replace a string in all files but unable to use the register to check the file exists in the loop.
Below playbook is a success for one file, how can I achieve the same for 25 files?
- hosts: webserver
vars:
strings:
- user1
- user2
tasks:
- name: Check /home/user/test1.conf exists
stat:
path: /home/user/test1.conf
register: stat_result
- name: Replace string in test1.conf
replace:
dest: /home/user/test1.conf
backup: yes
regexp: '^Hello'
replace: "Hello {{ strings | join(' ')}}"
when: stat_result.stat.exists == True
Use find module instead of stat and iterate over the results:
- hosts: webserver
vars:
strings:
- user1
- user2
tasks:
- name: Get a list of test*.conf in /home/user
find:
paths: /home/user
patterns: test*.conf
register: my_find
- name: Replace strings in files found
replace:
dest: "{{ item.path }}"
backup: yes
regexp: '^Hello'
replace: "Hello {{ strings | join(' ')}}"
with_items: "{{ my_find.files }}"
Your replace task is not idempotent, it will add strings infinitely on subsequent runs.

Resources