Feuerfest

Just the private blog of a Linux sysadmin

Puppet is dead. Long live OpenVox!

Photo by cottonbro studio: https://www.pexels.com/photo/people-toasting-wine-glasses-3171837/

This is an update to my previous blogpost Puppet goes enshittyfication (Updated).

I the meantime the fork has happened. It's called OpenVox (https://github.com/openvoxproject) in reference to VoxPupuli - the name of community of module maintainer, authors and various other contributors around Puppet. But as we all now know, the community is dead. At least for Perforce. Well... As long as they can't get any real money out of it anyways..

The most non-surprising part? As of now there are no officially maintained container images for Puppet anymore.

Martin Alfke's betadots GmbH took over the maintenance of the puppetserver and puppetdb container images. As Puppet by Perforce did abandon them years ago. Now with the fork happening and Puppet effectively being a closed-source software product - and depending on how it develops - little to absolutely no support from Perforce, it simply makes no sense for the betadots GmbH anymore to do the free work for Puppet by Perforce. And they did so effective immediately. Understandably.

Hence they will be maintaining the openvoxserver & openvoxdb container images.

They announced this in a post on their betadots dev.to blog, in german but translation should work well. Read it here: https://dev.to/betadots/das-neue-puppet-open-source-projekt-heisst-openvox-2330

A questionable decision...

This means that in 2025 there are no container images for Puppet with official vendor support.

And as much as I like how this shows the power of a strong open source community...

I can't find a phrase strongly worded enough to describe this utter strategic mismanagement, so just look at this picture instead:

Photo by Photo By: Kaboompics.com: https://www.pexels.com/photo/a-short-haired-woman-holding-a-pair-of-eyeglasses-4491435/

Comments

Puppet goes enshittyfication (Updated)

Photo by Pixabay: https://www.pexels.com/photo/computer-screen-turned-on-159299/

This one came unexpected. Puppetlabs, the company behind the configuration management software Puppet, was purchased by Perforce Software in 2022 (and renamed to "Puppet by Perforce") and now, in November 2024 we start to see the fallout of this.

As Puppetlabs announced on November 7th 2024 in a blogpost they are, to use an euphemism: "Moving the Puppet source code in-house."

Or in their words (emphasizes by me):

In early 2025, Puppet will begin to ship any new binaries and packages developed by our team to a private, hardened, and controlled location. Our intention with this change is not to limit community access to Puppet source code, but to address the growing risk of vulnerabilities across all software applications today while continuing to provide the security, support, and stability our customers deserve.

They then go on in length to state why this doesn't affect customers/the community and that the community still can get access to that private, hardened and controlled location via a separate "development license (EULA)". However currently no information about the nature of that EULA is known and information will be released in early 2025 so after the split was made.

To say it bluntly: I call that bullshit. The whole talk around security and supply-chain risks is non-sense. If Puppet really wanted to enhance the technical security of their software product they could have achieved so in a myriad of other ways.

  • Like integrating a code scanner into their build pipelines
  • Doing regular code audits (with/from external companies)
  • Introducing a four-eyes-principle before commits are merged into the main branch
  • Participating in bug-bounty programs
  • And so on...

There is simply no reason to limit the access to the source-code to achieve that goal. (And I am not even touching the topic of FUD or how open source enables easier & faster spotting of software defects/vulnerabilities.) Therefore this can only be viewed as a straw-man fallacy type of expression to masquerade the real intention. I instead see it as what it truly is: An attempt to maximize revenue. After all Perforce wants to see a return for their investment. And as fair as this is, the "how" lets much to be desired...

We already have some sort-of proof. Ben Ford, a former Puppet employee wrote a blogpost Everything is on fire.... in mid October 2024 stating his negative experience with the executives and vice-presidents of Puppet he made in 2023 when he tried to explain the whole community topic to them (emphasizes by me):

"I know from personal experience with the company that they do not value the community for itself. In 2023, they flew me to Boston to explain the community to execs & VPs. Halfway through my presentation, they cut me off to demand to know how we monetize and then they pivoted into speculation on how we would monetize. There was zero interest in the idea that a healthy community supported a strong ecosystem from which the entire value of the company and product was derived. None. If the community didn’t literally hand them dollars, then they didn’t want to invest in supporting it."

I find that astonishing. Puppet is such a complex piece of configuration management software and has so many community-developed tools supporting it (think about g10k) that a total neglect of everything the community has achieved is mind-blowingly short-sighted. Puppet itself doesn't manage to keep up with all the tools they have released in the past. The ways of tools like Geppetto or the Puppet Plugin for IntellJ IDEA speak for themselves. Promising a fully-fledged Puppet IDE based on Eclispe and then letting it rot? No official support from "Puppet by Perforce" for one of the most used and commercially successful integrated development environment (IDE)? Wow. This is work the community contributes. And as we now know Puppet gives a damn about that. Cool.

EDIT November 13th 2024: I forgot to add some important facts regarding Puppets' ecosystem and the community:

I consider at least the container images to be of utmost priority for many customers. And neglecting all important tools around your core-product isn't going to help either. These are exactly the type of requirements customers have/questions they ask.

  • How can we run it ourself? Without constantly buying expensive support.
  • How long will it take until we build up sufficient experience?
  • What technology knowledge do our employees need in order to provide a flawless service?
  • How can we ease the routine tasks? / What tools are there to help us during daily business?

Currently Puppet has a steep learning curve which is only made easier thanks to the community. And now we know Perforce doesn't see this as any kind of addition to their companies' value. Great.

EDIT END

The most shocking part for myself was: That the Apache 2.0 license doesn't require that the source code itself is available. Simply publishing a Changelog should be enough to stay legally compliant (not talking about staying morally compliant here...). And as he pointed out in another blogpost from November 8th, 2024 there is reason they cannot change the license (emphasizes by me to match the authors'):

"But here’s the problem. It was inconsistently maintained over the history of the project. It didn’t even exist for the first years of Puppet and then later on it would regularly crash or corrupt itself and months would go by without CLA enforcement. If Perforce actually tried to change the license, it would require a long and costly audit and then months or years of tracking down long-gone contributors and somehow convincing them to agree to the license change.

I honestly think that’s the real reason they didn’t change the license. Apache 2 allows them to close the source away and only requires that they tell you what they changed. A changelog might be enough to stay technically compliant. This lets them pretend to be open source without actually participating."

I absolutely agree with him. They wanted to go closed-source but simply couldn't as previously they never intended to. Or as someone on the internet said: "Luckily the CLA is ironclad." So instead they did what was possible and that is moving the source-code to an internal repository. Using that as the source for all official Puppet packages - but will we as Community still have access to those packages?

For me, based on how the blogpost is written, I tend to say: No. Say goodbye to https://yum.puppetlabs.com/ and https://apt.puppetlabs.com/. Say goodbye to an easy way of getting your Puppet Server, Agent and Bolt packages for your Linux distribution of choice.

Update 15th November 2024: I asked Ben Ford in one of his Linkedin posts if there is a decision regarding the repositories and he replied with: "We will be meeting next week to discuss details. We'll all know a bit more then." As good as it is that this topic isn't off the table it still adds to the current uncertainty. Personally I would have thought that those are the details you finalize before making such an announcement.. But ah well, everyone is different.. Update End

A myriad of new problems

This creates a myriad of new problems.

1. We will see a breakline between "Puppet by Perforce"-Puppet packages and Community-packages in technical compatibility and, most likely, functionality too.

This mostly depends on how well Puppet contributes back to the Open Source repository and/or how well-written the Changelog is and regarding that I invite you to check some of their release notes for new Puppet server versions (Puppet Server 7 Release Notes / Puppet Server 8 Release Notes) although it got better with version 8... Granted they already stated the following in their blogpost (emphasizes by me):

We will release hardened Puppet releases to a new location and will slow down the frequency of commits of source code to public repositories.

This means customers using the open source variant of Puppet will be in somewhat dangerous waters regarding compatibility towards the commercial variant and vice-versa. And I'm not speaking about the inter-compatibility between Puppet servers from different packages alone. Things like "How the Puppet CA works" or "How are catalogues generated" etc. Keep in mind: Migrating from one product to the other can also get significantly harder.

This could even affect Puppet module development in case the commercial Puppet server contains resource types the community based one doesn't or does implement them slightly different. This will affect customers on both sides badly and doesn't make a good look for Puppet. Is Perforce sure this move wasn't sponsored by RedHat/Ansible? Their biggest competitioner?

2. Documentation desaster

As bad as the state of Puppet documentation is (I find it extremely lacking in every aspect) at least you have one and it's the only one. Starting 2025 we will have two sets of documentation. Have fun working out the kinks..

Additionally documentation wont get better. Apparently this source states that "Perforce actually axed our entire Docs team!" How good will a Changelog or the documentation be when it's nobody's responsibility?

3. Community provided packages vs. vendor packages

Nearly all customers I worked at have some kind of policy regarding what type of software is allowed on a system and how that is defined. Sometimes this goes so far as "No community supported software. Only software with official vendor support". Starting 2025 this would mean these customers would need to move to Puppet Enterprise and ditch the community packages. The problem I foresee is this: Many customers already use Ansible in parallel and most operations teams are tired having to use two configuration management solutions. This gives them a strong argument in favour of Ansible. Especially in times of economic hard-ship and budget cuts.

But again: Having packages from Puppet itself at least makes sure you have the same packages everywhere. In 2025 when the main, sole and primary source for those packages goes dark numerous others are likely to appear. Remember Oracles' move to make the Oracle JVM a paid-only product for commercial use? And how that fostered the creation of dozens of different JVMs? Yeah, that's a somewhat possible scenario for the Puppet Server and Agent too. Although I doubt we will ever see more than 3-4 viable parallel solutions at anytime given the amount of work and that Puppet isn't that widely required as a JVM is. Still this poses a huge operational risk for every customer.

4. Was this all intentional?

I'm not really sure if Perforce considered all this. However they are not stupid. They sure must see the ramifications of their change. And this will lead to customers asking themself ugly questions. Questions like: "Was this kind of uncertainty intentional?" This shatters trust on a basic level. Trust that might never be retained.

5. Community engagement & open source contributors

Another big question is community engagement. We now have a private equity company which thinks nothing about the community and the community knows this. There is already a drop in activity since the acquisition of Puppet by Perforce. I think this trend will continue. After all, with the current situation we will have a "We take everything from the community we want, but decide very carefully what and if we are giving anything back in return." This doesn't work for many open source contributors. And it is the main reason why many will view Puppet as being closed source from 2025 onward. Despite being technically still open source - but again the community values moral & ethics higher than legal correctness.

So, where are we heading?

Personally I wouldn't be too surprised if this is the moment where we are looking back to in the future and say: "This is the start of the downfall. This is when Puppet became more and more irrelevant until it's demise." As my personal viewpoint is that Puppet lacked vision and discipline for some years. Lot's of stuff was created, promoted and abandoned. Lot's of stuff was handed-over to the community to maintain it. But still the ecosystem wasn't made easier, wasn't streamlined. Documentation wasn't as detailed as it should be. Tools and command-line clients lacked certain features you'd have to work around yourself. And so on.. I even ditched Puppet for my homelab recently in favour of Ansible. The overhead I had to carry out to keep it running, the work on-top which was generated by Puppet itself, just to keep it running. Ansible doesn't have all of that.

In my text Get the damn memo already: Java11 reached end-of-life years ago I wrote:

If you sell software, every process involved in creating that piece of software should be treated as part of your core business and main revenue stream. Giving it the attention it deserves. If you don't, I'm going to make a few assumptions about your business. And those assumptions won't be favourable.

And this includes the community around your product. Especially more so for open source software.

Second I won't be surprised if many customers don't take the bite, don't switch to a commercial license, ride Puppet as long as it is feasible and then just switch to Ansible.

Maybe we will also see a fork. Giving the community the possibility to break with Puppet functionality. Not having to maintain compatibility any longer.

Time will tell.

New developments

This was added on November 15th: There are now the first commnity-build packages available. So looks like a fork is happening.

Read: https://overlookinfratech.com/2024/11/13/fork-announce/

EDIT: A newer post regarding the developments around the container topic and fork is here: Puppet is dead. Long live OpenVox!

Comments

Puppet's optional parameters might not be what you think they are

Photo by Kevin Ku: https://www.pexels.com/photo/data-codes-through-eyeglasses-577585/

Recently I encountered a puppet-lint warning regarding one of the classes I maintain at a customer. And this warning lead me down a rabbit hole of things I knew, things I understood and things I didn't know and apparently haven't grasp fully before. Surprisingly I never encountered this warning before. Despite being, most likely, a pretty common one.

So, I learned a bit or two about "optional parameters" in Puppet and thought this will give a decent read for my blog.

The problem

Take the following class definition. The code/logic is omitted as it doesn't matter (likewise I removed the puppet-strings documentation at the start of the manifests). We can purely focus on the class definition.

class profile::services::test (
  String $blatest,
  String $password = "test",
  Pattern[/^\d+\.\d+\.\d+(?:-\d+)?$/] $version = '11.2.3-4',
  String $system = 'SOMEEXAMPELSTRING',
  Optional[Hash[Stdlib::Port, Stdlib::Host]] $backupservers,
) {
# intentionally left empty
}

puppet-lint printed out the following warning:

WARNING: optional parameter listed before required parameter on line 6 (check: parameter_order)

And I was stumped by it. "Line 6 IS an optional parameter!" I thought. "There is no parameter defined after this, so how can it be listed before a required parameter?" I was confused. I moved line 6 around and sometimes the warning would vanished, sometimes not. Always defying what I thought I knew was correct.

The documentation is always right?

When you pass a certain amount of time you should stop to fiddle around and start solving it in an iterative way. So I went on to read the documentation. Thinking that maybe I missed some change in the Puppet DSL.

That's when I came across the paragraph on "Display order of parameters" as it mentioned the term "optional parameter". However.. It defined it in a totally different way I was used to use this term.

Display order of parameters

In parameterized class and defined resource type definitions, you can list required parameters before optional parameters (that is, parameters with defaults). Required parameters are parameters that are not set to anything, including undef. For example, parameters such as passwords or IP addresses might not have reasonable default values.

You can also group related parameters, order them alphabetically, or in the order you encounter them in the code. How you order parameters is personal preference.

Note that treating a parameter like a namevar and defaulting it to $title or $name does not make it a required parameter. It should still be listed following the order recommended here.

Source: The Puppet language style guide: Display order of parameters

And here I learned that: Any parameter with an associated default-value is called an optional parameter. But what about the Optional-data type?

Puppet goes on to give us one good and one bad example regarding the ordering:

Good:

class dhcp (
  $dnsdomain,
  $nameservers,
  $default_lease_time = 3600,
  $max_lease_time     = 86400,
) {}

Bad:

class ntp (
  $options   = "iburst",
  $servers,
  $multicast = false,
) {}

This recommendation is the reason why the puppetlabs-puppet-lint Gem enforces the order of: Required parameters first, optional parameters last. Where "optional parameter" again means: Any parameter with an associated default-value.

I changed line 6 by setting an empty hash as the default-value and the puppet-lint warning was gone. I also could have moved line 6 above or below line 2 (String $blatest,). Which would have fixed the warning too.

But here it is more or less the coding-style to list Optional-data type parameters after all others. Regardless of being a required or optional parameter. And again, this is being done here this way as people watch them as "optional parameters" in the sense of "I don't have to use if I don't need them". And here the requirement for parameter ordering bites the official definition of "optional parameters"...

The solution:

class profile::services::test (
  String $blatest,
  String $password = "test",
  Pattern[/^\d+\.\d+\.\d+(?:-\d+)?$/] $version = '11.2.3-4',
  String $system = 'SOMEEXAMPELSTRING',
  Optional[Hash[Stdlib::Port, Stdlib::Host]] $backupservers = {},
) {
# intentionally left empty
}

A bit more explanation

Now that we have clarified what an optional parameter is: You are either already confused, or ask yourself where the confusion originates from. So, without further ado, let me introduce you to the Optional data type.

The Optional data type

The Optional data type wraps one other data type, and results in a data type that matches anything that type would match plus undef. This is useful for matching values that are allowed to be absent. It takes one required parameter.

Source: Puppert: Values, data types, and aliases: The Optional data type

Most likely you have seen that parameters in Puppet classes are defined with an identifier of the type of data they will store. Same as it's required in any programming language where you have to define type of the variable (Integer, Float, Boolean, String, etc.). The only difference to Puppet is that in Puppet this is not enforced (as to avoid the term "optional" here. 😅)

If we adopt the given "good example" from above, we can make it look like this:

class dhcp (
  String $dnsdomain,
  Hash[String] $nameservers,
  Optional[Integer] $default_lease_time = 3600,
  Integer $max_lease_time               = 86400,
) {}

Here $default_lease_time is an optional parameter, right? Yes, but not because it uses the Optional data type. It's only an optional parameter because it has a default-value of 3600 assigned. Likewise $max_lease_time is an optional parameter too.

And here the problem originates.

Most of people I encountered use the term "optional parameter" to refer to the $default_lease_time parameter and not $max_lease_time. Which is absolutely understandable given how your speech works, how we like to name things and how we combine those two.

Adding to this is the fact that parameters which are initialized with the additional Optional-data type are allowed to be undef additionally to the other types of data defined. Effectively making it optional to assign a value to them. And this is exactly how these type of parameters are often used. Hence the term "optional parameter" sounds logical when referring to these parameters.

Technically however, that's wrong. Alas in my case it was the reason why I spent more time than I liked fixing that one linter warning. But I learned something along that way. I think that's what matters, right?

A little bit more confusion?

When reading through all data language types definitions and data types I found a data type I knowingly never encountered before. The Undef and NotUndef data types.

The Undef data type

The data type of undef is Undef. It matches only the value undef, and takes no parameters.

Several abstract data types can match the undef value:

  • The Data type matches undef in addition to several other data types.
  • The Any type matches any value, including undef.
  • The Optional type wraps one other data type, and returns a type that matches undef in addition to that type.
  • The Variant type can accept the Undef type as a parameter, which makes the resulting data type match undef.
  • The NotUndef type matches any value except undef.

Source: Puppert: Values, data types, and aliases: The Undef data type

The NotUndef data type

The NotUndef type matches any value except undef. It can also wrap one other data type, resulting in a type that matches anything the original type would match except undef. It accepts one optional parameter.

Source: Puppert: Values, data types, and aliases: The NotUndef data type

And yes, they are useful for what they are designed. But I REALLY wished Puppet would rename that Optional data-type to something else. (Is: CanBeUndef still available? 😂)

Conclusion

All definition problems aside: This shows again why the usage of proper development/analyze tools like Linters is so important. It not only helps reducing errors, no. It forces you to understand what you are doing. 😉

Comments