vagrant-unbundled 1.9.1.1 → 1.9.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/CHANGELOG.md +126 -0
  4. data/LICENSE +1 -1
  5. data/README.md +1 -1
  6. data/bin/vagrant +11 -0
  7. data/contrib/bash/completion.sh +9 -9
  8. data/lib/vagrant.rb +4 -2
  9. data/lib/vagrant/action/builtin/box_add.rb +13 -8
  10. data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +67 -14
  11. data/lib/vagrant/action/builtin/provision.rb +10 -5
  12. data/lib/vagrant/action/general/package_setup_files.rb +51 -0
  13. data/lib/vagrant/action/general/package_setup_folders.rb +37 -0
  14. data/lib/vagrant/batch_action.rb +4 -2
  15. data/lib/vagrant/box_collection.rb +17 -5
  16. data/lib/vagrant/bundler.rb +110 -12
  17. data/lib/vagrant/cli.rb +1 -1
  18. data/lib/vagrant/environment.rb +4 -4
  19. data/lib/vagrant/errors.rb +32 -0
  20. data/lib/vagrant/shared_helpers.rb +14 -0
  21. data/lib/vagrant/ui.rb +3 -3
  22. data/lib/vagrant/util.rb +7 -1
  23. data/lib/vagrant/util/command_deprecation.rb +56 -0
  24. data/lib/vagrant/util/credential_scrubber.rb +29 -0
  25. data/lib/vagrant/util/guest_inspection.rb +47 -0
  26. data/lib/vagrant/util/platform.rb +217 -27
  27. data/lib/vagrant/util/powershell.rb +25 -0
  28. data/lib/vagrant/util/safe_exec.rb +9 -1
  29. data/lib/vagrant/util/ssh.rb +1 -1
  30. data/lib/vagrant/util/subprocess.rb +21 -2
  31. data/lib/vagrant/util/which.rb +6 -4
  32. data/plugins/commands/box/command/list.rb +1 -1
  33. data/plugins/commands/package/command.rb +3 -2
  34. data/plugins/commands/plugin/action.rb +2 -1
  35. data/plugins/commands/plugin/action/expunge_plugins.rb +20 -5
  36. data/plugins/commands/plugin/action/install_gem.rb +0 -8
  37. data/plugins/commands/plugin/command/expunge.rb +18 -5
  38. data/plugins/commands/plugin/command/mixin_install_opts.rb +1 -4
  39. data/plugins/commands/plugin/gem_helper.rb +5 -1
  40. data/plugins/commands/up/command.rb +1 -1
  41. data/plugins/commands/validate/command.rb +31 -0
  42. data/plugins/commands/validate/plugin.rb +17 -0
  43. data/plugins/communicators/ssh/communicator.rb +50 -25
  44. data/plugins/communicators/winrm/communicator.rb +8 -54
  45. data/plugins/communicators/winrm/config.rb +3 -0
  46. data/plugins/communicators/winrm/helper.rb +1 -1
  47. data/plugins/communicators/winrm/shell.rb +38 -32
  48. data/plugins/communicators/winssh/communicator.rb +161 -0
  49. data/plugins/communicators/winssh/config.rb +30 -0
  50. data/plugins/communicators/winssh/plugin.rb +21 -0
  51. data/plugins/guests/arch/cap/change_host_name.rb +0 -3
  52. data/plugins/guests/arch/cap/configure_networks.rb +1 -1
  53. data/plugins/guests/atomic/cap/change_host_name.rb +0 -3
  54. data/plugins/guests/darwin/cap/change_host_name.rb +0 -4
  55. data/plugins/guests/debian/cap/change_host_name.rb +0 -3
  56. data/plugins/guests/debian/cap/configure_networks.rb +2 -1
  57. data/plugins/guests/elementary/guest.rb +10 -0
  58. data/plugins/guests/elementary/plugin.rb +15 -0
  59. data/plugins/guests/esxi/cap/public_key.rb +63 -0
  60. data/plugins/guests/esxi/plugin.rb +11 -0
  61. data/plugins/guests/freebsd/cap/change_host_name.rb +0 -4
  62. data/plugins/guests/gentoo/cap/change_host_name.rb +7 -5
  63. data/plugins/guests/gentoo/cap/configure_networks.rb +57 -21
  64. data/plugins/guests/linux/cap/mount_smb_shared_folder.rb +20 -53
  65. data/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +10 -58
  66. data/plugins/guests/linux/cap/network_interfaces.rb +8 -1
  67. data/plugins/guests/linux/cap/nfs.rb +5 -14
  68. data/plugins/guests/linux/guest.rb +3 -3
  69. data/plugins/guests/omnios/cap/change_host_name.rb +0 -3
  70. data/plugins/guests/openbsd/cap/change_host_name.rb +0 -4
  71. data/plugins/guests/photon/cap/change_host_name.rb +0 -3
  72. data/plugins/guests/pld/cap/change_host_name.rb +0 -3
  73. data/plugins/guests/redhat/cap/change_host_name.rb +2 -9
  74. data/plugins/guests/redhat/cap/configure_networks.rb +43 -21
  75. data/plugins/guests/slackware/cap/change_host_name.rb +0 -3
  76. data/plugins/guests/suse/cap/change_host_name.rb +0 -3
  77. data/plugins/guests/tinycore/cap/mount_nfs.rb +3 -8
  78. data/plugins/guests/windows/cap/configure_networks.rb +0 -4
  79. data/plugins/guests/windows/cap/mount_shared_folder.rb +13 -1
  80. data/plugins/guests/windows/scripts/mount_volume.ps1.erb +1 -1
  81. data/plugins/hosts/windows/cap/ps.rb +6 -1
  82. data/plugins/kernel_v2/config/vm.rb +6 -4
  83. data/plugins/providers/docker/action.rb +4 -7
  84. data/plugins/providers/docker/action/build.rb +1 -1
  85. data/plugins/providers/docker/action/create.rb +3 -0
  86. data/plugins/providers/docker/config.rb +27 -1
  87. data/plugins/providers/docker/driver.rb +15 -2
  88. data/plugins/providers/docker/driver/compose.rb +287 -0
  89. data/plugins/providers/docker/errors.rb +16 -0
  90. data/plugins/providers/docker/provider.rb +25 -10
  91. data/plugins/providers/hyperv/action.rb +33 -8
  92. data/plugins/providers/hyperv/action/export.rb +39 -0
  93. data/plugins/providers/hyperv/action/import.rb +23 -4
  94. data/plugins/providers/hyperv/action/package.rb +16 -0
  95. data/plugins/providers/hyperv/action/package_metadata_json.rb +34 -0
  96. data/plugins/providers/hyperv/action/package_setup_files.rb +16 -0
  97. data/plugins/providers/hyperv/action/package_setup_folders.rb +18 -0
  98. data/plugins/providers/hyperv/action/package_vagrantfile.rb +34 -0
  99. data/plugins/providers/hyperv/config.rb +20 -4
  100. data/plugins/providers/hyperv/driver.rb +12 -0
  101. data/plugins/providers/hyperv/scripts/export_vm.ps1 +15 -0
  102. data/plugins/providers/hyperv/scripts/get_network_mac.ps1 +28 -0
  103. data/plugins/providers/hyperv/scripts/has_vmcx_support.ps1 +11 -0
  104. data/plugins/providers/hyperv/scripts/import_vm_vmcx.ps1 +10 -4
  105. data/plugins/providers/hyperv/scripts/import_vm_xml.ps1 +9 -3
  106. data/plugins/providers/hyperv/scripts/set_vm_integration_services.ps1 +37 -0
  107. data/plugins/providers/virtualbox/action/package_setup_files.rb +7 -42
  108. data/plugins/providers/virtualbox/action/package_setup_folders.rb +6 -26
  109. data/plugins/providers/virtualbox/driver/base.rb +10 -0
  110. data/plugins/providers/virtualbox/driver/version_5_0.rb +11 -11
  111. data/plugins/providers/virtualbox/driver/version_5_1.rb +3 -721
  112. data/plugins/providers/virtualbox/provider.rb +9 -5
  113. data/plugins/providers/virtualbox/synced_folder.rb +1 -1
  114. data/plugins/providers/virtualbox/util/compile_forwarded_ports.rb +3 -1
  115. data/plugins/provisioners/ansible/cap/guest/arch/ansible_install.rb +2 -2
  116. data/plugins/provisioners/ansible/cap/guest/debian/ansible_install.rb +8 -8
  117. data/plugins/provisioners/ansible/cap/guest/fedora/ansible_install.rb +9 -5
  118. data/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +1 -1
  119. data/plugins/provisioners/ansible/cap/guest/pip/pip.rb +5 -3
  120. data/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb +7 -3
  121. data/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb +1 -1
  122. data/plugins/provisioners/ansible/cap/guest/ubuntu/ansible_install.rb +3 -3
  123. data/plugins/provisioners/ansible/config/guest.rb +7 -1
  124. data/plugins/provisioners/ansible/provisioner/guest.rb +1 -1
  125. data/plugins/provisioners/chef/cap/freebsd/chef_install.rb +18 -0
  126. data/plugins/provisioners/chef/cap/freebsd/chef_installed.rb +22 -0
  127. data/plugins/provisioners/chef/plugin.rb +10 -0
  128. data/plugins/provisioners/docker/cap/linux/docker_installed.rb +1 -0
  129. data/plugins/provisioners/salt/bootstrap-salt.ps1 +4 -4
  130. data/plugins/provisioners/shell/config.rb +2 -2
  131. data/plugins/provisioners/shell/provisioner.rb +66 -4
  132. data/plugins/pushes/atlas/push.rb +6 -0
  133. data/plugins/pushes/local-exec/config.rb +2 -2
  134. data/plugins/synced_folders/unix_mount_helpers.rb +105 -0
  135. data/templates/commands/init/Vagrantfile.erb +6 -0
  136. data/templates/commands/init/Vagrantfile.min.erb +3 -0
  137. data/templates/guests/debian/network_dhcp.erb +2 -2
  138. data/templates/guests/gentoo/network_systemd.erb +16 -0
  139. data/templates/guests/redhat/network_dhcp.erb +1 -0
  140. data/templates/guests/redhat/network_static.erb +1 -1
  141. data/templates/guests/redhat/network_static6.erb +1 -1
  142. data/templates/locales/en.yml +72 -3
  143. data/templates/locales/providers_docker.yml +15 -0
  144. data/test/acceptance/provider-virtualbox/linked_clone_spec.rb +1 -1
  145. data/test/unit/plugins/commands/init/command_test.rb +7 -0
  146. data/test/unit/plugins/commands/up/command_test.rb +65 -0
  147. data/test/unit/plugins/commands/validate/command_test.rb +52 -0
  148. data/test/unit/plugins/communicators/ssh/communicator_test.rb +58 -2
  149. data/test/unit/plugins/communicators/winrm/communicator_test.rb +14 -26
  150. data/test/unit/plugins/communicators/winrm/helper_test.rb +12 -0
  151. data/test/unit/plugins/communicators/winrm/shell_test.rb +54 -15
  152. data/test/unit/plugins/communicators/winssh/communicator_test.rb +525 -0
  153. data/test/unit/plugins/guests/arch/cap/configure_networks_test.rb +5 -0
  154. data/test/unit/plugins/guests/esxi/cap/public_key_test.rb +48 -0
  155. data/test/unit/plugins/guests/linux/cap/mount_nfs_test.rb +1 -1
  156. data/test/unit/plugins/guests/linux/cap/mount_smb_shared_folder.rb +71 -0
  157. data/test/unit/plugins/guests/linux/cap/mount_virtual_box_shared_folder_test.rb +43 -0
  158. data/test/unit/plugins/guests/linux/cap/network_interfaces_test.rb +10 -10
  159. data/test/unit/plugins/guests/redhat/cap/configure_networks_test.rb +132 -12
  160. data/test/unit/plugins/guests/windows/cap/mount_shared_folder_test.rb +23 -0
  161. data/test/unit/plugins/providers/docker/driver_compose_test.rb +268 -0
  162. data/test/unit/plugins/provisioners/ansible/config/guest_test.rb +9 -0
  163. data/test/unit/plugins/provisioners/ansible/provisioner_test.rb +2 -2
  164. data/test/unit/plugins/pushes/atlas/push_test.rb +151 -150
  165. data/test/unit/templates/guests/debian/network_dhcp_test.rb +1 -0
  166. data/test/unit/templates/guests/gentoo/systemd_network_test.rb +73 -0
  167. data/test/unit/templates/guests/redhat/network_dhcp_test.rb +18 -0
  168. data/test/unit/vagrant/action/builtin/box_add_test.rb +27 -0
  169. data/test/unit/vagrant/action/builtin/handle_forwarded_port_collisions_test.rb +170 -0
  170. data/test/unit/vagrant/action/builtin/provision_test.rb +208 -0
  171. data/test/unit/vagrant/box_collection_test.rb +98 -0
  172. data/test/unit/vagrant/environment_test.rb +17 -0
  173. data/test/unit/vagrant/shared_helpers_test.rb +12 -0
  174. data/test/unit/vagrant/util/command_deprecation_test.rb +106 -0
  175. data/test/unit/vagrant/util/env_test.rb +43 -0
  176. data/test/unit/vagrant/util/platform_test.rb +8 -0
  177. data/test/unit/vagrant/util/subprocess_test.rb +61 -0
  178. data/test/vagrant-spec/Vagrantfile.spec +78 -0
  179. data/test/vagrant-spec/boxes/.keep +0 -0
  180. data/test/vagrant-spec/configs/vagrant-spec.config.virtualbox.rb +10 -0
  181. data/test/vagrant-spec/scripts/centos-run.virtualbox.sh +8 -0
  182. data/test/vagrant-spec/scripts/centos-setup.virtualbox.sh +14 -0
  183. data/test/vagrant-spec/scripts/ubuntu-run.virtualbox.sh +8 -0
  184. data/test/vagrant-spec/scripts/ubuntu-setup.virtualbox.sh +12 -0
  185. data/vagrant.gemspec +6 -11
  186. data/version.txt +1 -1
  187. metadata +1694 -1835
  188. data/plugins/communicators/winrm/scripts/elevated_shell.ps1.erb +0 -101
@@ -12,6 +12,12 @@ module Vagrant
12
12
  # @return [String]
13
13
  DEFAULT_SERVER_URL = "https://atlas.hashicorp.com"
14
14
 
15
+ # Max number of seconds to wait for joining an active thread.
16
+ #
17
+ # @return [Integer]
18
+ # @note This is not the maxium time for a thread to complete.
19
+ THREAD_MAX_JOIN_TIMEOUT = 60
20
+
15
21
  # This holds a global lock for the duration of the block. This should
16
22
  # be invoked around anything that is modifying process state (such as
17
23
  # environmental variables).
@@ -102,4 +108,12 @@ module Vagrant
102
108
 
103
109
  Pathname.new(path).expand_path
104
110
  end
111
+
112
+ # This returns true/false if the running version of Vagrant is
113
+ # a pre-release version (development)
114
+ #
115
+ # @return [Boolean]
116
+ def self.prerelease?
117
+ Gem::Version.new(Vagrant::VERSION).prerelease?
118
+ end
105
119
  end
data/lib/vagrant/ui.rb CHANGED
@@ -53,7 +53,7 @@ module Vagrant
53
53
  # We're being called in a trap-context. Wrap in a thread.
54
54
  Thread.new do
55
55
  @logger.info { "#{method}: #{message}" }
56
- end.join
56
+ end.join(THREAD_MAX_JOIN_TIMEOUT)
57
57
  end
58
58
  end
59
59
  end
@@ -128,7 +128,7 @@ module Vagrant
128
128
  @lock.synchronize do
129
129
  safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}")
130
130
  end
131
- end.join
131
+ end.join(THREAD_MAX_JOIN_TIMEOUT)
132
132
  end
133
133
  end
134
134
 
@@ -244,7 +244,7 @@ module Vagrant
244
244
  safe_puts(format_message(type, message, **opts),
245
245
  io: channel, printer: printer)
246
246
  end
247
- end.join
247
+ end.join(THREAD_MAX_JOIN_TIMEOUT)
248
248
  end
249
249
 
250
250
  def format_message(type, message, **opts)
data/lib/vagrant/util.rb CHANGED
@@ -1,15 +1,21 @@
1
1
  module Vagrant
2
2
  module Util
3
3
  autoload :Busy, 'vagrant/util/busy'
4
+ autoload :CommandDeprecation, 'vagrant/util/command_deprecation'
4
5
  autoload :Counter, 'vagrant/util/counter'
6
+ autoload :CredentialScrubber, 'vagrant/util/credential_scrubber'
7
+ autoload :DeepMerge, 'vagrant/util/deep_merge'
5
8
  autoload :Env, 'vagrant/util/env'
6
9
  autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'
10
+ autoload :GuestInspection, 'vagrant/util/guest_inspection'
7
11
  autoload :Platform, 'vagrant/util/platform'
8
12
  autoload :Retryable, 'vagrant/util/retryable'
9
13
  autoload :SafeExec, 'vagrant/util/safe_exec'
14
+ autoload :SilenceWarnings, 'vagrant/util/silence_warnings'
10
15
  autoload :StackedProcRunner, 'vagrant/util/stacked_proc_runner'
11
- autoload :TemplateRenderer, 'vagrant/util/template_renderer'
12
16
  autoload :StringBlockEditor, 'vagrant/util/string_block_editor'
13
17
  autoload :Subprocess, 'vagrant/util/subprocess'
18
+ autoload :TemplateRenderer, 'vagrant/util/template_renderer'
19
+ autoload :Which, 'vagrant/util/which'
14
20
  end
15
21
  end
@@ -0,0 +1,56 @@
1
+ module Vagrant
2
+ module Util
3
+ # Automatically add deprecation notices to commands
4
+ module CommandDeprecation
5
+
6
+ # @return [String] generated name of command
7
+ def deprecation_command_name
8
+ name_parts = self.class.name.split("::")
9
+ [
10
+ name_parts[1].sub('Command', ''),
11
+ name_parts[3]
12
+ ].compact.map(&:downcase).join(" ")
13
+ end
14
+
15
+ def self.included(klass)
16
+ klass.class_eval do
17
+ class << self
18
+ if method_defined?(:synopsis)
19
+ alias_method :non_deprecated_synopsis, :synopsis
20
+
21
+ def synopsis
22
+ if !non_deprecated_synopsis.to_s.empty?
23
+ "#{non_deprecated_synopsis} [DEPRECATED]"
24
+ else
25
+ non_deprecated_synopsis
26
+ end
27
+ end
28
+ end
29
+ end
30
+ alias_method :non_deprecated_execute, :execute
31
+
32
+ def execute(*args, &block)
33
+ @env[:ui].warn(I18n.t("vagrant.commands.deprecated",
34
+ name: deprecation_command_name
35
+ ) + "\n")
36
+ non_deprecated_execute(*args, &block)
37
+ end
38
+ end
39
+ end
40
+
41
+ # Mark command deprecation complete and fully disable
42
+ # the command's functionality
43
+ module Complete
44
+ def self.included(klass)
45
+ klass.include(CommandDeprecation)
46
+ klass.class_eval do
47
+ def execute(*_)
48
+ raise Vagrant::Errors::CommandDeprecated,
49
+ name: deprecation_command_name
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,29 @@
1
+ module Vagrant
2
+ module Util
3
+ # Utility class to remove credential information from strings
4
+ class CredentialScrubber
5
+ # String used to replace credential information
6
+ REPLACEMENT_TEXT = "*****".freeze
7
+
8
+ # Attempt to remove detected credentials from string
9
+ #
10
+ # @param [String] string
11
+ # @return [String]
12
+ def self.scrub(string)
13
+ string = url_scrubber(string)
14
+ end
15
+
16
+ # Detect URLs and remove any embedded credentials
17
+ #
18
+ # @param [String] string
19
+ # @return [String]
20
+ def self.url_scrubber(string)
21
+ string.gsub(%r{(ftp|https?)://[^\s]+@[^\s]+}) do |address|
22
+ uri = URI.parse(address)
23
+ uri.user = uri.password = REPLACEMENT_TEXT
24
+ uri.to_s
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ module Vagrant
2
+ module Util
3
+ # Helper methods for inspecting guests to determine if specific services
4
+ # or applications are installed and in use
5
+ module GuestInspection
6
+ # Linux specific inspection helpers
7
+ module Linux
8
+
9
+ ## systemd helpers
10
+
11
+ # systemd is in used
12
+ #
13
+ # @return [Boolean]
14
+ def systemd?(comm)
15
+ comm.test("systemctl | grep '^-\.mount'")
16
+ end
17
+
18
+ # systemd hostname set is via hostnamectl
19
+ #
20
+ # @return [Boolean]
21
+ def hostnamectl?(comm)
22
+ comm.test("hostnamectl")
23
+ end
24
+
25
+ ## nmcli helpers
26
+
27
+ # nmcli is installed
28
+ #
29
+ # @return [Boolean]
30
+ def nmcli?(comm)
31
+ comm.test("nmcli")
32
+ end
33
+
34
+ # NetworkManager currently controls device
35
+ #
36
+ # @param comm [Communicator]
37
+ # @param device_name [String]
38
+ # @return [Boolean]
39
+ def nm_controlled?(comm, device_name)
40
+ comm.test("nmcli d show #{device_name}") &&
41
+ !comm.test("nmcli d show #{device_name} | grep unmanaged")
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -3,6 +3,7 @@ require "shellwords"
3
3
  require "tmpdir"
4
4
 
5
5
  require "vagrant/util/subprocess"
6
+ require "vagrant/util/powershell"
6
7
 
7
8
  module Vagrant
8
9
  module Util
@@ -27,6 +28,23 @@ module Vagrant
27
28
  return @_cygwin
28
29
  end
29
30
 
31
+ def wsl?
32
+ if !defined?(@_wsl)
33
+ @_wsl = false
34
+ SilenceWarnings.silence! do
35
+ # Use PATH values to check for `/mnt/c` path indicative of WSL
36
+ if ENV.fetch("PATH", "").downcase.include?("/mnt/c")
37
+ # Validate WSL via uname output
38
+ uname = Subprocess.execute("uname", "-r")
39
+ if uname.exit_code == 0 && uname.stdout.downcase.include?("microsoft")
40
+ @_wsl = true
41
+ end
42
+ end
43
+ end
44
+ end
45
+ @_wsl
46
+ end
47
+
30
48
  [:darwin, :bsd, :freebsd, :linux, :solaris].each do |type|
31
49
  define_method("#{type}?") do
32
50
  platform.include?(type.to_s)
@@ -42,27 +60,17 @@ module Vagrant
42
60
  # Checks if the user running Vagrant on Windows has administrative
43
61
  # privileges.
44
62
  #
63
+ # From: https://support.microsoft.com/en-us/kb/243330
64
+ # SID: S-1-5-19
65
+ #
45
66
  # @return [Boolean]
46
67
  def windows_admin?
47
68
  return @_windows_admin if defined?(@_windows_admin)
48
69
 
49
- # We lazily-load this because it is only available on Windows
50
- require "win32/registry"
51
-
52
- # Verify that we have administrative privileges. The odd method of
53
- # detecting this is based on this StackOverflow question:
54
- #
55
- # https://stackoverflow.com/questions/560366/
56
- # detect-if-running-with-administrator-privileges-under-windows-xp
57
70
  @_windows_admin = -> {
58
- begin
59
- Win32::Registry::HKEY_USERS.open("S-1-5-19") {}
60
-
61
- # The above doesn't seem to be 100% bullet proof. See GH-5616.
62
- return (`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil?
63
- rescue Win32::Registry::Error
64
- return false
65
- end
71
+ ps_cmd = '(new-object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)'
72
+ output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
73
+ return output == 'True'
66
74
  }.call
67
75
 
68
76
  return @_windows_admin
@@ -78,15 +86,13 @@ module Vagrant
78
86
  # @return [Boolean]
79
87
  def windows_hyperv_admin?
80
88
  return @_windows_hyperv_admin if defined?(@_windows_hyperv_admin)
89
+
81
90
  @_windows_hyperv_admin = -> {
82
- begin
83
- username = ENV["USERNAME"]
84
- process = Subprocess.execute("net", "localgroup", "Hyper-V Administrators")
85
- return process.stdout.include?(username)
86
- rescue Errors::CommandUnavailableWindows
87
- return false
88
- end
91
+ ps_cmd = "[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups | ForEach-Object { if ($_.Value -eq 'S-1-5-32-578'){ Write-Host 'true'; break }}"
92
+ output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
93
+ return output == 'true'
89
94
  }.call
95
+
90
96
  return @_windows_hyperv_admin
91
97
  end
92
98
 
@@ -199,11 +205,16 @@ module Vagrant
199
205
  def windows_unc_path(path)
200
206
  path = path.gsub("/", "\\")
201
207
 
202
- # If the path is just a drive letter, then return that as-is
203
- return path + "\\" if path =~ /^[a-zA-Z]:\\?$/
204
-
205
208
  # Convert to UNC path
206
- "\\\\?\\" + path.gsub("/", "\\")
209
+ if path =~ /^[a-zA-Z]:\\?$/
210
+ # If the path is just a drive letter, then return that as-is
211
+ path + "\\"
212
+ elsif path.start_with?("\\\\")
213
+ # If the path already starts with `\\` assume UNC and return as-is
214
+ path
215
+ else
216
+ "\\\\?\\" + path.gsub("/", "\\")
217
+ end
207
218
  end
208
219
 
209
220
  # Returns a boolean noting whether the terminal supports color.
@@ -229,6 +240,185 @@ module Vagrant
229
240
  return @_platform
230
241
  end
231
242
 
243
+ # Determine if given path is within the WSL rootfs. Returns
244
+ # true if within the subsystem, or false if outside the subsystem.
245
+ #
246
+ # @param [String] path Path to check
247
+ # @return [Boolean] path is within subsystem
248
+ def wsl_path?(path)
249
+ wsl? && !path.to_s.downcase.start_with?("/mnt/")
250
+ end
251
+
252
+ # Convert a WSL path to the local Windows path. This is useful
253
+ # for conversion when calling out to Windows executables from
254
+ # the WSL
255
+ #
256
+ # @param [String, Pathname] path Path to convert
257
+ # @return [String]
258
+ def wsl_to_windows_path(path)
259
+ if wsl? && wsl_windows_access?
260
+ if wsl_path?(path)
261
+ parts = path.split("/")
262
+ parts.delete_if(&:empty?)
263
+ [wsl_windows_appdata_local, "lxss", *parts].join("\\")
264
+ else
265
+ path = path.to_s.sub("/mnt/", "")
266
+ parts = path.split("/")
267
+ parts.first << ":"
268
+ path = parts.join("\\")
269
+ path
270
+ end
271
+ else
272
+ path
273
+ end
274
+ end
275
+
276
+ # Automatically convert a given path to a Windows path. Will only
277
+ # be applied if running on a Windows host. If running on Windows
278
+ # host within the WSL, the actual Windows path will be returned.
279
+ #
280
+ # @param [Pathname, String] path Path to convert
281
+ # @return [String]
282
+ def windows_path(path)
283
+ path = cygwin_windows_path(path)
284
+ path = wsl_to_windows_path(path)
285
+ if windows? || wsl?
286
+ path = windows_unc_path(path)
287
+ end
288
+ path
289
+ end
290
+
291
+ # Allow Vagrant to access Vagrant managed machines outside the
292
+ # Windows Subsystem for Linux
293
+ #
294
+ # @return [Boolean]
295
+ def wsl_windows_access?
296
+ if !defined?(@_wsl_windows_access)
297
+ @_wsl_windows_access = wsl? && ENV["VAGRANT_WSL_ENABLE_WINDOWS_ACCESS"]
298
+ end
299
+ @_wsl_windows_access
300
+ end
301
+
302
+ # The allowed windows system path Vagrant can manage from the Windows
303
+ # Subsystem for Linux
304
+ #
305
+ # @return [Pathname]
306
+ def wsl_windows_accessible_path
307
+ if !defined?(@_wsl_windows_accessible_path)
308
+ access_path = ENV["VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH"]
309
+ if access_path.to_s.empty?
310
+ access_path = wsl_windows_home.gsub("\\", "/").sub(":", "")
311
+ access_path[0] = access_path[0].downcase
312
+ access_path = "/mnt/#{access_path}"
313
+ end
314
+ @_wsl_windows_accessible_path = Pathname.new(access_path)
315
+ end
316
+ @_wsl_windows_accessible_path
317
+ end
318
+
319
+ # Checks given path to determine if Vagrant is allowed to bypass checks
320
+ #
321
+ # @param [String] path Path to check
322
+ # @return [Boolean] Vagrant is allowed to bypass checks
323
+ def wsl_windows_access_bypass?(path)
324
+ wsl? && wsl_windows_access? &&
325
+ path.to_s.start_with?(wsl_windows_accessible_path.to_s)
326
+ end
327
+
328
+ # If running within the Windows Subsystem for Linux, this will provide
329
+ # simple setup to allow sharing of the user's VAGRANT_HOME directory
330
+ # within the subsystem
331
+ #
332
+ # @param [Environment] env
333
+ # @param [Logger] logger Optional logger to display information
334
+ def wsl_init(env, logger=nil)
335
+ if wsl?
336
+ if ENV["VAGRANT_WSL_ENABLE_WINDOWS_ACCESS"]
337
+ wsl_validate_matching_vagrant_versions!
338
+ shared_user = ENV["VAGRANT_WSL_WINDOWS_ACCESS_USER"]
339
+ if shared_user.to_s.empty?
340
+ shared_user = wsl_windows_username
341
+ end
342
+ if logger
343
+ logger.warn("Windows Subsystem for Linux detected. Allowing access to user: #{shared_user}")
344
+ logger.warn("Vagrant will be allowed to control Vagrant managed machines within the user's home path.")
345
+ end
346
+ if ENV["VAGRANT_HOME"] || ENV["VAGRANT_WSL_DISABLE_VAGRANT_HOME"]
347
+ logger.warn("VAGRANT_HOME environment variable already set. Not overriding!") if logger
348
+ else
349
+ home_path = wsl_windows_accessible_path.to_s
350
+ ENV["VAGRANT_HOME"] = File.join(home_path, ".vagrant.d")
351
+ if logger
352
+ logger.info("Overriding VAGRANT_HOME environment variable to configured windows user. (#{ENV["VAGRANT_HOME"]})")
353
+ end
354
+ true
355
+ end
356
+ else
357
+ if env.local_data_path.to_s.start_with?("/mnt/")
358
+ raise Vagrant::Errors::WSLVagrantAccessError
359
+ end
360
+ end
361
+ end
362
+ end
363
+
364
+ # Fetch the Windows username currently in use
365
+ #
366
+ # @return [String, Nil]
367
+ def wsl_windows_username
368
+ if !@_wsl_windows_username
369
+ result = Util::Subprocess.execute("cmd.exe", "/c", "echo %USERNAME%")
370
+ if result.exit_code == 0
371
+ @_wsl_windows_username = result.stdout.strip
372
+ end
373
+ end
374
+ @_wsl_windows_username
375
+ end
376
+
377
+ # Fetch the Windows user home directory
378
+ #
379
+ # @return [String, Nil]
380
+ def wsl_windows_home
381
+ if !@_wsl_windows_home
382
+ result = Util::Subprocess.execute("cmd.exe", "/c" "echo %USERPROFILE%")
383
+ if result.exit_code == 0
384
+ @_wsl_windows_home = result.stdout.gsub("\"", "").strip
385
+ end
386
+ end
387
+ @_wsl_windows_home
388
+ end
389
+
390
+ # Fetch the Windows user local app data directory
391
+ #
392
+ # @return [String, Nil]
393
+ def wsl_windows_appdata_local
394
+ if !@_wsl_windows_appdata_local
395
+ result = Util::Subprocess.execute("cmd.exe", "/c", "echo %LOCALAPPDATA%")
396
+ if result.exit_code == 0
397
+ @_wsl_windows_appdata_local = result.stdout.gsub("\"", "").strip
398
+ end
399
+ end
400
+ @_wsl_windows_appdata_local
401
+ end
402
+
403
+ # Confirm Vagrant versions installed within the WSL and the Windows system
404
+ # are the same. Raise error if they do not match.
405
+ def wsl_validate_matching_vagrant_versions!
406
+ valid = false
407
+ result = Util::Subprocess.execute("vagrant.exe", "version")
408
+ if result.exit_code == 0
409
+ windows_version = result.stdout.match(/Installed Version: (?<version>.+$)/)
410
+ if windows_version
411
+ windows_version = windows_version[:version].strip
412
+ valid = windows_version == Vagrant::VERSION
413
+ end
414
+ end
415
+ if !valid
416
+ raise Vagrant::Errors::WSLVagrantVersionMismatch,
417
+ wsl_version: Vagrant::VERSION,
418
+ windows_version: windows_version || "unknown"
419
+ end
420
+ end
421
+
232
422
  # @private
233
423
  # Reset the cached values for platform. This is not considered a public
234
424
  # API and should only be used for testing.