Puppet Strings style guide

To document your module with Puppet Strings, add descriptive tags and comments to your module code. Write consistent, clear code comments, and include at least basic information about each element of your module (such as classes or defined types).

Strings uses YARD-style tags and comments, along with the structure of the module code, to generate complete reference information for your module. Whenever you update your code, update your documentation comments at the same time.

This style guide applies to:
  • Puppet Strings version 2.0 or later

  • Puppet 4.0 or later

For information about the specific meaning of the terms 'must,' 'must not,' 'required,' 'should,' 'should not,' 'recommend,' 'may,' and 'optional,' see RFC 2119.

The module README

In your module README, include basic module information and extended usage examples for common use cases. The README tells users what your module does and how to use it. Strings generates reference documentation, so typically, there is no need to include a reference section in your README. However, Strings does not generate information for type aliases or facts; if your module includes these elements, include a short reference section in your README with information about these elements only.

Include the following sections in the README:

Module description
What the module does and why it is useful.
Setup
Prerequisites for module use and getting started information.
Usage
Instructions and examples for common use cases or advanced configuration options.
Reference
Only if the module contains facts or type aliases, include a short Reference section. Other reference information is handled by Strings, so don't repeat it in the README.
Limitations
Operating system compatibility and known issues.
Development
Guidelines for contributing to the module

Comment style guidelines

Strings documentation comments inside module code follow these rules and guidelines:
  • Place an element's documentation comment immediately before the code for that element. Do not put a blank line between the comment and its corresponding code.

  • Each comment tag (such as @example) may have more than one line of comments. Indent additional lines with two spaces.

  • Keep each comment line to no more than 140 characters, to improve readability.

  • Separate comment sections (such as @summary, @example, or the @param list) with a blank comment line (that is, a # with no additional content), to improve readability.

  • Untagged comments for a given element are output in an overview section that precedes all tagged information for that code element.

  • If an element, such as a class or parameter, is deprecated, indicate it in the description for that element with Deprecated in bold.

Classes and defined types

Document each class and defined type, along with its parameters, with comments before the code. List the class and defined type information in the following order:
  1. A @summary tag, a space, and then a summary describing the class or defined type.

  2. Other tags such as @see, @note, or @api private.

  3. Usage examples, each consisting of:

    1. An @example tag with a description of a usage example on the same line.

    2. A code example showing how the class or defined type is used. Place this example directly under the @example tag and description, indented two spaces.

  4. One @param tag for each parameter in the class or defined type. See the parameters section for formatting guidelines.

Parameters

Add parameter information as part of any class, defined type, or function that accepts parameters. Include the parameter information in the following order:
  1. The @param tag, a space, and then the name of the parameter.

  2. A description of what the parameter does. This may be either on the same line as the @param tag or on the next line, indented with two spaces.

  3. Additional information about valid values that is not clear from the data type. For example, if the data type is [String], but the value must specifically be a path, say so here.

  4. Other information about the parameter, such as warnings or special behavior. For example:

    # @param noselect_servers
    #   Specifies one or more peers to not sync with. Puppet appends 'noselect' to each matching item in the `servers` array.

Example class

# @summary configures the Apache PHP module
#
# @example Basic usage
#   class { 'apache::mod::php':
#     package_name => 'mod_php5',
#     source       => '/etc/php/custom_config.conf',
#     php_version  => '7',
#   }
#
# @see http://php.net/manual/en/security.apache.php
#
# @param package_name
#   Names the package that installs mod_php
# @param package_ensure
#   Defines ensure for the PHP module package
# @param path
#   Defines the path to the mod_php shared object (.so) file.
# @param extensions
#   Defines an array of extensions to associate with PHP.
# @param content
#   Adds arbitrary content to php.conf.
# @param template
#   Defines the path to the php.conf template Puppet uses to generate the configuration file.
# @param source
#   Defines the path to the default configuration. Values include a puppet:/// path.
# @param root_group
#   Names a group with root access
# @param php_version
#   Names the PHP version Apache will be using.
#
class apache::mod::php (
  $package_name     = undef,
  $package_ensure   = 'present',
  $path             = undef,
  Array $extensions = ['.php'],
  $content          = undef,
  $template         = 'apache/mod/php.conf.erb',
  $source           = undef,
  $root_group       = $::apache::params::root_group,
  $php_version      = $::apache::params::php_version,
)
 {
 …
 }

Example defined type

# @summary
#   Create and configure a MySQL database.
#
# @example Create a database
#   mysql::db { 'mydb':
#     user     => 'myuser',
#     password => 'mypass',
#     host     => 'localhost',
#     grant    => ['SELECT', 'UPDATE'],
#   }
#
# @param name
#   The name of the database to create. (dbname)
# @param user
#   The user for the database you're creating.
# @param password
#   The password for $user for the database you're creating.
# @param dbname
#   The name of the database to create.
# @param charset
#   The character set for the database.
# @param collate
#   The collation for the database.
# @param host
#   The host to use as part of user@host for grants.
# @param grant
#   The privileges to be granted for user@host on the database.
# @param sql
#   The path to the sqlfile you want to execute. This can be single file specified as string, or it can be an array of strings.
# @param enforce_sql
#   Specifies whether to execute the sqlfiles on every run. If set to false, sqlfiles  runs only once.
# @param ensure
#   Specifies whether to create the database. Valid values are 'present', 'absent'. Defaults to 'present'.
# @param import_timeout
#   Timeout, in seconds, for loading the sqlfiles. Defaults to 300.
# @param import_cat_cmd
#   Command to read the sqlfile for importing the database. Useful for compressed sqlfiles. For example, you can use 'zcat' for .gz files.

Functions

For custom Ruby functions, place documentation strings immediately before each dispatch call. For functions written in Puppet, place documentation strings immediately before the function name.

Include the following information for each function:
  1. An untagged docstring describing what the function does.

  2. One @param tag for each parameter in the function. See the parameters section for formatting guidelines.

  3. A @return tag with the data type and a description of the returned value.

  4. Optionally, a usage example, consisting of:

    1. An @example tag with a description of a usage example on the same line.

    2. A code example showing how the function is used. Place this example directly under the @example tag and description, indented two spaces.

Example Ruby function with one potential return type

# An example 4.x function.
Puppet::Functions.create_function(:example) do
  # @param first The first parameter.
  # @param second The second parameter.
  # @return [String] Returns a string.
  # @example Calling the function
  #   example('hi', 10)
  dispatch :example do
    param 'String', :first
    param 'Integer', :second
  end

  # ...
end

Example Ruby function with multiple potential return types

If the function has more than one potential return type, specify a @return tag for each. Begin each tag string with "if" to differentiate between cases.

# An example 4.x function.
Puppet::Functions.create_function(:example) do
  # @param first The first parameter.
  # @param second The second parameter.
  # @return [String] If second argument is less than 10, the name of one item.
  # @return [Array] If second argument is greater than 10, a list of item names.
  # @example Calling the function.
  #   example('hi', 10)
  dispatch :example do
    param 'String', :first
    param 'Integer', :second
  end

  # ...
end

Puppet function example

# @param name the name to say hello to.
# @return [String] Returns a string.
# @example Calling the function.
#    example(‘world’)
function example(String $name) {
    “hello, $name”
}

Resource types

Add descriptions to the type and its attributes by passing either a here document (or "heredoc") or a short string to the desc method.

Strings automatically detects much of the information for types, including the parameters and properties, collectively known as attributes. To document the resource type itself, pass a heredoc to the desc method immediately after the type definition. Using a heredoc allows you to use multiple lines and Strings comment tags for your type documentation. For details about heredocs in Puppet, see the topic about heredocs in the language reference.

For attributes, where a short description is usually enough, pass a string to desc in the attribute. As with the @param tag, keep descriptions to 140 or fewer characters. If you need a longer description for an attribute, pass a heredoc to desc in the attribute itself.

You do not need to add tags for other method calls. Every other method call present in a resource type is automatically included and documented by Strings, and each attribute is updated accordingly in the final documentation. This includes method calls such as defaultto, newvalue, and namevar. If your type dynamically generates attributes, document those attributes with the @!puppet.type.param and @!puppet.type.property tags before the type definition. You may not use any other tags before the resource type definition.

Document the resource type description in the following order:
  1. Directly under the type definition, indented two spaces, the desc method, with a heredoc including a descriptive delimiting keyword, such as DESC.

  2. A @summary tag with a summary describing the type.

  3. Optionally, usage examples, each consisting of:

    1. An @example tag with a description of a usage example on the same line.

    2. Code example showing how the type is used. Place this example directly under the @example tag and description, indented two spaces.

For types created with the resource API, follow the guidelines for standard resource types, but pass the heredoc or documentation string to a desc key in the data structure. You can include tags and multiple lines with the heredoc. Strings extracts the heredoc information along with other information from this data structure.

Example resource API type

The heredoc and documentation strings that Strings uses are called out in bold in this code example:

Puppet::ResourceApi.register_type(
  name: 'apt_key',
  docs: <<-EOS,
@summary Fancy new type.
@example Fancy new example.
 apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':
   source => 'http://apt.puppetlabs.com/pubkey.gpg'
 }

This type provides Puppet with the capabilities to
manage GPG keys needed by apt to perform package validation. Apt has its own GPG keyring that can be manipulated through the `apt-key` command.

**Autorequires**:
If Puppet is given the location of a key file which looks like an absolute path this type will autorequire that file.
EOS
  attributes:   {
    ensure:      {
      type: 'Enum[present, absent]',
       desc: 'Whether this apt key should be present or absent on the target system.'**
    },
    id:          {
      type:      'Variant[Pattern[/\A(0x)?[0-9a-fA-F]{8}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{16}\Z/], Pattern[/\A(0x)?[0-9a-fA-F]{40}\Z/]]',
      behaviour: :namevar,
       desc:      'The ID of the key you want to manage.',**
    },
    # ...
    created:     {
      type:      'String',
      behavior: :read_only,
      desc:      'Date the key was created, in ISO format.',**
    },
  },
  autorequires: {
    file:    '$source', # will evaluate to the value of the `source` attribute
    package: 'apt',
  },
)

Puppet tasks and plans

Strings documents Puppet tasks automatically, taking all information from the task metadata. Document task plans just as you would a class or defined type, with tags and descriptions in the plan file.

List the plan information in the following order:
  1. A @summary tag, a space, and then a summary describing the plan.

  2. Other tags such as @see, @note, or @api private.

  3. Usage examples, each consisting of:

    1. An @example tag with a description of a usage example on the same line.

    2. Code example showing how the plan is used. Place this example directly under the @example tag and description, indented two spaces.

  4. One @param tag for each parameter in the plan. See the parameters section for formatting guidelines. For example:
    # @summary A simple plan.
    #
    # @param param1
    #   First param.
    # @param param2
    #   Second param.
    # @param param3
    #   Third param.
    plan baz(String $param1, $param2, Integer $param3 = 1) {
      run_task('foo::bar', $param1, blerg => $param2)
    }