vagrant-unbundled 2.2.9.0 → 2.2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +60 -0
  3. data/README.md +5 -5
  4. data/contrib/README.md +1 -0
  5. data/contrib/sudoers/linux-suse +2 -2
  6. data/contrib/zsh/_vagrant +736 -0
  7. data/contrib/zsh/generate_zsh_completion.rb +166 -0
  8. data/lib/vagrant/action.rb +3 -0
  9. data/lib/vagrant/action/builder.rb +52 -18
  10. data/lib/vagrant/action/builtin/box_add.rb +6 -5
  11. data/lib/vagrant/action/builtin/cloud_init_setup.rb +127 -0
  12. data/lib/vagrant/action/builtin/cloud_init_wait.rb +30 -0
  13. data/lib/vagrant/action/builtin/handle_box.rb +1 -1
  14. data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +13 -13
  15. data/lib/vagrant/action/builtin/has_provisioner.rb +36 -0
  16. data/lib/vagrant/action/builtin/mixin_provisioners.rb +1 -0
  17. data/lib/vagrant/action/builtin/mixin_synced_folders.rb +20 -21
  18. data/lib/vagrant/action/builtin/set_hostname.rb +5 -1
  19. data/lib/vagrant/action/builtin/synced_folders.rb +10 -0
  20. data/lib/vagrant/action/builtin/trigger.rb +3 -2
  21. data/lib/vagrant/action/hook.rb +59 -24
  22. data/lib/vagrant/action/warden.rb +25 -5
  23. data/lib/vagrant/box.rb +5 -4
  24. data/lib/vagrant/bundler.rb +6 -1
  25. data/lib/vagrant/errors.rb +37 -1
  26. data/lib/vagrant/machine.rb +47 -0
  27. data/lib/vagrant/machine_index.rb +27 -1
  28. data/lib/vagrant/plugin/v2/command.rb +5 -1
  29. data/lib/vagrant/plugin/v2/components.rb +6 -0
  30. data/lib/vagrant/plugin/v2/manager.rb +14 -0
  31. data/lib/vagrant/plugin/v2/plugin.rb +12 -0
  32. data/lib/vagrant/plugin/v2/synced_folder.rb +50 -0
  33. data/lib/vagrant/plugin/v2/trigger.rb +6 -5
  34. data/lib/vagrant/ui.rb +1 -1
  35. data/lib/vagrant/util/ansi_escape_code_remover.rb +1 -1
  36. data/lib/vagrant/util/caps.rb +48 -0
  37. data/lib/vagrant/util/credential_scrubber.rb +1 -1
  38. data/lib/vagrant/util/directory.rb +19 -0
  39. data/lib/vagrant/util/downloader.rb +3 -3
  40. data/lib/vagrant/util/guest_hosts.rb +68 -0
  41. data/lib/vagrant/util/install_cli_autocomplete.rb +118 -0
  42. data/lib/vagrant/util/ipv4_interfaces.rb +15 -0
  43. data/lib/vagrant/util/is_port_open.rb +8 -19
  44. data/lib/vagrant/util/network_ip.rb +11 -1
  45. data/lib/vagrant/util/powershell.rb +1 -1
  46. data/lib/vagrant/util/subprocess.rb +9 -1
  47. data/lib/vagrant/vagrantfile.rb +1 -1
  48. data/plugins/commands/autocomplete/command/install.rb +49 -0
  49. data/plugins/commands/autocomplete/command/root.rb +64 -0
  50. data/plugins/commands/autocomplete/plugin.rb +18 -0
  51. data/plugins/commands/destroy/command.rb +6 -2
  52. data/plugins/communicators/ssh/communicator.rb +7 -1
  53. data/plugins/communicators/winrm/helper.rb +1 -1
  54. data/plugins/communicators/winssh/communicator.rb +1 -1
  55. data/plugins/guests/alpine/cap/change_host_name.rb +10 -11
  56. data/plugins/guests/alt/cap/change_host_name.rb +40 -53
  57. data/plugins/guests/arch/cap/change_host_name.rb +5 -14
  58. data/plugins/guests/arch/cap/configure_networks.rb +27 -10
  59. data/plugins/guests/atomic/cap/change_host_name.rb +5 -14
  60. data/plugins/guests/darwin/cap/change_host_name.rb +10 -6
  61. data/plugins/guests/debian/cap/change_host_name.rb +11 -11
  62. data/plugins/guests/esxi/cap/public_key.rb +3 -1
  63. data/plugins/guests/freebsd/cap/change_host_name.rb +10 -6
  64. data/plugins/guests/gentoo/cap/change_host_name.rb +14 -22
  65. data/plugins/guests/haiku/cap/rsync.rb +19 -0
  66. data/plugins/guests/haiku/plugin.rb +15 -0
  67. data/plugins/guests/linux/cap/change_host_name.rb +46 -0
  68. data/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +4 -11
  69. data/plugins/guests/linux/cap/persist_mount_shared_folder.rb +62 -0
  70. data/plugins/guests/linux/plugin.rb +10 -0
  71. data/plugins/guests/omnios/cap/change_host_name.rb +10 -16
  72. data/plugins/guests/openbsd/cap/change_host_name.rb +10 -6
  73. data/plugins/guests/photon/cap/change_host_name.rb +9 -15
  74. data/plugins/guests/pld/cap/change_host_name.rb +11 -17
  75. data/plugins/guests/redhat/cap/change_host_name.rb +10 -5
  76. data/plugins/guests/slackware/cap/change_host_name.rb +11 -17
  77. data/plugins/guests/solaris11/plugin.rb +5 -0
  78. data/plugins/guests/suse/cap/change_host_name.rb +12 -11
  79. data/plugins/hosts/darwin/cap/fs_iso.rb +49 -0
  80. data/plugins/hosts/darwin/plugin.rb +10 -0
  81. data/plugins/hosts/linux/cap/fs_iso.rb +49 -0
  82. data/plugins/hosts/linux/cap/rdp.rb +1 -1
  83. data/plugins/hosts/linux/plugin.rb +10 -0
  84. data/plugins/hosts/windows/cap/fs_iso.rb +48 -0
  85. data/plugins/hosts/windows/cap/rdp.rb +1 -1
  86. data/plugins/hosts/windows/plugin.rb +15 -0
  87. data/plugins/kernel_v2/config/cloud_init.rb +126 -0
  88. data/plugins/kernel_v2/config/disk.rb +40 -18
  89. data/plugins/kernel_v2/config/vm.rb +122 -13
  90. data/plugins/kernel_v2/config/vm_provisioner.rb +13 -2
  91. data/plugins/kernel_v2/config/vm_trigger.rb +5 -1
  92. data/plugins/providers/docker/action.rb +8 -17
  93. data/plugins/providers/docker/action/forwarded_ports.rb +2 -0
  94. data/plugins/providers/docker/action/prepare_forwarded_port_collision_params.rb +61 -0
  95. data/plugins/providers/docker/cap/has_communicator.rb +11 -0
  96. data/plugins/providers/docker/communicator.rb +1 -1
  97. data/plugins/providers/docker/driver.rb +35 -0
  98. data/plugins/providers/docker/plugin.rb +5 -0
  99. data/plugins/providers/hyperv/action.rb +2 -0
  100. data/plugins/providers/hyperv/action/configure.rb +8 -0
  101. data/plugins/providers/hyperv/cap/cleanup_disks.rb +54 -0
  102. data/plugins/providers/hyperv/cap/configure_disks.rb +200 -0
  103. data/plugins/providers/hyperv/cap/validate_disk_ext.rb +34 -0
  104. data/plugins/providers/hyperv/config.rb +5 -0
  105. data/plugins/providers/hyperv/driver.rb +80 -0
  106. data/plugins/providers/hyperv/plugin.rb +25 -0
  107. data/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 +28 -0
  108. data/plugins/providers/hyperv/scripts/dismount_vhd.ps1 +13 -0
  109. data/plugins/providers/hyperv/scripts/get_vhd.ps1 +16 -0
  110. data/plugins/providers/hyperv/scripts/get_vm_status.ps1 +1 -1
  111. data/plugins/providers/hyperv/scripts/list_hdds.ps1 +17 -0
  112. data/plugins/providers/hyperv/scripts/new_vhd.ps1 +31 -0
  113. data/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 +25 -0
  114. data/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 +18 -0
  115. data/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 +24 -0
  116. data/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +8 -0
  117. data/plugins/providers/virtualbox/action.rb +12 -1
  118. data/plugins/providers/virtualbox/action/forward_ports.rb +2 -2
  119. data/plugins/providers/virtualbox/cap/cleanup_disks.rb +40 -9
  120. data/plugins/providers/virtualbox/cap/configure_disks.rb +230 -77
  121. data/plugins/providers/virtualbox/cap/mount_options.rb +35 -0
  122. data/plugins/providers/virtualbox/cap/validate_disk_ext.rb +10 -3
  123. data/plugins/providers/virtualbox/driver/meta.rb +3 -0
  124. data/plugins/providers/virtualbox/driver/version_5_0.rb +96 -21
  125. data/plugins/providers/virtualbox/model/storage_controller.rb +135 -0
  126. data/plugins/providers/virtualbox/model/storage_controller_array.rb +100 -0
  127. data/plugins/providers/virtualbox/plugin.rb +18 -1
  128. data/plugins/providers/virtualbox/synced_folder.rb +1 -0
  129. data/plugins/provisioners/container/client.rb +1 -1
  130. data/plugins/provisioners/shell/provisioner.rb +15 -9
  131. data/plugins/synced_folders/nfs/synced_folder.rb +3 -1
  132. data/plugins/synced_folders/smb/cap/default_fstab_modification.rb +11 -0
  133. data/plugins/synced_folders/smb/cap/mount_options.rb +36 -0
  134. data/plugins/synced_folders/smb/plugin.rb +10 -0
  135. data/plugins/synced_folders/smb/synced_folder.rb +1 -1
  136. data/plugins/synced_folders/unix_mount_helpers.rb +14 -0
  137. data/templates/guests/arch/{network_dhcp.erb → default_network/network_dhcp.erb} +0 -0
  138. data/templates/guests/arch/{network_static.erb → default_network/network_static.erb} +0 -0
  139. data/templates/guests/arch/{network_static6.erb → default_network/network_static6.erb} +0 -0
  140. data/templates/guests/arch/systemd_networkd/network_dhcp.erb +6 -0
  141. data/templates/guests/arch/systemd_networkd/network_static.erb +9 -0
  142. data/templates/guests/arch/systemd_networkd/network_static6.erb +9 -0
  143. data/templates/guests/linux/etc_fstab.erb +6 -0
  144. data/templates/locales/en.yml +121 -11
  145. data/templates/locales/providers_docker.yml +4 -0
  146. data/vagrant.gemspec +8 -7
  147. data/version.txt +1 -1
  148. metadata +1492 -1309
@@ -92,14 +92,34 @@ module Vagrant
92
92
  # A somewhat confusing function which simply initializes each
93
93
  # middleware properly to call the next middleware in the sequence.
94
94
  def finalize_action(action, env)
95
- klass, args, block = action
95
+ if action.is_a?(Builder::StackItem)
96
+ klass = action.middleware
97
+ args = action.arguments.parameters
98
+ keywords = action.arguments.keywords
99
+ block = action.arguments.block
100
+ else
101
+ klass = action
102
+ args = []
103
+ keywords = {}
104
+ end
96
105
 
97
- # Default the arguments to an empty array. Otherwise in Ruby 1.8
98
- # a `nil` args will actually pass `nil` into the class.
99
- args ||= []
106
+ args = nil if args.empty?
107
+ keywords = nil if keywords.empty?
100
108
 
101
109
  if klass.is_a?(Class)
102
- klass.new(self, env, *args, &block)
110
+ # NOTE: We need to detect if we are passing args and/or
111
+ # keywords and do it explicitly. Earlier versions
112
+ # are not as lax about splatting keywords when the
113
+ # target method is not expecting them.
114
+ if args && keywords
115
+ klass.new(self, env, *args, **keywords, &block)
116
+ elsif args
117
+ klass.new(self, env, *args, &block)
118
+ elsif keywords
119
+ klass.new(self, env, **keywords, &block)
120
+ else
121
+ klass.new(self, env, &block)
122
+ end
103
123
  elsif klass.respond_to?(:call)
104
124
  # Make it a lambda which calls the item then forwards
105
125
  # up the chain
@@ -57,12 +57,13 @@ module Vagrant
57
57
  # @param [Symbol] provider The provider that this box implements.
58
58
  # @param [Pathname] directory The directory where this box exists on
59
59
  # disk.
60
- def initialize(name, provider, version, directory, **opts)
60
+ # @param [String] metadata_url Metadata URL for box
61
+ def initialize(name, provider, version, directory, metadata_url: nil)
61
62
  @name = name
62
63
  @version = version
63
64
  @provider = provider
64
65
  @directory = directory
65
- @metadata_url = opts[:metadata_url]
66
+ @metadata_url = metadata_url
66
67
 
67
68
  metadata_file = directory.join("metadata.json")
68
69
  raise Errors::BoxMetadataFileNotFound, name: @name if !metadata_file.file?
@@ -120,7 +121,7 @@ module Vagrant
120
121
  #
121
122
  # @param [Hash] download_options Options to pass to the downloader.
122
123
  # @return [BoxMetadata]
123
- def load_metadata(**download_options)
124
+ def load_metadata(download_options={})
124
125
  tf = Tempfile.new("vagrant-load-metadata")
125
126
  tf.close
126
127
 
@@ -132,7 +133,7 @@ module Vagrant
132
133
  end
133
134
 
134
135
  opts = { headers: ["Accept: application/json"] }.merge(download_options)
135
- Util::Downloader.new(url, tf.path, **opts).download!
136
+ Util::Downloader.new(url, tf.path, opts).download!
136
137
  BoxMetadata.new(File.open(tf.path, "r"))
137
138
  rescue Errors::DownloaderError => e
138
139
  raise Errors::BoxMetadataDownloadError,
@@ -632,7 +632,12 @@ module Vagrant
632
632
  self_spec.runtime_dependencies.each { |d| gem d.name, *d.requirement.as_list }
633
633
  # discover all the gems we have available
634
634
  list = {}
635
- directories = [Gem::Specification.default_specifications_dir]
635
+ if Gem.respond_to?(:default_specifications_dir)
636
+ spec_dir = Gem.default_specifications_dir
637
+ else
638
+ spec_dir = Gem::Specification.default_specifications_dir
639
+ end
640
+ directories = [spec_dir]
636
641
  Gem::Specification.find_all{true}.each do |spec|
637
642
  list[spec.full_name] = spec
638
643
  end
@@ -100,7 +100,7 @@ module Vagrant
100
100
 
101
101
  def translate_error(opts)
102
102
  return nil if !opts[:_key]
103
- I18n.t("#{opts[:_namespace]}.#{opts[:_key]}", opts)
103
+ I18n.t("#{opts[:_namespace]}.#{opts[:_key]}", **opts)
104
104
  end
105
105
  end
106
106
 
@@ -304,6 +304,14 @@ module Vagrant
304
304
  error_key(:clone_machine_not_found)
305
305
  end
306
306
 
307
+ class CloudInitNotFound < VagrantError
308
+ error_key(:cloud_init_not_found)
309
+ end
310
+
311
+ class CloudInitCommandFailed < VagrantError
312
+ error_key(:cloud_init_command_failed)
313
+ end
314
+
307
315
  class CommandDeprecated < VagrantError
308
316
  error_key(:command_deprecated)
309
317
  end
@@ -340,6 +348,10 @@ module Vagrant
340
348
  error_key(:corrupt_machine_index)
341
349
  end
342
350
 
351
+ class CreateIsoHostCapNotFound < VagrantError
352
+ error_key(:create_iso_host_cap_not_found)
353
+ end
354
+
343
355
  class DarwinMountFailed < VagrantError
344
356
  error_key(:darwin_mount_failed)
345
357
  end
@@ -428,6 +440,10 @@ module Vagrant
428
440
  error_key(:host_explicit_not_detected)
429
441
  end
430
442
 
443
+ class ISOBuildFailed < VagrantError
444
+ error_key(:iso_build_failed)
445
+ end
446
+
431
447
  class LinuxMountFailed < VagrantError
432
448
  error_key(:linux_mount_failed)
433
449
  end
@@ -796,6 +812,10 @@ module Vagrant
796
812
  error_key(:ssh_key_type_not_supported)
797
813
  end
798
814
 
815
+ class SSHNoExitStatus < VagrantError
816
+ error_key(:ssh_no_exit_status)
817
+ end
818
+
799
819
  class SSHNoRoute < VagrantError
800
820
  error_key(:ssh_no_route)
801
821
  end
@@ -924,6 +944,22 @@ module Vagrant
924
944
  error_key(:virtualbox_disks_defined_exceed_limit)
925
945
  end
926
946
 
947
+ class VirtualBoxDisksControllerNotFound < VagrantError
948
+ error_key(:virtualbox_disks_controller_not_found)
949
+ end
950
+
951
+ class VirtualBoxDisksNoSupportedControllers < VagrantError
952
+ error_key(:virtualbox_disks_no_supported_controllers)
953
+ end
954
+
955
+ class VirtualBoxDisksPrimaryNotFound < VagrantError
956
+ error_key(:virtualbox_disks_primary_not_found)
957
+ end
958
+
959
+ class VirtualBoxDisksUnsupportedController < VagrantError
960
+ error_key(:virtualbox_disks_unsupported_controller)
961
+ end
962
+
927
963
  class VirtualBoxGuestPropertyNotFound < VagrantError
928
964
  error_key(:virtualbox_guest_property_not_found)
929
965
  end
@@ -1,4 +1,5 @@
1
1
  require_relative "util/ssh"
2
+ require_relative "action/builtin/mixin_synced_folders"
2
3
 
3
4
  require "digest/md5"
4
5
  require "thread"
@@ -10,6 +11,8 @@ module Vagrant
10
11
  # API for querying the state and making state changes to the machine, which
11
12
  # is backed by any sort of provider (VirtualBox, VMware, etc.).
12
13
  class Machine
14
+ extend Vagrant::Action::Builtin::MixinSyncedFolders
15
+
13
16
  # The box that is backing this machine.
14
17
  #
15
18
  # @return [Box]
@@ -556,6 +559,41 @@ module Vagrant
556
559
  result
557
560
  end
558
561
 
562
+ # Returns the state of this machine. The state is queried from the
563
+ # backing provider, so it can be any arbitrary symbol.
564
+ #
565
+ # @param [Symbol] state of machine
566
+ # @return [Entry] entry of recovered machine
567
+ def recover_machine(state)
568
+ entry = @env.machine_index.get(index_uuid)
569
+ if entry
570
+ @env.machine_index.release(entry)
571
+ return entry
572
+ end
573
+
574
+ entry = MachineIndex::Entry.new(id=index_uuid, {})
575
+ entry.local_data_path = @env.local_data_path
576
+ entry.name = @name.to_s
577
+ entry.provider = @provider_name.to_s
578
+ entry.state = state
579
+ entry.vagrantfile_path = @env.root_path
580
+ entry.vagrantfile_name = @env.vagrantfile_name
581
+
582
+ if @box
583
+ entry.extra_data["box"] = {
584
+ "name" => @box.name,
585
+ "provider" => @box.provider.to_s,
586
+ "version" => @box.version.to_s,
587
+ }
588
+ end
589
+
590
+ @state_mutex.synchronize do
591
+ entry = @env.machine_index.recover(entry)
592
+ @env.machine_index.release(entry)
593
+ end
594
+ return entry
595
+ end
596
+
559
597
  # Returns the user ID that created this machine. This is specific to
560
598
  # the host machine that this was created on.
561
599
  #
@@ -581,6 +619,15 @@ module Vagrant
581
619
  end
582
620
  end
583
621
 
622
+ # This returns the set of shared folders that should be done for
623
+ # this machine. It returns the folders in a hash keyed by the
624
+ # implementation class for the synced folders.
625
+ #
626
+ # @return [Hash<Symbol, Hash<String, Hash>>]
627
+ def synced_folders
628
+ self.class.synced_folders(self)
629
+ end
630
+
584
631
  protected
585
632
 
586
633
  # Returns the path to the file that stores the UID.
@@ -231,6 +231,32 @@ module Vagrant
231
231
  Entry.new(id, struct)
232
232
  end
233
233
 
234
+ # Reinsert a machine into the global index if it has
235
+ # a valid existing uuid but does not currently exist
236
+ # in the index.
237
+ #
238
+ # @param [Entry] entry
239
+ # @return [Entry]
240
+ def recover(entry)
241
+ @lock.synchronize do
242
+ with_index_lock do
243
+ # Reload the data
244
+ unlocked_reload
245
+ # Don't recover if entry already exists in the global
246
+ return entry if find_by_prefix(entry.id)
247
+
248
+ lock_file = lock_machine(entry.id)
249
+ if !lock_file
250
+ raise Errors::MachineLocked,
251
+ name: entry.name,
252
+ provider: entry.provider
253
+ end
254
+ @machine_locks[entry.id] = lock_file
255
+ end
256
+ end
257
+ return set(entry)
258
+ end
259
+
234
260
  protected
235
261
 
236
262
  # Finds a machine where the UUID is prefixed by the given string.
@@ -452,7 +478,7 @@ module Vagrant
452
478
  # Creates a {Vagrant::Environment} for this entry.
453
479
  #
454
480
  # @return [Vagrant::Environment]
455
- def vagrant_env(home_path, **opts)
481
+ def vagrant_env(home_path, opts={})
456
482
  Vagrant::Util::SilenceWarnings.silence! do
457
483
  Environment.new({
458
484
  cwd: @vagrantfile_path,
@@ -61,7 +61,7 @@ module Vagrant
61
61
 
62
62
  opts.parse!(argv)
63
63
  return argv
64
- rescue OptionParser::InvalidOption, OptionParser::MissingArgument
64
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument, OptionParser::AmbiguousOption
65
65
  raise Errors::CLIInvalidOptions, help: opts.help.chomp
66
66
  end
67
67
 
@@ -230,6 +230,10 @@ module Vagrant
230
230
  color_index = 0
231
231
 
232
232
  machines.each do |machine|
233
+ if machine.state && machine.state.id != :not_created && !@env.machine_index.include?(machine.index_uuid)
234
+ machine.recover_machine(machine.state.id)
235
+ end
236
+
233
237
  # Set the machine color
234
238
  machine.ui.opts[:color] = color_order[color_index % color_order.length]
235
239
  color_index += 1
@@ -64,6 +64,11 @@ module Vagrant
64
64
  # @return [Registry<Symbol, Array<Class, Integer>>]
65
65
  attr_reader :synced_folders
66
66
 
67
+ # This contains all the registered synced folder capabilities.
68
+ #
69
+ # @return [Hash<Symbol, Registry>]
70
+ attr_reader :synced_folder_capabilities
71
+
67
72
  def initialize
68
73
  # The action hooks hash defaults to []
69
74
  @action_hooks = Hash.new { |h, k| h[k] = [] }
@@ -78,6 +83,7 @@ module Vagrant
78
83
  @provider_capabilities = Hash.new { |h, k| h[k] = Registry.new }
79
84
  @pushes = Registry.new
80
85
  @synced_folders = Registry.new
86
+ @synced_folder_capabilities = Hash.new { |h, k| h[k] = Registry.new }
81
87
  end
82
88
  end
83
89
  end
@@ -257,7 +257,21 @@ module Vagrant
257
257
  end
258
258
  end
259
259
  end
260
+
261
+ # This returns all the registered synced folder capabilities.
262
+ #
263
+ # @return [Hash]
264
+ def synced_folder_capabilities
265
+ results = Hash.new { |h, k| h[k] = Registry.new }
260
266
 
267
+ @registered.each do |plugin|
268
+ plugin.components.synced_folder_capabilities.each do |synced_folder, caps|
269
+ results[synced_folder].merge!(caps)
270
+ end
271
+ end
272
+
273
+ results
274
+ end
261
275
  # This registers a plugin. This should _NEVER_ be called by the public
262
276
  # and should only be called from within Vagrant. Vagrant will
263
277
  # automatically register V2 plugins when a name is set on the
@@ -247,6 +247,18 @@ module Vagrant
247
247
  nil
248
248
  end
249
249
 
250
+ # Defines a capability for the given synced folder. The block should return
251
+ # a class/module that has a method with the capability name, ready
252
+ # to be executed. This means that if it is an instance method,
253
+ # the block should return an instance of the class.
254
+ #
255
+ # @param [String] synced_folder The name of the synced folder
256
+ # @param [String] cap The name of the capability
257
+ def self.synced_folder_capability(synced_folder, cap, &block)
258
+ components.synced_folder_capabilities[synced_folder.to_sym].register(cap.to_sym, &block)
259
+ nil
260
+ end
261
+
250
262
  # Returns the internal data associated with this plugin. This
251
263
  # should NOT be called by the general public.
252
264
  #
@@ -3,6 +3,49 @@ module Vagrant
3
3
  module V2
4
4
  # This is the base class for a synced folder implementation.
5
5
  class SyncedFolder
6
+ class Collection < Hash
7
+
8
+ # @return [Array<Symbol>] names of synced folder types
9
+ def types
10
+ keys
11
+ end
12
+
13
+ # Fetch the synced plugin folder of the given type
14
+ #
15
+ # @param [Symbol] t Synced folder type
16
+ # @return [Vagrant::Plugin::V2::SyncedFolder]
17
+ def type(t)
18
+ f = detect { |k, _| k.to_sym == t.to_sym }.last
19
+ raise KeyError, "Unknown synced folder type" if !f
20
+ f.values.first[:plugin]
21
+ end
22
+
23
+ # Converts to a regular Hash and removes
24
+ # plugin instances so the result is ready
25
+ # for serialization
26
+ #
27
+ # @return [Hash]
28
+ def to_h
29
+ c = lambda do |h|
30
+ h.keys.each do |k|
31
+ if h[k].is_a?(Hash)
32
+ h[k] = c.call(h[k].to_h.clone)
33
+ end
34
+ end
35
+ h
36
+ end
37
+ h = c.call(super)
38
+ h.values.each do |f|
39
+ f.values.each do |g|
40
+ g.delete(:plugin)
41
+ end
42
+ end
43
+ h
44
+ end
45
+ end
46
+
47
+ include CapabilityHost
48
+
6
49
  # This is called early when the synced folder is set to determine
7
50
  # if this implementation can be used for this machine. This should
8
51
  # return true or false.
@@ -54,6 +97,13 @@ module Vagrant
54
97
  # @param [Hash] opts
55
98
  def cleanup(machine, opts)
56
99
  end
100
+
101
+ def _initialize(machine, synced_folder_type)
102
+ plugins = Vagrant.plugin("2").manager.synced_folders
103
+ capabilities = Vagrant.plugin("2").manager.synced_folder_capabilities
104
+ initialize_capabilities!(synced_folder_type, plugins, capabilities, machine)
105
+ self
106
+ end
57
107
  end
58
108
  end
59
109
  end
@@ -37,7 +37,7 @@ module Vagrant
37
37
  # @param [Symbol] stage :before or :after
38
38
  # @param [String] guest The guest that invoked firing the triggers
39
39
  # @param [Symbol] type Type of trigger to fire (:action, :hook, :command)
40
- def fire(name, stage, guest, type)
40
+ def fire(name, stage, guest, type, all: false)
41
41
  if community_plugin_detected?
42
42
  @logger.warn("Community plugin `vagrant-triggers detected, so core triggers will not fire")
43
43
  return
@@ -50,7 +50,7 @@ module Vagrant
50
50
  name = name.to_sym
51
51
 
52
52
  # get all triggers matching action
53
- triggers = find(name, stage, guest, type)
53
+ triggers = find(name, stage, guest, type, all: all)
54
54
 
55
55
  if !triggers.empty?
56
56
  @logger.info("Firing trigger for #{type} #{name} on guest #{guest}")
@@ -66,19 +66,19 @@ module Vagrant
66
66
  # @param [String] guest The guest that invoked firing the triggers
67
67
  # @param [Symbol] type Type of trigger to fire
68
68
  # @return [Array]
69
- def find(name, stage, guest, type)
69
+ def find(name, stage, guest, type, all: false)
70
70
  triggers = nil
71
71
  name = nameify(name)
72
72
 
73
73
  if stage == :before
74
74
  triggers = config.before_triggers.select do |t|
75
- (t.command == :all && !t.ignore.include?(name)) ||
75
+ (all && t.command.respond_to?(:to_sym) && t.command.to_sym == :all && !t.ignore.include?(name.to_sym)) ||
76
76
  (type == :hook && matched_hook?(t.command, name)) ||
77
77
  nameify(t.command) == name
78
78
  end
79
79
  elsif stage == :after
80
80
  triggers = config.after_triggers.select do |t|
81
- (t.command == :all && !t.ignore.include?(name)) ||
81
+ (all && t.command.respond_to?(:to_sym) && t.command.to_sym == :all && !t.ignore.include?(name.to_sym)) ||
82
82
  (type == :hook && matched_hook?(t.command, name)) ||
83
83
  nameify(t.command) == name
84
84
  end
@@ -89,6 +89,7 @@ module Vagrant
89
89
  type: type,
90
90
  guest_name: guest
91
91
  end
92
+
92
93
  filter_triggers(triggers, guest, type)
93
94
  end
94
95