Puppet: managehome on user type only works when user doesn’t exist

puppet

I'm looking for clarification here. It seems the managehome attribute of the user defined type only works when the user doesn't exist. Have a look at this DSL

user { 'artifactory':
        ensure     => 'present',
        home       => '/home/artifactory',
        managehome => true,
}

file { '/home/artifactory/data':
        ensure  => link,
        target  => '/var/lib',
        require => User['artifactory'],
}

The first time I run this it works fine, however, if I delete the artifactory user's home directory, then run it again, puppet barfs.

Error: Could not set 'link' on ensure: No such file or directory

My first thought is really? Take a look at the documentation

Whether to manage the home directory when managing the user. This will
create the home directory when ensure => present

If I delete the user and try again it works. So is this by design or is it a bug? It seems delicate to me.

Best Answer

From a runtime perspective puppet checks the status of the user on the system and compares it against the manifest. If the user does not exist on the system then puppet runs the appropriate useradd command to create it. If the user is not supposed to exist, and does, then it runs the appropriate userdel command. If some attribute of the user, such as group membership, uid, name, etc, has changed then it issues the appropriate gpasswd or usermod command.

Unfortunately, the documentation on the user type isn't the clearest. The managehome parameter isn't so much making a statement about that directory as it is an option to the useradd, usermod, or userdel command. So if you set managehome => true and change the location of the home directory then it will be created, if you delete the user it will be deleted, and if you add the user it will be created. It does not, however, ensure that the directory exists at all times.

If this is required then I would recommend you create a file type and set an appropriate require. Something like this:

user { 'artifactory':
    ensure     => 'present',
    home       => '/home/artifactory',
    managehome => true,
}

file { 
  '/home/artifactory/data':
    ensure  => link,
    target  => '/var/lib',
    require => [ User['artifactory'], File['artifactoryhomedir'] ]; 
  '/home/artifactory':
    ensure => directory,
    alias => 'artifactoryhomedir',
    require => User['artifactory'];
}