Arbitrary host name resolution in Ansible
Question: Is there a way to resolve an arbitrary string as a host name in Ansible
`group_vars` file or in a Jinja2 template used by Ansible? Let's say, I want
to define a variable in `global_vars/all` that would contain one of the
several IP addresses that `www.google.com` resolves into. In this example, I
used `www.google.com` just as an example of a string that ca be resolved into
multiple IP addresses and yet I cannot use Ansible `hostvars` for the address
because I cannot ssh into it.

I tried to wire in Pythonic `socket.gethostbyname()` but could not get the
syntax right. At most, my variable became a literal "socket.gethostbyname('my-
host-1')".

I know I can fall back to a shell script and to take advantage of the tools
available in shell but I'd like to see if there is an elegant way to
accomplish this in Ansible.

The more gory details of the question are that I need to populate Postgres HBA
configuration file with IP addresses of the permitted hosts. I cannot use
their host names because the target deployment does not have reverse DNS that
is required for host name based HBA.

I really wish Postgres resolved the names in the configuration file and
matched it against the client's IP address instead of doing a reverse lookup
of the client's IP address and then matching the strings of host names. But
this is too much to expect and too long to wait. I need a workaround for now,
and I'd like to stay within Ansible for that, not having to offload this into
an external script.

Thank you for reading this far!


Answer: You can create a lookup plugin for this:

**Ansible 1.x:**

    
    
    import ansible.utils as utils
    import ansible.errors as errors
    import socket
    
    class LookupModule(object):
    
        def __init__(self, basedir=None, **kwargs):
            self.basedir = basedir
    
        def run(self, terms, inject=None, **kwargs):
    
            if not isinstance(terms, basestring):
                raise errors.AnsibleError("ip lookup expects a string (hostname)")
    
            return [socket.gethostbyname(terms)]
    

**Ansible 2.x:**

    
    
    import ansible.utils as utils
    import ansible.errors as errors
    from ansible.plugins.lookup import LookupBase
    import socket
    
    class LookupModule(LookupBase):
    
        def __init__(self, basedir=None, **kwargs):
            self.basedir = basedir
    
        def run(self, terms, variables=None, **kwargs):
    
            hostname = terms[0]
    
            if not isinstance(hostname, basestring):
                raise errors.AnsibleError("ip lookup expects a string (hostname)")
    
            return [socket.gethostbyname(hostname)]
    

Save this relative to your playbook as `lookup_plugins/ip.py`.

Then use it as `{{ lookup('ip', 'www.google.com') }}`

  * [More about lookups](http://docs.ansible.com/ansible/playbooks_lookups.html)
  * [(Not so much) More about creating lookup plugins](http://docs.ansible.com/ansible/developing_plugins.html#lookup-plugins)

