Modifying Virtual User Resources in Puppet

In an earlier post on using Puppet to manage user accounts, I showed how I was using virtual user resources to manage user accounts on Puppet-managed nodes. Today, I ran into a situation where I wanted one of these virtual user resources to have a different group membership on one class of nodes than on another class of nodes. In this post, I’ll show you how I managed to modify the group membership of a realized virtual user resource.

(Disclaimer: There are probably better, more elegant ways of solving this problem. The purpose of this post is to help stimulate discussion and encourage learning, not to say this is the only way to do something. Keep that in mind as you read.)

To refresh your memory, this is how the virtual user resources were being realized on individual nodes:

Note the use of capitalized “Account::Virtual”, which means we are referring to a specific, defined (virtually defined, at least) resource.

My first attempt was to try overriding, where I refer back to the realized user resource using a similar syntax, then specify a particular attribute (the groups attribute, in this case). I’d used this technique in the past with non-virtual resources (example here), but—unfortunately—it didn’t seem to work with virtual resources.

A web search took me to this Google Groups thread, where I found two critical pieces of information:

  1. Realizing apparently doesn’t allow overrides.
  2. You can use the collection function to modify realized resources.

Armed with that information, I added this code to the nodes.pp manifest to modify the group membership for a realized virtual resource on specific nodes:

That worked! On the nodes where this code was added, the account named “johndoe” was added to the group “othergroup” successfully.

Great, so this solution works, but really the bigger questions are these:

  • Are there better, more elegant ways of solving this particular problem?
  • What drawbacks are there to this solution?

Yes, I could modify the accounts::virtual class to include supplementary group memberships, and that’s probably a better long-term solution. However, that requires more testing, since you’re modifying code that affects user accounts across a number of systems. This solution, on the other hand, is pretty quick and relatively safe.

Thoughts? Ideas? I’d love to hear your feedback, so speak up in the comments below.

Tags: , ,

  1. Aaron’s avatar

    Ah! That’s brilliant. Too bad (I assume, at least) that can’t be done with parameterized classes.

  2. Gabriel’s avatar

    Well well, this is a good example on how to use collections with virtual resources.
    I have implemented my accounts module starting from your code, so far so good although I would like to review it in a future to make it a bit more flexible.
    Working fine so far, anyway.

  3. Paul’s avatar

    Hi Scott

    Thanks for the post, I’ve been battling passing variables for almost 2 days – I found you post on friday night and I’ve got it sorted already today.

    I’m trying to do overly complex stuff with SE Linux

    Thanks again.

  4. Adam’s avatar

    I build my initial user setup off your previous article and I ran into the same problem. It took me a while to figure out how to do this, but I ended up using default parameters in the virtual user definition. My code now looks something like this…

    define users::virtual( $uid, $realname, $password, $shell =’/bin/bash’, $gid = ‘users’) {

    user { title:

    gid => $gid,
    shell => $shell,


    file { “/home/${title}”:

    group => $gid,


    Then when I define my new virtual users, it’s all the same except I pass a ‘gid’ and ‘shell’ parameter. I hope that helps!


Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>