Custom functions in Ruby overview

Get started with an overview of Ruby custom functions.

Syntax of Ruby functions

To write a new function in Ruby, use the Puppet::Functions.create_function method. You don’t need to require any Puppet libraries. Puppet handle libraries automatically when it loads the function.
Puppet::Functions.create_function(:<FUNCTION NAME>) do
  dispatch :<METHOD NAME> do
    param '<DATA TYPE>', :<ARGUMENT NAME (displayed in docs/errors)>
    ...
  end

  def <METHOD NAME>(<ARGUMENT NAME (for local use)>, ...)
    <IMPLEMENTATION>
  end
end
The create_function method requires:
  • A function name.
  • A block of code (which takes no arguments). This block contains:
    • One or more signatures to configure the function’s arguments.
    • An implementation method for each signature. The return value of the implementation method is the return value of the function.
For example:
# /etc/puppetlabs/code/environments/production/modules/mymodule/lib/puppet/functions/mymodule/upcase.rb
Puppet::Functions.create_function(:'mymodule::upcase') do
  dispatch :up do
    param 'String', :some_string
  end

  def up(some_string)
    some_string.upcase
  end
end

Location

Place a Ruby function in its own file, in the lib/puppet/functions directory of either a module or an environment. The filename must match the name of the function, and have the .rb extension. For namespaced functions, each segment prior to the final one must be a subdirectory of functions, and the final segment must be the filename.

Function name File location
upcase <MODULES DIR>/mymodule/lib/puppet/functions/upcase.rb
upcase /etc/puppetlabs/code/environments/production/lib/puppet/functions/upcase.rb
mymodule::upcase <MODULES DIR>/mymodule/lib/puppet/functions/mymodule/upcase.rb
environment::upcase /etc/puppetlabs/code/environments/production/lib/puppet/functions/environment/upcase.rb
Functions are autoloaded and made available to other modules unless those modules specify dependencies. After a function is written and available (in a module where the autoloader can find it), you can call that function in any Puppet manifest that lists the containing module as a dependency, and also from your main manifest. If a module has a list of dependencies in its metadata.json file, it loads custom functions only from those specific dependencies.

Names

Function names are similar to class names. They consist of one or more segments. Each segment must start with a lowercase letter, and can include:

  • Lowercase letters

  • Numbers

  • Underscores

If a name has multiple segments, separate them with a double-colon (::) namespace separator.

Match each segment with this regular expression:

\A[a-z][a-z0-9_]*\Z

Match the full name with this regular expression:

\A([a-z][a-z0-9_]*)(::[a-z][a-z0-9_]*)*\Z

Function names can be either global or namespaced:

  • Global names have only one segment (str2bool), and can be used in any module or environment. Global names are shorter, but they’re not guaranteed to be unique — if you use a function name that is already in use by another module, Puppet might load the wrong module when you call it.

  • Namespaced names have multiple segments (stdlib::str2bool), and are guaranteed to be unique. The first segment is dictated by the function’s location:

    • In an environment, use environment (environment::str2bool).

    • In a module, use the module’s name (stdlib::str2bool for a function stored in the stdlib module).

Most functions have two name segments, although it’s legal to use more.

Examples of legal function names:

  • num2bool (a function that could come from anywhere)

  • postgresql::acls_to_resource_hash (a function in the postgresql module)

  • environment::hash_from_api_call (a function in an environment)

Examples of illegal function names:

  • 6_pack (must start with a letter)

  • _hash_from_api_call (must start with a letter)

  • Find-Resource (can only contain lowercase letters, numbers, and underscores)

Passing names to create_function as symbols

When you call the Puppet::Functions.create_function method, pass the function’s name to it as a Ruby symbol.

To turn a function name into a symbol:

  • If the name is global, prefix it with a colon (:str2bool).

  • If it’s namespaced: put the name in quotation marks, and prefix the full quoted string with a colon (:'stdlib::str2bool').

Related topics: Puppet modules, Environments, Main manifest, Module metadata, Ruby symbols.