RFC: Module For Explicitly Handling /etc/hosts

Hey all,

I’m a few weeks into Ansible and am loving it so far.

One of the only things I miss from Puppet is a first class handling of hosts files on remote machines. (See: http://docs.puppetlabs.com/references/latest/type.html#host) In particular, I manipulate the /etc/hosts files of my nodes reasonably often, and in ways that can be a pain with only lineinfile. I’ve written a first cut of a module that should alleviate some of this, but I was hoping to get a little feedback before opening a pull request.

A few use cases that are a bit of a pain with only lineinfile:

  • I’d like to ensure that ‘my-awesome-hostname’ is an alias of ‘10.100.15.23’. I don’t want to clobber any other aliases that are there, but I want ‘my-awesome-hostname’ to be added if it’s absent. Add a new line for the IP if there wasn’t one. (This is particularly roundabout with lineinfile because there can be multiple lines for that ip address, any one of which can contain ‘my-awesome-hostname’.)

  • /etc/hosts lines can have comments on them, and I want to preserve those comments. I just want to make sure ‘1.2.3.4’ is aliased to ‘foo’.

  • I’m adding four new app boxes. Make sure the following hostnames are correctly wired up to the right IPs. This means they point to the right IPs in the right /etc/hosts files, and also that they don’t point to any other IPs.

  • Make sure ‘deprecated-hostname’ doesn’t point to any IPs. Leave the IPs there with any other hosts that alias to them, but remove the line if ‘deprecated-hostname’ was the only name pointing to the IP.

  • I want this ip/hostname line to have a comment above it that reads “This is necessary for streaming replication.”

A good module should also abstract away the hosts handling of different OSes.

I was hoping to get feedback on the following:

  • Does this sound like a reasonable module?

  • If so, how would you want to use it? What would you want it to support?

Thanks in advance,
-Dan

There was recently a discussion about this, and it was decided that for single files like hosts it’s best to use the modules we have already and not write modules that manage a single file (see also sudoers discussions).

This is fair, but there are a bunch of things that you could handle with lineinfile, but which are easier with first class support and common enough to merit it. Consider the modules for sysctl, cron, etc. These essentially manage single files.

Having modules that make it that much easier to handle common things makes ansible easier to learn. On the modules page, I can ctrl-f for “host” and find something that has exactly the semantics I want – X and Y point to Z, W doesn’t point to anything, etc. Expressing that with lineinfile is gross.

Thoughts?

   - Does this sound like a reasonable module?
   - If so, how would you want to use it? What would you want it to support?

I don't think I would use it. For one, if I absolutely need /etc/hosts
put in place I'd use `template'. Other than that, DNS is what most
people I know use, so there's no need for updating /etc/hosts files.

        -JP

Hosts files are an inefficient and error prone way to manage host/IP mappings, that is why they invented DNS. But if you must have it, use the template module to manage it.

Does this sound like a reasonable module?
If so, how would you want to use it? What would you want it to support?

Personally, I would love to see this module included. I'm currently in
the process of setting up Ansible at work and provide virtual machines
(using Vagrant) that will match the production environment.

I'm using some local_action calls to update /etc/hosts on the host
machine running Vagrant to add entries to the VM's IP addresses, but
using lineinfile here is an absolute cludge.

While I agree with Brian that DNS is preferred when possible, this is
one example of where that is not possible* and using /etc/hosts is
more appropriate. Additionally, templating /etc/hosts won't fly here,
because I don't want to hijack my colleagues' hosts files, only manage
a few entries of the supplied VM's.

* Technically, I could force my colleagues to run a local DNS server
to achieve the same thing, but this is highly inconvenient.

I also vote yes to having modules that handle specific configuration formats such as hosts or sudoers instead of relying on just templates.
So yeah, I think it’s a good idea.

Ah, yes. In some contexts, DNS is a nonstarter, but even when it’s not, it can be excessive when /etc/hosts/ is sufficient.

I prefer modules that know the semantics of a config file and abstract them away to manipulating lines in files directly, especially when the latter is tricky with just regexes, e.g. adding a single hostname to an ip. Task-specific modules also have the benefit of abstracting away OS-specific quirks.

Alas, there is no voting here, but feedback is welcome!

I do agree that in general modules that allow abstract thinking are better than ones that don’t in the case where dynamic edits are required. I personally am not a fan of lineinfile – it’s a last resort.

However, 95% of our users will be using DNS, the remainder are usually templating host files, so our general criteria is to include modules a good chunk of everyone can use.

Generally speaking it’s better when you can push down the exact model of what you want rather than relying on something that is a hybrid of what might previously be there and what you are saying should be.

For instance, in the above aproach, you could easily build up a lot of invalid host entries because they weren’t explicitly listed in the config management.

Also adding 5000 host file entries via 5000 actions – something that most people wouldn’t do now (since it’s much more logical to template it) – would appear very frustrating if someone tried it.

This is reasonable. If all but a tiny fraction should be managing their hosts without this module, adding it will do more harm than good.

Thanks for the feedback!
-D