pdizz
pdizz

Reputation: 4240

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

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',
    }
}

Upvotes: 8

Views: 13009

Answers (3)

mfandrade
mfandrade

Reputation: 83

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.

Upvotes: 1

Filipe Giusti
Filipe Giusti

Reputation: 2953

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',
    }
}

Upvotes: 6

bartavelle
bartavelle

Reputation: 917

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,
        ...
    }
}

Upvotes: 12

Related Questions