Lineinfile - Skip/Update an item inside "with_items" using conditions

610 views
Skip to first unread message

farrukh ahmed

unread,
Aug 5, 2022, 2:43:59 AM8/5/22
to Ansible Project
I have a question.

Can an item inside "with_items" or "loop" be skipped? using condition "when some_variable is not defined" ?

Here is my play.

- name: "Update text in the file"
  lineinfile:
    path: /path-to-the-file/
    backrefs: yes
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
  with_items:
    - { regexp: '^text1', line: "text1 = {{ VAR1 }}", when: VAR1 is defined }  
    - { regexp: '^text2', line: "text2 = {{ VAR2 }}" }  
    - { regexp: '^text3', line: "text3 = {{ VAR3 }}" }


What I'm trying to achieve is, it should replace the line only when VAR1 value is defined, else it should skip this item and move on to 2nd item.

Vladimir Botka

unread,
Aug 5, 2022, 5:18:05 AM8/5/22
to farrukh ahmed, ansible...@googlegroups.com
On Thu, 4 Aug 2022 23:43:59 -0700 (PDT)
farrukh ahmed <farrukha...@gmail.com> wrote:

> with_items:
> - { regexp: '^text1', line: "text1 = {{ VAR1 }}", when: VAR1 is defined }
> - { regexp: '^text2', line: "text2 = {{ VAR2 }}" }
> - { regexp: '^text3', line: "text3 = {{ VAR3 }}" }

Set *default* to avoid errors, add attribute *def*, and select lines.
For example,

shell> cat pb.yml
---
- hosts: localhost
gather_facts: false
vars:
lines:
- regexp: '^text1'
line: 'text1 = {{ VAR1|d("undef") }}'
def: '{{ VAR1 is defined }}'
- regexp: '^text2'
line: 'text2 = {{ VAR2|d("undef") }}'
def: '{{ VAR2 is defined }}'
- regexp: '^text3'
line: 'text3 = {{ VAR3|d("undef") }}'
def: '{{ VAR3 is defined }}'
tasks:
- debug:
var: item
loop: "{{ lines|selectattr('def') }}"

gives

shell> ansible-playbook pb.yml -e VAR1=test

PLAY [localhost]
*********************************************************************

TASK [debug]
*********************************************************************
ok: [localhost] => (item={'regexp': '^text1', 'line': 'text1 = test',
'def': True}) => ansible_loop_var: item item:
def: true
line: text1 = test
regexp: ^text1

--
Vladimir Botka

farrukh ahmed

unread,
Aug 5, 2022, 7:31:54 AM8/5/22
to Ansible Project
Thanks for your reply Vladimir Botka.

This is my actual case:

 defaults > main.yml
---
# defaults file for redis_configs
redis_config_path: /etc/redis/redis.conf

# Default Params Values
MAX_MEM: 3000
TCP_KEEPALIVE: 0
TCP_BACKLOG: 511
MAX_CLIENTS: 15000
TIMEOUT: 1500


And this is: 

Tasks > main.yml

---

- name: "Update Redis Parameters in {{ redis_config_path }}"
  lineinfile:
    path: "{{ redis_config_path }}"
  backrefs: yes
  regexp: "{{ item.regexp }}"
  line: "{{ item.line }}"
  with_items:
    - { regexp: '^maxmemory', line: "maxmemory {{ MAX_MEM }}mb", when: {{ MAX_MEM }} is defined }
    - { regexp: '^tcp-keepalive', line: "tcp-keepalive {{ TCP_KEEPALIVE }}", when: {{ TCP_KEEPALIVE }} is defined }
    - { regexp: '^tcp-backlog', line: "tcp-backlog {{ TCP_BACKLOG }}", when: {{ TCP_BACKLOG }} is defined}
    - { regexp: '^maxclients', line: "maxclients {{ MAX_CLIENTS }}", when: {{ MAX_CLIENTS }} is defined}
    - { regexp: '^timeout', line: "timeout {{ TIMEOUT }}" }


I want this to check if each variable inside an item is defined then make the changes to the line in the file, otherwise skip only those items which variables is not defined.
For Instance, If I comment out the variable MAX_MEM from the defaults > main.yml. like below:

# Default Params Values
##MAX_MEM: 3000
TCP_KEEPALIVE: 0
TCP_BACKLOG: 511
MAX_CLIENTS: 15000
TIMEOUT: 1500 

Then the execution should skip changes to the line where MAX_MEM is undefined, and the rest lines should be changed as they defined.

Is it possible?


Stefan Hornburg (Racke)

unread,
Aug 5, 2022, 7:49:34 AM8/5/22
to ansible...@googlegroups.com
Sorry, but it eludes me why you didn't come up with the actual case in the first place.  I see no point in wasting everyone's time.

Regards

            Racke
> --
> You received this message because you are subscribed to the Google Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/0eaa1c36-727c-47a8-bebc-6f38db9f4971n%40googlegroups.com <https://groups.google.com/d/msgid/ansible-project/0eaa1c36-727c-47a8-bebc-6f38db9f4971n%40googlegroups.com?utm_medium=email&utm_source=footer>.


--
Automation expert - Ansible and friends
Linux administrator & Debian maintainer
Perl Dancer & conference hopper

Todd Lewis

unread,
Aug 5, 2022, 8:03:34 AM8/5/22
to ansible...@googlegroups.com
    - name: "Update Redis Parameters in {{ redis_config_path }}"
      lineinfile:
        path: "{{ redis_config_path }}"
        backrefs: yes
        regexp: "{{ item.regexp }}"
        line: "{{ item.line }}"
      when: item.line is match(omit)
      with_items:
        - { regexp: '^maxmemory',     line: "maxmemory {{ MAX_MEM | d(omit) }}mb" }
        - { regexp: '^tcp-keepalive', line: "tcp-keepalive {{ TCP_KEEPALIVE | d(omit) }}" }
        - { regexp: '^tcp-backlog',   line: "tcp-backlog {{ TCP_BACKLOG | d(omit) }}" }
        - { regexp: '^maxclients',    line: "maxclients {{ MAX_CLIENTS | d(omit) }}" }
        - { regexp: '^timeout',       line: "timeout {{ TIMEOUT }}" }

Todd Lewis

unread,
Aug 5, 2022, 8:22:03 AM8/5/22
to Ansible Project
That "when:" should be

    when: item.line is not search(omit)

farrukh ahmed

unread,
Aug 5, 2022, 11:27:05 AM8/5/22
to Ansible Project
Thanks @utoddl for your time and reply.


when:  item.line is not search(omit)

This solution actually worked for me.

Thanks & regards,

FARRUKH

farrukh ahmed

unread,
Dec 20, 2022, 6:47:21 AM12/20/22
to ansible...@googlegroups.com
Can we do the same with blockinfile?
For instance, if the variable is not found then omit only that item and move on to the next item and update it.

Here is my play
- name: insert/update php configurations in App_config_file
blockinfile:
path: "/etc/php/7.4/fpm/php.ini_bak"
marker: ";# {mark} ANSIBLE MANAGED BLOCK ###"
block: |
{% for items in item %}
{{ items }}
{% endfor %}
when: item is not search(omit)
with_items:
- { "display_errors = {{service_configurations.display_errors | d(omit) }}" }
- { "memory_limit = {{service_configurations.memory_limit | d(omit) }}M" }

Here is the output I'm getting:
root@aws-farrukhahmed-518:/etc/php/7.4/fpm# cat php.ini_bak
;# BEGIN ANSIBLE MANAGED BLOCK ###
memory_limit = {{service_configurations.memory_limit | d(omit) }}M
;# END ANSIBLE MANAGED BLOCK ###

root@aws-farrukhahmed-518:/etc/php/7.4/fpm#

Here is the command I'm using:
ansible-playbook -i hosts exec.yml -e '{"service_configurations":{"display_errors":"On","memory_limit":"128"}}' -vvv

The expected output should be:

;# BEGIN ANSIBLE MANAGED BLOCK ###
display_errors = On
memory_limit = 128M
;# END ANSIBLE MANAGED BLOCK ###


PS: It is mandatory for me to do this with the blockinfile module.

--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/hBHvqWAmixw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/2cf96c01-f0fc-4ed5-afdb-4329530ae06en%40googlegroups.com.

Dick Visser

unread,
Dec 20, 2022, 7:15:05 AM12/20/22
to ansible...@googlegroups.com
Hii

On Tue, 20 Dec 2022 at 12:47, farrukh ahmed <farrukha...@gmail.com> wrote:
>
> Can we do the same with blockinfile?

Maybe. But, what one can do, is not always what one should do - see below.

> PS: It is mandatory for me to do this with the blockinfile module.

This is not correct - the file should not be edited at all, because it
is a package provided file.
So, any updates will overwrite your changes. Plus you need to resort
to kludges (imho) like blockinfile.
What you should do, is put your local changes in a properly named ini
file below /etc/php/7.4/fpm/conf.d, which won't be touched by anyone
else.

Dick

farrukh ahmed

unread,
Dec 21, 2022, 6:30:36 AM12/21/22
to ansible...@googlegroups.com
Hello Team,

I have progressed but still not achieved my target with blockinfile module.
It should be updated the both items, as I passed both variables but It just updated the last item only i.e (memory_limit) 

Here is my play:
- name: update php configurations
blockinfile:
path: "{{ini_file_path}}" # set in defaults
marker: ";# {mark} ANSIBLE MANAGED BLOCK ###"
block: "{{ item.param }}"
loop:
- { param: "display_errors = {{service_configurations.display_errors | d(omit) }}"}
- { param: "memory_limit = {{service_configurations.memory_limit | d(omit) }}M"}
when: item.param is not search(omit)

The output I'm getting:
;# BEGIN ANSIBLE MANAGED BLOCK ###
memory_limit = 128M
;# END ANSIBLE MANAGED BLOCK ###

The output should be like this, if I passed both variables from the command line.
;# BEGIN ANSIBLE MANAGED BLOCK ###
display_errors = On
memory_limit = 128M
;# END ANSIBLE MANAGED BLOCK ###

The Command I'm using:
ansible-playbook -i hosts exec.yml -e '{"service_configurations":{"display_errors":"On","memory_limit":"128"}}'

I would be thankful for any help or ideas.

Thanks.
FARRUKH AHMED

--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/hBHvqWAmixw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.

Vladimir Botka

unread,
Dec 21, 2022, 10:14:48 AM12/21/22
to farrukh ahmed, ansible...@googlegroups.com
On Wed, 21 Dec 2022 16:30:03 +0500
farrukh ahmed <farrukha...@gmail.com> wrote:

> blockinfile:
> path: "{{ini_file_path}}" # set in defaults
> marker: ";# {mark} ANSIBLE MANAGED BLOCK ###"
> block: "{{ item.param }}"
> loop:
> - { param: "display_errors = {{service_configurations.display_errors |
> d(omit) }}"}
> - { param: "memory_limit = {{service_configurations.memory_limit | d(omit)
> }}M"}
> when: item.param is not search(omit)

The *marker* must be unique for each block. Otherwise the the blocks
will overwrite each other. For this purpose it would be practical to
change the structure of the iterated data. For example, the
simplified playbook below

shell> cat pb.yml
- hosts: localhost
tasks:
- blockinfile:
path: /tmp/test.ini
marker: "# {mark} {{ item.param }}"
block: |
{{ item.param }} = {{ item.value }}
loop:
- param: 'display_errors'
value: "{{ conf.errors }}"
- param: 'memory_limit'
value: "{{ conf.limit }}"

shell> ansible-playbook pb.yml -e '{"conf":{"errors":"On","limit":"128"}}'

works as expected and creates the file

shell> cat /tmp/test.ini
# BEGIN display_errors
display_errors = On
# END display_errors
# BEGIN memory_limit
memory_limit = 128
# END memory_limit

Fit the data and *marker* to your needs.

--
Vladimir Botka
Reply all
Reply to author
Forward
0 new messages