Defaulting Puppet to off in the Katello Scenario


#1

In a lot of scenarios a Puppetserver is not desired by the user. If it is, it may make a lot more sense to deploy it on a separate machine via the foreman-proxy-content scenario. This is easier in terms of upgrades, scaling and backups.

Current Situation

To get a default installation, the following command is executed:

foreman-installer --scenario [katello|foreman-proxy-content]

Both include a Puppetserver, even though it’s optional. To install without Puppetserver, the following command will achieve that.

foreman-installer --scenario [katello|foreman-proxy-content] --no-enable-puppet --foreman-proxy-puppet false --foreman-proxy-puppetca false --foreman-proxy-content-puppet false

It is also possible to only build a Puppet compile server (i.e., disable the CA):

# Rely on defaults
foreman-installer --scenario [katello|foreman-proxy-content] --puppet-server-ca false --foreman-proxy-puppetca false

# Explicit
foreman-installer --scenario [katello|foreman-proxy-content] --puppet-server true --foreman-proxy-puppet true --puppet-server-ca false --foreman-proxy-puppetca false --foreman-proxy-content-puppet true

Proposed Situation

In the first phase we focus on removing the Puppetserver installation from the default, making it optional. This means the argumentless installer will achieve the same result as the previous long command.

To enable the Puppetserver, the goal is that the following command works:

foreman-installer --scenario [katello|foreman-proxy-content] --puppet-server true

By default this includes the CA server. To only build a compile server, the CA server can be disabled as follows:

foreman-installer --scenario [katello|foreman-proxy-content] --puppet-server true --puppet-server-ca false

To do this, we need changes in Kafo to store more information in the answers file.

This assumes it’s possible to leverage Hiera to automatically couple answers, but there has been no proof of concept to show this works in practice. It may be possible through hooks. Worst case we will need the user to be explicit by passing in more parameters:

foreman-installer --scenario [katello|foreman-proxy-content] --puppet-server true --foreman-proxy-puppet true --puppet-server-ca true --foreman-proxy-puppetca true

Proposed Implementation

In building this, the initial focus will be the Kafo work to introduce an answers file version 2. This means we’ll need to store the file format somewhere. A logical place to store this is the scenario file. A helper to migrate the content should be provided by Kafo to easily upgrade.

To explain why a new file is needed, we’ll first need to look at answer file version 1. Generally is as follows:

classname_a: false # don't include this class
classname_b: true # include and use the defaults
classname_c:
  param: value # include and override the default(s)

A side effect of this is that it’s impossible to disable a class and store answers at the same time. Kafo will also store all defaults in their fully expanded form. This means we can’t use Hiera features to do lookups and it’s impossible to hide parameters even if the user shouldn’t touch them.

A draft proposal for the new format would be:

classname:
  enabled: true # Other values: false, always
  parameters:
    param: value
  blacklist:
    - param
  whitelist:
    - param

enabled now also accepts the option always which means there’s no way to disable a class. This makes sense in the katello scenario where certain classes shouldn’t be disabled because it breaks the installer. Generating the --[no-]enable-foreman-plugin-PLUGIN gives the illusion of control and only clutters the UI at best, breaking it at worst.

parameters is optional.

The whitelist supersedes the blacklist. Both are optional. It is possible to store an answer for a blacklisted or non-whitelisted parameter and it is passed to application. It just doesn’t show up in the UI. This allows setting a lookup answer. While technically not needed, it would mean that we’d need to detect the interpolation and disable kafo’s validation. This while most users wouldn’t even want to change it because it breaks their deployment.

The proposed default for Puppet would be:

puppet:
  enabled: false
  parameters:
    server_environments_owner: apache
    server_foreman_ssl_ca: "%{lookup('certs::puppet::ssl_ca_cert')}"
    server_foreman_ssl_cert: "%{lookup('certs::puppet::client_cert')}"
    server_foreman_ssl_key: "%{lookup('certs::puppet::client_key')}"
  blacklist:
    - server_environments_owner
    - server_foreman_ssl_ca
    - server_foreman_ssl_cert
    - server_foreman_ssl_key

There may be other options we wish to hide, but it’s wise to limit the scope for this project.

We should evaluate how many users do wish to change these values and if we’re not breaking some deployment. To allow users to unblacklist options it’s wise to keep generating the parser cache for these parameters. Then it’s as simple as removing them from the blacklist in the YAML file. This has a neglible overhead and saves developer time by not having to optimize an existing process.

Introducing answer coupling is more complicated because the answer is composed. It’s whether the puppet class is enabled and the answer to server (or server_ca). We also wish to support remote Puppetservers reached over HTTP in which case the puppet module is disabled, but the answer is still true. The user does need to be able to answer. At this point I have no concrete proposal on how to solve this which is why the worst case is requiring additional parameters.

Lastly we should get rid of the foreman_proxy_content::puppet answer. The best implementation depends on the feasibility of a few things, but can be done.

Other Related Tasks

We have many help texts and other documentation that needs to be evaluated.

One example is the command output to install a proxy after generating certificates for it. That includes a line to set the Foreman URL for the Puppetserver integration. That effectively enables the Puppet installation again, defeating the purpose. One solution is only implementing this change for the katello scenario and not foreman-proxy-content, but it’s likely not what we want.

The manual is another important task. We need a chapter about how to install Puppetserver for users who do want it.

Another is the Puppet environments integration in Katello/Pulp. Currently Katello can create environments for content hosts but this relies on Pulp writing out files for Puppetserver to use. If there’s no Puppetserver, it may fail. I haven’t done any research into this.

This will also need testing. Our current pipelines assume Puppet is present and passes in options which can also enable it.

Conclusion

There’s a few steps we need to take. First of all, we need to agree this is a good goal. Then my good approach needs to be agreed on. Of course it also needs to be implemented and tested. Once it’s merged, documentation needs to happen. While ambitious, I do want to target all of this to 1.24. That’s why I would like feedback, preferably soon :slight_smile: . If people are interested in helping with this, even better.


#2

I really like the idea of the Puppetserver being optional (also for Foreman not only Katello, but this will need a solution for the certficates). :+1:
How difficult is it to get this as additional scenarios like katello-with-puppet and katello-with-ansible?


#3

Currently we need to duplicate all migrations for each scenario. That means it might be easy to add one, but easy to mess up its maintenance. I am thinking about a common.migrations and how that could look like to simplify shared migrations that only reflect changes in Puppet modules rather than the actual scenario. That would make it much easier to add additional scenarios.

The question then becomes: what are valid scenarios? Do you also add a katello-with-puppet-and-ansible? The idea of the installer is that you can compose your own installation.

To demonstrate I wrote a scenario that split a vanilla Foreman into 3 servers:

  • puppet - a puppetserver that is both a compile server and a CA
  • server - a vanilla foreman that only runs foreman and dynflow
  • proxy - a vanilla foreman proxy that only runs foreman-proxy and talks to the others

It does register itself to puppet and runs the agent, but strictly speaking you could just configure puppet.conf and run puppet ssl bootstrap to get the certificates. It’s not fully automated (see the TODOs), but see this pipeline:


#4

Thanks @ekohl for nice writeup.

Have you considered not touching the existing answer files but introducing other file that would hold parameters for disabled classes? Or external file to keep the track of enabled/disabled classes. That would be perhaps easier than taking care of a migration. I like the new format structure though. If it lands in 1.24, then I’m happy with nicer and more descriptive answerfiles :slight_smile:


#5

I really like this idea, we currently have

  • a foreman server to deploy baremetal / virtual images.
  • a foreman/katello server and capsules to support repositories in content-views for CentOS
  • Red Hat Satellite and capsules for RedHat content (which uses foreman/katello)
  • Puppet Enterprise server.

We would like to use the Puppet Enterprise server to manage all the servers (including the above), but need to work around the puppet-servers running on all the above.

Ideally Foreman / Katello installs/manages itself without Puppet ór the modules / hiera can be transferred to the Puppet Enterprise server, greatly improving the way we deploy foreman as well as we can then fully puppetize its installation / upgrades as well.

Looking forward to release 1.24!

Regards, Eize Speerstra


#6

Using an external Puppet Enterprise server is on my agenda. Note that is not running the installer, but using it at runtime. Ideally getting reports out of it. I’ve done some research and have some ideas, but this is the first step to making that possible. Foreman Proxy together with Puppet in docker container has a slight preview in that direction.

We have users who do this manually. For Katello it’s currently not really supported for upgrades because a lot of logic is in the hooks, but I’m hoping we can make this easier in the future by removing those hooks. There’s also migrations and I don’t know how to deal with that. Currently it’s unsupported, but users who do this manually know how to read the CHANGELOGs and do it themselves.