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
@@ -0,0 +1,166 @@
1
+ require 'open3'
2
+
3
+ HEAD = """
4
+ #compdef _vagrant vagrant
5
+
6
+ # ZSH completion for Vagrant
7
+ #
8
+ # To use this completion add this to ~/.zshrc
9
+ # fpath=(/path/to/this/dir $fpath)
10
+ # compinit
11
+ #
12
+ # For development reload the function after making changes
13
+ # unfunction _vagrant && autoload -U _vagrant
14
+ """
15
+
16
+ BOX_LIST_FUNCTION = """
17
+ __box_list ()
18
+ {
19
+ _wanted application expl 'command' compadd $(command vagrant box list | awk '{print $1}' )
20
+ }
21
+ """
22
+
23
+ PLUGIN_LIST_FUNCTION = """
24
+ __plugin_list ()
25
+ {
26
+ _wanted application expl 'command' compadd $(command vagrant plugin list | awk '{print $1}')
27
+ }
28
+ """
29
+
30
+ ADD_FEATURE_FLAGS = ["remove", "repackage", "update", "repair", "uninstall"]
31
+ VAGRANT_COMMAND = "vagrant"
32
+
33
+ FLAG_REGEX = /--(\S)*/
34
+ CMDS_REGEX = /^(\s){1,}(\w)(\S)*/
35
+
36
+ def make_string_script_safe(s)
37
+ s.gsub("[","(").gsub("]",")").gsub("-","_").gsub("'", "")
38
+ end
39
+
40
+ def remove_square_brakets(s)
41
+ s.gsub("[","(").gsub("]",")")
42
+ end
43
+
44
+ def format_flags(group_name, flags)
45
+ group_name = make_string_script_safe(group_name)
46
+ opts_str = "local -a #{group_name} && #{group_name}=(\n"
47
+ flags.each do |flag, desc|
48
+ opts_str = opts_str + " '#{remove_square_brakets(flag)}=[#{make_string_script_safe(desc)}]'\n"
49
+ end
50
+ opts_str + ")"
51
+ end
52
+
53
+ def format_subcommand(group_name, cmds)
54
+ opts_str = "local -a #{group_name} && #{group_name}=(\n"
55
+ cmds.each do |cmd, desc|
56
+ opts_str = opts_str + " '#{cmd}:#{desc}'\n"
57
+ end
58
+ opts_str + ")"
59
+ end
60
+
61
+ def format_case(group_name, cmds, cmd_list, feature_string)
62
+ case_str = """case $state in
63
+ (command)
64
+ _describe -t commands 'command' #{group_name}
65
+ return
66
+ ;;
67
+
68
+ (options)
69
+ case $line[1] in
70
+ """
71
+
72
+ cmds.each do |cmd, desc|
73
+ if cmd_list.include?(cmd)
74
+ case_append = """ #{cmd})
75
+ _arguments -s -S : $#{make_string_script_safe(cmd)}_arguments #{feature_string if ADD_FEATURE_FLAGS.include?(cmd)} ;;
76
+ """
77
+ else
78
+ case_append = """ #{cmd})
79
+ __vagrant-#{cmd} ;;
80
+ """
81
+ end
82
+ case_str = case_str + case_append
83
+ end
84
+
85
+ case_str = case_str + """esac
86
+ ;;
87
+ esac
88
+ """
89
+ end
90
+
91
+ def extract_flags(top_level_commands)
92
+ flags = top_level_commands.map { |c| [c.match(FLAG_REGEX)[0], c.split(" ")[-1].strip] if c.strip.start_with?("--") }.compact
93
+ end
94
+
95
+ def extract_subcommand(top_level_commands)
96
+ cmds = top_level_commands.map { |c| [c.match(CMDS_REGEX)[0].strip, c.split(" ")[-1].strip] if c.match(CMDS_REGEX) }.compact
97
+ end
98
+
99
+ def get_top_level_commands(root_command, cmd_list)
100
+ stdout, stderr, status = Open3.capture3("vagrant #{root_command} -h")
101
+ top_level_commands = stdout.split("\n")
102
+
103
+ root_subcommand = extract_subcommand(top_level_commands)
104
+ commands = format_subcommand("sub_commands", root_subcommand)
105
+ if root_command == "box"
106
+ feature_string = "':feature:__box_list'"
107
+ elsif root_command == "plugin"
108
+ feature_string = "':feature:__plugin_list'"
109
+ else
110
+ feature_string = ""
111
+ end
112
+ case_string = format_case("sub_commands", root_subcommand, cmd_list, feature_string)
113
+
114
+ flags_def = ""
115
+ root_subcommand.each do |cmd, desc|
116
+ next if !cmd_list.include?(cmd)
117
+ stdout, stderr, status = Open3.capture3("vagrant #{root_command} #{cmd} -h")
118
+ cmd_help = stdout.split("\n")
119
+ flags_def = flags_def + format_flags("#{cmd}_arguments", extract_flags(cmd_help)) + "\n\n"
120
+ end
121
+
122
+ return commands, flags_def, case_string
123
+ end
124
+
125
+ def format_script(root_command, subcommands, funciton_name)
126
+ top_level_commands, top_level_args, state_case = get_top_level_commands(root_command, subcommands)
127
+
128
+ script = """
129
+ function #{funciton_name} () {
130
+
131
+ #{top_level_commands}
132
+
133
+ #{top_level_args}
134
+
135
+ _arguments -C ':command:->command' '*::options:->options'
136
+
137
+ #{state_case}
138
+ }
139
+ """
140
+ end
141
+
142
+ def generate_script
143
+ subcommand_list = {
144
+ "" => ["cloud", "destroy", "global-status", "halt", "help", "login", "init", "package", "port", "powershell", "provision", "push", "rdp", "reload", "resume", "ssh", "ssh-config", "status", "suspend", "up", "upload", "validate", "version", "winrm", "winrm-config"],
145
+ "box" => ["add", "list", "outdated", "prune", "remove", "repackage", "update"],
146
+ "snapshot" => ["delete", "list", "pop", "push", "restore", "save"],
147
+ "plugin" => ["install", "expunge", "license", "list", "repair", "uninstall", "update"],
148
+ }
149
+
150
+ script = """#{HEAD}
151
+ #{BOX_LIST_FUNCTION}
152
+ #{PLUGIN_LIST_FUNCTION}
153
+ """
154
+
155
+ subcommand_list.each do |cmd, opts|
156
+ if cmd != ""
157
+ function_name = "__vagrant-#{cmd}"
158
+ else
159
+ function_name = "_vagrant"
160
+ end
161
+ script = script + format_script(cmd, opts, function_name)
162
+ end
163
+ script
164
+ end
165
+
166
+ puts generate_script
@@ -14,6 +14,8 @@ module Vagrant
14
14
  autoload :BoxRemove, "vagrant/action/builtin/box_remove"
15
15
  autoload :Call, "vagrant/action/builtin/call"
16
16
  autoload :CleanupDisks, "vagrant/action/builtin/cleanup_disks"
17
+ autoload :CloudInitSetup, "vagrant/action/builtin/cloud_init_setup"
18
+ autoload :CloudInitWait, "vagrant/action/builtin/cloud_init_wait"
17
19
  autoload :Confirm, "vagrant/action/builtin/confirm"
18
20
  autoload :ConfigValidate, "vagrant/action/builtin/config_validate"
19
21
  autoload :Delayed, "vagrant/action/builtin/delayed"
@@ -24,6 +26,7 @@ module Vagrant
24
26
  autoload :HandleBox, "vagrant/action/builtin/handle_box"
25
27
  autoload :HandleBoxUrl, "vagrant/action/builtin/handle_box_url"
26
28
  autoload :HandleForwardedPortCollisions, "vagrant/action/builtin/handle_forwarded_port_collisions"
29
+ autoload :HasProvisioner, "vagrant/action/builtin/has_provisioner"
27
30
  autoload :IsEnvSet, "vagrant/action/builtin/is_env_set"
28
31
  autoload :IsState, "vagrant/action/builtin/is_state"
29
32
  autoload :Lock, "vagrant/action/builtin/lock"
@@ -17,6 +17,11 @@ module Vagrant
17
17
  # Vagrant::Action.run(app)
18
18
  #
19
19
  class Builder
20
+ # Container for Action arguments
21
+ MiddlewareArguments = Struct.new(:parameters, :block, :keywords, keyword_init: true)
22
+ # Item within the stack
23
+ StackItem = Struct.new(:middleware, :arguments, keyword_init: true)
24
+
20
25
  # This is the stack of middlewares added. This should NOT be used
21
26
  # directly.
22
27
  #
@@ -28,8 +33,8 @@ module Vagrant
28
33
  # see {#use} instead.
29
34
  #
30
35
  # @return [Builder]
31
- def self.build(middleware, *args, &block)
32
- new.use(middleware, *args, &block)
36
+ def self.build(middleware, *args, **keywords, &block)
37
+ new.use(middleware, *args, **keywords, &block)
33
38
  end
34
39
 
35
40
  def initialize
@@ -58,12 +63,21 @@ module Vagrant
58
63
  # of the middleware.
59
64
  #
60
65
  # @param [Class] middleware The middleware class
61
- def use(middleware, *args, &block)
66
+ def use(middleware, *args, **keywords, &block)
67
+ item = StackItem.new(
68
+ middleware: middleware,
69
+ arguments: MiddlewareArguments.new(
70
+ parameters: args,
71
+ keywords: keywords,
72
+ block: block
73
+ )
74
+ )
75
+
62
76
  if middleware.kind_of?(Builder)
63
77
  # Merge in the other builder's stack into our own
64
78
  self.stack.concat(middleware.stack)
65
79
  else
66
- self.stack << [middleware, args, block]
80
+ self.stack << item
67
81
  end
68
82
 
69
83
  self
@@ -71,8 +85,22 @@ module Vagrant
71
85
 
72
86
  # Inserts a middleware at the given index or directly before the
73
87
  # given middleware object.
74
- def insert(index, middleware, *args, &block)
75
- index = self.index(index) unless index.is_a?(Integer)
88
+ def insert(idx_or_item, middleware, *args, **keywords, &block)
89
+ item = StackItem.new(
90
+ middleware: middleware,
91
+ arguments: MiddlewareArguments.new(
92
+ parameters: args,
93
+ keywords: keywords,
94
+ block: block
95
+ )
96
+ )
97
+
98
+ if idx_or_item.is_a?(Integer)
99
+ index = idx_or_item
100
+ else
101
+ index = self.index(idx_or_item)
102
+ end
103
+
76
104
  raise "no such middleware to insert before: #{index.inspect}" unless index
77
105
 
78
106
  if middleware.kind_of?(Builder)
@@ -80,27 +108,32 @@ module Vagrant
80
108
  stack.insert(index, stack_item)
81
109
  end
82
110
  else
83
- stack.insert(index, [middleware, args, block])
111
+ stack.insert(index, item)
84
112
  end
85
113
  end
86
114
 
87
115
  alias_method :insert_before, :insert
88
116
 
89
117
  # Inserts a middleware after the given index or middleware object.
90
- def insert_after(index, middleware, *args, &block)
91
- index = self.index(index) unless index.is_a?(Integer)
118
+ def insert_after(idx_or_item, middleware, *args, **keywords, &block)
119
+ if idx_or_item.is_a?(Integer)
120
+ index = idx_or_item
121
+ else
122
+ index = self.index(idx_or_item)
123
+ end
124
+
92
125
  raise "no such middleware to insert after: #{index.inspect}" unless index
93
126
  insert(index + 1, middleware, *args, &block)
94
127
  end
95
128
 
96
129
  # Replaces the given middlware object or index with the new
97
130
  # middleware.
98
- def replace(index, middleware, *args, &block)
131
+ def replace(index, middleware, *args, **keywords, &block)
99
132
  if index.is_a?(Integer)
100
133
  delete(index)
101
- insert(index, middleware, *args, &block)
134
+ insert(index, middleware, *args, **keywords, &block)
102
135
  else
103
- insert_before(index, middleware, *args, &block)
136
+ insert_before(index, middleware, *args, **keywords, &block)
104
137
  delete(index)
105
138
  end
106
139
  end
@@ -123,8 +156,9 @@ module Vagrant
123
156
  def index(object)
124
157
  stack.each_with_index do |item, i|
125
158
  return i if item == object
126
- return i if item[0] == object
127
- return i if item[0].respond_to?(:name) && item[0].name == object
159
+ return i if item.middleware == object
160
+ return i if item.middleware.respond_to?(:name) &&
161
+ item.middleware.name == object
128
162
  end
129
163
 
130
164
  nil
@@ -252,18 +286,18 @@ module Vagrant
252
286
  # and after specific provider actions (like :up, :halt, etc) and
253
287
  # are different from true action triggers
254
288
  if env[:triggers]
255
- if !env[:triggers].find(env[:raw_action_name], :before, machine_name, :action).empty?
289
+ if !env[:triggers].find(env[:raw_action_name], :before, machine_name, :action, all: true).empty?
256
290
  hook.prepend(Vagrant::Action::Builtin::Trigger,
257
- env[:raw_action_name], env[:triggers], :before, :action)
291
+ env[:raw_action_name], env[:triggers], :before, :action, all: true)
258
292
  end
259
- if !env[:triggers].find(env[:raw_action_name], :after, machine_name, :action).empty?
293
+ if !env[:triggers].find(env[:raw_action_name], :after, machine_name, :action, all: true).empty?
260
294
  # NOTE: These after triggers need to be delayed before running to
261
295
  # allow the rest of the call stack to complete before being
262
296
  # run. The delayed action is prepended to the stack (not appended)
263
297
  # to ensure it is called first, which results in it properly
264
298
  # waiting for everything to finish before itself completing.
265
299
  builder = self.class.build(Vagrant::Action::Builtin::Trigger,
266
- env[:raw_action_name], env[:triggers], :after, :action)
300
+ env[:raw_action_name], env[:triggers], :after, :action, all: true)
267
301
  hook.prepend(Vagrant::Action::Builtin::Delayed, builder)
268
302
  end
269
303
  end
@@ -25,6 +25,7 @@ module Vagrant
25
25
  def initialize(app, env)
26
26
  @app = app
27
27
  @logger = Log4r::Logger.new("vagrant::action::builtin::box_add")
28
+ @parser = URI::RFC2396_Parser.new
28
29
  end
29
30
 
30
31
  def call(env)
@@ -44,7 +45,7 @@ module Vagrant
44
45
  u = u.gsub("\\", "/")
45
46
  if Util::Platform.windows? && u =~ /^[a-z]:/i
46
47
  # On Windows, we need to be careful about drive letters
47
- u = "file:///#{URI.escape(u)}"
48
+ u = "file:///#{@parser.escape(u)}"
48
49
  end
49
50
 
50
51
  if u =~ /^[a-z0-9]+:.*$/i && !u.start_with?("file://")
@@ -53,9 +54,9 @@ module Vagrant
53
54
  end
54
55
 
55
56
  # Expand the path and try to use that, if possible
56
- p = File.expand_path(URI.unescape(u.gsub(/^file:\/\//, "")))
57
+ p = File.expand_path(@parser.unescape(u.gsub(/^file:\/\//, "")))
57
58
  p = Util::Platform.cygwin_windows_path(p)
58
- next "file://#{URI.escape(p.gsub("\\", "/"))}" if File.file?(p)
59
+ next "file://#{@parser.escape(p.gsub("\\", "/"))}" if File.file?(p)
59
60
 
60
61
  u
61
62
  end
@@ -434,7 +435,7 @@ module Vagrant
434
435
  downloader_options[:ui] = env[:ui] if opts[:ui]
435
436
  downloader_options[:location_trusted] = env[:box_download_location_trusted]
436
437
  downloader_options[:box_extra_download_options] = env[:box_extra_download_options]
437
-
438
+
438
439
  Util::Downloader.new(url, temp_path, downloader_options)
439
440
  end
440
441
 
@@ -495,7 +496,7 @@ module Vagrant
495
496
  url ||= uri.opaque
496
497
  #7570 Strip leading slash left in front of drive letter by uri.path
497
498
  Util::Platform.windows? && url.gsub!(/^\/([a-zA-Z]:)/, '\1')
498
- url = URI.unescape(url)
499
+ url = @parser.unescape(url)
499
500
 
500
501
  begin
501
502
  File.open(url, "r") do |f|
@@ -0,0 +1,127 @@
1
+ require 'mime'
2
+ require 'tmpdir'
3
+
4
+ module Vagrant
5
+ module Action
6
+ module Builtin
7
+ class CloudInitSetup
8
+ TEMP_PREFIX = "vagrant-cloud-init-iso-temp-".freeze
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ @logger = Log4r::Logger.new("vagrant::action::builtin::cloudinit::setup")
13
+ end
14
+
15
+ def call(env)
16
+ machine = env[:machine]
17
+
18
+ user_data_configs = machine.config.vm.cloud_init_configs
19
+ .select { |c| c.type == :user_data }
20
+
21
+ if !user_data_configs.empty?
22
+ user_data = setup_user_data(machine, env, user_data_configs)
23
+ meta_data = { "instance-id" => "i-#{machine.id.split('-').join}" }
24
+
25
+ write_cfg_iso(machine, env, user_data, meta_data)
26
+ end
27
+
28
+ # Continue On
29
+ @app.call(env)
30
+ end
31
+
32
+ # @param [Vagrant::Machine] machine
33
+ # @param [Vagrant::Environment] env
34
+ # @param [Array<#VagrantPlugins::Kernel_V2::VagrantConfigCloudInit>] user_data_cfgs
35
+ # @return [MIME::Text] user_data
36
+ def setup_user_data(machine, env, user_data_cfgs)
37
+ machine.ui.info(I18n.t("vagrant.actions.vm.cloud_init_user_data_setup"))
38
+
39
+ text_cfgs = user_data_cfgs.map { |cfg| read_text_cfg(machine, cfg) }
40
+
41
+ user_data = generate_cfg_msg(machine, text_cfgs)
42
+ user_data
43
+ end
44
+
45
+ # Reads an individual cloud_init config and stores its contents and the
46
+ # content_type as a MIME text
47
+ #
48
+ # @param [Vagrant::Machine] machine
49
+ # @param [VagrantPlugins::Kernel_V2::VagrantConfigCloudInit] cfg
50
+ # @return [MIME::Text] text_msg
51
+ def read_text_cfg(machine, cfg)
52
+ if cfg.path
53
+ text = File.read(Pathname.new(cfg.path).expand_path(machine.env.root_path))
54
+ else
55
+ text = cfg.inline
56
+ end
57
+
58
+ # Note: content_type must remove the leading `text/` because
59
+ # the MIME::Text initializer hardcodes `text/` already to the type.
60
+ # We assume content_type is correct due to the validation step
61
+ # in VagrantConfigCloudInit.
62
+ content_type = cfg.content_type.split('/', 2).last
63
+ text_msg = MIME::Text.new(text, content_type)
64
+
65
+ text_msg
66
+ end
67
+
68
+ # Combines all known cloud_init configs into a multipart mixed MIME text
69
+ # message
70
+ #
71
+ # @param [Vagrant::Machine] machine
72
+ # @param [Array<MIME::Text>] text_msg - One or more text configs
73
+ # @return [MIME::Multipart::Mixed] msg
74
+ def generate_cfg_msg(machine, text_cfgs)
75
+ msg = MIME::Multipart::Mixed.new
76
+ msg.headers.set("MIME-Version", "1.0")
77
+
78
+ text_cfgs.each do |c|
79
+ msg.add(c)
80
+ end
81
+
82
+ msg
83
+ end
84
+
85
+ # Writes the contents of the guests cloud_init config to a tmp
86
+ # dir and passes that source directory along to the host cap to be
87
+ # written to an iso
88
+ #
89
+ # @param [Vagrant::Machine] machine
90
+ # @param [MIME::Multipart::Mixed] user_data
91
+ # @param [Hash] meta_data
92
+ def write_cfg_iso(machine, env, user_data, meta_data)
93
+ iso_path = nil
94
+
95
+ if env[:env].host.capability?(:create_iso)
96
+ begin
97
+ source_dir = Pathname.new(Dir.mktmpdir(TEMP_PREFIX))
98
+ File.open("#{source_dir}/user-data", 'w') { |file| file.write(user_data.to_s) }
99
+
100
+ File.open("#{source_dir}/meta-data", 'w') { |file| file.write(meta_data.to_yaml) }
101
+
102
+ iso_path = env[:env].host.capability(:create_iso,
103
+ source_dir, volume_id: "cidata")
104
+ attach_disk_config(machine, env, iso_path.to_path)
105
+ ensure
106
+ FileUtils.remove_entry(source_dir)
107
+ end
108
+ else
109
+ raise Errors::CreateIsoHostCapNotFound
110
+ end
111
+ end
112
+
113
+ # Adds a new :dvd disk config with the given iso_path to be attached
114
+ # to the guest later
115
+ #
116
+ # @param [Vagrant::Machine] machine
117
+ # @param [Vagrant::Environment] env
118
+ # @param [String] iso_path
119
+ def attach_disk_config(machine, env, iso_path)
120
+ @logger.info("Adding cloud_init iso '#{iso_path}' to disk config")
121
+ machine.config.vm.disk :dvd, file: iso_path, name: "vagrant-cloud_init-disk"
122
+ machine.config.vm.disks.each { |d| d.finalize! if d.type == :dvd && d.file == iso_path }
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end