Warning : found a duplicate dict key (ansible.builtin.command)

Hi

My ansible version :

[ansible@adm-ansible-infra-01 ansible-port-check]$ ansible --version
ansible [core 2.16.3]
  config file = /opt/ansible/playbooks-bebert/ansible-port-check/ansible.cfg
  configured module search path = ['/opt/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.12/site-packages/ansible
  ansible collection location = /opt/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.12.6 (main, Sep 23 2024, 09:58:19) [GCC 8.5.0 20210514 (Red Hat 8.5.0-22)] (/usr/bin/python3.12)
  jinja version = 3.1.2
  libyaml = True

My playbook code

---
- name: "Mon playbook de test d'ouverture de port avec CURL"
  hosts: frtwebservices
  tasks:
          - name: "Test d'ouverture vers serveur applicatif"
          #Test cas 1 port ouvert
            ansible.builtin.command:
                    cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8731"
          #Test cas 2 port non ouvert
            ansible.builtin.command:
                    cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8756"
         #Test cas 3 port ouvert mais pas de service utilisant le port sur la destination => OK
            ansible.builtin.command:
                    cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8753"
            ignore_errors: yes

...

Result

[ansible@adm-ansible-infra-01 ansible-port-check]$ ansible-playbook testport_curl.yaml
[WARNING]: While constructing a mapping from /opt/ansible/playbooks-bebert/ansible-port-check/testport_curl.yaml, line 5, column 13, found a duplicate dict key (ansible.builtin.command). Using last defined value only.

I’m working on a playbook to test port accessibility configuration requirement between some server on some port. My final goal is to have a friendly readable custom RECAP like this
{source_serveur} {target_server}{port_testing}{testResult {OK{lignGreen};KO{lignRed}}

To do this i use module ansible.builtin.command and execute remotely a curl commande to get back curl “rc” value :
0 : Port is open => OK
28 : Port is close => KO
7 : Port is open but nothing use it on remote server => OK (in my case as at requirement state my software aren’t install yet but have to be sure port is open on our firewall)

It’s the best way i find to do it but if some have a best practice better than mine don’t hesitate to make suggestion ;). I’m in test phase ;).

At beginning of my project i test command one by one and all work as attempt.

But now i have to use more than one command and i get this warning :

[ansible@adm-ansible-infra-01 ansible-port-check]$ ansible-playbook testport_curl.yaml
[WARNING]: While constructing a mapping from /opt/ansible/playbooks-bebert/ansible-port-check/testport_curl.yaml, line 5, column 13, found a duplicate dict key (ansible.builtin.command). Using last defined value only.

More only the last test result is return.

How to solve this warning to make all the port test (and they are a lot of them to do) ?

Thank for Help

cordialy,

You need to change the YAML to something like this:

          - name: "Test d'ouverture vers serveur applicatif 8731"
            #Test cas 1 port ouvert
            ansible.builtin.command:
              cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8731"
            ignore_errors: yes

          - name: "Test d'ouverture vers serveur applicatif 8756"
            #Test cas 2 port non ouvert
            ansible.builtin.command:
              cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8756"
            ignore_errors: yes

          - name: "Test d'ouverture vers serveur applicatif 8753"
           #Test cas 3 port ouvert mais pas de service utilisant le port sur la destination => OK
            ansible.builtin.command:
              cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8753"
            ignore_errors: yes

Or use a loop

I’d probably also use community.general.listen_ports_facts module to check for listening ports if you have SSH access to the remoteServer or the ansible.builtin.uri module if you want to use HTTP to check for HTTP services rather than curl.

1 Like

Looks like you only have one task but are trying to do three things in it. I think you need a - name: "whatever" for every ansible.builtin.command. If you want to group the three tasks somwhow, you might want to use a block. Maybe something like:

---
- name: "Mon playbook de test d'ouverture de port avec CURL"
  hosts: frtwebservices
  tasks:
    - name: "Test d'ouverture vers serveur applicatif"
      block:
        - name: Test cas 1 port ouvert
          ansible.builtin.command:
            cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8756"
        - name: Test cas 2 port non ouvert
          ansible.builtin.command:
            cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8756"
        - name: Test cas 3 port ouvert mais pas de service utilisant le port sur la destination => OK
          ansible.builtin.command:
            cmd: "/usr/bin/curl --connect-timeout 3 --silent --show-error remoteServer:8753"

I’m not sure where the ignore_errors: yes would fit in, the whole block or only the last / third task.

Hope this helps.

1 Like

Good point. using ansible.builtin.command should always be the last resort IMHO.

1 Like

Hi again,

Thank for this suggestion but the main goal of my project is to get a playbook that test if port are open on ours firewall between our servers solution.

community.general.listen_ports_facts module : seems to test statement of port remotely and don’t test communication through a firewall to this port (or i missanderstand?)

ansible.builtin.uri module : I think I use it because i’ve http and https communication test requirement to do through firewall to validate access to some webservices.

I’m testing you’re split name suggestion first.
Then try the loop suggestion and make a feedback

@mariolenz thx to your suggestion will make some search about block :wink:

thank for help

1 Like

The community.general.listen_ports_facts module lists the open ports on the localhost (the server the Ansible controller connects to) — if you want to check for open ports / port scan a server from outside that server to you could do something like use nmap, via the command module with it set to generate XML output and then parse that, for example see the tasks here.

I think ansible.builtin.wait_for can also be used to test if a port is open. That is, if some process is listening on this port put not if it’s HTTP(S). Anyway, maybe that’s already enough for your use-case.

1 Like