ansibleansible-awx

ansible port check for multiple location with multiple end points


I have a scenario

  1. I have multiple sources (3 sources )
  2. I have multiple end points (more than 10,000 end points)
  3. I have multiple ports (2 ports)

I modified the playbook after referencing few websites. ansible task - Locate running port on a list of servers and came up this this code

---
- name: TCP Port Checker
  hosts: all
  gather_facts: false
  vars:
    time_out: 2
    ports: [[80,443,8443,9090], [80,443,8443,9090], [80,443,8443,9090], [80,443,8443,9090], [80,443,8443,9090], [80,443,8443,9090] ]
    capsule: ['abc.com', 'bac.com', 'cab.com', 'baa.com', 'arc.com', 'maa.com']
    capsuleandport: "{{ dict(capsule | zip(ports)) }}"
  tasks:
    - name: Print vars
      ansible.builtin.debug:
        msg: "{{ capsule }} and {{ ports }}"

    - name: Check port
      ansible.builtin.wait_for:
        host: "{{ item.0.key }}"
        port: "{{ item.1 }}"
        timeout: "{{ time_out }}"
        msg: &error_msg "Timeout when waiting"
      loop: "{{ capsuleandport | dict2items | subelements('value') }}"
      ignore_errors: true
      register: caphost

    - name: Debug
      ansible.builtin.debug:
        msg: "the output of {{ caphost }}"

    - debug:
        var: dict(capsule | zip(ports))

    - name: save the Json data to a Variable as a Fact
      set_fact:
        jsondata: "{{ caphost.stdout | from_json }}"

All the hosts are able to communicate with the ports but I want to select the results that failed and put the target and port in a variable. How to do this one?


Solution

  • You are passing capsule which is a list (of servers) directly to the the host parameter which expects a string (i.e. one single server address). As very explicitly reported by your error message, your list is automagically cast to a string making your host parameter a string representation of the list (which makes an unknown address). What you want to do instead is test each port for each server.

    The most straightforward way is to create a list of tuples (host, port) with the product filter and loop on that. In a nutshell:

            - name: check port
              wait_for:
                host: "{{ item.0 }}"
                port: "{{ item.1 }}"
                timeout: "{{ time_out }}"
              loop: "{{ capsule | product(ports) }}"
              when: ansible_distribution == 'CentOS' or ansible_distribution == 'Rocky'
              register: out