How we can call a variable in ansible playbook while using loops

Deadly 提交于 2020-08-08 07:02:29

问题


I have two files where these file contains server names and server IP's, I want to change/replace some specific server names and IP addressees in both the files based on the requirement.

This is related to This Post <-- as it was asked to open a new post.

My scenario:

In the Below example files(file & file2) i need to do follows..

1 - In file1 and fil2 i have to replace fostrain01.example.com with dbfostrain01.example.com.

2 - Where in another line i have to replace 171.20.20.18 with 172.20.20.18 in both the files as well.

# cat /etc/file1
fostrain01.example.com
fostrain02.example.com
ServerIPS 171.20.20.16 171.20.20.17 171.20.20.18 171.20.20.19 171.20.20.20

# cat /etc/fil2
fostrain01.example.com
fostrain02.example.com  
ServerIPS 171.20.20.16 171.20.20.17 171.20.20.18 171.20.20.19 171.20.20.20

My Playbook:

---
- name: Replace file contents
  hosts: all
  gather_facts: false
  vars:
    files:
      - /etc/file1
      - /etc/file2
    from_str: "fostrain01.example.com"
    to_str: "dbfoxtrain01.example.com"
    from_ip: "^(.*)171\\.20\\.20\\.18(.*)$"
   to_ip: "\\g<1>172.20.20.18\\g<2>"
   
  tasks:
    - name: Replace elements in file
      replace:
        path: "{{ item.path }}"
        regexp: "{{ item.From }}"
        replace: "{{ item.To }}"
        backup: yes
      loop:
        # Replace the desired string
        - { path: "{{ item }}", From: "{{ from_str }}", To: "{{ to_str }}" }
        #  Replace the desired ip
        - { path: "{{ item }}", From: "{{ from_ip }}", To: "{{ to_ip }}" }

In the above playbook, i have defined the variables for each sections as you can see.

What I'm Missing and Would Like to Know:

I am missing to understand about How i can use or reference files variable in the path section of replace module in my playbook above while using loop.

Just to clarify, i'm talking about below one..

    files:
      - /etc/file1
      - /etc/file2

I am looking this to be fitted within the approach in the above playbook, as i know the other way around of doing it.

I am sorry, if i could not make it more clear.


回答1:


So file is a list of variable, as any list of varibales, the items are accessible via a 0-indexed key.

  • So in you case, the first element of the files list, containing /etc/file1 is accessible either via

    files.0
    

    Or

    files[0]
    
  • The second, containing /etc/file1 is accessible either via

    files.1
    

    Or

    files[1]
    
  • And so on, and so forth.


But there is a lot of other ways to do this:

  1. you could use product to merge your two lists
  2. you could use the loop_control parameter index_var to create your own index
  3. you could use the extended parameter of loop_control, that provides the extended variable ansible_loop.index0

All this said, to make it a little bit more generic, if I were you, I would use the product filter and go with a more simpler:

- name: Replace elements in file
  replace:
    path: "{{ item.0 }}"
    regexp: "{{ item.1.from }}"
    replace: "{{ item.1.to }}"
    backup: yes
  vars:
    paths:
      - /etc/file1
      - /etc/file2
    replaces:
      - from: "fostrain01.example.com"
        to: "dbfoxtrain01.example.com"
      - from: "^(.*)171\\.20\\.20\\.18(.*)$"
        to: "\\g<1>172.20.20.18\\g<2>"
  loop: "{{ paths | product(replaces) | list }}"

Because, then there is no reason to transform your list, it is already has it should for your replace task.
Mind that variables can be defined both at play or task level, if you need the replaces variable in other tasks, just bring it back up to the play level.




回答2:


You are almost there with your solution, Just you have to use files variable as an index key to the file selection as nicely illustrated by @β.εηοιτ.βε in his answer section.

So, to complete your code to make it working, it should be working as follows..

---
- name: Replace file contents
  hosts: all
  gather_facts: false
  vars:
    files:
      - /etc/file1
      - /etc/file2
    from_str: "fostrain01.example.com"
    to_str: "dbfoxtrain01.example.com"
    from_ip: "^(.*)171\\.20\\.20\\.18(.*)$"
   to_ip: "\\g<1>172.20.20.18\\g<2>"
  
tasks:
    - name: Replace elements in file
      replace:
        path: "{{ item.path }}"
        regexp: "{{ item.From }}"
        replace: "{{ item.To }}"
        backup: yes
      loop:
        # Replace the desired string
        - { path: "{{ files[0] }}", From: "{{ from_str }}", To: "{{ to_str }}" }
        - { path: "{{ files[0] }}", From: "{{ from_ip }}", To: "{{ to_ip }}" } 
        #  Replace the desired ip
        - { path: "{{ files[1] }}", From: "{{ from_str }}", To: "{{ to_str }}" }
        - { path: "{{ files[1] }}", From: "{{ from_ip }}", To: "{{ to_ip }}" }


来源:https://stackoverflow.com/questions/62875869/how-we-can-call-a-variable-in-ansible-playbook-while-using-loops

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!