Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

vagrant

puppet

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',
    }
}
like image 506
pdizz Avatar asked Dec 12 '13 18:12

pdizz


People also ask

How do I copy a file in puppet?

Make sure the path where you want to copy the file exists. Also, when you give the source, make sure you don't give the absolute path to the file. Puppet only needs the path to the location of the module which has the file. That is /modules/mymodule/ and then just give the file path as above.

What is ensure in puppet?

Explanation. There are services that should always be running and, if they are ever stopped, should be restarted. By setting the ensure service property to running (or true) puppet will check for the presence of the service on each run and restart it when it's absent.

How do you create a directory in puppet?

Adding a / to the end of a file name isn't enough to tell puppet to make a directory, so it creates a file instead, and silently drops the / off the end of the name. You can use a number of parameters from the file type to control the directories properties, such as the owner , group and mode (permissions).


3 Answers

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,
        ...
    }
}
like image 92
bartavelle Avatar answered Nov 08 '22 21:11

bartavelle


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',
    }
}
like image 40
Filipe Giusti Avatar answered Nov 08 '22 21:11

Filipe Giusti


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.

like image 21
mfandrade Avatar answered Nov 08 '22 22:11

mfandrade