Search code examples
linuxpuppetinfrastructure-as-code

Purging Puppet files where I don't manage the content


Trying to manage files created by an Exec in Puppet. I would like to make sure that we don't have any un-managed files.

Example code:

file { '/tmp/puppet_example':
  ensure => directory,
  purge  => true,
}
$files = [
  '/tmp/puppet_example/file1.json',
  # '/tmp/puppet_example/file2.json',
  '/tmp/puppet_example/file3.json',
]
$files.each |$file| {
  exec { "exec_${file}":
    creates => $file,
    command => "/usr/bin/touch ${file}",
    require => File['/tmp/puppet_example'],
  }
  file { $file:
    ensure  => file,
    replace => false,
    require => File['/tmp/puppet_example'],
  }
}

If an entry in $files get removed, the respective files are not purged.

What is the correct way of managing files where I don't manage the content? Or is this a feature of the replace attribute:

Setting this to false allows file resources to initialize files without overwriting future changes


Solution

  • If an entry in $files get removed, the respective files are not purged.

    I guess you're referring to the fact that you are managing the directory of these files with purge => true. Per the docs, however, purge is only relevant when you are managing a directory with recurse => true, which you are not doing.

    Consider the docs of recurse => true:

    If the source attribute is set, this behaves similarly to recurse => remote, automatically managing files from the source directory.

    This also enables the purge attribute, which can delete unmanaged files from a directory. See the description of purge for more details.

    The source attribute is not mandatory when using recurse => true, so you can enable purging in directories where all files are managed individually.

    (emphasis added).

    As far as I understand what you're looking for, you should be able to achieve it by adding (just) recurse => true to the File resource managing the directory:

    file { '/tmp/puppet_example':
      ensure  => directory,
      recurse => true,
      purge   => true,
    }
    

    What is the correct way of managing files where I don't manage the content? Or is this a feature of the replace attribute

    I take the point to be to put the files under nominal management to protect them from purging, but not otherwise to do anything with them. With respect to that:

    • Just declaring a File resource for a file puts it under management, regardless of which of the target file's properties are managed. This makes it ineligible for purging.

    • The replace attribute is not related to whether unmanaged files are purged. Indeed, it can't be: in order to apply such an attribute to a file, you need a File resource for it, which itself makes the file managed.

      replace controls whether the content of existing files is managed. It is relevant only if you also specify source or content, for otherwise, the content isn't managed anyway. If you do specify one of those, and also replace => false, then the contents are managed only in the event that Puppet creates the file on that run.

    • If you have both a file and that file's directory under management, then Puppet will automatically create a relationship between the two. You don't need to declare one explicitly (though doing so is harmless).

    Overall, the minimum you need to do is declare the files without any attributes:

      file { $file: }
    

    That defaults to ensure => file, so it will create an empty file if the file does not already exist at all. Otherwise, nothing about the file is managed. I like this particular form for your purposes, as I think it emphasizes that you're only nominally managing the designated file. Nevertheless, the form presented in the question is fine for your purposes too.