theforeman / foreman_default_hostgroup

A plugin to set the default hostgroup when hosts are created.
GNU General Public License v3.0
11 stars 29 forks source link

[RFE] Foreman plugin default_hostgroup dynamic hostgroup title #16

Open pvreman opened 9 years ago

pvreman commented 9 years ago

Description of problem: We have are using a fact called "foreman_hostgroup" that determines to which hostgroup a server has to be provisioned. Currently the facts map matching in the default_hostgroup plugin can allow such looking for a custom fact name. But it does not support to replace fact values inside the hostgroup key.

Steps to Reproduce:

  1. Install and configure the foreman_hostgroup plugin to match foreman_hostgroup

:default_hostgroup: :facts_map: "%{foreman_hostgroup}": "foreman_hostgroup": ".*"

  1. Client: Create a fact foreman_hostgroup "Dummy"
  2. Client: Run puppet on the client

Actual results: Hostgroup will be called %{foreman_hostgroup} instead Dummy

Expected results: Client registered to Hostgroup called Dummy

Additional info: See Foreman #6952 for the original request in the core foreman code.

logicminds commented 9 years ago

Interesting idea. While this method of assignment would be insecure since the fact could be changed by anyone and cause configuration of any arbitrary host group it might have some use cases. So this plugin doesn't support variable interpolation as you stated but with some additional code it could probably support a hostgroup name assignment where it uses the value of the provided fact as the host group name and would assign to the current host being processed. At least that is how I interpreted your request. This would have to bypass the facts map because its not really a mapping its more of an assignment since you already know what host group you want. During your provisioning process you spent the time to map your host manually by populating a file or generating a custom fact that does the mapping. As a work around I would take that mapping from your custom fact and interpolate that mapping into the default host group plugin mapping so that you could supply the mapping inside the yaml file. On a side note I believe that foreman also exposes a top scope variable called foreman_hostgroup which would probably collide with your custom fact in puppet.

earsdown commented 7 years ago

We'd be really interested in this, but I'd like to propose an alternative.

Hostgroup names containing numeric interpolation tokens (e.g. %{1}, %{2}, %{3}, etc) become populated with a captured group from regexp's in the facts_map, on a first-match basis. So this:

---
:default_hostgroup:
  :facts_map:
    "hostgroup_%{1}_%{2}":
      "location": "^([a-z]+-[a-z]+-[0-9]+)[a-z]+$"
      "hostname": "^([A-Za-z-]+)"
      "osfamily": "^(.+)$"

Would result in:

  { "location": "us-east-1a", "hostname": "mailserver01", "osfamily": "RedHat" } => "hostgroup_us-east-1_mailserver"
  { "location": "dungeon", "hostname": "MacBookPro", "osfamily": "Darwin" } => "hostgroup_MacBookPro_Darwin"

Useful because in our (and others') cases, hostgroup creation can be done by developers via the Foreman GUI, but those same developers wont have SSH access to modify the config, and we wouldn't want developers to have access to modify other entries either. Instead, we can create a single entry that matches on secure/trusted variables (which can't be overwritten by agents, e.g. %{::trusted.certname}), and it means we won't have to hard-code individual entries for each hostgroup (which number in the dozens).

This solution not only caters for @pvreman's requirement but I believe it also resolves the concerns raised by @logicminds .

As for error handling, in the example above, if the parser couldn't capture at least two groups from the regexp's in the :facts_map, it should fail. If it finds more than two, it should use the first two. Ideally, matching multiple groups from a single regexp should also be supported.

Even if we could modify the mapping from the Foreman UI, we'd have to somehow apply access control filters based on the hostgroup name, which might mean merging the feature into Foreman itself. Then we'd need an API and we'd need to manage the mapping via hammer. Which all sounds like way more work, and I'd take regexp group matching/interpolation support over that anyway.

GregSutcliffe commented 7 years ago

Mmm, that's an interesting take on it @earsdown. I'm not particularly worried about fact security (the ability to redefine a fact has been an issue for the lifetime of the plugin, after all), and changing a fact after provisioning the host won't matter (unless you have force=>true for changing hostgroups on hosts that already have one).

The complexity is a small concern, setting up the appropriate maps is tricky enough as it is. But with good docs, and perhaps an examples/ dir, that's manageable,

Overall, I think I like it. I can't promise when I might get to it, but if you're feeling keen and want to jump in, I can help you out with it :)

bin-doph commented 1 year ago

I would like to implement this feature (replacing facts in hostgroup names), the question I have is, what should happen if a referenced fact does not exist, for example

---
:default_hostgroup:
  :facts_map:
    "%{customer}/%{osfamily}":
      "osfamily": ".*"

osfamily = Debian customer = not set

if the hostgroup name is %{customer}/%{osfamily} and the fact customer is not set, which option should I chose

  1. parse everything that is possible, leave unresolvable variables intact => %{customer}/Debian
  2. just remove the reference => /Debian
  3. insert generic error tag => ERROR/Debian
  4. abort parsing and return the input string back => %{customer}/%{osfamily}
  5. abort parsing, log info and return an empty string => ''

cheers