Create resource if it doesn't exist, but do not update it if it does already exist

66 views
Skip to first unread message

Kris Knigga

unread,
Nov 13, 2014, 12:00:59 PM11/13/14
to puppet...@googlegroups.com
I've been poring through documentation and haven't found anything yet, so I'll throw the question out here.

With puppet, is there a way to define a resource in such a way that when applied to a client for the first time it is created, but if the resource already exists on the client nothing is changed?  Specifically, I'd like to do this with users.

Here is my situation: in the past my organization has poorly managed user UIDs across machines (multiple users in puppet with the same UID, creating users in puppet that conflict with system users' UIDs, etc).  This resulted in numerous, frustrating UID conflicts.  I've been working on cleaning this up, but the mass renumbering of important existing users has all sorts of production-impacting risks.  What I'd like to do is tell puppet to create these users with their new, conflict-free UIDs on new machines but have it not touch users that are already created on existing machines.  This will allow us to use a slow, methodical approach to fixing the UIDs on old machines to help mitigate the risks.

Any thoughts are appreciated.

Kris

Doug Forster

unread,
Nov 13, 2014, 12:21:33 PM11/13/14
to puppet...@googlegroups.com
The best option I have found is creating a custom fact for local users.

# This custom fact pulls out all local users from the /etc/passwd file
# and returns the collection as a comma-separated list.

Facter.add(:local_users) do
  setcode do
    users = Array.new
    File.open("/etc/passwd").each do |line|
      next if line.match(/^\s|^#|^$/)
      users << line.split(':').first
    end
    users.join(',')
  end
end

Then you can find out if the user is on the box in your manifest with:
$user_exists = $name in split($::local_users, ',')

The other added benefit is you now have a custom fact for all servers that gets stored in puppetdb.


--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/puppet-users/b64d9e28-e58d-46de-b1ea-a5db0b2890fd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Doug Forster

unread,
Nov 13, 2014, 12:24:07 PM11/13/14
to puppet...@googlegroups.com
Sorry that fact tells you the users with set passwords. You get the idea though.

Kris Knigga

unread,
Nov 13, 2014, 1:13:39 PM11/13/14
to puppet...@googlegroups.com
That's actually another good point, Doug.  It would be awesome to have puppet create users with an initial password hash, but then ignore future changes to the hash (as when a user updates his own password).

I have a feeling that there are a number of situations where it would be nice to have puppet create resources with some initial set of settings, but then ignore when the on-machine configuration diverges from what's configured in puppet.

Perhaps this needs a new feature request?

Felix Frank

unread,
Nov 15, 2014, 6:12:36 PM11/15/14
to puppet...@googlegroups.com
Hi,

you can work around your issue with the following evil-ish construct:

define my_user($uid,...)
exec {
"newly-create-user-$name":
command => "useradd -u $uid $name",
unless => "getent passwd $name",
}
->
user { $name:
# do NOT manage uid here
...
}
}

It's not ideal, but then situations in which you cannot declare the full
final state for Puppet to sync to never are.

I imagine that a feature request towards implementing a means to change
properties to creation-time parameters will be quite controversial. I
would recommend taking the scenario to the puppet-dev list as well, or
perhaps instead of opening the request outright.

Cheers,
Felix
Reply all
Reply to author
Forward
0 new messages