Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for running from inside a wsl2 vm #279

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
source 'https://rubygems.org'

group :development do
gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.9.4'
gem 'vagrant', :git => 'https://github.com/hashicorp/vagrant.git', :tag => 'v2.3.7'
end

group :plugins do
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Vagrant Host Manager

`vagrant-hostmanager` is a Vagrant plugin that manages the `hosts` file on guest machines (and optionally the host). Its goal is to enable resolution of multi-machine environments deployed with a cloud provider where IP addresses are not known in advance.

Do you like what we do? Consider supporting us through Patreon. All of the money goes directly back into growing our collection of open source and free software.
[![Patreon](https://img.shields.io/badge/patreon-donate-red.svg)](https://www.patreon.com/devopsgroup)

Installation
------------

Expand Down Expand Up @@ -188,12 +191,10 @@ To contribute, fork then clone the repository, and then the following:

**Developing**

1. Ideally, install the version of Vagrant as defined in the `Gemfile`
1. Install [Ruby](https://www.ruby-lang.org/en/documentation/installation/)
2. Currently the Bundler version is locked to 1.14.6, please install this version.
* `gem install bundler -v '1.14.6'`
3. Then install vagrant-hostmanager dependancies:
* `bundle _1.14.6_ install`
1. Install [RVM](https://rvm.io/rvm/install)
2. If using MacOS, follow these [OpenSSL instructions](https://github.com/rvm/rvm/issues/5252#issuecomment-1298835941)
3. Use Ruby v3.0.0 `rvm use 3.0.0`
4. Run `bundle install`

**Testing**

Expand All @@ -212,7 +213,7 @@ To release a new version of vagrant-hostmanager you will need to do the followin

*(only contributors of the GitHub repo and owners of the project at RubyGems will have rights to do this)*

1. First, bump the version in ~/lib/vagrant-hostmanager/version.rb:
1. First, bump, commit, and push the version in ~/lib/vagrant-hostmanager/version.rb:
* Follow [Semantic Versioning](http://semver.org/).
2. Then, create a matching GitHub Release (this will also create a tag):
* Preface the version number with a `v`.
Expand Down
4 changes: 1 addition & 3 deletions lib/vagrant-hostmanager/action/update_guest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ def initialize(app, env)

def call(env)
if @config.hostmanager.manage_guest?
env[:ui].info I18n.t('vagrant_hostmanager.action.update_guest', {
:name => @machine.name
})
env[:ui].info I18n.t('vagrant_hostmanager.action.update_guest', name: @machine.name)
@updater.update_guest(@machine)

@app.call(env)
Expand Down
6 changes: 3 additions & 3 deletions lib/vagrant-hostmanager/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ def validate(machine)
# check if aliases option is an Array
if !machine.config.hostmanager.aliases.kind_of?(Array) &&
!machine.config.hostmanager.aliases.kind_of?(String)
errors << I18n.t('vagrant_hostmanager.config.not_an_array_or_string', {
errors << I18n.t('vagrant_hostmanager.config.not_an_array_or_string', **{
:config_key => 'hostmanager.aliases',
:is_class => aliases.class.to_s,
})
end

if !machine.config.hostmanager.ip_resolver.nil? &&
!machine.config.hostmanager.ip_resolver.kind_of?(Proc)
errors << I18n.t('vagrant_hostmanager.config.not_a_proc', {
errors << I18n.t('vagrant_hostmanager.config.not_a_proc', **{
:config_key => 'hostmanager.ip_resolver',
:is_class => ip_resolver.class.to_s,
})
Expand All @@ -72,7 +72,7 @@ def validate(machine)
def validate_bool(key, value)
if ![TrueClass, FalseClass].include?(value.class) &&
value != UNSET_VALUE
I18n.t('vagrant_hostmanager.config.not_a_bool', {
I18n.t('vagrant_hostmanager.config.not_a_bool', **{
:config_key => key,
:value => value.class.to_s
})
Expand Down
54 changes: 46 additions & 8 deletions lib/vagrant-hostmanager/hosts_file/updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,45 @@ def update_host
# copy and modify hosts file on host with Vagrant-managed entries
file = @global_env.tmp_path.join('hosts.local')

if WindowsSupport.windows?
if WindowsSupport.windows? || WindowsSupport.wsl?
# lazily include windows Module
class << self
include WindowsSupport unless include? WindowsSupport
end
hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
windir = ENV['WINDIR']
if WindowsSupport.wsl?
Dir.chdir('/mnt/c'){
windir = `cmd.exe /c echo %WINDIR%`.strip
}
# convert wsl path to windows path
if file.to_s =~ /\/mnt\/[a-z]\//
win_file = file.to_s.sub(/^\/mnt\/([a-z])\//, '\1:\\').gsub('/', '\\')
else
win_file = "\\\\wsl\$\\#{ENV['WSL_DISTRO_NAME']}" + file.to_s.gsub('/', '\\')
end
win_hosts_location = "#{windir}\\System32\\drivers\\etc\\hosts"
hosts_location = "/mnt/" + windir[0].downcase + "/" + windir[3..-1] + "/System32/drivers/etc/hosts"

# add to both, windows host and wsl machine
copy_proc = Proc.new {
wsl_copy_file(file, hosts_location, win_file, win_hosts_location)
`[ -w "/etc/hosts" ] && cat "#{file}" > "/etc/hosts" || sudo cp "#{file}" "/etc/hosts"`
}
else
hosts_location = "#{windir}\\System32\\drivers\\etc\\hosts"
copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
end
line_endings = "crlf"
else
hosts_location = '/etc/hosts'
copy_proc = Proc.new { `[ -w #{hosts_location} ] && cat #{file} > #{hosts_location} || sudo cp #{file} #{hosts_location}` }
copy_proc = Proc.new { `[ -w "#{hosts_location}" ] && cat "#{file}" > "#{hosts_location}" || sudo cp "#{file}" "#{hosts_location}"` }
line_endings = "lf"
end

FileUtils.cp(hosts_location, file)
if WindowsSupport.wsl?
FileUtils.chmod("+w", file)
end

if update_file(file, nil, true, line_endings)
copy_proc.call
Expand All @@ -88,8 +112,8 @@ def update_file(file, resolving_machine = nil, include_id = true, line_endings)

def update_content(file_content, resolving_machine, include_id, line_endings)
id = include_id ? " id: #{read_or_create_id}" : ""
header = "## vagrant-hostmanager-start#{id}\n"
footer = "## vagrant-hostmanager-end\n"
header = "## vagrant-hostmanager-start#{id}"
footer = "## vagrant-hostmanager-end"
body = get_machines
.map { |machine| get_hosts_file_entry(machine, resolving_machine) }
.join
Expand Down Expand Up @@ -146,12 +170,12 @@ def get_new_content(header, footer, body, old_content, line_endings)
if body.empty?
block = "\n"
else
block = "\n\n" + header + body + footer + "\n"
block = "\n\n" + header + "\n" + body + footer + "\n\n"
end
# Pattern for finding existing block
header_pattern = Regexp.quote(header)
footer_pattern = Regexp.quote(footer)
pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE)
pattern = Regexp.new("[\r\n]*#{header_pattern}.*?#{footer_pattern}[\r\n]*", Regexp::MULTILINE)
# Replace existing block or append
content = old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block
if line_endings == "crlf"
Expand Down Expand Up @@ -183,6 +207,10 @@ def self.windows?
RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
end

def self.wsl?
ENV.include?('WSLENV')
end

require 'win32ole' if windows?

def windows_copy_file(source, dest)
Expand All @@ -195,6 +223,16 @@ def windows_copy_file(source, dest)
end
end

def wsl_copy_file(source, dest, win_source, win_dest)
begin
# First, try Ruby copy
FileUtils.cp(source, dest)
rescue Errno::EACCES
# Access denied, try with elevated privileges
system('powershell.exe', 'Start-Process -Verb Runas -FilePath cmd.exe -Argumentlist "/C","copy","' + win_source + '","' + win_dest + '"')
end
end

private

def windows_copy_file_elevated(source, dest)
Expand Down
2 changes: 1 addition & 1 deletion lib/vagrant-hostmanager/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module VagrantPlugins
module HostManager
VERSION = '1.8.7'
VERSION = '1.8.10'
end
end
2 changes: 1 addition & 1 deletion vagrant-hostmanager.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ Gem::Specification.new do |gem|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.require_paths = ['lib']

gem.add_development_dependency 'bundler', '~> 1.3'
gem.add_development_dependency 'bundler'
gem.add_development_dependency 'rake'
end