Puppet "file" resource emptied a directory

I'm in the somewhat embarrassing position of having unintentionally deleted multiple TB of important data via Puppet, and I'm just trying to understand why this might have happened.

Firstly, I'm pretty sure the reason it's gone (as in unrecoverable except via backups) is:

File { backup => false }

in my site.pp. The nodes were set up to hard mount something via NFS, so a mount point /mount, and a line in fstab like this:

nfsserver:/mount   /mount  nfs   <options> 0 0

I wanted to get rid of the mount, and replace it with a symlink to the same eventual location (though a different path).

My puppet manifest looked like this:

class symlinks::linkdirtest ( ) { 
        file { '/mount':
            ensure => "link",
            target => "/anotherdir/mount",
        }
        mount { "/mount":
            ensure => "absent",
        }
}

This yielded the following when doing a puppet run:

notice: /Stage[main]/Symlinks::Linkdirtest/File[/mount]: Not removing directory; use 'force' to override

So, I duly (or stupidly) added:

class symlinks::linkdirtest ( ) { 
        file { '/mount':
            ensure => "link",
            target => "/anotherdir/mount",
                    force => "true",
        }
....

And lo and behold, puppet proceeded to consign the contents of the all-important mount to oblivion, while the mount point itself remained.

Any idea why this might have happened?

Thanks


Solution 1:

It replaced that directory with a link: Documentation

Under 'force':

"Replace directories with files or links"

For future reference, you can try running in noop mode to see what changes will be made:

puppet agent --test --debug --noop --show-diff

Solution 2:

Next to testing puppet runs before you apply them you should also remember that the order in which you write your puppet code isn't always the order in which puppet runs. In this instance you should have defined the order. You have to umount first before the symlinking happens. You could have done that as follows:

class symlinks::linkdirtest ( ) { 
    file { '/mount':
        ensure => "link",
        target => "/anotherdir/mount",
    }
    mount { "/mount":
        ensure => "absent",
        before => File['/mount'],
    }
}