Skip to content

Commit

Permalink
Add a new force_empty_mountpoints configuration option
Browse files Browse the repository at this point in the history
vagrant-bindfs was not used to do anything to mount points before mount,
except ensuring they exist. Hence, if you tried to bind a folder to a
non-empty directory without explicitly allowing Fuse to do so (with the
`nonempty` Fuse option), mount will fail.

This add a new configuration option to the vagrant-bindfs plugin to
make sure mount points are empty. Unless you allow Fuse to not mind with
the `nonempty` Fuse option, mount point will first be destroyed (with
`rm -rf`) then recreated (with `mkdir -p`) before mount.

As this can be dangerous and covers only really specific use cases, it
is disabled by default.
  • Loading branch information
gael-ian committed Jan 30, 2018
1 parent 94943aa commit f4aee4d
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 0 deletions.
28 changes: 28 additions & 0 deletions README.md
Expand Up @@ -171,6 +171,34 @@ end
**This feature only works with exact version match and does not try to resolve dependencies.**
In particular, Fuse will always be installed from the latest version available in repositories (_via_ Homebrew Cask for OS X guests).

### `force_empty_mountpoints`

By default, `vagrant-bindfs` won't try to empty an existing mount point before mount. Hence, if you try to bind a folder to a non-empty directory without explicitly allowing Fuse to do so (with the `nonempty` Fuse option), mount will fail.

You can ask `vagrant-bindfs` to make sure the mount points are empty with the `config.bindfs.force_empty_mountpoints` option.
Mount poitns will then be destroyed (with `rm -rf`) prior to mount, unless you allow Fuse to not mind (with the `nonempty` Fuse option).


```ruby
Vagrant.configure("2") do |config|

config.bindfs.force_empty_mountpoint = true

# This exemple assume two directories exist in your VM:
# - `a/non/empty/mount/point/and/its/content`
# - `another/non/empty/mount/point/and/its/content`

# `a/non/empty/mount/point` will be destroyed before mount and
# all its content will be lost.
config.bindfs.bind_folder "/vagrant", "a/non/empty/mount/point"

# `a/non/empty/mount/point` will not be destroyed before mount
# but its content will not be accessible while in use by bindfs.
config.bindfs.bind_folder "/vagrant", "a/non/empty/mount/point", o: :nonempty

end
```

## Contributing

If you find this plugin useful, we could use a few enhancements!
Expand Down
1 change: 1 addition & 0 deletions Vagrantfile
Expand Up @@ -35,6 +35,7 @@ Vagrant.configure('2') do |config|

# For a more detailled output when you test, set this to true.
config.bindfs.debug = false
config.bindfs.force_empty_mountpoints = true

test_machines.each do |distro, options|
config.vm.define "vagrant-bindfs-test-#{distro}" do |machine|
Expand Down
16 changes: 16 additions & 0 deletions lib/vagrant-bindfs/vagrant/actions/mounter.rb
Expand Up @@ -56,12 +56,28 @@ def bind_folders!
)

machine.communicate.tap do |comm|

if empty_mountpoint?(folder)
comm.sudo("rm -rf #{folder.destination}")
detail I18n.t(
'vagrant-bindfs.actions.mounter.force_empty_mountpoints',
dest: folder.destination
)
end

comm.sudo("mkdir -p #{folder.destination}")
comm.sudo(command.to_s(bindfs_full_path), error_class: VagrantBindfs::Vagrant::Error, error_key: 'bindfs.mount_failed')
debug(command.to_s(bindfs_full_path))
end
end
end

def empty_mountpoint?(folder)
return false unless config.force_empty_mountpoints
return false if folder.options.key?('o') and !folder.options['o'].match(%r{nonempty}).nil?
true
end

end
end
end
Expand Down
7 changes: 7 additions & 0 deletions lib/vagrant-bindfs/vagrant/config.rb
Expand Up @@ -12,6 +12,7 @@ class Config < ::Vagrant.plugin('2', :config)
attr_accessor :binded_folders

attr_accessor :skip_validations
attr_reader :force_empty_mountpoints

def initialize
@debug = false
Expand All @@ -26,6 +27,7 @@ def initialize
'perms' => 'u=rwX:g=rD:o=rD')

@skip_validations = []
@force_empty_mountpoints = false
end

def debug=(value)
Expand All @@ -44,6 +46,10 @@ def default_options=(options = {})
@default_options = Bindfs::OptionSet.new(nil, options)
end

def force_empty_mountpoints=(value)
@force_empty_mountpoints = (value == true)
end

def binded_folder=(*_any_variant)
raise VagrantBindfs::Vagrant::ConfigError, :binded_folders
end
Expand All @@ -66,6 +72,7 @@ def merge(other)
result.binded_folders = binded_folders.merge(other.binded_folders)

result.skip_validations = (skip_validations + other.skip_validations).uniq
result.force_empty_mountpoints = (force_empty_mountpoints || other.force_empty_mountpoints)
end
end

Expand Down
1 change: 1 addition & 0 deletions locales/en.yml
Expand Up @@ -20,6 +20,7 @@ en:
mounter:
start: "Creating bind mounts after %{hook}..."
entry: "%{source} => %{dest}"
force_empty_mountpoints: "All content in '%{dest}' as been removed before mount"


validations:
Expand Down
17 changes: 17 additions & 0 deletions spec/vagrantfile_helper.rb
Expand Up @@ -8,4 +8,21 @@ def tests_setup(machine, options = {})
machine.bindfs.bind_folder '/etc',
'/etc-binded-after-provisioning',
options.merge(owner: 'root', after: :provision)


machine.vm.provision :shell do |p|
p.name = "create non emtpy mountpoints"
p.inline = <<-COMMANDS
mkdir -p /home/vagrant/mountpoint/non/empty
mkdir -p /home/vagrant/mountpoint-nonempty/non/empty
COMMANDS
end

machine.bindfs.bind_folder '/etc',
'/home/vagrant/mountpoint',
options.merge(owner: 'root', after: :provision)

machine.bindfs.bind_folder '/etc',
'/home/vagrant/mountpoint-nonempty',
options.merge(owner: 'root', o: 'nonempty', after: :provision)
end

0 comments on commit f4aee4d

Please sign in to comment.