pytest-dev / pytest-testinfra

Testinfra test your infrastructures
https://testinfra.readthedocs.io
Apache License 2.0
2.37k stars 355 forks source link

socket test for '::ffff:127.0.0.1:8060' #286

Open igilbert opened 6 years ago

igilbert commented 6 years ago

netstat -n -l -t tcp 0 0 ::ffff:127.0.0.1:8060 :::* LISTEN

host.socket('tcp://127.0.0.1:8060').is_listening evaluated to false in testinfra 1.10.1 should be true!?

elliotweiser commented 6 years ago

I'd recommend adding some more information to your issue. The following details would be useful.

  1. OS version
  2. Distro version (if Linux)
  3. Docker container (if using a public Docker container)

Anything you can think of that would help someone reading this to reproduce your issue could prove useful.

igilbert commented 6 years ago

I'm using a private docker image.

cat /etc/redhat-release CentOS release 6.8 (Final)

uname -r 3.10.0-514.6.2.el7.x86_64

It seems that Testinfra cannot parse it when 'netstat' cmd return a 'Local Address' like ' ::ffff:127.0.0.1:8060', and evaluate host.socket('tcp://127.0.0.1:8060').is_listening to false

elliotweiser commented 6 years ago

@igilbert Based on your netstat output, it sounds like the listening socket of your server is using the IPv4 loopback device, but in the IPv6 namespace. Out of curiosity, what happens if you use the following code?

host.socket('tcp6://::ffff:127.0.0.1:8060')

It certainly might be a parsing error. As a user of Testinfra, I would agree that your test should have returned True. I pulled a centos:6.8 Docker image and did the following to aid you.

# Install nc
yum install -y nc

# Start a listening socket (which terminates after the first connection)
nc -l ::ffff:127.0.0.1 8060 &

# Show netstat output
netstat -nlt

# Connect to the listening socket using IPv4
nc -vz4 127.0.0.1 8060

# Restart the listening socket
nc -l ::ffff:127.0.0.1 8060 &

# This time, connect using IPv6
nc -vz6 ::ffff:127.0.0.1 8060

Netstat output:

[root@ff8c13f4e8cd /]# netstat -n -l -t
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State
tcp        0      0 ::ffff:127.0.0.1:8060       :::*                        LISTEN

Testing w/ IPv4:

[root@ff8c13f4e8cd /]# nc -vz4 127.0.0.1 8060
Connection to 127.0.0.1 8060 port [tcp/*] succeeded!

Testing w/ IPv6 (after recreating the socket)

[root@ff8c13f4e8cd /]# nc -vz6 ::ffff:127.0.0.1 8060
Connection to ::ffff:127.0.0.1 8060 port [tcp/*] succeeded!

Conclusions:

  1. Your test should work if you change your protocol to tcp6
  2. Testinfra should cover the edge-case where the IPv6 address contains an IPv4 address (as long as the protocol also uses IPv4)

Let me know the output of your test using tcp6, and then we can figure out where to go from here. I can probably cook up a patch to cover the edge-case.

igilbert commented 6 years ago

Many thanks! Testinfra version 1.10.1 which I am using does not support the following socketspec? socketspec = 'tcp6://::ffff:127.0.0.1:8060'

Here is the error info: def parse_socketspec(socketspec):

    protocol, address = socketspec.split("://", 1)

    if protocol not in ("udp", "tcp", "unix"):
        raise RuntimeError(
            "Cannot validate protocol '%s'. Should be tcp, udp or unix" % (
              protocol,))

E RuntimeError: Cannot validate protocol 'tcp6'. Should be tcp, udp or unix

D:\Python27\lib\site-packages\testinfra\modules\socket.py:29: RuntimeError

philpep commented 6 years ago

Yes tcp6 isn't a valid specifier.

@elliotweiser thanks for debugging ! Does it mean that for a listening socket ::ffff:a.b.c.d testinfra should expect ::ffff:a.b.c.d and a.b.c.d to be listening ?

One weird thing is that ::ffff:127.0.0.1 seems different than ::1.

elliotweiser commented 6 years ago

Apologies for muddying the waters. I think I crossed some wires in my mind when I thought tcp6 would be valid protocol for the URL string. Maybe because Goss does something like that.

Yeah, this is an edge case where both ::ffff:a.b.c.d (common for "new" services that are preparing to be IPv6-compatible) and a.b.c.d IP addresses are both technically valid (based on my netstat/nc output above).