0

I have to two array from mysql query and I want to make a host comparison. For example, the result of mysql result is like list1 & list2.

- name:
  set_fact:
    list1:
      - host: '[\"X.XXX.XX.XXX\"]'
        username: username1
      - host: '[\"X.XXX.XX.XXX\"]'
        username: username2
      - host: '[\"X.XXX.XX.XXX\"]'
        username: username3
      - host: 
        - '[\"XX.XXX.XX.XXX\"]' 
        - '[\"XX.X.X.XXX\"]'
        username: username4
      - host: '[\"XX.X.X.XXX\"]'
        username: username5
      - host: '[\"localhost\"]'
        username: username6
      - host: '[\"XX.XXX.XX.XXX\"]'
        username: username7
    list2: 
      - host: 'X.XXX.XX.XXX'
        username: username1
      - host: 'localhost'
        username: username2
      - host: 'XX.XXX.XX.XXX'
        username: username3
      - host: 'localhost'
        username: username4
      - host: 'XX.X.X.XXX'
        username: username5
  tags: [diff]

As you see, list2 from mysql query sent back hosts with some unecessary chars and I want to remove them because when making the comparison, the condition is false.

- name: Comparison of two lists
  debug: 
    msg: "{{ item.0.username }}({{ item.0.host }}) == {{ item.1.username }}({{ item.1.host }}) {{ item.0.username == item.1.username }}"
  loop: "{{ list1 | product(list2) | list }}"
  when: 
    - "{{ item.0.host == item.1.host }} == True"
  register: output
  tags: [diff]

Here is the output from Ansible :

skipping: [staging1-sql0] => (item=[{'host': '[\\"X.XXX.XX.XXX\\"]', 'username': 'username1'}, {'host': 'X.XXX.XX.XXX', 'username': 'username1'}]) 
skipping: [staging1-sql0] => (item=[{'host': '[\\"X.XXX.XX.XXX\\"]', 'username': 'username2'}, {'host': 'localhost', 'username': 'username2'}]) 
skipping: [staging1-sql0] => (item=[{'host': '[\\"X.XXX.XX.XXX\\"]', 'username': 'username3'}, {'host': 'XX.XXX.XX.XXX', 'username': 'username3'}]) 

How can I fix this ?

1 Answers1

0

Are you using other lists or this should be loop: "{{ list1 | product(list2) | list }}" instead?

I tried this code and it worked:

- hosts: localhost
  gather_facts: no

  tasks:

  - name:
    set_fact:
      list1:
        - host: '[\"X.XXX.XX.XXX\"]'
          username: username1
        - host: '[\"X.XXX.XX.XXX\"]'
          username: username2
        - host: '[\"X.XXX.XX.XXX\"]'
          username: username3
        - host: 
          - '[\"XX.XXX.XX.XXX\"]' 
          - '[\"XX.X.X.XXX\"]'
          username: username4
        - host: '[\"XX.X.X.XXX\"]'
          username: username5
        - host: '[\"localhost\"]'
          username: username6
        - host: '[\"XX.XXX.XX.XXX\"]'
          username: username7
      list2: 
        - host: 'X.XXX.XX.XXX'
          username: username1
        - host: 'localhost'
          username: username2
        - host: 'XX.XXX.XX.XXX'
          username: username3
        - host: 'localhost'
          username: username4
        - host: 'XX.X.X.XXX'
          username: username5
    tags: [diff]

  - name: Comparison of two lists
    debug: 
      msg:
        - "{{ list1_username }}{{ list1_host }} == {{ list2_username}}({{ list2_host}}) {{ list1_username == list2_username }}"
    loop: "{{ list1 | product(list2) | list }}"
    when: list1_host == list2_host
    register: output
    tags: [diff]
    vars:
      list1_host: "{{ (item.0.host|replace('[\\\"','')|replace('\\\"]','')) }}"
      list1_username: "{{ item.0.username }}"
      list2_host: "{{ item.1.host }}"
      list2_username: "{{ item.1.username }}"

Hints:

  • No need to use jinja templating in when clauses.
  • Sometimes it's better to create arguments to the task to clarify variable's attributes inside a looping
  • Instead of using debug, you can set the information to a variable or append to a list
  • Be careful to always test your code with better data variation and use block and rescue to prevent fatal runtime errors.

I don't really know what are you doing but you can improve you code by using select filter, including a task file while looping through the first list and then comparing with the second one, using templates and other things... Share the whole case and we can help better.

guistela
  • 104
  • 4
  • Sorry my bad, yes it should be `loop: "{{ list1 | product(list2) | list }}"` Indeed, my code isn't that good. I'm currently working to improve it. What I exactly want to do by doing this, is to create a playbook "Users to remove" that will remove users. Basically, I have two servers : Ansible et MySQL. I extract informations such as Username and Ip and I compare them to find the username and ip that is my Ansible server, but not in my MySQL server. I have to make an optimal playbook for the case that a username has several ips. Thank you for the code I'll try it rn and let you know it works. – Mansour NDIAYE Apr 02 '21 at 11:14