Checking if a file exists in Puppet

Welcome to my next blog post about Puppet. This one covers something I found on another blog, so it is nothing I “invented” or something like that.

During the last weeks, I spent much time writing Puppet manifests for several tasks, e.g. preventing logrotate from stumbling across wrong file permissions and stuff like that.

At some point I had to check if a file exists which surprisingly was harder than I thought – Puppet does not have a feature which does that _and_ doesn’t throw an error if the file does not exist.
I knew that this would lead me to writing another Facter script…

Writing the Facter script and Puppet manifest

At first create the file /etc/puppet/modules/customfacts/lib/facter/file_exists.rb:

require"puppet"
module Puppet::Parser::Functions
newfunction(:file_exists, :type => :rvalue) do |args|
if File.exists?(args[0])
return 1
else
return 0
end
end
end

Then create the Puppet manifest /etc/puppet/manifests/xenuser_org-010-check_if_file_exists.pp:

if file_exists ("/etc/somefile") == 1 {
file { "/etc/somefile":
ensure => present,
owner => backup,
group => backup,
mode => 0640,
}
}

Now simply run the Puppet manifest by using this command:

sudo puppet apply /etc/puppet/manifests/xenuser_org-010-check_if_file_exists.pp

Maybe also use -v in order to see what’s happening; afterwards create the file /etc/somefile and then run the manifest again:

sudo touch /etc/somefile
sudo puppet apply /etc/puppet/manifests/xenuser_org-010-check_if_file_exists.pp

Have a look at /etc/somefile (e.g. with “ls -lah –color”) and notice that it now belongs the the backup user and group.

Analyzing the Facter script and Puppet manifest

In the first step we created a custom ruby script and placed it on the right location where Facter can find it. Facter runs on every system there the Puppet agent is installed.

Inside the Puppet manifest we are now able to access the freshly created function “file_exists”.

Summary

I still don’t know why Puppet lacks some (in my eyes) essential features in comparison to Cfengine 2/3. But well, adding the missing functionality was not difficult and it can’t hurt to learn a little Ruby 🙂

As usual, you are able to download both the Facter script and the Puppet manifest here: file_exists.rb, xenuser_org-010-check_if_file_exists.pp.

 

 

Edit: Some hints why I did not use exec and other methods

After having published this post, I have been asked on Twitter and here on my blog why I did not use exec or other already existing methods to solve my problem.

Well, I probably should have mentioned that I still use Puppet 2.7 and had to solve a specific problem with Puppet.

In my case, I had specific files in a log directory which were, for an unknown reason, touched by something/someone else; the files where then left in an unknown state (e.g. wrong ownership).
I had to find a way to ensure that the ownerships and attributes are always correct, otherwise logrotate will fail. However, in my case the log files are not present on every system. That is why I had to write my manifest in a way that it gets only executed if a specific directory exists.
exec calls (and later in Puppet 3.x “unless”) could also help, yes. But I am not quite sure what is more ugly – using shell commands or a custom facter script 🙂

4 thoughts on “Checking if a file exists in Puppet

  1. In general, in puppet you describe the final state that you’d like to reach with your system, so if you want a resource of type file you can simply use that on your manifest.

    The only time I’ve used something similar is when I had to run an “exec” unless a specific file/directory already exists, but this can be done with the exec attributes.

    example: unzip an archive unless a directory already exists

    exec { “my_exec_task”:
    command => “tar zxf /home/user/tmp/test.tar.gz”,
    creates => “/home/user/tmp/new_directory”,
    path => “/usr/local/bin/:/bin/”,
    }

    http://docs.puppetlabs.com/references/latest/type.html#exec-attribute-creates

    Could this work for you ?

    Best regards and congrats for your nice blog.

  2. Hey,

    thank you very much for your comment and the feedback. I appreciate it! What I should probably mention in my blog post is that I still use Puppet 2.7.x, always try to avoid exec calls and had to solve a specific problem (I will edit my blog post later to make that more clear).

    In my case, I had specific files in a log directory which were, for an unknown reason, touched by something/someone else; the files where then left in an unknown state (e.g. wrong ownership).
    I had to find a way to ensure that the ownerships and attributes are always correct, otherwise logrotate will fail. However, in my case the log files are not present on every system. That is why I had to write my manifest in a way that it gets only executed if a specific directory exists.

    exec calls (and later in Puppet 3.x “unless”) could also help, yes. But I am not quite sure what is more ugly – using shell commands or a custom facter script 🙂

    Nevertheless, thanks again for your comment! Feel free to comment again if you would like to share your opinion.

    Best regards
    Valentin

    PS: I like your blog!

  3. Hi Matt,

    without knowing what your error message is, I assume that your Puppet installation doesn’t find the facter file. You should check if it’s within your lib path for “puppet apply” runs.

Comments are closed.