ansible_fqdn should use platform.node() instead of socket.getfqdn()

Hi Ansible devs,

I’ve just discovered, to my surprise and annoyance, that the ansible_fqdn fact is obtained by calling socket.getfqdn(). This means the socket module does a reverse DNS lookup on the host’s IP address (not sure which one). If anyone changes the reverse DNS, or if it is not set properly, it results in unexpected behaviour when using this fact. My expectation was that this fact would be looked up from the system’s own hostname, instead of DNS.

Would you consider fixing this by calling platform.node() instead? This looks up the hostname properly, and is not dependent on reverse DNS. Its result is therefore predictable and reliable.

Regards,

Anand

​Hi Anand,​

Goeden avond Serge,

​There is a separate ansible-devel mailing list for discussing code​.

Thanks. I didn’t know about the -devel mailing list. However, I’m mostly just a user, and hardly do development. I guess my post was more of a request to the developers, as well as an alert to other users about the reliability of the ansible_fqdn fact. I only cited code to help pinpoint the issue.

Regards,

Anand

The python documentation says this about platform.node()

     Returns the computer�s network name (may not be fully qualified!). An
     empty string is returned if the value cannot be determined.

So there's no guarantee that the system's hostname is a FQDN, not any more than using socket.getfqdn().

I guess it's up to you to set the hostname correctly in /etc/hosts if you don't want to depend on DNS. That's a best practice anyway.

Excerpts from Dag Wieers's message of 2013-11-12 16:19:31 -0500:

The python documentation says this about platform.node()

     Returns the computer’s network name (may not be fully qualified!). An
     empty string is returned if the value cannot be determined.

So there's no guarantee that the system's hostname is a FQDN, not any more
than using socket.getfqdn().

I would further add that concept of a FQDN is pretty meaningless without
DNS (or, as you note, /etc/hosts). The only thing the kernel itself
even *knows* about as a hostname is the dumb string set by
`sethostname()`. Conventionally, one sets that to the "short" hostname.

Even the `hostname` command resorts to the resolver subsystem when asked
for the FQDN.

You'll note that the 'ansible_hostname' fact *is* resolved via
`platform.node()`, correctly: platform.node() eventually gets its
information from the `uname()` system call, which on Linux (and _not_
necessarily other Unices) is the same at the string set by
`sethostname()`.

I think it could be argued that 'ansible_hostname' should be set to the
entirety of the output of `platform.node()`, however. Currently that
output is split on a period and only the first segment is returned.
Technically, there is no reason the system's nodename couldn't be
'foo.bar', for example. On the other hand, most users will expect
'ansible_hostname' to be the "short" hostname. It could be confusing to
users who _do_ set the nodename/hostname to a string with a period in
it, however, to only get the first bit of it back.

Perhaps there should be an 'ansible_nodename' that returns the contents
of `platform.node()` unedited? I could see in some cases having that
information be useful.

Also related, is that in the following circumstance there is no way to
retrieve the "short" version of the FQDN:

    nodename = 'foo.bar'
    FQDN_via_DNS = 'hey.example.org'

In this case, 'ansible_hostname' will give 'foo', while 'ansible_fqdn'
will give 'hey.example.org'. To get the "short" version of the FQDN,
you'll need to do "ansible_fqdn.split('.')[0]", which is really not all
that bad considering you're already doing something insane.

Not sure if this is something that should be noted in the docs, given
that we all, occasionally, do things that are insane. Perhaps a section
explaining the facts returned by setup and where they come from, for
"advanced" users, would be useful.

There is totally a way -- split it in Jinja

-- Michael