Specifying dependency ordering inside of lambda functions

50 views
Skip to first unread message

Joshua Schaeffer

unread,
Feb 20, 2017, 7:27:39 PM2/20/17
to Puppet Users
Hello all,

I was reviewing some of my company's Puppet manifests that we use when deploying certain server types. In one of them we were calling a lot of user and group resources, which I found repetitive, so I just grouped all the users and groups into their own hashes, then I just ran an each function on both hashes. My issues comes in where I want to explicitly call my dependency. The users I'm creating are being set with GID's I'm also creating, so I want to make sure that the groups are created first. However, because I'm specifying my user and group resources inside an each lambda and using a variable as my namevar I can't call out the resource. Here is the code I have in the manifest:

# Add host automation groups.
$groups
.each |$group, $groupdetail| {
       
group { $group:
               
*       => $groupdetail,
       
}
}


# Add host automation users.
$users
.each |$user, $userdetail| {
        user
{ $user:
               
*       => $userdetail,
       
}
}

As you can see I can't put a "before => User['resource_name']" in the group resource, because each user resource is dynamic. What is the recommended approach in this situation? I just want to make sure that all the groups are created before the users are created.

Thanks,
Joshua Schaeffer

John Gelnaw

unread,
Feb 20, 2017, 11:29:34 PM2/20/17
to Puppet Users
I can think of three options:

1) Break the user / group definitions into their own classes, and "require" the group class in your user definition class.

2) In some cases, Puppet does an implicit require-- it's possible your code would work as-is, and the catalog would recognize the need to create groups first.  I don't know if this is expected behavior or not any longer, but perhaps one of the devs could comment.  Since they're defined in the same class, I would hope Puppet would be smart enough to recognize the need to define a group before defining a user that's a member of that group.

3) Don't worry about it-- let it fail.  I run puppet twice per hour, and if it can't define the user because the group is missing, it can still define the group on the first pass.  Then the next pass, the user will get created, because this time the group already exists.  Ugly, mildly irritating, but still effective.  Obviously, this isn't a good option if you're paying attention to the exit status of the puppet run, but if you're just running the puppet agent every so often, should be fine.

Robert

unread,
Feb 21, 2017, 4:21:07 AM2/21/17
to puppet...@googlegroups.com
Hi Joshua,

As you can see I can't put a "before => User['resource_name']" in the group resource, because each user resource is dynamic. What is the recommended approach in this situation? I just want to make sure that all the groups are created before the users are created.

I didn't tried it now but
 Group <| |> -> User <| |>
should work I believe.

Best
Rp

Chadwick Banning

unread,
Feb 21, 2017, 6:44:14 AM2/21/17
to Puppet Users
Autorequires: If Puppet is managing the user’s primary group (as provided in the gid attribute) or any group listed in the groups attribute then the user resource will autorequire that group. If Puppet is managing any role accounts corresponding to the user’s roles, the user resource will autorequire those role accounts.

jcbollinger

unread,
Feb 21, 2017, 8:50:16 AM2/21/17
to Puppet Users


On Tuesday, February 21, 2017 at 5:44:14 AM UTC-6, Chadwick Banning wrote:
Autorequires: If Puppet is managing the user’s primary group (as provided in the gid attribute) or any group listed in the groups attribute then the user resource will autorequire that group. If Puppet is managing any role accounts corresponding to the user’s roles, the user resource will autorequire those role accounts.


^^^^ this.

In other words, you don't need to explicitly specify relationships between User and Group resources to ensure that the groups to which a given user belongs are managed before the user himself.  I can perhaps see an argument for doing so anyway in a class coded as you describe for the original, but it is foolish to go out of your way and complicate your manifests to re-express relationships that are already there.  It's even worse to add altogether irrelevant relationships in order to facilitate doing so.  I'd simply add a comment to the manifest to document that you're relying on the autorequirements.


John

Joshua Schaeffer

unread,
Feb 21, 2017, 1:11:48 PM2/21/17
to Puppet Users
#3 is actually what we do now. we always get a bunch of errors on the first pass through, then the second pass through works fine. That of course was before I changed the manifest to just loop through the users. Whoever wrote the file statically called each user and group resource. My preliminary testing after changing the code and rearranging it has been good, so I think #2 applies to me now. I didn't see any errors related to groups not existing, but I'll need to retest on a clean box to make sure. If I still get errors then I'll look into possibly putting them into their own classes and requiring the class.

Thanks for your responses they are what I was looking for.

Joshua Schaeffer

Joshua Schaeffer

unread,
Feb 21, 2017, 1:13:11 PM2/21/17
to Puppet Users
Thanks, this is very helpful and my preliminary testing is showing that this is what is happening.
Reply all
Reply to author
Forward
0 new messages