<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: David Sandilands</title>
    <description>The latest articles on Forem by David Sandilands (@davidsandilands).</description>
    <link>https://forem.com/davidsandilands</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F794037%2F837f3094-db39-41c2-83f8-9aa244996486.jpg</url>
      <title>Forem: David Sandilands</title>
      <link>https://forem.com/davidsandilands</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/davidsandilands"/>
    <language>en</language>
    <item>
      <title>Lets get our facts straight</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Thu, 13 Mar 2025 16:03:24 +0000</pubDate>
      <link>https://forem.com/puppet/lets-get-our-facts-straight-2631</link>
      <guid>https://forem.com/puppet/lets-get-our-facts-straight-2631</guid>
      <description>&lt;p&gt;During some recent user discussions there was some confusion on some logging coming from a &lt;code&gt;pdk test unit&lt;/code&gt; run. See some example output below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root@rocky8-320 test_320 $ pdk test unit
pdk (INFO): Using Ruby 3.2.3
pdk (INFO): Using Puppet 8.6.0
[✔] Preparing to run the unit tests.
/opt/puppetlabs/pdk/private/ruby/3.2.3/bin/ruby -I/opt/puppetlabs/pdk/share/cache/ruby/3.2.0/gems/rspec-core-3.13.0/lib:/opt/puppetlabs/pdk/share/cache/ruby/3.2.0/gems/rspec-support-3.13.1/lib /opt/puppetlabs/pdk/share/cache/ruby/3.2.0/gems/rspec-core-3.13.0/exe/rspec --pattern spec/\{aliases,classes,defines,functions,hosts,integration,plans,tasks,type_aliases,types,unit\}/\*\*/\*_spec.rb --format progress
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"Rocky", :operatingsystemrelease=&amp;gt;"/^8/", :hardwaremodel=&amp;gt;"x86_64"}, using v4.5.0 instead
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"OracleLinux", :operatingsystemrelease=&amp;gt;"/^7/", :hardwaremodel=&amp;gt;"x86_64"}, using v4.2.2 instead
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"RedHat", :operatingsystemrelease=&amp;gt;"/^8/", :hardwaremodel=&amp;gt;"x86_64"}, using v4.5.2 instead
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"Scientific", :operatingsystemrelease=&amp;gt;"/^7/", :hardwaremodel=&amp;gt;"x86_64"}, using v4.2.2 instead
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"Debian", :operatingsystemrelease=&amp;gt;"/^10/", :hardwaremodel=&amp;gt;"x86_64"}, using v4.5.0 instead
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"Ubuntu", :operatingsystemrelease=&amp;gt;"/^18\\.04/", :hardwaremodel=&amp;gt;"x86_64"}, using v4.5.0 instead
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"windows", :operatingsystemrelease=&amp;gt;"\"2019\"", :hardwaremodel=&amp;gt;"x86_64"}, using v4.4.0 instead
No facts were found in the FacterDB for Facter v4.5.1 on {:operatingsystem=&amp;gt;"windows", :operatingsystemrelease=&amp;gt;"\"10\"", :hardwaremodel=&amp;gt;"x86_64"}, using v4.4.0 instead
Run options: exclude {:bolt=&amp;gt;true}
..........

Coverage Report:

Total resources:   1
Touched resources: 0
Resource coverage:  0.00%

Untouched resources:
  Notify[Hello world]


Finished in 0.50081 seconds (files took 12.36 seconds to load)
10 examples, 0 failures

root@rocky8-320 test_320 $
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This raised questions&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Isn't operatingsystemsrelease and operatingsystem legacy facts?&lt;/li&gt;
&lt;li&gt;Why couldn't it find Facter at 4.5.1?&lt;/li&gt;
&lt;li&gt;Why are some OS having to use much older facter 4.2.2 and 4.4.0?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So to answer these questions lets understand what PDK is doing when it calls PDK test unit and runs its rspec tests. There are two particularly useful projects from Vox Pupuli &lt;a href="https://github.com/voxpupuli/facterdb" rel="noopener noreferrer"&gt;https://github.com/voxpupuli/facterdb&lt;/a&gt;, providing the fact sets for different OS during testing and &lt;a href="https://github.com/voxpupuli/rspec-puppet-facts" rel="noopener noreferrer"&gt;https://github.com/voxpupuli/rspec-puppet-facts&lt;/a&gt; which provide the magic behind the loop you see in the templated rspec tests:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;on_supported_os(test_on).each do |os, os_facts|&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This loop essentially reads your metadata.json file of what OS are supported by your module which looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "operatingsystem_support": [
    {
      "operatingsystem": "RedHat",
      "operatingsystemrelease": [
        "7",
        "8",
        "9"
      ]
    },
    {
      "operatingsystem": "Windows",
      "operatingsystemrelease": [
        "10",
        "2012",
        "2012 R2",
        "2016",
        "2019",
        "2022"
      ]
    },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that brings us to the first question aren't operatingsystem and operatingsystemrelease legacy facts? Well yes they were but if you look at the &lt;a href="https://www.puppet.com/docs/puppet/8/modules_metadata.html#:~:text=json%20file%2C%20which%20contains%20important,(PDK)%2C%20the%20metadata" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; this this just the parameter names for the metadata.json file to specify what OS and what versions you are supporting.&lt;/p&gt;

&lt;p&gt;This loop then runs the get_facts function from FacterDB for each OS and each version your module supports. If you take a look at some of the data in FacterDB you will see in the facts folder set of folders of different Facter Versions and then files named by OS and Version such as this for Redhat 9 for Facter 4.11 &lt;a href="https://github.com/voxpupuli/facterdb/blob/master/facts/4.11/redhat-9-x86_64.facts" rel="noopener noreferrer"&gt;https://github.com/voxpupuli/facterdb/blob/master/facts/4.11/redhat-9-x86_64.facts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at the output below we see this produces an output of facts which you may notice are missing some facts which are overly specific or have had the node name updated to generic name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3b0b9d7fozox1o91wn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3b0b9d7fozox1o91wn6.png" alt="Image description" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allows you to have sample facts for each OS release on different versions of facter.&lt;/p&gt;

&lt;p&gt;So why couldn't it find Facter at 4.5.1 (the gem version PDK was using during these tests) and had to use something else? Well if you first notice the folder structure only goes down to 4.5 and if we first look at &lt;a href="https://github.com/voxpupuli/facterdb/blob/f13db5f0b90f8a3c9272a0dae03ba9875301c4cf/facts/4.5/rocky-8-x86_64.facts" rel="noopener noreferrer"&gt;Rocky 8&lt;/a&gt; which is in the 4.5 folder we see the facterversion in the file is &lt;/p&gt;

&lt;p&gt;&lt;code&gt;"facterversion": "4.5.0"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So the person who provided this data ran it in facter 4.5.0 hence this message was just a warning that there is a small missmatch but its purely informational and for that level of minor difference it unlikely to affect testing. &lt;/p&gt;

&lt;p&gt;Now looking at Rhel 7 which could only find 4.2.2 well we can see its not in the folder and this is because Rhel 7 exited support at this point and 4.2 was the last valid supported version of facter for it.&lt;/p&gt;

&lt;p&gt;So hopefully this has made this process a bit clearer and made you appreciate how useful these projects are too.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Lets get started with Puppet Core</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Tue, 25 Feb 2025 10:16:11 +0000</pubDate>
      <link>https://forem.com/puppet/lets-get-started-with-puppet-core-3p5j</link>
      <guid>https://forem.com/puppet/lets-get-started-with-puppet-core-3p5j</guid>
      <description>&lt;p&gt;So you have seen &lt;a href="https://www.puppet.com/blog/puppet-core" rel="noopener noreferrer"&gt;Puppet Core&lt;/a&gt; is available as a &lt;a href="https://www.puppet.com/products/puppet-core" rel="noopener noreferrer"&gt;customer&lt;/a&gt; or on a developer license and you now want to get hold of the packages. If you are a user with more than 25 nodes make sure you speak to &lt;a href="https://www.puppet.com/products/puppet-core" rel="noopener noreferrer"&gt;sales&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The first step is to make sure you have signed the EULA at &lt;a href="https://forge.puppet.com/eula" rel="noopener noreferrer"&gt;https://forge.puppet.com/eula&lt;/a&gt; , in this case I have signed up as a developer user. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5u5sfwgu250v56kw2dtr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5u5sfwgu250v56kw2dtr.png" alt="Image description" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9oj1aoqv698bfwecbfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9oj1aoqv698bfwecbfz.png" alt="Image description" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1u1d1kthyzjct06ww8y3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1u1d1kthyzjct06ww8y3.png" alt="Image description" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you need to create a forge API key, first make sure you have multifactor authentication enabled in settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnu6kvxao2a7hf1y3l47h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnu6kvxao2a7hf1y3l47h.png" alt="Image description" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then when you create the key it will only be displayed once so I would recommend storing it in an appropriate secure secret store, I am using 1password for this demo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpbut84mct50dhr7biaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhpbut84mct50dhr7biaz.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have the key, you can see in the install &lt;a href="https://www.puppet.com/docs/puppet/8/install_puppet" rel="noopener noreferrer"&gt;instructions&lt;/a&gt; various locations for Puppet core content depending on your OS install type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin9e5xtks8pqdvss8934.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin9e5xtks8pqdvss8934.png" alt="Image description" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will show examples of using Alma Linux 9 and Windows 11.&lt;/p&gt;

&lt;p&gt;For Alma this is a simple job of installing the release package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[root@DESKTOP-E3QS517:~]# yum install https://yum-puppetcore.puppet.com/public/puppet8-release-el-9.noarch.rpm
Last metadata expiration check: 2:08:56 ago on Mon Feb 24 14:37:10 2025.
puppet8-release-el-9.noarch.rpm                                                                                                                                                                                                              3.6 kB/s | 8.2 kB     00:02
Dependencies resolved.
=============================================================================================================================================================================================================================================================================
 Package                                                              Architecture                                                Version                                                            Repository                                                         Size
=============================================================================================================================================================================================================================================================================
Installing:
 puppet8-release                                                      noarch                                                      10.4.0-0.el9                                                       @commandline                                                      8.2 k

Transaction Summary
=============================================================================================================================================================================================================================================================================
Install  1 Package

Total size: 8.2 k
Installed size: 2.0 k
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                                                                                                                                                                                     1/1
  Installing       : puppet8-release-10.4.0-0.el9.noarch                                                                                                                                                                                                                 1/1
warning: Unable to get systemd shutdown inhibition lock: Could not activate remote peer.

  Verifying        : puppet8-release-10.4.0-0.el9.noarch                                                                                                                                                                                                                 1/1

Installed:
  puppet8-release-10.4.0-0.el9.noarch

Complete!
[root@DESKTOP-E3QS517:~]# vi /etc/yum.repos.d/puppet8-release.repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then adding your forge API key to the repo configuration. Don't change the username it's supposed to be forge-key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[puppet8]
name=Puppet 8 Repository el 9 - $basearch
baseurl=https://yum-puppetcore.puppet.com/puppet8/el/9/$basearch
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-2025-04-06-puppet8-release
enabled=1
gpgcheck=1

## Add authentication here by uncommenting and filling in values

#username=forge-key
#password=&amp;lt;api_key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then search the packages to make sure the packages are visible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[root@DESKTOP-E3QS517:~]# yum search puppet
Last metadata expiration check: 2:46:27 ago on Mon Feb 24 14:37:34 2025.
======================================================================================== Name &amp;amp; Summary Matched: puppet =========================================================================================
puppet-agent.x86_64 : The Puppet Agent package contains all of the elements needed to run puppet, including ruby and facter.
puppet8-release.noarch : Release packages for the Puppet 8 repository
puppetdb.noarch : Puppet Labs puppetdb
puppetdb-termini.noarch : Termini for puppetdb
puppetserver.noarch : Puppet Labs puppetserver
============================================================================================ Summary Matched: puppet ============================================================================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Windows I used the curl command and I am using the 1Password CLI to allow me to read in my stored forge key. This simply downloads the agent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -J -O -u forge-key:$(op read op://Employee/puppetcorekey/password) 'https://artifacts-puppetcore.puppet.com/v1/download?os_name=windows&amp;amp;os_version=11&amp;amp;version=8.11.0&amp;amp;os_arch=x64'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 43.6M  100 43.6M    0     0  62.5M      0 --:--:-- --:--:-- --:--:-- 62.6M
 ls .\puppet-agent-8.11.0-x64.msi

    Directory: C:\Users\david.sandilands

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          24/02/2025    16:25       45749760 puppet-agent-8.11.0-x64.msi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So simple as that we now have the Puppet core packages secured with the forge keys. Let us know if there any further details you are looking for with Puppet Core.&lt;/p&gt;

</description>
      <category>puppet</category>
      <category>puppetcore</category>
    </item>
    <item>
      <title>Louis, I think this is the beginning of a beautiful friendship</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Thu, 23 Jan 2025 10:34:40 +0000</pubDate>
      <link>https://forem.com/puppet/louis-i-think-this-is-the-beginning-of-a-beautiful-friendship-3p2b</link>
      <guid>https://forem.com/puppet/louis-i-think-this-is-the-beginning-of-a-beautiful-friendship-3p2b</guid>
      <description>&lt;p&gt;There have been a lot of concerns and questions about Puppet and the Community over the past couple of months since the changes were &lt;a href="https://www.puppet.com/blog/open-source-puppet-updates-2025" rel="noopener noreferrer"&gt;announced&lt;/a&gt; . It has taken Perforce and the Community time to work out how to meet the Communities need for autonomy, Perforces business needs and legal responsibilities for items like trademark, all while ensuring the rich Puppet ecosystem of content and tools remain compatible. &lt;/p&gt;

&lt;p&gt;OpenVox have created what we would describe as a soft fork, where they create a new name space and project name OpenVox but the use of 'puppet'; in forked source code follows Apache 2.0 licensing with the intent to retain compatibility, and attribute the Puppet trademark appropriately to avoid brand confusion. Simply this ensures binaries, libraries, etc do not need renamed and ensures Perforces responsibility as a trademark holder is met.&lt;/p&gt;

&lt;p&gt;To ensure this new partnership works well we will be taking a number of steps in order to guarantee long term interoperability to the benefit of all current and future Puppet users.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Perforce and the Community will partner together on a language steering group to ensure we continues to develop the language specification and ensure ecosystem compatibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Everyone will have access to EULA signed builds from Perforce for development purposes which will be released on a 6 week cycle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will be revitalizing our trusted Contributor and Champions programs while also ensuring our own staff are enabled to contribute&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An event plan will be created to help our community and customers know where they can come and collaborate with us&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We congratulate OpenVox on their &lt;a href="https://voxpupuli.org/blog/2025/01/21/openvox-release/" rel="noopener noreferrer"&gt;first release&lt;/a&gt; and look forward to shortly releasing Puppet Core which will offer hardened binaries with bug and vulnerability support to give customers a more accessible level for enterprise support.&lt;/p&gt;

&lt;p&gt;Look out for further announcements and hopefully we will see many of you at Cfgmgmt Camp in two weeks&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Puppet Community Townhall Recap</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Wed, 18 Dec 2024 18:58:18 +0000</pubDate>
      <link>https://forem.com/puppet/puppet-community-townhall-recap-333j</link>
      <guid>https://forem.com/puppet/puppet-community-townhall-recap-333j</guid>
      <description>&lt;p&gt;I would like to thank everyone who joined us for our Community Townhall. We appreciate the questions, concerns, and feedback.&lt;/p&gt;

&lt;p&gt;To summarize the call, we clarified the changes and the reasons behind them. We acknowledged Puppet’s maturity as a product, the rising cost to secure and maintain open-source Puppet (OSP) and need to balance downstream priorities required of Enterprise customers while reinvesting in the freedom of the community to grow OSP under the Apache 2.0 license.&lt;/p&gt;

&lt;p&gt;We also communicated our go-forward plans to formalize programs that support and recognize Puppet contributors and provide support for community-run regional user groups. We recognize that these programs previously existed, but we are looking to gather input from the community to ensure these programs are re-launched in a meaningful way. We communicated plans to discuss this live with community members at &lt;a href="https://www.cfgmgmtcamp.eu/ghent2025/" rel="noopener noreferrer"&gt;cfgmgmt camp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After a few brief slides, we opened to the floor for questions. Here is a summary of the Q&amp;amp;A session. We didn’t have time to fully address all the questions asked during the live session, so I have provided additional clarification in this blog summary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Community Ownership&lt;/strong&gt; – Several questions &amp;amp; concerns were raised over the location and ownership of the open-source repositories. We addressed that the repos would remain in the puppetlabs name space which Perforce would continue to fund, including covering costs for contributor licenses and build pipelines/infrastructure.&lt;/p&gt;

&lt;p&gt;As far as ownership goes, Perforce communicated a plan that grants ownership of the following to the collective community under the Apache 2.0 license:&lt;/p&gt;

&lt;p&gt;• Co-author the source code of the project &lt;br&gt;
• Approve commits / changes&lt;br&gt;
• Maintain security fixes  / defect fixes&lt;br&gt;
• Create binaries, packages, Gems&lt;br&gt;
• Create/Maintain Modules in a compatible way&lt;/p&gt;

&lt;p&gt;Puppet &amp;amp; Perforce have historically owned this. In this new community-led model, Perforce is a part of the collective community, not the sole owners or gatekeepers of the community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Control and decision making&lt;/strong&gt; - It was asked how conflicts would be resolved going forward, and who would have majority control. Community members expressed concern with Perforce having too much power. Our view is that the collective community would have to work together to establish the correct process, structure, and bylaws. Mechanisms, such as the language steering committee, would allow us to work out ways that ensure compatibility and interoperability for the Puppet ecosystem. We do not aim to have majority stake, just equal representation as other community members. Our goal is to provide support for the community in this new model, and we still plan to contribute. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contributions v Reviews&lt;/strong&gt; - We discussed the reduction in contributions by community members over the past several years. Attendees indicated that this was a result of the infrequent and slow review process by the Puppet and Perforce team. The Perforce team agreed and acknowledged this as part of the prioritization problem we have been experiencing – a leading reason why we want to remove ourselves as a gatekeeper. In the new model, Perforce is no longer a gatekeeper. The collective community would have the ability to approve commits and changes.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardened packages&lt;/strong&gt; -  Questions were asked about the hardened OSP packages available in Perforce’s private repository, specifically what hardening will be provided. Perforce has a well-established, standardized set of processes and tools for product hardening that we apply consistently across our commercial offerings. Over time, we’ve developed a proven methodology that includes industry-leading security assessments, code reviews, and penetration testing procedures. Our approach involves leveraging a vetted toolchain for security scanning and adhering to a rigorous security checklist throughout the development lifecycle. By following these standardized practices, we ensure that Perforce commercial products pass thorough hardening measures before reaching our customers. The hardened OSP packages are no exception. We will provide further details, including SLAs, when the offering launches in early 2025.&lt;/p&gt;

&lt;p&gt;We also confirmed that the community will have free access to the hardened OSP packages in the Perforce private repository under the terms of 25 node limited development license.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cnfgmgmt camp geography&lt;/strong&gt; - It was highlighted that many members would not be able to make cnfgmgmt camp and we agreed to investigate options to facilitate remote voting / viewing. We will ensure that the broader community has a chance to weigh in and vote.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trademark&lt;/strong&gt; - It was asked if the Puppet trademark could be used in the community project for various naming purposes. In short, the Perforce team said “no”. We understand that the open-source community is interested in using our trademark, and we appreciate the community’s enthusiasm for Puppet. However, our trademark represents a significant investment in our brand, reputation, and the quality we guarantee to our customers. &lt;/p&gt;

&lt;p&gt;This choice isn’t a reflection on the community’s efforts or intentions. It is simply a matter of preserving the integrity of the Puppet brand and ensuring that any products or materials bearing the Puppet name continue to meet the criteria we have established. We appreciate your understanding and respect for our position.&lt;/p&gt;

&lt;p&gt;Again, I would like to thank everyone for taking part in the Puppet Community Town Hall. Many of the concerns raised reflect the difficulty of having community contributions overlayed into a release process that Puppet and Perforce have fully controlled. We understand that this announcement and our intent to remediate these concerns can have the adverse effect of raising more questions than answers, but we are eager to find a path forward through ongoing conversations with the Puppet community. We believe that we share a common goal for increased adoption and success of Puppet across a diverse range of customer needs.&lt;/p&gt;

&lt;p&gt;For those that could not make it, the &lt;a href="https://perforce.zoom.us/rec/share/jCtSw0FMTW6RaXmtEhIbgaemsKHCE5983RNcoSIMAk4_RBaHgVE9bBzd4zbeKL7L.Os4K_vvwokditeQi" rel="noopener noreferrer"&gt;recording&lt;/a&gt; is available. (Passcode: E4^x02M8)&lt;br&gt;
Please reach out to us on Puppet’s Community slack or at &lt;a href="mailto:puppet-community-questions@perforce.com"&gt;puppet-community-questions@perforce.com&lt;/a&gt; with any questions. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Forge Compatibility Reports for module management</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Mon, 16 Dec 2024 14:00:37 +0000</pubDate>
      <link>https://forem.com/puppet/forge-compatibility-reports-for-module-management-n7k</link>
      <guid>https://forem.com/puppet/forge-compatibility-reports-for-module-management-n7k</guid>
      <description>&lt;p&gt;It was the moment I dreaded: my Puppet modules would be running perfectly, and then a Puppet upgrade, new module, or module update would break the harmony. I would need to scramble to work out dependencies between modules and make sure everything could be brought up to date and be compatible.&lt;/p&gt;

&lt;p&gt;This process often required a giant spreadsheet, where I would slowly copy out details from the Forge and check them over and over while I negotiated with my team about which versions we had to stick for certain requirements. And even while this was happening, I still had to watch out to see if module upgrades had new decencies or worse deprecations — then I would need to revisit the Sudoku-like spreadsheet again.&lt;/p&gt;

&lt;p&gt;The great news is this is no longer needed — with the new Compatibility Report, the Forge does the hard work for us.&lt;/p&gt;

&lt;p&gt;Starting out, we need to provide a baseline for the compatibility report, this can either be done from your existing module download information or by providing a &lt;code&gt;Puppetfile&lt;/code&gt;. See &lt;a href="https://help.puppet.com/forge/current/Content/users/enable_download_reporting.htm" rel="noopener noreferrer"&gt;enabling download reporting&lt;/a&gt; if you want to set up your module download information. &lt;/p&gt;

&lt;p&gt;The advantage of providing a Puppetfile is it gives you the flexibility to try different configurations without worrying about affecting your current download information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidk21b7rmhxq2fwtfkdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidk21b7rmhxq2fwtfkdf.png" alt="Choose a source for module details" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we have chosen our download information or uploaded a Puppetfile, we can then select the version of PE or Puppet we want to baseline to. This is especially useful for users who want to catch up this include versions like 6 and 7 and PE 2019 and 2021.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxteb087v692izcda6xvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxteb087v692izcda6xvt.png" alt="Choose a version to target upgrade" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have a compatibility report highlighting modules that need updates, where dependencies have been added, deprecations, and incompatibilities. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a31oiwazrdk12fkes7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a31oiwazrdk12fkes7b.png" alt="Compatibility report" width="800" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also examine the changes in the module version suggested by clicking see changes to the right of the suggest version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybdt77ki3yvqd89x29ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybdt77ki3yvqd89x29ls.png" alt="Changes in suggested module version" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A new Puppetfile containing the suggestions and new dependencies can be downloaded clicking the download Puppetfile button on the top right of the report. Incompatibilities will be left at their original version.&lt;/p&gt;

&lt;p&gt;If you (like me) have that team that insists they need to pin to a certain version of a module, you can select modules and see which version would be compatible for the Puppet/PE version you are targeting&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftarq5zid02y5cchzftqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftarq5zid02y5cchzftqy.png" alt="Pin a modules version in compatibility report" width="800" height="754"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbls81p5jhs7qs8gvg1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbls81p5jhs7qs8gvg1y.png" alt="Choose a compatible module version to pin" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then generate a specific report, in this case we can actually immediately see the module version I have chosen for Apache can not be made compatible with the other dependency requirements in the Puppetfile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgkxnvm5c7jgv8qrxgxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgkxnvm5c7jgv8qrxgxi.png" alt="Compatibility module report with pinned version" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s worth noting that you can keep up to 25 reports, so you can experiment and compare reports.&lt;/p&gt;

&lt;p&gt;Beyond the core use case of upgrading Puppet, the report also gives you the ability to test adding modules to a Puppet file, update a module version, or removing modules.&lt;/p&gt;

&lt;p&gt;So a big “thank you!” to the Forge team and grateful farewell to that awful spreadsheet!”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://help.puppet.com/forge/current/Content/intro/comp_rept_overview.htm" rel="noopener noreferrer"&gt;https://help.puppet.com/forge/current/Content/intro/comp_rept_overview.htm&lt;/a&gt;&lt;/p&gt;

</description>
      <category>puppet</category>
      <category>upgrades</category>
      <category>dependencies</category>
      <category>module</category>
    </item>
    <item>
      <title>Open Source Puppet Survey</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Thu, 11 Jul 2024 11:30:16 +0000</pubDate>
      <link>https://forem.com/puppet/open-source-puppet-survey-ne1</link>
      <guid>https://forem.com/puppet/open-source-puppet-survey-ne1</guid>
      <description>&lt;p&gt;Hello all,&lt;/p&gt;

&lt;p&gt;We value your input and as we investigate future roadmap initiatives for Open Source Puppet, we'd like to learn more about your experience with Open Source Puppet, and your views and opinions on a couple of important related topics.&lt;/p&gt;

&lt;p&gt;This survey will take just approximately 7 minutes of your time and will remain open until July 25th.&lt;/p&gt;

&lt;p&gt;Past feedback from our Open Source users has been incredibly helpful, and we sincerely appreciate your continued participation. Your feedback helps us understand your needs better and guides our decision making on current and future offerings for our Open Source user base.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forms.office.com/Pages/ResponsePage.aspx?id=0Wa2lXWaq0mVo4lp-83AjJGTd62UuY1LoMw2Pz6g7BdUN09BUFBJSjkxSUJETTJDT1FOOTJIODVHUC4u" rel="noopener noreferrer"&gt;Open Source Puppet Survey&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>survey</category>
      <category>puppet</category>
    </item>
    <item>
      <title>Puppet certificate renewals</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Thu, 06 Jun 2024 12:47:22 +0000</pubDate>
      <link>https://forem.com/puppet/puppet-certificate-renewals-4gml</link>
      <guid>https://forem.com/puppet/puppet-certificate-renewals-4gml</guid>
      <description>&lt;p&gt;After a number of customer sessions it was apparent that there were a number of places and tools which could be used to handle Puppet certificates and it would be good to have a written summary to be able to step through. This article aims to give a summary of what we need to do to keep Puppet certificates in date.&lt;/p&gt;

&lt;p&gt;In summary: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We must understand when our Console Certificate and SAML certificates will expire and renew it in advance (PE only)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We must understand when our Certificate Authority (CA) will expire and renew it in advance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When we renew our CA we must distribute that new CA to both clients and integrations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Separately all clients including the Primary itself have an agent signed certificate which will expire separately and must be renewed in advance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Console and SAML expiry&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a Puppet generated generated console and SAML certificates expiry is every 824 days and the articles [regenerate console certificate],(&lt;a href="https://www.puppet.com/docs/pe/latest/regenerate_console_cert" rel="noopener noreferrer"&gt;https://www.puppet.com/docs/pe/latest/regenerate_console_cert&lt;/a&gt;)&lt;br&gt;
covers how to check the expiry date as well as delete the current console certificate and replace with a Puppet run. While &lt;a href="https://www.puppet.com/docs/pe/latest/regenerate_saml_cert" rel="noopener noreferrer"&gt;regnerate SAML certificate&lt;/a&gt; covers the same for SAML if you have configured it. &lt;/p&gt;

&lt;p&gt;If you are using a custom console certificate ultimately you will replace the expiring certificate using  &lt;a href="https://www.puppet.com/docs/pe/2023.6/use_a_custom_ssl_cert_for_the_console" rel="noopener noreferrer"&gt;the custom ssl certificate for console&lt;/a&gt; article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CA expiry.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;For Primaries built pre-Puppet 6 this would be a 5 year expiry period, which we would extend now to 20 years as Puppet 6 and onwards does.&lt;/p&gt;

&lt;p&gt;This expiry date is visible at &lt;a href="https://primary.example.com/#/certificates/certs" rel="noopener noreferrer"&gt;https://primary.example.com/#/certificates/certs&lt;/a&gt; ,using the &lt;a href="https://forge.puppet.com/modules/puppetlabs/pe_status_check/readme#fact-pe_status_check" rel="noopener noreferrer"&gt;pe_status_check&lt;/a&gt; module S0005 fact status check or using the CA_extend module &lt;a href="https://forge.puppet.com/modules/puppetlabs/ca_extend/tasks" rel="noopener noreferrer"&gt;check_ca_expiry&lt;/a&gt; task.&lt;/p&gt;

&lt;p&gt;When it needs renewed we recommend using the CA_extend module &lt;a href="https://forge.puppet.com/modules/puppetlabs/ca_extend/plans" rel="noopener noreferrer"&gt;extend_ca_cert&lt;/a&gt; plan&lt;/p&gt;

&lt;p&gt;Following this the new CA should then be distributed to all agents using CA_extend module &lt;a href="https://forge.puppet.com/modules/puppetlabs/ca_extend/plans" rel="noopener noreferrer"&gt;upload_ca_cert&lt;/a&gt; plan or by simply running a script on each agent which deletes / moves the old CA  at &lt;code&gt;C:\ProgramData\PuppetLabs\puppet\etc\ssl\certs\ca.pem&lt;/code&gt; or &lt;code&gt;/etc/puppetlabs/puppet/ssl/certs/ca.pem&lt;/code&gt; depending on nix or Windows platform and runs &lt;code&gt;puppet agent -t&lt;/code&gt;. This will request the new CA from the Puppet primary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For CD4PE steps 4 to 6 should be followed in &lt;a href="https://www.puppet.com/docs/continuous-delivery/4.x/cd_troubleshooting#configure-pe-manually" rel="noopener noreferrer"&gt;CD4PE manually configure PE integration&lt;/a&gt; to obtain and copy and paste the new CA into the Puppet integration page&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signed agents&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We would recommend upgrading to Puppet 8 which would automate this step as shown on the &lt;a href="https://www.puppet.com/blog/puppet-8" rel="noopener noreferrer"&gt;blog article&lt;/a&gt; but agents by default pre-Puppet 8 will have a 5 years expiry. There are multiple ways to search agents about to expire. The CA_extend module has a &lt;a href="https://forge.puppet.com/modules/puppetlabs/ca_extend/tasks" rel="noopener noreferrer"&gt;check_agent_expiry&lt;/a&gt; task. (This will report a default period of within 3 months but can be adjusted), the pe_status_check module has &lt;a href="https://forge.puppet.com/modules/puppetlabs/pe_status_check/readme#fact-pe_status_check" rel="noopener noreferrer"&gt;AS001 fact status check&lt;/a&gt;, which combined with a PQL search will allow you to check for all agents expiring. As per doc example &lt;code&gt;puppet query 'inventory[certname] { facts.agent_status_check.AS001 = false }'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The command to renew agents can be run via &lt;code&gt;puppet infra run regenerate_agent_certificate&lt;/code&gt; which can also be run via the enterprise task plan &lt;code&gt;enterprise_tasks::agent_cert_regen&lt;/code&gt; and both can be fed by a query such as puppet plan run &lt;code&gt;enterprise_tasks::agent_cert_regen agent=$(puppet query 'inventory[certname] { facts.agent_status_check.AS001 = false }' \| jq -r '.[].certname' \| paste -sd, -) master=$(puppet config print certname)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Hopefully this has pulled together all the information you need to keep ahead of certificate expiry and put in place suitable automation.&lt;/p&gt;

</description>
      <category>certificates</category>
      <category>puppet</category>
      <category>ca</category>
    </item>
    <item>
      <title>Selecting targets for plans in Puppet Enterprise</title>
      <dc:creator>David Sandilands</dc:creator>
      <pubDate>Mon, 13 Mar 2023 17:41:14 +0000</pubDate>
      <link>https://forem.com/puppet/selecting-targets-for-plans-in-puppet-enterprise-52fk</link>
      <guid>https://forem.com/puppet/selecting-targets-for-plans-in-puppet-enterprise-52fk</guid>
      <description>&lt;p&gt;This article was previously published on the Puppet blog by Steve Axthelm.&lt;/p&gt;

&lt;p&gt;Do you author plans for Puppet Enterprise? Looking for ways to improve them? Read on!&lt;/p&gt;

&lt;p&gt;The Puppet Plan language allows a variety of methods to pick targets. In this article we will explore two of these methods (TargetSpec parameters and PuppetDB queries) and how plan authors can employ the latter to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improve the user experience of running the plans.&lt;/li&gt;
&lt;li&gt;Reduce input errors.&lt;/li&gt;
&lt;li&gt;Restrict the scope of nodes that the plan can execute against.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: the following examples assume that you are running against targets that have the Puppet agent installed. You can achieve similar results for targets that are not running the Puppet agent by gathering facts with the facts plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  TargetSpec parameters
&lt;/h2&gt;

&lt;p&gt;The most basic target input a plan can have is a parameter that is a &lt;a href="https://puppet.com/docs/bolt/latest/writing_plans.html#targetspec" rel="noopener noreferrer"&gt;TargetSpec&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plan test::targets(
  TargetSpec $nodes_to_target,
){
  run_command("whoami", $nodes_to_target)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users running the plan on the command line can then supply the targets through an inventory file, a list of FQDNs (fully qualified domain names), etc., and Puppet Enterprise Console users will be presented with a plain text input where they can enter FQDNs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq71kw1rmu4oxdr9ozb98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq71kw1rmu4oxdr9ozb98.png" alt="Run a plan" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is very flexible, but when authoring plans that other users will run, this much flexibility is often neither required nor desired, and also introduces the possibility for entry error. General user experience guidelines include error prevention when possible, so let's take a look at an alternative method for target input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Enum Parameters and PuppetDB Queries
&lt;/h2&gt;

&lt;p&gt;Using Enum type parameters is a great way to decrease the chances of user input errors. We could hard-code the targets into the plan and allow users to choose a set of targets. This would solve for user entry errors, but it would be fragile. We can specify targets in a more robust manner by using PuppetDB queries. Perhaps we have an application monitoring team that watches over web servers, load balancers and database servers. We can provide them with a quick way to select the types of hosts on which they are interested in running a task. &lt;a href="https://puppet.com/docs/puppetdb/latest/api/query/v4/pql.html" rel="noopener noreferrer"&gt;PuppetDB queries&lt;/a&gt; are very flexible and can query for hosts using a variety of methods.&lt;/p&gt;

&lt;p&gt;This plan takes a server_type parameter, queries all targets that fit the &lt;code&gt;server_type&lt;/code&gt; profile through a PuppetDB query that checks if they have &lt;code&gt;Apache&lt;/code&gt;, &lt;code&gt;Haproxy&lt;/code&gt;, or &lt;code&gt;Postgresql::Server&lt;/code&gt; classes applied to the hosts, and returns the last boot time for each host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plan server_team::check_boot_time(
  Enum['Webservers', 'Balancers', 'Database'] $server_type,
){
  $server_type_query = case $server_type {
    'Webservers': { 'resources[certname] { type = "Class" and title = "Apache" }' }
    'Balancers': { 'resources[certname] { type = "Class" and title = "Haproxy" }' }
    'Database': { 'resources[certname] { type = "Class" and title = "Postgresql::Server" }' }
  }

  $server_type_results = puppetdb_query($server_type_query)
  $server_type_targets = $server_type_results.map |$r| { $r["certname"] }

  run_task("reboot::last_boot_time", $server_type_targets)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command line interface (CLI) users can then run the plan with &lt;code&gt;puppet plan run server_team::check_boot_time server_type=&amp;lt;value&amp;gt;&lt;/code&gt; and Puppet Enterprise Console users are presented with a select form control where they can choose the type:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F88d7gc6x0jt73dze9a3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F88d7gc6x0jt73dze9a3h.png" alt="PE Plan Parameters" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a big improvement in user experience for the users who will run the plan and it also bakes in limited scope with respect to which nodes the plan can be run against. &lt;a href="https://puppet.com/docs/puppet/7/lang_facts_builtin_variables.html#lang_facts_builtin_variables-trusted-facts" rel="noopener noreferrer"&gt;Trusted facts&lt;/a&gt; can also be employed in the queries to make the scope limiting more secure. This plan takes two parameters, &lt;code&gt;rhel_major_version&lt;/code&gt;, and &lt;code&gt;trusted_domain&lt;/code&gt;, constructs a PuppetDB query from those using facts and trusted facts, and then simply echoes out the &lt;code&gt;trusted_domain&lt;/code&gt; for each host returned from the query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plan server_team::echo_trusted_domain(
  Enum['6', '7', '8'] $rhel_major_version,
  Enum['vm', 'com', 'net'] $trusted_domain,
){
  $target_query = "trusted.domain = '$trusted_domain' and facts.os.family = 'RedHat' and facts.os.release.major = '$rhel_major_version'"

  $target_query_result = puppetdb_query("inventory[certname] { $target_query }")
  $command_targets = $target_query_result.map |$r| { $r["certname"] }

  run_command("echo $trusted_domain", $command_targets)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CLI users can run the plan with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;puppet plan run server_team::echo_trusted_domain rhel_major_version=&amp;lt;value&amp;gt; trusted_domain=&amp;lt;value&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Puppet Enterprise Console users will be presented with select form controls for the parameters:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2f5ez0384th9drc7y5b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2f5ez0384th9drc7y5b4.png" alt="Puppet parameter values 2" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the user supplies a value for either of the parameters that are not one of the enumerated options, an error will be thrown:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;puppet plan run server_team::echo_trusted_domain rhel_major_version=7 trusted_domain=info&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "kind": "bolt/pal-error",
  "msg": "test::targets: parameter 'trusted_domain' expects a match for Enum['com', 'net', 'vm'], got 'info'",
  "details": {
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that users who run your plans will be able to supply only the parameter values you expect.&lt;/p&gt;

&lt;p&gt;While the plans presented are simple in nature, hopefully they will spark some ideas for how you can improve the experience of the users who run plans that you author.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://puppet.com/docs/bolt/latest/plans.html" rel="noopener noreferrer"&gt;Learn more&lt;/a&gt; about orchestrating workflows with Bolt plans.&lt;br&gt;
&lt;a href="https://puppet.com/docs/pe/latest/plans-in-pe.html" rel="noopener noreferrer"&gt;Learn more&lt;/a&gt; about Bolt plans in Puppet Enterprise.&lt;/p&gt;

</description>
      <category>puppet</category>
      <category>bolt</category>
      <category>plans</category>
      <category>targetspec</category>
    </item>
  </channel>
</rss>
