FacterDB

FacterDB and fact sets

The puppet-debugger internally leverages the facterdb gem to load pre-cached facts into the debugger session. This is partly why it starts up so fast. You can tell the debugger to use a different set of facts from a different kernel, OS version, facter version or any custom combination that facterdb supports. This is all controlled via the facterdb-filter.

At some point you may need to override the debugger’s default fact set with something of your own choosing. You can do this by setting one of the environment variables below.

  • DEBUGGER_FACTERDB_FILTER Sets the entire filter
  • DEBUGGER_FACTER_OS_VERSION Sets the OS version (only works with RHEL clones and Fedora)
  • DEBUGGER_FACTER_OS_NAME Sets the OS name (only works with RHEL clones and Fedora)
  • DEBUGGER_FACTER_VERSION Sets the facter version to use in the debugger session (uses facter 3.1 for puppet 4.4+ and facter 2.4 for 3.8-4.4)

By default the entire filter looks something like operatingsystem=Fedora and operatingsystemrelease=23 and architecture=x86_64 and facterversion=/^3\\.1/ depending on the puppet version currently running.

Below are some examples of loading up different fact sets for various operating systems and then running a lookup for each example fact set.

puppet debugger --facterdb-filter 'facterversion=/^3.6./ and operatingsystem=windows' --test -e '$os[family]'

puppet debugger --facterdb-filter 'facterversion=/^3.6./ and osfamily=RedHat' --test -e '$os[family]'

puppet debugger --facterdb-filter 'facterversion=/^3.6./ and osfamily=Darwin' --test -e '$os[family]'

You can force the debugger to use real facts from the current node too:

puppet debugger --no-facterdb --test -e '$os[family]'

You can display the current facterdb filter by running facterdb_filter from the debugger session.

Why do facter versions matter? While facter and puppet work independently just fine, newer forge modules utilize certain data structures found only in newer versions of facter. So its really up to the puppet code you use. With facter 3, almost every fact is now a data structure. So if you are having issues with facts not existing in the debugger you may need to change the facter version DEBUGGER_FACTER_VERSION to something different.

Custom FacterDB facts

As of FacterDB 0.4.0 we can now supply custom external fact sets to facterDB.. This is a huge deal because you can take the facts from any system and play around with the fact data in the debugger. This makes the debugger appear as it was run on that system. Moreover, you can create shareable fact sets for your entire team. To use an external fact set you first need to grab the facts from the system you wish to “mock”. This can be done with puppet facts or even puppetdb queries and then create a file with the values hash.

Take the values from the values hash only and place inside a new file.

{
  "name": "macbook-pro-10.domain",
  "values": {
    "custom_datacenter_fact": "iceland",
    "puppetversion": "5.3.2",
    "architecture": "x86_64",
    "kernel": "Darwin",
    "domain": "domain"
  }
}

This can be easily done if you have jq installed.

puppet facts | jq '.values' > /tmp/custom_facts/datacenter_a/2.4/os_x.facts

Once you have created a directory with one or more fact files you just need to set an environment variable to tell facterDB about the custom fact sets.

export FACTERDB_SEARCH_PATHS="/tmp/custom_facts/"

Now everytime you start the puppet debugger, facterDB will use these custom fact files as part of the facterDB database. However, you will still need to provide a search filter that references your custom fact because there are over a thousand facterDB fact sets.

puppet debugger --facterdb-filter 'custom_datacenter_fact=iceland'

Alternatively you can bypass the internal facterDB database by setting export FACTERDB_SKIP_DEFAULTDB=true and force your custom facts to be the only facts facterDB uses.

When exporting facterDB environment variables you will also change the behavior for rspec_puppet_facts and other gems that also rely on facterDB. So please remember to unset the variables if not needed*