Puppet upgrade in 2023.4 and later

PE2023.4 introduced a new major version of Puppet. Consider the information presented here about changes in Puppet 8 that might impact your Puppet Enterprise (PE) installation, and plan accordingly before upgrading.

License key update required

To upgrade from versions earlier than PE 2023.8.2, you need a license key in the file format /etc/puppetlabs/suite-license.lic. For instructions on updating the license key, see Upgrading agents.

Legacy facts no longer collected or sent to Puppet Server

Puppet 8 completes the transition away from legacy facts, which were deprecated in Puppet 7. Starting in Puppet 8, legacy facts are no longer collected or sent to the Puppet Server. Instead of using legacy facts, which were written as key-value pairs, Puppet 8 now uses structured facts, which are array and hash data structures.

Starting in PE 2023.4, to help ensure that nodes are classified correctly, the PE node classifier service examines your node group rules and automatically replaces most legacy facts with exact equivalent structured facts.

Some legacy facts cannot be mapped to an exact equivalent structured fact, so they must be manually removed or replaced by a close equivalent structured fact. The classifier generates warning messages in the logs prompting you to remove or replace any unmappable legacy facts that are included in your node group rules. For a list of unmappable legacy facts together with close equivalent structured facts you can use, see the table below.

Starting in PE 2023.4, the installer examines your existing node group rules and if any unmappable legacy facts are found, the installation process stops with a warning. To proceed with installation, you can manually replace or remove unmappable legacy facts and re-run the installer.

To avoid disruptions associated with legacy facts, take the following actions as required.

  • If you have Puppet code containing legacy facts, you can use the legacy_facts plugin in the puppet-lint tool to automatically convert any legacy facts that map to an exact equivalent structured fact.
  • If legacy facts are referenced in your Embedded Ruby (ERB) templates, your Embedded Puppet (EPP) templates, or in your Hiera configuration file, you must manually find those legacy facts and either remove them or replace them with exact or close equivalent structured facts.
  • If you plan to use any of the /v*/classified/nodes endpoints, you must enter structured facts to obtain accurate results.
  • If unmappable legacy facts are included in any of your PE node group rules or in any Puppet code you use, you must manually remove those legacy facts or replace them with close equivalent structured facts. See the table below for more information.

The following table lists the unmappable legacy facts that cannot be automatically converted by the PE classifier or the legacy_facts plugin in the puppet-lint tool. You can manually replace these unmappable legacy facts with their respective close equivalent structured facts.

Unmappable legacy factClose equivalent structured facts
memoryfree_mb

Returned a double specifying the size of the free system memory, in mebibytes.

$facts['memory']['system'][available']

or

$facts['memory']['system']['available_bytes']

See Facter documentation on memory.

memorysize_mb

Returned a double specifying the size of the total system memory, in mebibytes.

$facts['memory']['system']['total']

or

$facts['memory']['system']['total_bytes']

See Facter documentation on memory.

swapfree_mb

Returned a string specifying the size of the free swap memory, in mebibytes.

$facts['memory']['swap']['available']

or

$facts['memory']['swap']['available_bytes']

See Facter documentation on memory.

swapsize_mb

Returned a string specifying the size of the total swap memory, in mebibytes.

$facts['memory']['swap']['used']

or

$facts['memory']['swap']['used_bytes']

See Facter documentation on memory.

blockdevices

Returned a string containing all block devices separated by a comma.

Can be replicated using puppetlabs/stdlib and the following:

join(keys($facts['disks']), ',')

interfaces

Returned a string containing all interfaces separated by a comma.

Can be replicated using puppetlabs/stdlib and the following:

join(keys($facts['networking']['interfaces']), ',')

zones

Returned a string containing all zone names separated by a comma.

Can be replicated using puppetlabs/stdlib and the following:

join(keys($facts['solaris_zones']['zones']), ',')

sshfp_dsa

Returned a string containing both the SHA1 and SHA256 fingerprint for the DSA algorithm.

Can be replicated using the following string:

"$facts['ssh']['dsa']['fingerprints']['sha1'] $facts['ssh']['dsa']['fingerprints']['sha256']"

See Facter documentation on SSH.

sshfp_ecdsa

Returned a string containing both the SHA1 and SHA256 fingerprint for the ECDSA algorithm.

Can be replicated using the following string:

"$facts['ssh']['ecdsa']['fingerprints']['sha1'] $facts['ssh']['ecdsa']['fingerprints']['sha256']"

See Facter documentation on SSH.

sshfp_ed25519

Returned a string containing both the SHA1 and SHA256 fingerprint for the Ed25519 algorithm.

Can be replicated using the following string:

"$facts['ssh']['ed25519']['fingerprints']['sha1'] $facts['ssh']['ed25519']['fingerprints']['sha256']"

See Facter documentation on SSH.

sshfp_rsa

Returned a string containing both the SHA1 and SHA256 fingerprint for the RSA algorithm.

Can be replicated using the following string:

"$facts['ssh']['rsa']['fingerprints']['sha1'] $facts['ssh']['rsa']['fingerprints']['sha256']"

See Facter documentation on SSH.

Strict mode enabled by default

Starting in Puppet 8, strict validation is enabled by default through the strict=error and strict_variables=true settings in puppet.conf. With these default settings, if your Puppet code does not conform to strict rules, then catalog compilation fails with an error. To avoid disruption, consider the following points and manually update your code where necessary.

  • Automatic type coercion is not allowed in strict mode. For example, a string such as “1”+1 in your Puppet code cannot be automatically converted to a numeric. For more information about automatic type coercion see, Automatic coercion in the Open Source Puppet documentation.
  • Unknown variables are not permitted with the default strict mode settings in Puppet 8. For example, if you use modules that contain unknown variables, catalog compilations will fail. Before upgrading PE, review your puppetserver.log files and address the issues identified in any existing warnings about unknown variables. Resolving issues helps ensure that existing warnings do not become fatal errors after you run the upgrade.
  • If your Hiera code references legacy facts in top-level variables, then those variables cannot be defined because Puppet agents no longer collect or send legacy facts. When top-level variables are undefined, strict validation causes Hiera lookups to fail. For example, when strict mode is enabled, a lookup error occurs with the following hierarchy:
    hierarchy:
      - name: "osfamily"
        path: "%{osfamily}.yaml"

    To avoid Hiera lookup failures, replace the legacy fact with the equivalent structured fact as follows:

    hierarchy:
      - name: "osfamily"
        path: "%{facts.os.family}.yaml".

    If a hierarchy currently references an optional fact, you must use the facts hash as follows to ensure that the Hiera lookup proceeds to the common layer when agents omit the fact:

    hierarchy:
      - name: "optional"
        path: "%{facts.optional}.yaml"
      - name: "common"
        path: "common.yaml".

If you want to permit automatic type coercions after upgrading, you can disable strict mode in the console:

  1. Click Node groups > PE Infrastructure > PE Agent.
  2. Select the Classes tab and locate the puppet_enterprise::profile::agent class.
  3. From the Parameter name dropdown, select strict and enter "warning" as the value.
  4. Click Add to node group and commit your changes.

Alternatively, you can disable strict mode using the CLI:

  1. On the Puppet Server host, run puppet config set strict warning --section main.
  2. Restart the pe-puppetserver service by running systemctl restart pe-puppetserver.

If you want to permit unknown variables after upgrading, you must change the strict_variables setting to false on all nodes that run pe-puppetserver. You can do this by running the following tasks on the Puppet Server host:

puppet task run puppet_conf \
  --params '{"action":"set","setting":"strict_variables","value":"false"}' \
  --query 'resources[certname] { type = "Class" and title = "Puppet_enterprise::Profile::Master" }'

puppet task run service name=pe-puppetserver action=restart \
  --query 'resources[certname] { type = "Class" and title = "Puppet_enterprise::Profile::Master" }'
If you disable strict mode settings, you must still ensure that you remove all references to legacy facts from your global layer, environment layer, and module layer hiera.yaml files. Otherwise, Hiera lookups will return corrupted data to compilers.

Lazy resolution of deferred data types

In Puppet 7, Deferred data types were resolved eagerly at the beginning of the agent run. However, in Puppet 8, the Deferred data type instructs the agent to call functions dynamically during the Puppet run. This functionality is particularly useful for tasks like retrieving a password from a secret store over HTTPS and saving it in a configuration file.

During the Puppet run in Puppet 8, the agent sequentially executes deferred functions based on their order within resource declarations. If a deferred function requires any resources, like an SDK necessary to interact with a secret store, these dependencies can be automatically managed before the deferred function is executed.

After upgrading to Puppet 8, if you encounter Puppet run errors due to resource compatibility issues in your Puppet code, you can turn on the preprocess_deferred setting so the agent calls deferred functions and identifies dependency errors before a Puppet run starts.

To turn on the preprocess_deferred setting:

  1. In the PE console, click Node groups > PE Infrastructure > PE Agent.
  2. Select the Classes tab and locate the puppet_enterprise::profile::agent class.
  3. From the Parameter name dropdown, select preprocess_deferred and enter true as the value.
  4. Click Add to node group and commit your changes.

Ruby version upgrade

The upgrade to Ruby 3.2 in Puppet 8 might result in compatibility issues that affect Puppet extensions in your code. To check compatibility, use the latest version of PDK to update and test your modules.

You must re-install third party gems when the Ruby version used by Puppet changes as part of an upgrade. For example, if Puppet 7 (which uses Ruby 2.7), changes to Puppet 8 (which uses Ruby 3.2), as part of a PE upgrade, third party gems must be reinstalled. Puppet agent runs fail after upgrading if gems are not re-installed. We recommend that you review gem dependencies to identify what is in use in your environment as these are not covered by the compatibility checks performed by the PDK.

Gems installed for use by the Puppet agent can be listed with:

  • /opt/puppetlabs/puppet/bin/gem list –local

Gems installed for use by the Puppet Server can be listed with:

  • /opt/puppetlabs/bin/puppetserver gem list –local

Note that the above lists contain some gems, included with PE, that must not be re-installed. Compare the output against lists generated from a fresh PE installation or the documentation for installed modules in order to discover third party gems that have been added.

OpenSSL version upgrade

Puppet 8 includes OpenSSL 3.0. This upgrade might result in compatibility issues when the agent is connecting to other servers in your environment. To avoid SSL errors, ensure that the OpenSSL version used by your servers is updated to OpenSSL 3.0.

Hiera 3 gem removed

All deprecated Hiera 3 functionality is implemented in Hiera 5, which is included in Puppet 8. If your PE infrastructure relies on a custom Hiera 3 backend, you must manually install the Hiera 3 gem on all Puppet Server hosts or convert your backend to Hiera 5. For further information, see Upgrading to Hiera 5.

PSON removed

In previous releases, Pure JavaScript Open Notation (PSON) was used in Puppet to serialize data for transmission. PSON was deprecated in Puppet 7 and is removed in Puppet 8.

Be aware that errors may occur due to PSON removal. For example, prior to upgrading to PE 2023.8, Puppet 7 agents may log the following message:

Info: Unable to serialize catalog to json, retrying with pson. PSON is deprecated and will be removed in a future release

After upgrading to PE 2023.8, the message may change to a compilation error:

Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Failed to serialize Puppet::Resource::Catalog for 'failing-agent.example': Could not render to Puppet::Network::Format[rich_data_json]: source sequence is illegal/malformed utf-8

What to do if you get a compilation error:

Find all resources where the UTF-8 replacement character, \ufffd, was substituted for binary data, by running the following SQL query on the PE primary node, or PE XL database node.

This query does not find resources used by nodes that have not successfully compiled a catalog prior to an upgrade.
cat <<'EOF' | runuser -u pe-postgres -- /opt/puppetlabs/server/bin/psql -d pe-puppetdb -x -f- | tee /tmp/binary-resources.txt
SELECT DISTINCT type, file, line, name AS parameter
FROM resource_params AS p
JOIN catalog_resources AS r ON p.resource = r.resource
WHERE p.value ~ '\ufffd'
EOF

In order to clear the errors, update the manifest files returned by the query (a report is saved to /tmp/binary-resources.txt) and either remove binary data, or wrap it using the binary data type or binary_file() functions as documented in the following sections: