Ask Your Question

How to configure multiple files with multiple sources in one file ressource?

asked 2016-11-08 02:22:34 -0500

Rainer gravatar image


I am a puppet beginner and I'm looking for way to declare a file ressource that manages several files that again may come from different sources. The idea is to have a small manifest file where different files may come from a very particular source directory like for a hostname or a more general source directory with files specific to all hosts with eg a particular operation system:

This is the idea:

file { [ '/etc/nsswitch.conf',
        '/etc/cups/client.conf', ]:
            owner   => root,
            group   => root,
            mode    => 644,
            source  => [
             'puppet:///modules/my-files/$::operatingsystem/$::lsbdistrelease',  # source directories

So puppet:///modules/my-files/$::operatingsystem/$::lsbdistrelease is thought to be a directory that might contain the file "client.conf" in its subdirectory "etc/cups/" (i.e. puppet:///modules/my-files/$::operatingsystem/$::lsbdistrelease/etc/cups/client.conf). This way many files could managed in just one file ressource with the flexibility that a file could be specific to just one host or eg for all hosts with one operation system.

The manifest from above does not work, it results in directories beeing created instead files that should have been copied.

Is there a way to acive what I would like to do?

Thanks a lot Rainer

edit retag flag offensive close merge delete


The only way that you would be able to really do that is with iteration, either in puppet4 using each(), or in puppet 3 with a defined resource. Which version of puppet are you using?

DarylW gravatar imageDarylW ( 2016-11-09 08:15:43 -0500 )edit

I am using puppet 3, whats a defined resource? Rainer

Rainer gravatar imageRainer ( 2016-11-09 08:44:20 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2016-11-08 10:19:13 -0500

Kevin T gravatar image

I have a module that does the same as what your asking but in slightly different way. This is still a work in progress!

First things to install in your nodules directory.. This module is rootdir but also needs two functions.

1/  puppet/modules/rootdir/


    exists.rb is : # James Fellows 8/8/12: cloned from git:// then 
    dirname.rb is from 

module Puppet::Parser::Functions
  newfunction(:dirname, :type => :rvalue, :doc => <<-EOS
    Returns the dirname of a path.
  ) do |arguments|

    if arguments.size < 1 then
      raise(Puppet::ParseError, "dirname(): No arguments given")
    if arguments.size > 1 then
      raise(Puppet::ParseError, "dirname(): Too many arguments given (#{arguments.size})")
    unless arguments[0].is_a?(String)
      raise(Puppet::ParseError, 'dirname(): Requires string as argument')

    return File.dirname(arguments[0])

2/ manifest/init.pp is:

  define dd($type, $user, $group, $mode) {
  notify { "Item ${name}:${type} has value ${user}, group ${group} and mode ${mode}": }

     # List all the options for the name delivery for the given name
     # e.g.
     #  a.
     #  b. name:RedHat-7
     #  c. name:RedHat-7.2
     #  d. name:RedHat
     #  e. name
     # These are the TAGS..
     $a = "puppet:///modules/rootdir/${name}:${::fqdn}"
     $b = "puppet:///modules/rootdir/${name}:${::operatingsystem}-${::operatingsystemmajrelease}"
     $c = "puppet:///modules/rootdir/${name}:${::operatingsystem}-${::operatingsystemrelease}"
     $d = "puppet:///modules/rootdir/${name}:${::operatingsystem}"
     $e = "puppet:///modules/rootdir/${name}"

    # Work out what name file we will deliver given the order of things
    # were checking from the root dir 
    if exists($a) { notify { "File is $a": } $pathsource="$a"}
    elsif exists($b) { notify { "File is $b": } $pathsource="$b"}
    elsif exists($c) { notify { "File is $c": } $pathsource="$c"}
    elsif exists($d) { notify { "File is $d": } $pathsource="$d"}
    elsif exists($e) { notify { "File is $e": } $pathsource="$e"}
    else { notify { "File is empty for $name":} $pathsource=""}

  # Check we need to deliver the name from pathsource.
  # i.e. has the path source been set to a given file for this client
  if ($pathsource)
    $dir = dirname($name)
    if ($type == 'FILE')
     # Check to see if the directory is present first. For new installs
     # of files we need to create the pathname first on the client
     #notify { "Directory name is ${dir}":}
     exec { "mkdir -p ${dir}":
    path   => '/usr/bin:/usr/sbin:/bin',
    unless => "test -d ${dir}",
     } ->
     file { $name:
            ensure  => present,
            path    => "$name",
        owner   => "$user",
        group   => "$group",
        mode    => "$mode",
            source  => "puppet:///modules/$pathsource",

  # Deal with Directories
  if ($type == 'DIR' )
     exec { "Deal with ${dir}":
        command=> "mkdir -p ${dir}",
    path   => '/usr/bin:/usr/sbin:/bin',
    unless => "test -d ${dir}",
     } ->
     file { $name:
            ensure  => directory,
            path    => "$name",
        owner   => "$user",
        group   => "$group",
        mode    => "$mode",

  # Deal with permissions only
  if ($type == 'MODE' )
     file { $name:
            path    => "$name",
        owner   => "$user",
        group   => "$group",
        mode    => "$mode",

# Define the rootdir values for delivery of all the files we are managing
# with this module.
class rootdir {

  # Load in the data to check for the osr
  $filehash = hiera('rootdir::osr')

  # Set up the defaults for a given file 
  $filehashDefaults = {
    type  => 'UNKNOWN',
    user  => 'root',
    group => 'root',
    mode  => '644 ...
edit flag offensive delete link more


Thank you very much Kevin T. I will give your solution a try to see if I can do what I want. Rainer

Rainer gravatar imageRainer ( 2016-11-09 06:09:10 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools


Asked: 2016-11-08 02:22:34 -0500

Seen: 42 times

Last updated: Nov 08 '16