The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com

Feature #8940

host type should have an optional canonical_hostname parameter

Added by Rob Terhaar over 3 years ago. Updated 11 months ago.

Status:AcceptedStart date:08/11/2011
Priority:NormalDue date:
Assignee:Franz Pletz% Done:

0%

Category:host
Target version:-
Affected Puppet version:2.6.8 Branch:
Keywords:

We've Moved!

Ticket tracking is now hosted in JIRA: https://tickets.puppetlabs.com

This ticket is now tracked at: https://tickets.puppetlabs.com/browse/PUP-1171


Description

If you compare the behavior of the Exec type to the Host type, Exec is more flexible because it has a command => parameter. This is useful if you would like to create multiple Execs with different namevars, but similar commands.

When working with the Host type, I’ve found that the namevar becomes the “canonical_hostname”, and there is no way to override this. Here’s a specific example of when having multiple Host resources with the same namevar would be useful:

  @@host  { "$fqdn":
    host_aliases  => $hostname,
    ip            => $private_ip_interface,
    tag           => "normal_server_private-${region}",
  }

  @@host  { "${fqdn}":
    host_aliases  => $hostname,
    ip            => $public_ip_interface,
    tag           => "normal_server_public-${region}",
  }

Since both exported resources have the same namevar, I receive a parse error:

Error 400 on SERVER: Duplicate definition: Host[puppet.dev.server.com] is already defined in file /etc/puppet/modules/hosts/manifests/collect.pp at line 33; cannot redefine at /etc/puppet/modules/hosts/manifests/collect.pp:43 on node puppet.dev.server.com

However, If the Host type had the ability to pass a canonical hostname (fqdn) argument, I could do:

  @@host  { "${fqdn}-private":
    canonical_hostname => $fqdn
    host_aliases  => $hostname,
    ip            => $private_ip_interface,
    tag           => "normal_server_private-${region}",
  }

  @@host  { "${fqdn}-public":
    canonical_hostname => $fqdn
    host_aliases  => $hostname,
    ip            => $public_ip_interface,
    tag           => "normal_server_public-${region}",
  }

Related issues

Related to Puppet - Refactor #6247: exec and notify types have different implementations for ... Accepted 02/07/2011
Duplicated by Puppet - Bug #12438: host type does not understand multiple IP addresses Duplicate 02/05/2012

History

#1 Updated by Rob Terhaar over 3 years ago

This is potentially related to #6247

#2 Updated by James Turnbull over 3 years ago

  • Status changed from Unreviewed to Needs Decision
  • Assignee set to Nigel Kersten

#3 Updated by Nigel Kersten over 3 years ago

  • Status changed from Needs Decision to Needs More Information

Can we get an example of the hosts file output you’re wanting to get to?

I think I know what it is, but it would make verification easier.

#4 Updated by Rob Terhaar over 3 years ago

I’d like to be able to manage conditional hosts files based on data center location. e.g., for EC2 servers in us-west-1, I’d like to populate a /etc/hosts file with private NAT addresses for similar nodes that are also in us-west-1, but also populate nodes in us-west-1 with public IP addresses for nodes that are in us-east-1. vice versa,

I’d also like to populate the /etc/hosts files on my Rackspace servers with private IPs for other Rackspace nodes, and public IPs for EC2 nodes.

The only way that I can imagine implementing this is to not use Exported resources and resort to some ERB hacks, but if I was able to Export multiple hosts entries from each server, I could easily realize them conditionally.

Given the above Export example:

  @@host  { "${fqdn}-private":
    canonical_hostname => $fqdn
    host_aliases  => $hostname,
    ip            => $private_ip_interface,
    tag           => "normal_server_private-${region}",
  }

  @@host  { "${fqdn}-public":
    canonical_hostname => $fqdn
    host_aliases  => $hostname,
    ip            => $public_ip_interface,
    tag           => "normal_server_public-${region}",
  }

I would build a realize class that would work like:

Host <<| tag == normal_server_private-${region} |>>

Which would realize all private IPs in the similar region, but then do

Host <<| tag != normal_server_public-${region} |>>

To realize public hosts entries on all dissimilar regions.

I really hope this is clear, and hope that my execution isn’t completely insane.

#5 Updated by Stefan Schulte over 3 years ago

Maybe I miss something here but try to replace canonical_hostname with name and you should be ok.

#6 Updated by Rob Terhaar over 3 years ago

Thanks Stefan, I tried overriding the namevar with a parameter, but that fails with a “cannot reassign, name already taken” error. Sorry I can’t dig up the actual error, I’m traveling for a few weeks and am away from the lab.

#7 Updated by Franz Pletz almost 3 years ago

  • Category set to host
  • Target version set to 2.7.x

The problem is that the name parameter of the host type, which is the first hostname written to the hosts file after the IP address, is the namevar. Only one combination of type and namevar can exist. Therefore the namevar and the canonical hostname written to the hosts file should be separated.

I’m willing to write a patch. Is the naming of the parameter (canonical_hostname) acceptable?

#8 Updated by James Turnbull almost 3 years ago

  • Status changed from Needs More Information to Accepted
  • Assignee changed from Nigel Kersten to Franz Pletz

I think we’d take a patch for this!

#9 Updated by Stefan Schulte almost 3 years ago

While I do not have a quick alternative I don’t really like the idea that a host resource can now have a title, a name and a canonical_hostname and all can have different values.

The reason why it is not possible to create two host resources with different titles but the same name (as I suggested earlier) is that puppet will automatically create an alias for a resource with the namevar if namevar and title differ.

At one time this aliasing did not work and was classified as a bug: #8596. Working around this again with a third parameter leads to awkwardness in my opinion.

In my opinion there are two problems here:

  • the error should not be raised with virtual or exported resources because we do not really have a conflict there. The error should however be raised when the user wants to realize both resources on the same host
  • ultimately the host type should use a composite namevar of the two keyattributes name and ipaddress because you may also want two localhost entries (say one for ipv4 and one for ipv6) on the same host. Unfortunately the parsedfile provider is not able to handle that yet.

#10 Updated by Rob Terhaar almost 3 years ago

I think that "canonical_hostname" as an official parameter name is a bit too pedantic. I took this term from the Linux man pages for /etc/hosts, but I doubt that most people would understand what it really means. I think that just host is more correct.

It would be great if the Host resource type followed the same pattern as the Exec resource- where the Namevar is the default command action, unless command is otherwise defined.

From man hosts in Debian:

For each host a single line should be present with the following information:

              IP_address canonical_hostname [aliases...]

#11 Updated by Anonymous almost 3 years ago

Stefan Schulte wrote:

While I do not have a quick alternative I don’t really like the idea that a host resource can now have a title, a name and a canonical_hostname and all can have different values.

I am inclined to worry about it from this perspective, also.

  • ultimately the host type should use a composite namevar of the two keyattributes name and ipaddress because you may also want two localhost entries (say one for ipv4 and one for ipv6) on the same host. Unfortunately the parsedfile provider is not able to handle that yet.

I almost agree with this: I think that the IP address should be the primary key for this, and the rest of the content should not be part of the name.

The behaviour of the resolver with /etc/hosts containing duplicate records is undefined, and varies between platforms. On some systems it is treated, I understand, as a hash based on the IP field…

Moving away from ParsedFile is absolutely acceptable here, and wouldn’t hold up the patch getting merged at all.

Rob Terhaar wrote:

It would be great if the Host resource type followed the same pattern as the Exec resource- where the Namevar is the default command action, unless command is otherwise defined.

If we stuck with a composite var, or something like that, this seems acceptable. It feels very much like a work-around, and that work-around derives from the fact that we modeled the wrong key (hostname, not IP) in the type.

My strong preference would be a patch that: 1. Used ip rather than name as the primary name. 2. Supported ordering of names associated with an IP string, when they are in a hash. 3. Targetted Telly.

Making that one change should fix the fundamental conflict in here, because it aligns the Puppet model and the underlying model.

#12 Updated by Stefan Schulte almost 3 years ago

Rob Terhaar wrote:

It would be great if the Host resource type followed the same pattern as the Exec resource- where the Namevar is the default command action, unless command is otherwise defined.

the command parameter ALWAYS specifies the action. But if you do not set the command parameter explicitly it will be implicitly set to the resource’s title (because the command parameter is the namevar)

This actually is true for the host resource:

Simple manifest:

# cat /tmp/test.pp 
host { 'bazinga':
  name   => 'localhost',
  ip     => '127.0.0.2',
}

localhost is currently 127.0.0.1. If I apply the catalog it will be changed. The title is ignored.

# puppet apply /tmp/test.pp
notice: /Stage[main]//Host[bazinga]/ip: ip changed '127.0.0.1' to '127.0.0.2'
notice: Finished catalog run in 0.13 seconds

The difference between an exec resource and a host resource is that the following does work

exec { 'foo':
  command => '/bin/true',
}
exec { 'bar':
  command => '/bin/true',
}

while the following does not

host { 'foo':
  name => 'localhost',
}
host { 'bar':
  name => 'localhost',
}

Will raise an error

Cannot alias Host[bar] to ["localhost"] at /tmp/test.pp:6; resource ["Host", "localhost"] already defined

The reason is that in exec.rb the resource type is marked with @isomorphic=false. So if the desire is that the host type should behave like the exec type this is really a trivial change.

#13 Updated by Stefan Schulte almost 3 years ago

Daniel Pittman wrote:

I almost agree with this: I think that the IP address should be the primary key for this, and the rest of the content should not be part of the name.

maybe we should then also rename the type? Because we are not managing host(names) anymore, we are managing ip addresses.

#14 Updated by Anonymous almost 3 years ago

Stefan Schulte wrote:

Daniel Pittman wrote:

I almost agree with this: I think that the IP address should be the primary key for this, and the rest of the content should not be part of the name.

maybe we should then also rename the type? Because we are not managing host(names) anymore, we are managing ip addresses.

It manages the /etc/hosts file, so I am inclined to think the name is good.

#15 Updated by Rob Terhaar almost 3 years ago

Confirmed that setting @isomorphic=false in lib/puppet/type/host.rb allows my expected behavior of the hosts resource. (thank you, Stefan)

I agree with Daniel that the IP should be the primary key, not the FQDN.

#16 Updated by Rob Terhaar almost 3 years ago

However, I found today that setting @isomorphic=false in host.rb breaks purge

  resources { host:
    purge => true
  }

#17 Updated by Anonymous almost 2 years ago

  • Target version deleted (2.7.x)

#18 Updated by Ryan DeShone about 1 year ago

Has there been any further progress on this? I am in a setup where we have servers connected to multiple private networks. I’d like them to be able to export a host entry for each network they are connected to, then have it collected by the other machines on that network. Right now, this is preventing me from being able to do so.

#19 Updated by Nick Walker 11 months ago

Redmine Issue #8940 has been migrated to JIRA:

https://tickets.puppetlabs.com/browse/PUP-1171

Also available in: Atom PDF