Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.
  • Labs icon Lab
  • A Cloud Guru
Google Cloud Platform icon
Labs

Writing Custom Puppet Facts

There are multiple ways we can provide our own facts to our Puppet infrastructure, including plain-text eternal facts files, executable scripts, and via writing Ruby fact plugins. Custom facts are plugins that leverage Ruby to either provide static fact data or evaluate and command as well as provide the output for the value of the fact. These custom facts can be written so they are as simple as providing us a key-value pair or as complicated as some of the structured data sets we see when we query for our `os`-based facts. In this lab, we'll create a custom aggregate fact that provides us with data about our host's web server (should it exist), learn how to create structured facts, and use various coding techniques to ensure our facts work on all systems.

Google Cloud Platform icon
Labs

Path Info

Level
Clock icon Intermediate
Duration
Clock icon 30m
Published
Clock icon Jul 26, 2019

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Set the Web Server Fact

    1. Move into the nginx module directory:

      cd /etc/puppetlabs/code/environments/production/modules/nginx/
      
    2. Create the plugin library location for Facter:

      sudo mkdir -p lib/facter
      
    3. Create and open a file called web.rb in the plugin location:

      sudo vim lib/facter/web.rb
      
    4. At its most basic, if we wanted to write a single, non-structured fact that output our web server information, we could write something like:

      Facter.add(:web) do
        setcode do
          'Nginx'
        end
      end
      

      Notice how this includes the Facter.add line to set our fact name, and the setcode statement, which provides us our output. Since we just want to supply the text Nginx, that is all we put in our statement block.

    5. However, since we need this to become a structured, aggregate fact, we're going to refactor this so we can add more facts to our code. Let's first define the overall web fact as an aggregate, which means the resolution of our web fact can be read in separate chunks:

      Facter.add(:web, :type => :aggregate) do
      
    6. Next, we want to replace our setcode statement with chunk, which lets us define the different parts of our structured fact:

      Facter.add(:web, :type => :aggregate) do
        chunk(:server) do
      
    7. We now need to update the structure of our output, so it resembles the JSON output we expected when we query for facts. To this, let's create a variable, web, then add our Nginx value as a structured key-value pair:

      Facter.add(:web, :type => :aggregate) do
        chunk(:server) do
          web = {:server => 'Nginx'}
          web
        end
      end
      

      Save and exit.

    8. Let's now test our fact:

      sudo puppet agent -t
      sudo facter -p web
      sudo facter -p web.server
      
  2. Challenge

    Set the Version Fact

    1. Back in the lib/facter/web.rb file, create a second chunk line, this one called version; include a line at the end calling the web variable:

        chunk(:version) do
          web
        end
      
    2. We're going to check our version by using a slightly edited version of the nginx -v command — which means we need nginx for this fact to work. Let's add an if statement checking for nginx:

        chunk(:version) do
          if Facter::Core::Execution.which('nginx') != nil
          end
          web
        end
      
    3. Finally, we want to execute the appropriate command and have the output sent to a structured line mapped to web. Because our command is on the long side, you may want to create a variable for its output:

        chunk(:version) do
          if Facter::Core::Execution.which('nginx') != nil
            version = Facter::Core::Execution.execute('nginx -v 2>&1 | grep -Po [0-9]+\.[0-9]+\.[0-9]+')
            web = {:version => version}
          end
          web
        end
      
    4. If desired, save and test your code thus far.

  3. Challenge

    Set the Fact for the Amount of Running Web Processes

    Mimic the same structures as the previous chunks to create the stanza that provides the amount of running processes:

      chunk(:processes) do
       processes = Facter::Core::Execution.execute('pgrep nginx | wc -l')
       web = {:processes => processes }
       web
      end
    

    The full file should look like:

    Facter.add(:web, :type => :aggregate) do
      chunk(:server) do
       web = {:server => 'Nginx'}
       web
      end
    
      chunk(:version) do
       if Facter::Core::Execution.which('nginx') != nil
         version = Facter::Core::Execution.execute('nginx -v 2>&1 | grep -Po [0-9]+\.[0-9]+\.[0-9]+')
         web = {:version => version}
       end
       web
      end
    
      chunk(:processes) do
       processes = Facter::Core::Execution.execute('pgrep nginx | wc -l')
       web = {:processes => processes }
       web
      end
    end
    
  4. Challenge

    Test the New Facts

    Test that each fact works, as well as the overall web fact. Note that the second server is provided so you can test on a node with Nginx, as well as one without it (remember, our Puppet master does not have Nginx installed):

    sudo puppet agent -t
    sudo facter -p web
    sudo facter -p web.server
    sudo facter -p web.version
    sudo facter -p web.processes
    

The Cloud Content team comprises subject matter experts hyper focused on services offered by the leading cloud vendors (AWS, GCP, and Azure), as well as cloud-related technologies such as Linux and DevOps. The team is thrilled to share their knowledge to help you build modern tech solutions from the ground up, secure and optimize your environments, and so much more!

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.

Start learning by doing today

View Plans