13

I am creating a user as follow

user { $username:
    comment => "$name",
    shell   => "$shell",
    managehome => false,
    password  => "$password",
    groups => $groups
}

Now as u can see I am doing a managehome is false Now later down the lane I need to push a file to the user’s home directory.

$key = "${homedir}/${name}/file"

    file { $key:
    ensure => present,
    owner  => $username,
    group  => $username,
    mode   => 600,
    content => "$keyvalue",
    subscribe => User[$username],
}

How can I get the user’s home directory for this?

Quintin Par
  • 4,373
  • 11
  • 49
  • 72

4 Answers4

12

Hm, i think there you'll need a facter modul to do that and a little hacky manifest file...

facter module: This will register facter variables for all users. like "home_root" or "home_apache".

require 'etc'

Etc.passwd { |user|

   Facter.add("home_#{user.name}") do
      setcode do
         user.dir
      end
   end

}

and then you can use them inside your manifest file like this:

$username = "root"
$home = "home_$username"
$home_path = inline_template("<%= scope.lookupvar('::$home') %>")

file { "$home_path/test.txt":
   content => "huhu",
}

Perhaps there is a better way, but i'm afraid not.

jfried
  • 451
  • 3
  • 4
  • Can you give me some guidance on where to put this manifests? I have my basic class in init.pp and where do I go from there? – Quintin Par Aug 24 '12 at 13:59
  • 1
    @QuintinPar i've just started to upload some puppet examples or best practices to github. you'll find this example (facter class) here: https://github.com/drandor/puppet-examples/tree/master/modules/user you need to have pluginsync activated on your master and your agent. the second code can be used anywhere in your *.pp files. The puppet configuration and node manifests (with stages) can be found here: https://github.com/drandor/puppet-config – jfried Aug 24 '12 at 23:22
  • 1
    If the user does not yet exist on the machine (new user is added), home_user fact is not available. Creating new users might need two Puppet runs. On the first run, $home_path is empty, and this might lead to unwanted results. – Mikko Oct 10 '12 at 09:27
4

I tried to find a solution for the exactly same problem, and it turned out it's best to take a slightly different approach.

Define home directory explicitly, for example:

user { $username:
    comment    => "comment",
    home       => "/home/${username}",
    managehome => false,
    # ...
}

When managehome is false, the home directory is not even created. So you have to specifically define it. It's often best to make a custom definition for the whole user:

define custom_user($username, $password) {
    user { $username:
        home     => "/home/${username}",
        password => $password,
        # etc.
    }
    file { "/home/${username}":
        ensure  => directory,
        owner   => $username,
        require => User[$username],
        # etc.
    }
}

You can add more parameters, for example $keyvalue, and create a keyfile if that parameter is given.

You can also define a global variable $home = "/home" (OS specific, if needed) and get home dir with "${home}/${username}".

Edit: Using hash to define user-specific home directories

More recent Puppet versions (>= 2.6) support hashes. It would be possible to define a hash containing username => /path/to/home mappings for each user:

$home = {
    normal_user => '/home/normal_user',
    backup      => '/var/backup',
    mysql       => '/var/lib/mysql'
}

For any username, it is then easy to get home directory with $home['username'].

Home directory hash with fallback

Most of the time, it would be best to have a "fallback default" if user does not exist in the hash. In theory this is possible, although syntax becomes a little cryptic and bloated:

$home = { ... }
$default_home = '/home'

user {$username:
    home => has_key($home, $username) ? {
                true => $home[$username], 
                false => "${default_home}/${username}" 
            }
    # ...
}
Mikko
  • 955
  • 8
  • 14
  • 2
    This does ont work when /home is not the default. say /var/lib/psql – Quintin Par Aug 26 '12 at 05:00
  • @Barry: Did you read the rest of the answer, "user-specific home directories"? (The answer was edited after the comment by Quintin Par) – Mikko Oct 10 '12 at 09:19
  • @Mikko Yeap, and I tried to upvote the correct (accepted) answer. It was locked. –  Oct 14 '12 at 00:23
2

This question is old, but still relevant. There is in fact a better way now. Add a custom fact to [module]/lib/facter/home_dirs.rb containing the following:

require 'etc'

Facter.add(:home_dirs) do
  setcode do

    home_dirs = {}   
    Etc.passwd { |user|
      home_dirs[user.name] = user.dir
    }

    home_dirs

  end
end

Then you can access the data in the manifest thusly:

$facts['home_dirs']['some_username']

Bear in mind that this only works if the user already exists prior to the puppet run. If the user is getting created during the run, the home directory should be already known or at least predictable. Puppet is designed to create order, after all.

Hope this helps someone.

C. Taylor
  • 161
  • 2
0

When the accounts module is available and all accounts are created via hiera, then below block creates a file in each users home directory, assuming you don't care about system user accounts besides root.

require accounts::user::defaults

# filter out accounts with ensure=absent or managehome=false 
$managed_accounts = $accounts::user_list.filter |$name, $account| {
  (!has_key($account, 'managedhome') or $account['managedhome']) and (!has_key($account, 'ensure') or $account['ensure']!='absent')
}

# Add a file to each users
$managed_accounts.each |$name, $account| {
  $user_home_dir = has_key($account, 'home') ? {
    true    => $account['home'],
    default => $name ? {
      'root'  => $accounts::user::defaults::root_home,
      default => $accounts::user::defaults::home_template.sprintf($name),
    },
  }

  # Push a file to the user’s home directory.
  file { "${user_home_dir}/.helloworld":
    ensure  => file,
    owner   => $name,
    content => "Hi ${name}",
    require => User[$name],
  }
}

The $user_home_dir should be correct for all users that are

  1. managed with accounts,
  2. are ensured to be present
  3. for non-standard home directories.