Idempotent user/group creation

Hi,

I’m trying to find an idempotent way to define a user and group with the following specifications:

group "mfcobol" do
end

user "mfcobol" do
    gid "mfcobol"
    home "/home/mfcobol"
    shell "/bin/bash"
end

But it leads to non-idempotent actions being taken every time the cookbook is executed:

  * group[mfcobol] action create
    - alter group mfcobol
    - replace group members with new list of members
  * user[mfcobol] action create
    - alter user mfcobol

If I specify the user/group in any resource before having created it, it will fail (because of the missing resource).

Anyone has any tips ?

Which Chef client are you using. The snippet you provided is idempotent
on at least 12.2

Are you sure that some recipe that runs after your snippet is not
changing the group or the user. That would make sense in this case.

I have had a lot of issues with Chef not being fully idempotent with the
group provider. See https://github.com/chef/chef/issues/3149 for a
description of what does and does not work as expected.

I often have to resort to Guards when I want to get idempotent behavior
with groups and memberships

require “etc”

group “mfcobol” do
members [ “mfcobol” ]
append true
action :manage
not_if { Etc.getgrnam(“mfcobol”).mem.include?(“mfcobol”) }
end

I’m using Chef 12.4.1 on AIX. No other parts of the recipes touch that group or user, but files/folders are created with their ownership.

My issue is exactly what is describe on https://github.com/chef/chef/issues/3149:

  • The group is emptied out at the group resource definition because the user might not exist yet so I can create it while assigning the user in the first run
  • The user is created and the group is modified to take the new user into account.

What you are most likely seeing here is the AIX group or user provider
not acting “correctly” The example you provided works find under RedHat
and Debian Linux. The reason that it does is because the group "mfcobol"
does not get populated with any users after the run. The passwd and
group entries look like this

/etc/passwd:mfcobol:x:1000:1000::/home/mfcobol:/bin/bash

/etc/group:mfcobol:x:1000:

The logic in the linux specific provider sees that the user and group
specified match what exists on the system and do not make changes on the
next run.

It does this through some logic using the Ruby “etc” module (group_info
= Etc.getgrnam(@new_resource.group_name))

The 1st thing you can try is the following to see if the issue is in the
etc module or deeper in the AIX specific code. If this makes your recipe
idempotent then it seems like there is an issue with the AIX provider

require ‘etc’

group “mfcobol” do

action :create

not_if { Etc.getgrnam(“mfcobol”) rescue nil }

end

user “mfcobol” do

gid “mfcobol”

home “/home/mfcobol”

shell “/bin/bash”

not_if { Etc.getpwnam(“mfcobol”) rescue nil }

end