I have a scenario
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?
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