Puppet Evaluation Error. Error while evaluating a Resource Statement - Unknown resource type

So you got the Error while evaluating a Resource Statement, Unknown resource type with Puppet and are searching for solutions?

You are lucky, because right now we are going to see what it means, why it happens and how to solve it.

TL;DR

The module that provides the referred Unknown resource type is not available where your Puppet code is compiled.

Find the module you need in the metadata.json file of the module where the code fails (refer to the provided file path).

Solve by adding the dependency module to your Puppetfile, or running the puppet module install command.

Decomposing the “Unknown resource type” Puppet error message [JUNIOR]

Your error message may look like (we are going later to see which parts can be different for you):

Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: Error while evaluating a Resource Statement, Unknown resource type: 'concat' (file: /etc/puppetlabs/code/environments/production/modules/openvpn/manifests/config.pp, line: 6, column: 5) on node lab.psick.io

Here’s how to decompose it:

Error: Could not retrieve catalog from remote server: Error 500 on SERVER:  

This is your Puppet agent reporting an Error, saying that it was not able to get the catalog of the resources to apply from the server and got a 500 error (yes, Puppet client and server communicate over https). Next is shown the actual server error message:

Server Error: Evaluation Error: Error while evaluating a Resource Statement Unknown resource type: 'concat' 

This is the specific message, where instead of ‘concat’ there can be any Puppet resource, and gives us the key information for solving it: Puppet is looking for a resource type, here ‘concat’, and it doesn’t find it.

(file: /etc/puppetlabs/code/environments/production/modules/openvpn/manifests/config.pp, line: 6, column: 5)

Another key information: where Puppet failed to compile our code. In a normal client-server infrastructure, the file path is on the Puppet server’s filesystem (path may be different, what matters is that this is the file to check). If there’s no server involved and you use the puppet apply command, then the path is on your local filesystem.

on node lab.psick.io

This is your client node where Puppet agent was run.

A few Puppet basic principles. [BEGINNER]

Puppet manages any kind of computer related item, it uses its own language, written in files like the /etc/puppetlabs/code/environments/production/modules/openvpn/manifests/config.pp of the above example, where we can declare what are the resources we want to manage on our system(s) (lab.psick.io).

Puppet is shipped with some core resource types like ‘package’, ‘service’, ‘file’, ‘user’, etc. We use them to manage, guess what, packages, services, files, and users on Operating Systems like Windows, Linux, MacOS. For example code as follows automates the installation of the nginx package and manages its service on any node where is used:

    package { 'nginx':
      ensure => present,
    }
    service { 'nginx':
      ensure => running,
      enable => true,
    }

Puppet is used typically to automate the management of configurations on multiple servers or desktop systems, but can be used to manage virtually anything which is IT related: network devices, cloud resources, etc.

This is possible thanks to Puppet’s extensible and modular structure.

Additional resource types can therefore be found in Puppet modules which are shared on sites like GitHub and on a public repository called the Forge.

Whatever its name, in Puppet language, we always declare a resource type with the following syntax:

    resource_type { 'title':
      parameters,
    }

Our problem here is that in line 6 column 5 in the /etc/puppetlabs/code/environments/production/modules/openvpn/manifests/config.pp file on our server, we have a resource declaration like

    concat { '/etc/default/openvpn':
      owner => root,
      group => 0,
      mode  => '0644',
      warn  => true,
    }

that uses the resource ‘concat’ which is not available, because it’s not a native resource type shipped with Puppet itself, and we don’t have the module that provides it.

How to solve Unknown resource type errors [JUNIOR]

The quick answer is to install the module that contains the resource type you are trying to use, and the quick way to find it is to look at the dependencies of the module which is using the missing resource.

Puppet modules can require other modules, in this case the ‘openvpn’ module requires an additional module which provides the ‘concat’ resource.

The dependencies of every module are defined in the metadata.json file, at the root of the module directory, and indeed in our /etc/puppetlabs/code/environments/production/modules/openvpn/metadata.json we have the following:

{
  "name": "puppet-openvpn",
  "version": "10.2.1",
  "author": "Vox Pupuli",
  [...]
  "dependencies": [
    {
      "name": "puppetlabs/concat",
      "version_requirement": ">= 4.1.0 < 8.0.0"
    },
    {
      "name": "puppetlabs/stdlib",
      "version_requirement": ">= 4.25.0 < 9.0.0"
    }
  ]
}

The important information here is:

  • we are using the module puppet/openvpn (Here ‘puppet’ is the user name on the Forge of the Vox Pupuli community of modules authors)
  • This module depends on 2 additional modules: puppetlabs/concat and puppetlabs/stdlib, they are both from the ‘puppetlabs’ Forge user, which is the Puppet company itself)

So, in order to use the puppet/openvpn module we also need the puppetlabs/concat and puppetlabs/stdlib modules.

Some info about where Puppet code lives [JUNIOR]

In our example the missing resource is on the file /etc/puppetlabs/code/environments/production/modules/openvpn/manifests/config.pp, this whole path has a meaning and you need to know it if you work with Puppet:

  • /etc/puppetlabs/code/environments/ is the default value for the $environmentpath configuration entry. Where the different Puppet environments are stored.
  • production is the name of a Puppet environment, the default value
  • modules is the default directory where an environment stores its modules
  • openvpn is the name of the module that contains the config.pp file
  • manifests is the directory in every module, where we place our Puppet code in manifests: files with .pp extension written in Puppet Domain Specific Language (DSL).
  • config.pp is the manifest with Puppet code where we declare the resource which failed.

So the metadata.json with info about the dependency modules is to searched at the root of our openvpn module: /etc/puppetlabs/code/environments/production/modules/openvpn.

The modules listed under “dependencies” in the metadata.json file are what we need and we need them in the right place, more precisely in the Puppet’s $modulepath : a configuration entry which displays a colon-separated list of directories where Puppet searches for modules.

Oh, incidentally, you can show all Puppet’s configuration entries with the command:

    puppet config print all

and the specific one that matters here, the modulepath, where Puppet looks for modules:

    $ sudo puppet config print modulepath
    /etc/puppetlabs/code/environments/production/modules:/etc/puppetlabs/code/modules:/opt/puppetlabs/puppet/modules

So all we need to do is to install the missing modules.

Installing modules [JUNIOR]

We can install additional modules in various ways which depends on how is managed Puppet code on our systems.

Using the Puppetfile

If we are using a Puppet server, it’s likely and advisable that in your company you are managing the full content of the /etc/puppetlabs/code/environments/ dir with r10k (if using Puppet Open Source) or Code Manager (in Puppet Enterprise), so you should never manually touch any file there: a deployment procedure, eventually driven by a CI/CD tool, will do it for you.

In this case any new external module should be listed in your control-repo’s Puppetfile.

The control repo is a single git repository which contains all the Puppet code and data we need to manage the whole infrastructure. Every node uses a Puppet environment (default is called production), which has the contents of the control repo.

When it is deployed by tools like r10k or CodeManager, commonly used in Puppet world, for each branch of the control repo a Puppet environment is created in the $environmentpath.

When an environment is deployed two things happen:

  • The content of the control-repo relevant branch (for example production) is copied/synced to its /etc/puppetlabs/code/environments/production directory.
  • The modules listed in the control-repo’s Puppetfile are deployed under the modules subdir of the environment/branch: /etc/puppetlabs/code/environments/production/modules.

In the Puppetfile our missing modules can be added as follows:

mod 'puppetlabs/concat', '7.2.0'
mod 'puppetlabs/stdlib', '8.4.0'

The version names, and the actual syntax can be seen on the module’s page on the Forge.

Using the puppet module install command

If you are using Puppet in apply mode, without any Puppet server involved, or (blames on you!) you manage your manifests directly, on your servers’s /etc/puppetlabs/code/environments/ dir, you can install the needed modules by using the Puppet module command.

It automatically installs the latest version of the defined modules (using the format: forge_user/module_name or forge_user-module_name) and their eventual dependencies:

$ sudo puppet module install puppetlabs/concat
$ sudo puppet module install puppetlabs/stdlib

To list the installed modules use:

$ sudo puppet module list

Note than while the puppet module install command automatically installs every dependency, you have to specify them all in the Puppetfile.

Common cases of Unknown resource type errors and remedies [INTERMEDIATE]

So, I hope it’s clear that any kind of Puppet Unknown resource type error can be solved by adding the missing module which provides the resource we are trying to use.

The best approach is just to check the dependencies in the metadata.json file as just described, but, if you are copying random code from the Internet or working with legacy modules without the metadata.json file to check, you may find useful the reference here.

As a reference, we list here some common resource types and the relevant modules which provide them, with an extra bit of information which is worth knowing.

Resource Type Module
concat puppetlabs/concat
archive puppet/archive
line_line puppetlabs/stdlib
anchor puppetlabs/stdlib
vcsrepo puppetlabs/vcsrepo
ini_setting puppetlabs/inifile
ini_subsetting puppetlabs/inifile
firewall puppetlabs/firewall
firewallchain puppetlabs/firewallchain

In Puppet 6.0 some built-in resource types have been moved to separated “core” modules. Normally you can ignore them as they are included in the puppet-agent package, still if you have a Unknown resource type error with any of the following resources, here are the relevant modules which provide them:

Resource Type Module
mount puppetlabs/mount_core
augeas puppetlabs/augeas_core
zfs puppetlabs/zfs_core
zpool puppetlabs/zfs_core
yumrepo puppetlabs/yumrepo_core
host puppetlabs/host_core
selboolean puppetlabs/selinux_core
selmodule puppetlabs/selinux_core
zone puppetlabs/zone_core
cron puppetlabs/cron_core
scheduled_task puppetlabs/scheduled_task
sshkeys puppetlabs/sshkeys_core
mailalias puppetlabs/mailalias_core
maillist puppetlabs/maillist_core
nagios_* puppetlabs/nagios_core

The puppetlabs/nagios_core module provides the following, previously built in, types: nagios_command, nagios_contact, nagios_contactgroup, nagios_host, nagios_hostdependency, nagios_hostescalation, nagios_hostextinfo, nagios_hostgroup, nagios_service, nagios_servicedependency, nagios_serviceescalation, nagios_serviceextinfo, nagios_servicegroup and nagios_timeperiod.

There is a set of modules which implement common types using the Augeas tool. They are the so called Augeas Providers:

Resource Type Module
pam herculesteam/augeasproviders_pam
shellvar herculesteam/augeasproviders_shellvar
ssh_config herculesteam/augeasproviders_ssh
sshd_config herculesteam/augeasproviders_ssh
sshd_config_subsystem herculesteam/augeasproviders_ssh
sshd_config_match herculesteam/augeasproviders_ssh
sysctl herculesteam/augeasproviders_sysctl
kernel_parameter herculesteam/augeasproviders_grub
grub_config herculesteam/augeasproviders_grub
grub_menuentry herculesteam/augeasproviders_grub
grub_user herculesteam/augeasproviders_grub
mounttab herculesteam/augeasproviders_mounttab
pg_hba herculesteam/augeasproviders_postgresql
syslog herculesteam/augeasproviders_syslog
syslog_filter herculesteam/augeasproviders_syslog
syslog herculesteam/augeasproviders_syslog
puppet_auth herculesteam/augeasproviders_puppet
nrpe_command herculesteam/augeasproviders_nagios
apache_directive herculesteam/augeasproviders_apache
apache_setenv herculesteam/augeasproviders_apache

If you use Puppet to manage Windows, you might need these resources and modules:

Resource Type Module
registry_key puppetlabs/registry
registry_value puppetlabs/registry
reboot puppetlabs/reboot
dsc puppetlabs/dsc_lite
acl puppetlabs/acl
chocolateysource puppetlabs/chocolatey
chocolateyfeature puppetlabs/chocolatey

As a general reference, if the missing resource type has a double colon in its name, (like: apache::vhost), then the name of the module HAS to be the first part before the double quotes (apache). Next problem would be to find the right apache module from the Forge, and that can take some time if it’s not referenced in the metadata.json file.

If you bumped into code which is using example42’s revolutionary Puppet modules, be aware of the following:

Resource Type Module
tp::install example42/tp
tp::conf example42/tp
tp::dir example42/tp
tp::repo example42/tp
tp::test example42/tp
tp::info example42/tp
psick::* example42/psick

(*) Any defined resource type (also called define) from the psick module, there are quite a few: psick::puppet::access, psick::puppet::module, psick::puppet::set_external_fact, psick::netinstall, psick::yum::repo, psick::yum::plugin, psick::rclocal::script, psick::profile::script, psick::sudo::directive, psick::network::route, psick::network::routing_table, psick::network::set_lo_ip, psick::network::interface, psick::network::rule, psick::network::validate_gw, psick::network::netplan, psick::network::netplan::interface, psick::bolt::project, psick::limits::limit, psick::limits::config, psick::nfs::export, psick::nfs::mount, psick::openssh::keypair, psick::openssh::keyscan, psick::openssh::keygen, psick::openssh::config, psick::systemd::unit_file, psick::java::install_tarball, psick::services::init_script, psick::services::systemd_script, psick::archive, psick::users::managed, psick::aws::cli::script, psick::git::config, psick::php::module, psick::php::pear::module, psick::php::pear::config, psick::sysctl::set, psick::chruby::gem, psick::tools::create_dir, psick::tools::gpgkey, psick::kmod::module.

Conclusions

Hope this has been useful, thanks for reading. Let me know if you like similar posts on Puppet errors, I might do more of them.

If you need quick support for any Puppet related error or problem, just contact me via the link in the top right: if the solution is quick (as it would be the one for an error like this), it’ll be without any cost or obligation.

If it’s Puppet related, I know I can help, and I’m glad to.

Alessandro Franceschi

Twitter: @alvagante GitHub: @alvagante