vagrant-unbundled 2.2.6.0 → 2.2.9.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/.hashibot.hcl +14 -0
  3. data/CHANGELOG.md +93 -2
  4. data/README.md +1 -3
  5. data/bin/vagrant +23 -0
  6. data/contrib/bash/completion.sh +13 -1
  7. data/lib/vagrant.rb +25 -0
  8. data/lib/vagrant/action.rb +5 -0
  9. data/lib/vagrant/action/builder.rb +145 -24
  10. data/lib/vagrant/action/builtin/box_add.rb +11 -4
  11. data/lib/vagrant/action/builtin/box_check_outdated.rb +12 -15
  12. data/lib/vagrant/action/builtin/cleanup_disks.rb +56 -0
  13. data/lib/vagrant/action/builtin/delayed.rb +26 -0
  14. data/lib/vagrant/action/builtin/disk.rb +52 -0
  15. data/lib/vagrant/action/builtin/handle_box.rb +2 -0
  16. data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +28 -9
  17. data/lib/vagrant/action/builtin/mixin_provisioners.rb +19 -1
  18. data/lib/vagrant/action/builtin/ssh_run.rb +21 -3
  19. data/lib/vagrant/action/builtin/trigger.rb +36 -0
  20. data/lib/vagrant/action/hook.rb +20 -2
  21. data/lib/vagrant/action/runner.rb +11 -26
  22. data/lib/vagrant/action/warden.rb +4 -18
  23. data/lib/vagrant/box_metadata.rb +17 -3
  24. data/lib/vagrant/bundler.rb +260 -53
  25. data/lib/vagrant/cli.rb +4 -2
  26. data/lib/vagrant/errors.rb +24 -0
  27. data/lib/vagrant/machine.rb +9 -6
  28. data/lib/vagrant/plugin/manager.rb +25 -14
  29. data/lib/vagrant/plugin/v2/command.rb +1 -1
  30. data/lib/vagrant/plugin/v2/manager.rb +53 -0
  31. data/lib/vagrant/plugin/v2/plugin.rb +1 -0
  32. data/lib/vagrant/plugin/v2/trigger.rb +64 -26
  33. data/lib/vagrant/shared_helpers.rb +28 -0
  34. data/lib/vagrant/ui.rb +50 -4
  35. data/lib/vagrant/util.rb +1 -0
  36. data/lib/vagrant/util/curl_helper.rb +8 -5
  37. data/lib/vagrant/util/downloader.rb +5 -1
  38. data/lib/vagrant/util/file_checksum.rb +6 -2
  39. data/lib/vagrant/util/guest_inspection.rb +9 -1
  40. data/lib/vagrant/util/io.rb +7 -27
  41. data/lib/vagrant/util/is_port_open.rb +1 -2
  42. data/lib/vagrant/util/map_command_options.rb +33 -0
  43. data/lib/vagrant/util/numeric.rb +69 -0
  44. data/lib/vagrant/util/platform.rb +8 -1
  45. data/plugins/commands/box/command/outdated.rb +14 -2
  46. data/plugins/commands/cloud/locales/en.yml +1 -1
  47. data/plugins/commands/cloud/publish.rb +1 -1
  48. data/plugins/commands/snapshot/command/save.rb +13 -8
  49. data/plugins/commands/ssh_config/command.rb +1 -1
  50. data/plugins/communicators/ssh/communicator.rb +18 -23
  51. data/plugins/communicators/winrm/config.rb +1 -1
  52. data/plugins/communicators/winrm/shell.rb +1 -1
  53. data/plugins/communicators/winssh/communicator.rb +126 -38
  54. data/plugins/communicators/winssh/config.rb +3 -7
  55. data/plugins/guests/alpine/cap/rsync.rb +1 -1
  56. data/plugins/guests/alpine/plugin.rb +16 -0
  57. data/plugins/guests/centos/cap/flavor.rb +24 -0
  58. data/plugins/guests/centos/guest.rb +9 -0
  59. data/plugins/guests/centos/plugin.rb +20 -0
  60. data/plugins/guests/darwin/cap/mount_vmware_shared_folder.rb +99 -13
  61. data/plugins/guests/darwin/plugin.rb +5 -0
  62. data/plugins/guests/debian/cap/configure_networks.rb +14 -6
  63. data/plugins/guests/linux/cap/halt.rb +9 -1
  64. data/plugins/guests/linux/cap/mount_smb_shared_folder.rb +16 -0
  65. data/plugins/guests/linux/cap/reboot.rb +48 -0
  66. data/plugins/guests/linux/plugin.rb +10 -0
  67. data/plugins/guests/redhat/cap/flavor.rb +3 -1
  68. data/plugins/guests/redhat/cap/nfs_client.rb +2 -2
  69. data/plugins/guests/redhat/cap/smb.rb +20 -0
  70. data/plugins/guests/redhat/plugin.rb +5 -0
  71. data/plugins/guests/suse/cap/change_host_name.rb +2 -2
  72. data/plugins/guests/windows/cap/public_key.rb +3 -3
  73. data/plugins/guests/windows/cap/reboot.rb +2 -1
  74. data/plugins/hosts/darwin/cap/nfs.rb +11 -0
  75. data/plugins/hosts/darwin/plugin.rb +5 -0
  76. data/plugins/hosts/linux/cap/nfs.rb +21 -2
  77. data/plugins/kernel_v2/config/disk.rb +199 -0
  78. data/plugins/kernel_v2/config/ssh_connect.rb +24 -0
  79. data/plugins/kernel_v2/config/vm.rb +109 -4
  80. data/plugins/kernel_v2/config/vm_provisioner.rb +4 -1
  81. data/plugins/kernel_v2/config/vm_trigger.rb +2 -5
  82. data/plugins/providers/docker/driver.rb +38 -10
  83. data/plugins/providers/docker/errors.rb +4 -0
  84. data/plugins/providers/docker/executor/local.rb +7 -1
  85. data/plugins/providers/hyperv/action/export.rb +4 -2
  86. data/plugins/providers/hyperv/driver.rb +10 -9
  87. data/plugins/providers/hyperv/scripts/set_vm_integration_services.ps1 +3 -3
  88. data/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +6 -6
  89. data/plugins/providers/virtualbox/action.rb +2 -0
  90. data/plugins/providers/virtualbox/action/clean_machine_folder.rb +10 -1
  91. data/plugins/providers/virtualbox/action/export.rb +4 -2
  92. data/plugins/providers/virtualbox/action/import.rb +8 -4
  93. data/plugins/providers/virtualbox/action/prepare_clone_snapshot.rb +4 -2
  94. data/plugins/providers/virtualbox/action/snapshot_delete.rb +4 -2
  95. data/plugins/providers/virtualbox/action/snapshot_restore.rb +4 -2
  96. data/plugins/providers/virtualbox/cap/cleanup_disks.rb +54 -0
  97. data/plugins/providers/virtualbox/cap/configure_disks.rb +287 -0
  98. data/plugins/providers/virtualbox/cap/validate_disk_ext.rb +27 -0
  99. data/plugins/providers/virtualbox/driver/base.rb +15 -0
  100. data/plugins/providers/virtualbox/driver/meta.rb +14 -2
  101. data/plugins/providers/virtualbox/driver/version_5_0.rb +142 -2
  102. data/plugins/providers/virtualbox/driver/version_6_1.rb +39 -0
  103. data/plugins/providers/virtualbox/plugin.rb +21 -0
  104. data/plugins/provisioners/ansible/cap/guest/alpine/ansible_install.rb +44 -0
  105. data/plugins/provisioners/ansible/cap/guest/arch/ansible_install.rb +20 -3
  106. data/plugins/provisioners/ansible/cap/guest/debian/ansible_install.rb +4 -5
  107. data/plugins/provisioners/ansible/cap/guest/fedora/ansible_install.rb +2 -2
  108. data/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +2 -2
  109. data/plugins/provisioners/ansible/cap/guest/pip/pip.rb +8 -4
  110. data/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb +2 -2
  111. data/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb +2 -1
  112. data/plugins/provisioners/ansible/cap/guest/ubuntu/ansible_install.rb +3 -3
  113. data/plugins/provisioners/ansible/plugin.rb +5 -0
  114. data/plugins/provisioners/ansible/provisioner/base.rb +1 -1
  115. data/plugins/provisioners/container/client.rb +203 -0
  116. data/plugins/provisioners/container/config.rb +83 -0
  117. data/plugins/provisioners/container/installer.rb +13 -0
  118. data/plugins/provisioners/container/plugin.rb +23 -0
  119. data/plugins/provisioners/container/provisioner.rb +28 -0
  120. data/plugins/provisioners/docker/cap/{redhat → centos}/docker_install.rb +10 -7
  121. data/plugins/provisioners/docker/cap/centos/docker_start_service.rb +24 -0
  122. data/plugins/provisioners/docker/client.rb +4 -175
  123. data/plugins/provisioners/docker/config.rb +2 -72
  124. data/plugins/provisioners/docker/installer.rb +3 -5
  125. data/plugins/provisioners/docker/plugin.rb +6 -6
  126. data/plugins/provisioners/docker/provisioner.rb +4 -10
  127. data/plugins/provisioners/podman/cap/centos/podman_install.rb +35 -0
  128. data/plugins/provisioners/podman/cap/linux/podman_installed.rb +13 -0
  129. data/plugins/provisioners/podman/cap/redhat/podman_install.rb +26 -0
  130. data/plugins/provisioners/podman/client.rb +12 -0
  131. data/plugins/provisioners/podman/config.rb +28 -0
  132. data/plugins/provisioners/podman/installer.rb +33 -0
  133. data/plugins/provisioners/podman/plugin.rb +38 -0
  134. data/plugins/provisioners/podman/provisioner.rb +52 -0
  135. data/plugins/provisioners/salt/provisioner.rb +4 -0
  136. data/plugins/provisioners/shell/config.rb +1 -6
  137. data/plugins/provisioners/shell/provisioner.rb +54 -25
  138. data/plugins/synced_folders/smb/synced_folder.rb +1 -1
  139. data/templates/commands/init/Vagrantfile.erb +1 -1
  140. data/templates/locales/en.yml +123 -4
  141. data/templates/locales/providers_docker.yml +2 -0
  142. data/templates/nfs/exports_darwin.erb +7 -0
  143. data/vagrant.gemspec +8 -9
  144. data/version.txt +1 -1
  145. metadata +3731 -3663
  146. data/lib/vagrant/action/builtin/after_trigger.rb +0 -31
  147. data/lib/vagrant/action/builtin/before_trigger.rb +0 -28
  148. data/plugins/provisioners/docker/cap/redhat/docker_start_service.rb +0 -16
@@ -62,9 +62,11 @@ module Vagrant
62
62
  # Initialize and execute the command class, returning the exit status.
63
63
  result = 0
64
64
  begin
65
- @triggers.fire_triggers(@sub_command.to_sym, :before, nil, :command) if Vagrant::Util::Experimental.feature_enabled?("typed_triggers")
65
+ @triggers.fire(@sub_command, :before, nil, :command) if
66
+ Vagrant::Util::Experimental.feature_enabled?("typed_triggers")
66
67
  result = command_class.new(@sub_args, @env).execute
67
- @triggers.fire_triggers(@sub_command.to_sym, :after, nil, :command) if Vagrant::Util::Experimental.feature_enabled?("typed_triggers")
68
+ @triggers.fire(@sub_command, :after, nil, :command) if
69
+ Vagrant::Util::Experimental.feature_enabled?("typed_triggers")
68
70
  rescue Interrupt
69
71
  @env.ui.info(I18n.t("vagrant.cli_interrupt"))
70
72
  result = 1
@@ -248,6 +248,10 @@ module Vagrant
248
248
  error_key(:bundler_error)
249
249
  end
250
250
 
251
+ class SourceSpecNotFound < BundlerError
252
+ error_key(:source_spec_not_found)
253
+ end
254
+
251
255
  class CantReadMACAddresses < VagrantError
252
256
  error_key(:cant_read_mac_addresses)
253
257
  end
@@ -396,6 +400,10 @@ module Vagrant
396
400
  error_key(:auto_empty, "vagrant.actions.vm.forward_ports")
397
401
  end
398
402
 
403
+ class ForwardPortHostIPNotFound < VagrantError
404
+ error_key(:host_ip_not_found, "vagrant.actions.vm.forward_ports")
405
+ end
406
+
399
407
  class ForwardPortCollision < VagrantError
400
408
  error_key(:collision_error, "vagrant.actions.vm.forward_ports")
401
409
  end
@@ -436,6 +444,10 @@ module Vagrant
436
444
  error_key(:machine_action_locked)
437
445
  end
438
446
 
447
+ class MachineFolderNotAccessible < VagrantError
448
+ error_key(:machine_folder_not_accessible)
449
+ end
450
+
439
451
  class MachineGuestNotReady < VagrantError
440
452
  error_key(:machine_guest_not_ready)
441
453
  end
@@ -456,6 +468,10 @@ module Vagrant
456
468
  error_key(:multi_vm_target_required)
457
469
  end
458
470
 
471
+ class NetplanNoAvailableRenderers < VagrantError
472
+ error_key(:netplan_no_available_renderers)
473
+ end
474
+
459
475
  class NetSSHException < VagrantError
460
476
  error_key(:net_ssh_exception)
461
477
  end
@@ -612,6 +628,10 @@ module Vagrant
612
628
  error_key(:plugin_install_license_not_found)
613
629
  end
614
630
 
631
+ class PluginInstallFailed < VagrantError
632
+ error_key(:plugin_install_failed)
633
+ end
634
+
615
635
  class PluginInstallSpace < VagrantError
616
636
  error_key(:plugin_install_space)
617
637
  end
@@ -900,6 +920,10 @@ module Vagrant
900
920
  error_key(:virtualbox_broken_version_040214)
901
921
  end
902
922
 
923
+ class VirtualBoxDisksDefinedExceedLimit < VagrantError
924
+ error_key(:virtualbox_disks_defined_exceed_limit)
925
+ end
926
+
903
927
  class VirtualBoxGuestPropertyNotFound < VagrantError
904
928
  error_key(:virtualbox_guest_property_not_found)
905
929
  end
@@ -62,6 +62,11 @@ module Vagrant
62
62
  # @return [Hash]
63
63
  attr_reader :provider_options
64
64
 
65
+ # The triggers with machine specific configuration applied
66
+ #
67
+ # @return [Vagrant::Plugin::V2::Trigger]
68
+ attr_reader :triggers
69
+
65
70
  # The UI for outputting in the scope of this machine.
66
71
  #
67
72
  # @return [UI]
@@ -160,8 +165,6 @@ module Vagrant
160
165
  # as extra data set on the environment hash for the middleware
161
166
  # runner.
162
167
  def action(name, opts=nil)
163
- @triggers.fire_triggers(name, :before, @name.to_s, :action)
164
-
165
168
  @logger.info("Calling action: #{name} on provider #{@provider}")
166
169
 
167
170
  opts ||= {}
@@ -210,8 +213,6 @@ module Vagrant
210
213
  ui.machine("action", name.to_s, "end")
211
214
  action_result
212
215
  end
213
-
214
- @triggers.fire_triggers(name, :after, @name.to_s, :action)
215
216
  # preserve returning environment after machine action runs
216
217
  return return_env
217
218
  rescue Errors::EnvironmentLockedError
@@ -230,6 +231,7 @@ module Vagrant
230
231
  def action_raw(name, callable, extra_env=nil)
231
232
  # Run the action with the action runner on the environment
232
233
  env = {
234
+ raw_action_name: name,
233
235
  action_name: "machine_action_#{name}".to_sym,
234
236
  machine: self,
235
237
  machine_action: name,
@@ -476,8 +478,9 @@ module Vagrant
476
478
 
477
479
  # We also set some fields that are purely controlled by Vagrant
478
480
  info[:forward_agent] = @config.ssh.forward_agent
479
- info[:forward_x11] = @config.ssh.forward_x11
480
- info[:forward_env] = @config.ssh.forward_env
481
+ info[:forward_x11] = @config.ssh.forward_x11
482
+ info[:forward_env] = @config.ssh.forward_env
483
+ info[:connect_timeout] = @config.ssh.connect_timeout
481
484
 
482
485
  info[:ssh_command] = @config.ssh.ssh_command if @config.ssh.ssh_command
483
486
 
@@ -51,7 +51,7 @@ module Vagrant
51
51
  @globalized = true
52
52
  @logger.debug("Enabling globalized plugins")
53
53
  plugins = installed_plugins
54
- bundler_init(plugins)
54
+ bundler_init(plugins, global: user_file.path)
55
55
  plugins
56
56
  end
57
57
 
@@ -66,7 +66,7 @@ module Vagrant
66
66
  @local_file = StateFile.new(env.local_data_path.join("plugins.json"))
67
67
  Vagrant::Bundler.instance.environment_path = env.local_data_path
68
68
  plugins = local_file.installed_plugins
69
- bundler_init(plugins)
69
+ bundler_init(plugins, local: local_file.path)
70
70
  plugins
71
71
  end
72
72
  end
@@ -80,7 +80,7 @@ module Vagrant
80
80
  #
81
81
  # @param [Hash] plugins List of plugins
82
82
  # @return [nil]
83
- def bundler_init(plugins)
83
+ def bundler_init(plugins, **opts)
84
84
  if !Vagrant.plugins_init?
85
85
  @logger.warn("Plugin initialization is disabled")
86
86
  return nil
@@ -99,7 +99,7 @@ module Vagrant
99
99
  )
100
100
  end
101
101
  begin
102
- Vagrant::Bundler.instance.init!(plugins)
102
+ Vagrant::Bundler.instance.init!(plugins, **opts)
103
103
  rescue StandardError, ScriptError => err
104
104
  @logger.error("Plugin initialization error - #{err.class}: #{err}")
105
105
  err.backtrace.each do |backtrace_line|
@@ -150,17 +150,28 @@ module Vagrant
150
150
  else
151
151
  result = local_spec
152
152
  end
153
- # Add the plugin to the state file
154
- plugin_file = opts[:env_local] ? @local_file : @user_file
155
- plugin_file.add_plugin(
156
- result.name,
157
- version: opts[:version],
158
- require: opts[:require],
159
- sources: opts[:sources],
160
- env_local: !!opts[:env_local],
161
- installed_gem_version: result.version.to_s
162
- )
163
153
 
154
+ if result
155
+ # Add the plugin to the state file
156
+ plugin_file = opts[:env_local] ? @local_file : @user_file
157
+ plugin_file.add_plugin(
158
+ result.name,
159
+ version: opts[:version],
160
+ require: opts[:require],
161
+ sources: opts[:sources],
162
+ env_local: !!opts[:env_local],
163
+ installed_gem_version: result.version.to_s
164
+ )
165
+ else
166
+ r = Gem::Dependency.new(name, opts[:version])
167
+ result = Gem::Specification.find { |s|
168
+ s.satisfies_requirement?(r) &&
169
+ s.activated?
170
+ }
171
+ raise Errors::PluginInstallFailed,
172
+ name: name if result.nil?
173
+ @logger.warn("Plugin install returned no result as no new plugins were installed.")
174
+ end
164
175
  # After install clean plugin gems to remove any cruft. This is useful
165
176
  # for removing outdated dependencies or other versions of an installed
166
177
  # plugin if the plugin is upgraded/downgraded
@@ -51,7 +51,7 @@ module Vagrant
51
51
  argv = @argv.dup
52
52
 
53
53
  # Default opts to a blank optionparser if none is given
54
- opts ||= OptionParser.new
54
+ opts ||= Vagrant::OptionParser.new
55
55
 
56
56
  # Add the help option, which must be on every command.
57
57
  opts.on_tail("-h", "--help", "Print this help") do
@@ -28,6 +28,59 @@ module Vagrant
28
28
  result
29
29
  end
30
30
 
31
+ # Find all hooks that are applicable for the given key. This
32
+ # lookup does not include hooks which are defined for ALL_ACTIONS.
33
+ # Key lookups will match on either string or symbol values. The
34
+ # provided keys is broken down into multiple parts for lookups,
35
+ # which allows defining hooks with an entire namespaced name,
36
+ # or a short suffx. For example:
37
+ #
38
+ # Assume we are given an action class
39
+ # key = Vagrant::Action::Builtin::SyncedFolders
40
+ #
41
+ # The list of keys that will be checked for hooks:
42
+ # ["Vagrant::Action::Builtin::SyncedFolders", "vagrant_action_builtin_synced_folders",
43
+ # "Action::Builtin::SyncedFolders", "action_builtin_synced_folders",
44
+ # "Builtin::SyncedFolders", "builtin_synced_folders",
45
+ # "SyncedFolders", "synced_folders"]
46
+ #
47
+ # @param key [Class, String] key Key for hook lookups
48
+ # @return [Array<Proc>]
49
+ def find_action_hooks(key)
50
+ result = []
51
+
52
+ generate_hook_keys(key).each do |k|
53
+ @registered.each do |plugin|
54
+ result += plugin.components.action_hooks[k]
55
+ result += plugin.components.action_hooks[k.to_sym]
56
+ end
57
+ end
58
+
59
+ result
60
+ end
61
+
62
+ # Generate all valid lookup keys for given key
63
+ #
64
+ # @param [Class, String] key Base key for generation
65
+ # @return [Array<String>] all valid keys
66
+ def generate_hook_keys(key)
67
+ if key.is_a?(Class)
68
+ key = key.name.to_s
69
+ else
70
+ key = key.to_s
71
+ end
72
+ parts = key.split("::")
73
+ [].tap do |keys|
74
+ until parts.empty?
75
+ x = parts.join("::")
76
+ keys << x
77
+ y = x.gsub(/([a-z])([A-Z])/, '\1_\2').gsub('::', '_').downcase
78
+ keys << y if x != y
79
+ parts.shift
80
+ end
81
+ end
82
+ end
83
+
31
84
  # This returns all the registered commands.
32
85
  #
33
86
  # @return [Registry<Symbol, Array<Proc, Hash>>]
@@ -71,6 +71,7 @@ module Vagrant
71
71
  # @return [Array] List of the hooks for the given action.
72
72
  def self.action_hook(name, hook_name=nil, &block)
73
73
  # The name is currently not used but we want it for the future.
74
+ hook_name = hook_name.to_s if hook_name
74
75
 
75
76
  hook_name ||= ALL_ACTIONS
76
77
  components.action_hooks[hook_name.to_sym] << block
@@ -30,58 +30,97 @@ module Vagrant
30
30
  @logger = Log4r::Logger.new("vagrant::trigger::#{self.class.to_s.downcase}")
31
31
  end
32
32
 
33
- # Fires all triggers, if any are defined for the action and guest. Returns early
33
+ # Fires all triggers, if any are defined for the named type and guest. Returns early
34
34
  # and logs a warning if the community plugin `vagrant-triggers` is installed
35
35
  #
36
- # @param [Symbol] action Vagrant command to fire trigger on
36
+ # @param [Symbol] name Name of `type` thing to fire trigger on
37
37
  # @param [Symbol] stage :before or :after
38
- # @param [String] guest_name The guest that invoked firing the triggers
39
- def fire_triggers(action, stage, guest_name, type)
38
+ # @param [String] guest The guest that invoked firing the triggers
39
+ # @param [Symbol] type Type of trigger to fire (:action, :hook, :command)
40
+ def fire(name, stage, guest, type)
40
41
  if community_plugin_detected?
41
42
  @logger.warn("Community plugin `vagrant-triggers detected, so core triggers will not fire")
42
43
  return
43
44
  end
44
45
 
45
- if !action
46
- @logger.warn("Action given is nil, no triggers will fire")
47
- return
48
- else
49
- action = action.to_sym
50
- end
46
+ return @logger.warn("Name given is nil, no triggers will fire") if !name
47
+ return @logger.warn("Name given cannot be symbolized, no triggers will fire") if
48
+ !name.respond_to?(:to_sym)
49
+
50
+ name = name.to_sym
51
51
 
52
52
  # get all triggers matching action
53
- triggers = []
53
+ triggers = find(name, stage, guest, type)
54
+
55
+ if !triggers.empty?
56
+ @logger.info("Firing trigger for #{type} #{name} on guest #{guest}")
57
+ @ui.info(I18n.t("vagrant.trigger.start", type: type, stage: stage, name: name))
58
+ execute(triggers)
59
+ end
60
+ end
61
+
62
+ # Find all triggers defined for the named type and guest.
63
+ #
64
+ # @param [Symbol] name Name of `type` thing to fire trigger on
65
+ # @param [Symbol] stage :before or :after
66
+ # @param [String] guest The guest that invoked firing the triggers
67
+ # @param [Symbol] type Type of trigger to fire
68
+ # @return [Array]
69
+ def find(name, stage, guest, type)
70
+ triggers = nil
71
+ name = nameify(name)
72
+
54
73
  if stage == :before
55
74
  triggers = config.before_triggers.select do |t|
56
- t.command == action || (t.command == :all && !t.ignore.include?(action))
75
+ (t.command == :all && !t.ignore.include?(name)) ||
76
+ (type == :hook && matched_hook?(t.command, name)) ||
77
+ nameify(t.command) == name
57
78
  end
58
79
  elsif stage == :after
59
80
  triggers = config.after_triggers.select do |t|
60
- t.command == action || (t.command == :all && !t.ignore.include?(action))
81
+ (t.command == :all && !t.ignore.include?(name)) ||
82
+ (type == :hook && matched_hook?(t.command, name)) ||
83
+ nameify(t.command) == name
61
84
  end
62
85
  else
63
86
  raise Errors::TriggersNoStageGiven,
64
- action: action,
87
+ name: name,
65
88
  stage: stage,
66
- guest_name: guest_name
67
- end
68
-
69
- triggers = filter_triggers(triggers, guest_name, type)
70
-
71
- if !triggers.empty?
72
- @logger.info("Firing trigger for action #{action} on guest #{guest_name}")
73
- @ui.info(I18n.t("vagrant.trigger.start", type: type, stage: stage, action: action))
74
- fire(triggers, guest_name)
89
+ type: type,
90
+ guest_name: guest
75
91
  end
92
+ filter_triggers(triggers, guest, type)
76
93
  end
77
94
 
78
95
  protected
79
96
 
97
+ # Convert object into name
98
+ #
99
+ # @param [Object, Class] object Object to name
100
+ # @return [String]
101
+ def nameify(object)
102
+ if object.is_a?(Class)
103
+ object.name.to_s
104
+ else
105
+ object.to_s
106
+ end
107
+ end
80
108
 
81
109
  #-------------------------------------------------------------------
82
110
  # Internal methods, don't call these.
83
111
  #-------------------------------------------------------------------
84
112
 
113
+ # Generate all valid lookup keys for given action key
114
+ #
115
+ # @param [Class, String] key Base key for generation
116
+ # @return [Array<String>] all valid keys
117
+ def matched_hook?(key, subject)
118
+ subject = nameify(subject)
119
+ Vagrant.plugin("2").manager.generate_hook_keys(key).any? do |k|
120
+ k == subject
121
+ end
122
+ end
123
+
85
124
  # Looks up if the community plugin `vagrant-triggers` is installed
86
125
  # and also caches the result
87
126
  #
@@ -133,12 +172,11 @@ module Vagrant
133
172
  return triggers
134
173
  end
135
174
 
136
- # Fires off all triggers in the given array
175
+ # Execute all triggers in the given array
137
176
  #
138
177
  # @param [Array] triggers An array of triggers to be fired
139
- def fire(triggers, guest_name)
178
+ def execute(triggers)
140
179
  # ensure on_error is respected by exiting or continuing
141
-
142
180
  triggers.each do |trigger|
143
181
  @logger.debug("Running trigger #{trigger.id}...")
144
182
 
@@ -186,4 +186,32 @@ module Vagrant
186
186
  end
187
187
  @_global_logger
188
188
  end
189
+
190
+ # Add a new block of default CLI options which
191
+ # should be automatically added to all commands
192
+ #
193
+ # @param [Proc] block Proc instance containing OptParser configuration
194
+ # @return [nil]
195
+ def self.add_default_cli_options(block)
196
+ if !block.is_a?(Proc)
197
+ raise TypeError,
198
+ "Expecting type `Proc` but received `#{block.class}`"
199
+ end
200
+ if block.arity != 1 && block.arity != -1
201
+ raise ArgumentError,
202
+ "Proc must accept OptionParser argument"
203
+ end
204
+ @_default_cli_options = [] if !@_default_cli_options
205
+ @_default_cli_options << block
206
+ nil
207
+ end
208
+
209
+ # Array of default CLI options to automatically
210
+ # add to commands.
211
+ #
212
+ # @return [Array<Proc>] Default optparse options
213
+ def self.default_cli_options
214
+ @_default_cli_options = [] if !@_default_cli_options
215
+ @_default_cli_options.dup
216
+ end
189
217
  end
@@ -75,6 +75,13 @@ module Vagrant
75
75
  def machine(type, *data)
76
76
  @logger.info("Machine: #{type} #{data.inspect}")
77
77
  end
78
+
79
+ # Yields self (UI)
80
+ # Provides a way for selectively displaying or not displaying
81
+ # updating content like download progress.
82
+ def rewriting
83
+ yield self
84
+ end
78
85
  end
79
86
 
80
87
  # This is a UI implementation that does nothing.
@@ -252,6 +259,31 @@ module Vagrant
252
259
  end
253
260
  end
254
261
 
262
+
263
+ class NonInteractive < Basic
264
+ def initialize
265
+ super
266
+ end
267
+
268
+ def rewriting
269
+ # no-op
270
+ end
271
+
272
+ def report_progress(progress, total, show_parts=true)
273
+ # no-op
274
+ end
275
+
276
+ def clear_line
277
+ @logger.warn("Using `clear line` in a non interactive ui")
278
+ say(:info, "\n", opts)
279
+ end
280
+
281
+ def ask(*args)
282
+ # Non interactive can't ask for input
283
+ raise Errors::UIExpectsTTY
284
+ end
285
+ end
286
+
255
287
  # Prefixed wraps an existing UI and adds a prefix to it.
256
288
  class Prefixed < Interface
257
289
  # The prefix for `output` messages.
@@ -290,7 +322,9 @@ module Vagrant
290
322
 
291
323
  [:clear_line, :report_progress].each do |method|
292
324
  # By default do nothing, these aren't formatted
293
- define_method(method) { |*args| @ui.send(method, *args) }
325
+ define_method(method) do |*args|
326
+ @ui.send(method, *args)
327
+ end
294
328
  end
295
329
 
296
330
  # For machine-readable output, set the prefix in the
@@ -329,16 +363,28 @@ module Vagrant
329
363
  target = opts[:target] if opts.key?(:target)
330
364
  target = "#{target}:" if target != ""
331
365
 
332
- # Get the lines. The first default is because if the message
333
- # is an empty string, then we want to still use the empty string.
334
366
  lines = [message]
335
- lines = message.split("\n") if message != ""
367
+ if message != ""
368
+ lines = [].tap do |l|
369
+ message.scan(/(.*?)(\n|$)/).each do |m|
370
+ l << m.first if m.first != "" || (m.first == "" && m.last == "\n")
371
+ end
372
+ end
373
+ lines << "" if message.end_with?("\n")
374
+ end
336
375
 
337
376
  # Otherwise, make sure to prefix every line properly
338
377
  lines.map do |line|
339
378
  "#{prefix}#{target} #{line}"
340
379
  end.join("\n")
341
380
  end
381
+
382
+ def rewriting
383
+ @ui.rewriting do |ui|
384
+ yield ui
385
+ end
386
+ end
387
+
342
388
  end
343
389
 
344
390
  # This is a UI implementation that outputs color for various types