vagrant-unbundled 2.2.14.0 → 2.2.16.0

Sign up to get free protection for your applications and to get access to all the features.
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}