vagrant-unbundled 2.2.14.0 → 2.2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -0
  3. data/bin/vagrant +27 -1
  4. data/contrib/README.md +1 -1
  5. data/lib/vagrant.rb +3 -1
  6. data/lib/vagrant/action/builtin/box_add.rb +13 -3
  7. data/lib/vagrant/action/builtin/box_check_outdated.rb +2 -1
  8. data/lib/vagrant/bundler.rb +15 -5
  9. data/lib/vagrant/environment.rb +1 -0
  10. data/lib/vagrant/errors.rb +12 -0
  11. data/lib/vagrant/machine_index.rb +1 -1
  12. data/lib/vagrant/patches/net-ssh.rb +186 -0
  13. data/lib/vagrant/plugin/manager.rb +20 -2
  14. data/lib/vagrant/util.rb +1 -0
  15. data/lib/vagrant/util/curl_helper.rb +7 -6
  16. data/lib/vagrant/util/guest_hosts.rb +1 -1
  17. data/lib/vagrant/util/numeric.rb +20 -0
  18. data/lib/vagrant/util/powershell.rb +30 -14
  19. data/lib/vagrant/vagrantfile.rb +1 -1
  20. data/plugins/commands/cloud/auth/middleware/add_authentication.rb +60 -31
  21. data/plugins/commands/cloud/auth/middleware/add_downloader_authentication.rb +34 -27
  22. data/plugins/commands/cloud/client/client.rb +10 -3
  23. data/plugins/commands/cloud/locales/en.yml +5 -1
  24. data/plugins/commands/cloud/provider/upload.rb +10 -0
  25. data/plugins/commands/cloud/publish.rb +10 -0
  26. data/plugins/commands/cloud/util.rb +10 -2
  27. data/plugins/commands/destroy/command.rb +1 -5
  28. data/plugins/guests/alpine/cap/configure_networks.rb +1 -1
  29. data/plugins/guests/fedora/guest.rb +4 -4
  30. data/plugins/guests/linux/cap/mount_smb_shared_folder.rb +1 -1
  31. data/plugins/guests/linux/cap/persist_mount_shared_folder.rb +1 -2
  32. data/plugins/guests/linux/cap/reboot.rb +21 -3
  33. data/plugins/guests/openwrt/cap/change_host_name.rb +19 -0
  34. data/plugins/guests/openwrt/cap/halt.rb +16 -0
  35. data/plugins/guests/openwrt/cap/insert_public_key.rb +20 -0
  36. data/plugins/guests/openwrt/cap/remove_public_key.rb +22 -0
  37. data/plugins/guests/openwrt/cap/rsync.rb +35 -0
  38. data/plugins/guests/openwrt/guest.rb +23 -0
  39. data/plugins/guests/openwrt/plugin.rb +61 -0
  40. data/plugins/providers/docker/driver.rb +2 -2
  41. data/plugins/providers/virtualbox/action/network.rb +12 -5
  42. data/plugins/providers/virtualbox/cap/mount_options.rb +5 -0
  43. data/plugins/providers/virtualbox/plugin.rb +5 -0
  44. data/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +1 -1
  45. data/plugins/provisioners/salt/bootstrap-salt.sh +7 -4
  46. data/plugins/synced_folders/smb/cap/mount_options.rb +2 -2
  47. data/templates/commands/init/Vagrantfile.min.erb +3 -0
  48. data/templates/guests/nixos/network.erb +5 -6
  49. data/templates/locales/en.yml +21 -4
  50. data/vagrant.gemspec +5 -11
  51. data/version.txt +1 -1
  52. metadata +2921 -29
@@ -179,8 +179,26 @@ module Vagrant
179
179
  result
180
180
  rescue Gem::GemNotFoundException
181
181
  raise Errors::PluginGemNotFound, name: name
182
- rescue Gem::Exception => e
183
- raise Errors::BundlerError, message: e.to_s
182
+ rescue Gem::Exception => err
183
+ @logger.warn("Failed to install plugin: #{err}")
184
+ @logger.debug("#{err.class}: #{err}\n#{err.backtrace.join("\n")}")
185
+ # Try and determine a cause for the failure
186
+ case err.message
187
+ when /install development tools first/
188
+ raise Errors::PluginNeedsDeveloperTools
189
+ when /library not found in default locations/
190
+ lib = err.message.match(/(\w+) library not found in default locations/)
191
+ if lib.nil?
192
+ raise Errors::BundlerError, message: err.message
193
+ end
194
+ raise Errors::PluginMissingLibrary,
195
+ library: lib.captures.first,
196
+ name: name
197
+ when /find header files for ruby/
198
+ raise Errors::PluginMissingRubyDev
199
+ else
200
+ raise Errors::BundlerError, message: err.message
201
+ end
184
202
  end
185
203
 
186
204
  # Uninstalls the plugin with the given name.
data/lib/vagrant/util.rb CHANGED
@@ -11,6 +11,7 @@ module Vagrant
11
11
  autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'
12
12
  autoload :GuestInspection, 'vagrant/util/guest_inspection'
13
13
  autoload :LoggingFormatter, 'vagrant/util/logging_formatter'
14
+ autoload :Numeric, 'vagrant/util/numeric'
14
15
  autoload :Platform, 'vagrant/util/platform'
15
16
  autoload :Retryable, 'vagrant/util/retryable'
16
17
  autoload :SafeExec, 'vagrant/util/safe_exec'
@@ -4,6 +4,7 @@ module Vagrant
4
4
 
5
5
  # Hosts that do not require notification on redirect
6
6
  SILENCED_HOSTS = [
7
+ "vagrantcloud-files-production.s3-accelerate.amazonaws.com".freeze,
7
8
  "vagrantcloud.com".freeze,
8
9
  "vagrantup.com".freeze
9
10
  ].freeze
@@ -21,6 +22,7 @@ module Vagrant
21
22
  # Accumulate progress_data
22
23
  progress_data << data
23
24
 
25
+ redirect_notify = false
24
26
  while true
25
27
  # If the download has been redirected and we are no longer downloading
26
28
  # from the original host, notify the user that the target host has
@@ -30,16 +32,15 @@ module Vagrant
30
32
  if !location.empty?
31
33
  location_uri = URI.parse(location)
32
34
 
33
- unless location_uri.host.nil?
34
- redirect_notify = false
35
+ if !location_uri.host.nil? && !redirect_notify
35
36
  logger.info("download redirected to #{location}")
36
37
  source_uri = URI.parse(source)
37
38
  source_host = source_uri.host.to_s.split(".", 2).last
38
39
  location_host = location_uri.host.to_s.split(".", 2).last
39
- if !redirect_notify && location_host != source_host && !SILENCED_HOSTS.include?(location_host)
40
- ui.rewriting do |ui|
41
- ui.clear_line
42
- ui.detail "Download redirected to host: #{location_uri.host}"
40
+ if location_host != source_host && !SILENCED_HOSTS.include?(location_host) && !SILENCED_HOSTS.include?(location_uri.host.to_s)
41
+ ui.rewriting do |_ui|
42
+ _ui.clear_line
43
+ _ui.detail "Download redirected to host: #{location_uri.host}"
43
44
  end
44
45
  end
45
46
  redirect_notify = true
@@ -17,7 +17,7 @@ module Vagrant
17
17
  basename = name.split(".", 2)[0]
18
18
  comm.sudo <<-EOH.gsub(/^ {14}/, '')
19
19
  grep -w '#{name}' /etc/hosts || {
20
- for i in {1..#{loop_bound}}; do
20
+ for i in #{[*1..loop_bound].join(' ')}; do
21
21
  grep -w "127.0.${i}.1" /etc/hosts || {
22
22
  echo "127.0.${i}.1 #{name} #{basename}" >> /etc/hosts
23
23
  break
@@ -49,6 +49,26 @@ module Vagrant
49
49
  bytes
50
50
  end
51
51
 
52
+ # Convert bytes to a user friendly string representation
53
+ #
54
+ # @param [Numeric] bytes Number of bytes to represent
55
+ # @return [String] user friendly output
56
+ def bytes_to_string(bytes)
57
+ # We want to locate the size that will return the
58
+ # smallest whole value number
59
+ BYTES_CONVERSION_MAP.sort { |a, b|
60
+ b.last <=> a.last
61
+ }.each do |suffix, size|
62
+ val = bytes.to_f / size
63
+ next if val < 1
64
+ val = sprintf("%.2f", val)
65
+ val.slice!(-1, 1) while val.end_with?("0")
66
+ val.slice!(-1, 1) if val.end_with?(".")
67
+ return "#{val}#{suffix}"
68
+ end
69
+ "#{bytes} byte#{"s" if bytes > 1}"
70
+ end
71
+
52
72
  # Rounds actual value to two decimal places
53
73
  #
54
74
  # @param [Integer] bytes
@@ -14,28 +14,44 @@ module Vagrant
14
14
  MINIMUM_REQUIRED_VERSION = 3
15
15
  # Number of seconds to wait while attempting to get powershell version
16
16
  DEFAULT_VERSION_DETECTION_TIMEOUT = 30
17
+ # Names of the powershell executable
18
+ POWERSHELL_NAMES = ["powershell", "pwsh"].map(&:freeze).freeze
19
+ # Paths to powershell executable
20
+ POWERSHELL_PATHS = [
21
+ "%WINDIR%/WindowsPowerShell/v1.0",
22
+ "%PROGRAMFILES%/PowerShell/7",
23
+ "%PROGRAMFILES%/PowerShell/6"
24
+ ].map(&:freeze).freeze
25
+
17
26
  LOGGER = Log4r::Logger.new("vagrant::util::powershell")
18
27
 
19
28
  # @return [String|nil] a powershell executable, depending on environment
20
29
  def self.executable
21
30
  if !defined?(@_powershell_executable)
22
- @_powershell_executable = "powershell"
31
+ # First start with detecting executable on configured path
32
+ POWERSHELL_NAMES.detect do |psh|
33
+ return @_powershell_executable = psh if Which.which(psh)
34
+ psh += ".exe"
35
+ return @_powershell_executable = psh if Which.which(psh)
36
+ end
37
+
38
+ # Now attempt with paths
39
+ paths = POWERSHELL_PATHS.map do |ppath|
40
+ result = Util::Subprocess.execute("cmd.exe", "/c", "echo #{ppath}")
41
+ result.stdout.gsub("\"", "").strip if result.exit_code == 0
42
+ end.compact
23
43
 
24
- if Which.which(@_powershell_executable).nil?
25
- # Try to use WSL interoperability if PowerShell is not symlinked to
26
- # the container.
27
- if Platform.wsl?
28
- @_powershell_executable += ".exe"
44
+ paths.each do |psh_path|
45
+ POWERSHELL_NAMES.each do |psh|
46
+ path = File.join(psh_path, psh)
47
+ return @_powershell_executable = path if Which.which(path)
29
48
 
30
- if Which.which(@_powershell_executable).nil?
31
- @_powershell_executable = "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe"
49
+ path += ".exe"
50
+ return @_powershell_executable = path if Which.which(path)
32
51
 
33
- if Which.which(@_powershell_executable).nil?
34
- @_powershell_executable = nil
35
- end
36
- end
37
- else
38
- @_powershell_executable = nil
52
+ # Finally test the msys2 style path
53
+ path = path.sub(/^([A-Za-z]):/, "/mnt/\\1")
54
+ return @_powershell_executable = path if Which.which(path)
39
55
  end
40
56
  end
41
57
  end
@@ -241,7 +241,7 @@ module Vagrant
241
241
  # configuration and attempt to load that
242
242
  if box.nil?
243
243
  @logger.warn("Failed to locate #{config.vm.box} with version #{config.vm.box_version}")
244
- @logger.warn("Performing lookup with inital values #{initial_box} with version #{initial_version}")
244
+ @logger.warn("Performing lookup with initial values #{initial_box} with version #{initial_version}")
245
245
  config.vm.box = original_box = initial_box
246
246
  config.vm.box_version = original_box = initial_version
247
247
  load_box_proc.call
@@ -1,5 +1,6 @@
1
1
  require "cgi"
2
2
  require "uri"
3
+ require "log4r"
3
4
 
4
5
  require Vagrant.source_root.join("plugins/commands/cloud/client/client")
5
6
 
@@ -27,55 +28,83 @@ module VagrantPlugins
27
28
 
28
29
  def initialize(app, env)
29
30
  @app = app
31
+ @logger = Log4r::Logger.new("vagrant::cloud::auth::authenticate-box-url")
30
32
  CloudCommand::Plugin.init!
31
33
  end
32
34
 
33
35
  def call(env)
34
- client = Client.new(env[:env])
35
- token = client.token
36
+ if ENV["VAGRANT_SERVER_ACCESS_TOKEN_BY_URL"]
37
+ @logger.warn("Adding access token as GET parameter by user request")
38
+ client = Client.new(env[:env])
39
+ token = client.token
36
40
 
37
- env[:box_urls].map! do |url|
38
- begin
39
- u = URI.parse(url)
40
- if u.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(u.host)
41
- u.host = TARGET_HOST
42
- u.to_s
43
- else
41
+ env[:box_urls].map! do |url|
42
+ begin
43
+ u = URI.parse(url)
44
+ if u.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(u.host)
45
+ u.host = TARGET_HOST
46
+ u.to_s
47
+ else
48
+ url
49
+ end
50
+ rescue URI::Error
44
51
  url
45
52
  end
46
- rescue URI::Error
47
- url
48
53
  end
49
- end
50
54
 
51
- server_uri = URI.parse(Vagrant.server_url.to_s)
55
+ server_uri = URI.parse(Vagrant.server_url.to_s)
52
56
 
53
- if token && !server_uri.host.to_s.empty?
54
- env[:box_urls].map! do |url|
55
- u = URI.parse(url)
57
+ if token && !server_uri.host.to_s.empty?
58
+ env[:box_urls].map! do |url|
59
+ begin
60
+ u = URI.parse(url)
56
61
 
57
- if u.host == server_uri.host
58
- if server_uri.host != TARGET_HOST && !self.class.custom_host_notified?
59
- env[:ui].warn(I18n.t("cloud_command.middleware.authentication.different_target",
60
- custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
61
- sleep CUSTOM_HOST_NOTIFY_WAIT
62
- self.class.custom_host_notified!
63
- end
62
+ if u.host == server_uri.host
63
+ if server_uri.host != TARGET_HOST && !self.class.custom_host_notified?
64
+ env[:ui].warn(I18n.t("cloud_command.middleware.authentication.different_target",
65
+ custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
66
+ sleep CUSTOM_HOST_NOTIFY_WAIT
67
+ self.class.custom_host_notified!
68
+ end
64
69
 
65
- q = CGI.parse(u.query || "")
70
+ q = CGI.parse(u.query || "")
66
71
 
67
- current = q["access_token"]
68
- if current && current.empty?
69
- q["access_token"] = token
70
- end
72
+ current = q["access_token"]
73
+ if current && current.empty?
74
+ q["access_token"] = token
75
+ end
71
76
 
72
- u.query = URI.encode_www_form(q)
77
+ u.query = URI.encode_www_form(q)
78
+ end
79
+
80
+ u.to_s
81
+ rescue URI::Error
82
+ url
83
+ end
73
84
  end
85
+ end
86
+ else
87
+ env[:box_urls].map! do |url|
88
+ begin
89
+ u = URI.parse(url)
90
+ q = CGI.parse(u.query || "")
91
+ if q["access_token"]
92
+ @logger.warn("Removing access token from URL parameter.")
93
+ q.delete("access_token")
94
+ if q.empty?
95
+ u.query = nil
96
+ else
97
+ u.query = URI.encode_www_form(q)
98
+ end
99
+ end
74
100
 
75
- u.to_s
101
+ u.to_s
102
+ rescue URI::Error
103
+ url
104
+ end
76
105
  end
106
+ @logger.warn("Authentication token not added as GET parameter.")
77
107
  end
78
-
79
108
  @app.call(env)
80
109
  end.freeze
81
110
  end
@@ -7,47 +7,54 @@ require_relative "./add_authentication"
7
7
  require Vagrant.source_root.join("plugins/commands/cloud/client/client")
8
8
 
9
9
  # Similar to AddAuthentication this middleware will add authentication for interacting
10
- # with Vagrant cloud. It does this by adding Authentication headers to a
11
- # Vagrant::Util::Downloader object.
10
+ # with Vagrant cloud. It does this by adding Authentication headers to a
11
+ # Vagrant::Util::Downloader object.
12
12
  module VagrantPlugins
13
13
  module CloudCommand
14
14
  class AddDownloaderAuthentication < AddAuthentication
15
15
 
16
- @@logger = Log4r::Logger.new("vagrant::clout::add_download_authentication")
16
+ def initialize(app, env)
17
+ super
18
+ @logger = Log4r::Logger.new("vagrant::cloud::auth::add-download-authentication")
19
+ end
17
20
 
18
21
  def call(env)
19
- client = Client.new(env[:env])
20
- token = client.token
21
- Vagrant::Util::CredentialScrubber.sensitive(token)
22
+ if ENV["VAGRANT_SERVER_ACCESS_TOKEN_BY_URL"]
23
+ @logger.warn("Authentication header not added due to user requested access token URL parameter")
24
+ else
25
+ client = Client.new(env[:env])
26
+ token = client.token
27
+ Vagrant::Util::CredentialScrubber.sensitive(token)
22
28
 
23
- begin
24
- target_url = URI.parse(env[:downloader].source)
25
- if target_url.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(target_url.host)
29
+ begin
30
+ target_url = URI.parse(env[:downloader].source)
31
+ if target_url.host != TARGET_HOST && REPLACEMENT_HOSTS.include?(target_url.host)
26
32
  target_url.host = TARGET_HOST
27
33
  env[:downloader].source = target_url.to_s
34
+ end
35
+ rescue URI::Error
36
+ # if there is an error, use current target_url
28
37
  end
29
- rescue URI::Error
30
- # if there is an error, use current target_url
31
- end
32
38
 
33
- server_uri = URI.parse(Vagrant.server_url.to_s)
34
- if token && !server_uri.host.to_s.empty?
35
- if target_url.host == server_uri.host
36
- if server_uri.host != TARGET_HOST && !self.class.custom_host_notified?
37
- env[:ui].warn(I18n.t("cloud_command.middleware.authentication.different_target",
38
- custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
39
- sleep CUSTOM_HOST_NOTIFY_WAIT
40
- self.class.custom_host_notified!
41
- end
39
+ server_uri = URI.parse(Vagrant.server_url.to_s)
40
+ if token && !server_uri.host.to_s.empty?
41
+ if target_url.host == server_uri.host
42
+ if server_uri.host != TARGET_HOST && !self.class.custom_host_notified?
43
+ env[:ui].warn(I18n.t("cloud_command.middleware.authentication.different_target",
44
+ custom_host: server_uri.host, known_host: TARGET_HOST) + "\n")
45
+ sleep CUSTOM_HOST_NOTIFY_WAIT
46
+ self.class.custom_host_notified!
47
+ end
42
48
 
43
- if Array(env[:downloader].headers).any? { |h| h.include?("Authorization") }
44
- @@logger.info("Not adding an authentication header, one already found")
45
- else
46
- env[:downloader].headers << "Authorization: Bearer #{token}"
49
+ if Array(env[:downloader].headers).any? { |h| h.include?("Authorization") }
50
+ @logger.info("Not adding an authentication header, one already found")
51
+ else
52
+ env[:downloader].headers << "Authorization: Bearer #{token}"
53
+ end
47
54
  end
48
- end
49
55
 
50
- env[:downloader]
56
+ env[:downloader]
57
+ end
51
58
  end
52
59
 
53
60
  @app.call(env)
@@ -18,6 +18,7 @@ module VagrantPlugins
18
18
  ######################################################################
19
19
  APP = "app".freeze
20
20
 
21
+ include Util
21
22
  include Vagrant::Util::Presence
22
23
 
23
24
  attr_accessor :client
@@ -32,7 +33,10 @@ module VagrantPlugins
32
33
  def initialize(env)
33
34
  @logger = Log4r::Logger.new("vagrant::cloud::client")
34
35
  @env = env
35
- @client = VagrantCloud::Client.new(access_token: token)
36
+ @client = VagrantCloud::Client.new(
37
+ access_token: token,
38
+ url_base: api_server_url
39
+ )
36
40
  end
37
41
 
38
42
  # Removes the token, effectively logging the user out.
@@ -72,7 +76,10 @@ module VagrantPlugins
72
76
  password: password, description: description, code: code)
73
77
 
74
78
  Vagrant::Util::CredentialScrubber.sensitive(r[:token])
75
- @client = VagrantCloud::Client.new(access_token: r[:token])
79
+ @client = VagrantCloud::Client.new(
80
+ access_token: r[:token],
81
+ url_base: api_server_url
82
+ )
76
83
  r[:token]
77
84
  end
78
85
  end
@@ -106,7 +113,7 @@ module VagrantPlugins
106
113
  end
107
114
 
108
115
  # Reset after we store the token since this is now _our_ token
109
- @client = VagrantCloud::Client.new(access_token: token)
116
+ @client = VagrantCloud::Client.new(access_token: token, url_base: api_server_url)
110
117
 
111
118
  nil
112
119
  end
@@ -75,6 +75,10 @@ en:
75
75
  Updated provider %{provider} on %{org}/%{box_name} for version %{version}
76
76
  not_found: |-
77
77
  Failed to locate %{provider_name} provider for %{org}/%{box_name} on version %{version}
78
+ direct_disable: |-
79
+ Vagrant is automatically disabling direct upload to backend storage.
80
+ Uploads directly to backend storage are currently only supported for
81
+ files 5G in size or smaller. Box file to upload is: %{size}
78
82
  version:
79
83
  create_success: |-
80
84
  Created version %{version} on %{org}/%{box_name} for version %{version}
@@ -112,7 +116,7 @@ en:
112
116
  Failed to update box %{org}/%{box_name}
113
117
  whoami:
114
118
  read_error: |-
115
- Failed to read organization %{org}
119
+ Failed to locate account information
116
120
  provider:
117
121
  create_fail: |-
118
122
  Failed to create provider %{provider} on box %{org}/%{box_name} for version %{version}