How do I make puppet copy a file only if source exists?

12,117

Solution 1

You could abuse file in this way :

$a = file('/etc/puppet/modules/local/files/bash_profile.local','/dev/null')
if($a != '') {
    file { '.bash_profile.local':
        content => $a,
        ...
    }
}

Solution 2

This is not exactly what you asked but you can supply multiple paths in the source, so you can have a default empty file if the user didn't supplied his own.

class local
{
    file { '.bash_profile.local':
        source => [
            'puppet:///modules/local/bash_profile.local',
            'puppet:///modules/local/bash_profile.local.default'
        ],
        path => '/home/vagrant/.bash_profile.local',
        replace => false,
        mode => 0644,
        owner => 'vagrant',
        group => 'vagrant',
    }
}

Solution 3

You can try something like this:

file { 'bash_profile.local':
    ensure => present,
    source => ['puppet:///modules/local/bash_profile.local', '/dev/null'],
    path   => '/home/vagrant/.bash_profile.local',
    before => Exec['clean-useless-file'],
}
exec { 'clean-useless-file':
    command => 'rm .bash_profile.local',
    onlyif  => 'test -s .bash_profile.local',
    cwd     => '/home/vagrant',
    path    => '/bin:/usr/bin',
}

If the admin don't make a copy of ".bash_profile.local" available in "modules/local/bash_profile.local", the file resource will use the second source and then create a blank file. Then, the "onlyif" test fails and the exec will remove the useless blank file.

Used this way this code can be a little cumbersome, but it's better than a provisioning failure. You may evaluate if retaining a blank .bash_profile.local file can be okay in your case. I normally use a variation of this, with wget instead of rm, to get a fresh copy of the file from the internet if it was not already made available as a source.

If you're using puppetmaster, be aware you can use it to provision the own server, presenting two versions of the catalog, according to the .bash_profile.local is present or not.

Share:
12,117
pdizz
Author by

pdizz

Updated on July 05, 2022

Comments

  • pdizz
    pdizz almost 2 years

    I am trying to provision a vagrant VM to allow users to supply their own bash_profile.local but I don't want this file tracked in the vm's vcs repo. I have a tracked bash_profile.local.dist file that they can rename. How can I tell puppet to only create a file if the source file exists? It is currently working correctly but logs an error during provisioning and this is what I'm trying to avoid.

    This is the manifest:

    class local
    {
        file { '.bash_profile.local':
            source => 'puppet:///modules/local/bash_profile.local',
            path => '/home/vagrant/.bash_profile.local',
            replace => false,
            mode => 0644,
            owner => 'vagrant',
            group => 'vagrant',
        }
    }