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',
}
}
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.
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.
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).
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,
...
}
}
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',
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With