Continuing my experimentation with Puppet I created my first class which takes parameters and sets those parameters using data in the master repository (for now).

Shortly after my initial post, I added a class called my_user to the profiles module to create and manage my user’s account on machines I manage. The first version looked like this:

class profiles::my_user {
    user {
        'my_login':
        ensure => present,
        comment => 'My Full Name',
        managehome => true,
        password => Sensitive('encrypted password'),
        purge_ssh_keys => true,
        shell => '/bin/bash'
    }
}

There are number of drawbacks to hard-coding the values like this - one of which is that my username, password and shell are not the same on all machines. Parameterizing these values make the class flexible for all of my use-cases (I specified default values for most):

class profiles::my_user (
    String $username = 'my_login',
    Sensitive $password = undef,
    String $shell = '/bin/zsh',
    Boolean $manage_shell = true
) {
    $shell_pkg = $shell ? {
        '/bin/bash' => 'bash',
        '/bin/zsh' => 'zsh'
    }

    if ( $manage_shell == true ) {
        package { $shell_pkg: }
    }

    user {
        $username:
        ensure => present,
        comment => 'My Full Name',
        managehome => true,
        password => $password,
        purge_ssh_keys => true,
        shell => $shell,
        require => Package[$shell_pkg]
    }
}

I choose to use the manage_ pattern, as opposed to detecting if the package is already required elsewhere, as this is recommended as the most common pattern used in the Puppet community. There are ways to detect if it is already specified and depend on it if not or ensure_packages from the stdlib module (however there are some interesting edgecases for ensure_packages).

Values for the parameters can be provided directly when using the module or via the hiera data system. In my previous post I did an initial configuration of hiera.yaml, and no modification of this configuration was needed.

In the process of moving these values into the data, I also replaced the pattern matching to attach classes in manifests/site.pp with this that uses the list in the classes key from the hiera data (this is now the sole content of site.pp):

hiera_include(classes)

In the data/common.yaml file goes the data that applies to all nodes (for now the password is here since I am only managing 2 VMs to test):

---
classes:
  - profiles::base

profiles::my_user::password: 'encrypted password'
lookup_options:
  profiles::my_user::password:
    convert_to: "Sensitive"

And in data/nodes/<node.fqdn.dom>.yaml node-specific data:

---
classes:
  - profiles::my_user
  - profiles::singularity

As, at present, I only have 2 VMs which are identical in terms of what puppet applies (they are running different operating systems) I simply created a symlink to the first’s node-specific data file for the second. There are techniques for using Puppet’s facts (such as facts.whereami and facts.group in the example) to select the data but I have not looked into this further yet.