vagrant-hostmanager 1.2.3 → 1.3.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.
- data/README.md +35 -0
- data/lib/vagrant-hostmanager/command.rb +1 -1
- data/lib/vagrant-hostmanager/config.rb +16 -2
- data/lib/vagrant-hostmanager/hosts_file.rb +76 -21
- data/lib/vagrant-hostmanager/version.rb +1 -1
- data/locales/en.yml +1 -0
- data/vagrant-hostmanager.gemspec +1 -0
- metadata +4 -3
data/README.md
CHANGED
@@ -72,6 +72,41 @@ Use:
|
|
72
72
|
config.vm.provision :hostmanager
|
73
73
|
```
|
74
74
|
|
75
|
+
Custom IP resolver
|
76
|
+
------------------
|
77
|
+
|
78
|
+
You can customize way, how host manager resolves IP address
|
79
|
+
for each machine. This might be handy in case of aws provider,
|
80
|
+
where host name is stored in ssh_info hash of each machine.
|
81
|
+
This causes generation of invalid /etc/hosts file.
|
82
|
+
|
83
|
+
Custom IP resolver gives you oportunity to calculate IP address
|
84
|
+
for each machine by yourself. For example:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
config.hostmanager.ip_resolver = proc do |vm|
|
88
|
+
if hostname = (vm.ssh_info && vm.ssh_info[:host])
|
89
|
+
`host #{hostname}`.split("\n").last[/(\d+\.\d+\.\d+\.\d+)/, 1]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
Windows support
|
95
|
+
---------------
|
96
|
+
|
97
|
+
Hostmanager will detect Windows guests and hosts and use the appropriate
|
98
|
+
path for the ```hosts``` file: ```%WINDIR%\System32\drivers\etc\hosts```
|
99
|
+
|
100
|
+
By default on a Windows host, the ```hosts``` file is not writable without
|
101
|
+
elevated privileges. If hostmanager detects that it cannot overwrite the file,
|
102
|
+
it will attempt to do so with elevated privileges, causing the
|
103
|
+
[UAC](http://en.wikipedia.org/wiki/User_Account_Control) prompt to appear.
|
104
|
+
|
105
|
+
### UAC limitations
|
106
|
+
|
107
|
+
Due to limitations caused by UAC, cancelling out of the UAC prompt will not cause any
|
108
|
+
visible errors, however the ```hosts``` file will not be updated.
|
109
|
+
|
75
110
|
Contribute
|
76
111
|
----------
|
77
112
|
Contributions are welcome.
|
@@ -6,6 +6,7 @@ module VagrantPlugins
|
|
6
6
|
attr_accessor :ignore_private_ip
|
7
7
|
attr_accessor :aliases
|
8
8
|
attr_accessor :include_offline
|
9
|
+
attr_accessor :ip_resolver
|
9
10
|
|
10
11
|
alias_method :enabled?, :enabled
|
11
12
|
alias_method :include_offline?, :include_offline
|
@@ -17,6 +18,9 @@ module VagrantPlugins
|
|
17
18
|
@ignore_private_ip = UNSET_VALUE
|
18
19
|
@include_offline = UNSET_VALUE
|
19
20
|
@aliases = []
|
21
|
+
@aliases = Array.new
|
22
|
+
@include_offline = false
|
23
|
+
@ip_resolver = nil
|
20
24
|
end
|
21
25
|
|
22
26
|
def finalize!
|
@@ -35,7 +39,8 @@ module VagrantPlugins
|
|
35
39
|
errors << validate_bool('hostmanager.include_offline', @include_offline)
|
36
40
|
errors.compact!
|
37
41
|
|
38
|
-
if
|
42
|
+
# check if aliases option is an Array
|
43
|
+
if !machine.config.hostmanager.aliases.kind_of?(Array) &&
|
39
44
|
!machine.config.hostmanager.aliases.kind_of?(String)
|
40
45
|
errors << I18n.t('vagrant_hostmanager.config.not_an_array_or_string', {
|
41
46
|
:config_key => 'hostmanager.aliases',
|
@@ -43,7 +48,16 @@ module VagrantPlugins
|
|
43
48
|
})
|
44
49
|
end
|
45
50
|
|
46
|
-
|
51
|
+
if !machine.config.hostmanager.ip_resolver.nil? &&
|
52
|
+
!machine.config.hostmanager.ip_resolver.kind_of?(Proc)
|
53
|
+
errors << I18n.t('vagrant_hostmanager.config.not_a_proc', {
|
54
|
+
:config_key => 'hostmanager.ip_resolver',
|
55
|
+
:is_class => ip_resolver.class.to_s,
|
56
|
+
})
|
57
|
+
end
|
58
|
+
|
59
|
+
errors.compact!
|
60
|
+
{ "HostManager configuration" => errors }
|
47
61
|
end
|
48
62
|
|
49
63
|
private
|
@@ -8,13 +8,13 @@ module VagrantPlugins
|
|
8
8
|
|
9
9
|
if (machine.communicate.test("uname -s | grep SunOS"))
|
10
10
|
realhostfile = '/etc/inet/hosts'
|
11
|
-
|
11
|
+
move_cmd = 'mv'
|
12
12
|
elsif (machine.communicate.test("test -d $Env:SystemRoot"))
|
13
|
-
|
14
|
-
|
13
|
+
realhostfile = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
|
14
|
+
move_cmd = 'mv -force'
|
15
15
|
else
|
16
16
|
realhostfile = '/etc/hosts'
|
17
|
-
|
17
|
+
move_cmd = 'mv'
|
18
18
|
end
|
19
19
|
# download and modify file with Vagrant-managed entries
|
20
20
|
file = @global_env.tmp_path.join("hosts.#{machine.name}")
|
@@ -34,19 +34,23 @@ module VagrantPlugins
|
|
34
34
|
def update_host
|
35
35
|
# copy and modify hosts file on host with Vagrant-managed entries
|
36
36
|
file = @global_env.tmp_path.join('hosts.local')
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
|
38
|
+
if WindowsSupport.windows?
|
39
|
+
# lazily include windows Module
|
40
|
+
class << self
|
41
|
+
include WindowsSupport unless include? WindowsSupport
|
42
|
+
end
|
43
|
+
|
42
44
|
hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
|
43
|
-
|
45
|
+
copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
|
46
|
+
else
|
47
|
+
hosts_location = '/etc/hosts'
|
48
|
+
copy_proc = Proc.new { `sudo cp #{file} #{hosts_location}` }
|
44
49
|
end
|
50
|
+
|
45
51
|
FileUtils.cp(hosts_location, file)
|
46
52
|
update_file(file)
|
47
|
-
|
48
|
-
# copy modified file using sudo for permission
|
49
|
-
`#{copy_cmd} #{file} #{hosts_location}`
|
53
|
+
copy_proc.call
|
50
54
|
end
|
51
55
|
|
52
56
|
private
|
@@ -54,6 +58,7 @@ module VagrantPlugins
|
|
54
58
|
def update_file(file)
|
55
59
|
# build array of host file entries from Vagrant configuration
|
56
60
|
entries = []
|
61
|
+
destroyed_entries = []
|
57
62
|
ids = []
|
58
63
|
get_machines.each do |name, p|
|
59
64
|
if @provider == p
|
@@ -62,8 +67,12 @@ module VagrantPlugins
|
|
62
67
|
id = machine.id
|
63
68
|
ip = get_ip_address(machine)
|
64
69
|
aliases = machine.config.hostmanager.aliases.join(' ').chomp
|
65
|
-
|
66
|
-
|
70
|
+
if id.nil?
|
71
|
+
destroyed_entries << "#{ip}\t#{host} #{aliases}"
|
72
|
+
else
|
73
|
+
entries << "#{ip}\t#{host} #{aliases}\t# VAGRANT ID: #{id}\n"
|
74
|
+
ids << id unless ids.include?(id)
|
75
|
+
end
|
67
76
|
end
|
68
77
|
end
|
69
78
|
|
@@ -71,6 +80,8 @@ module VagrantPlugins
|
|
71
80
|
begin
|
72
81
|
# copy each line not managed by Vagrant
|
73
82
|
File.open(file).each_line do |line|
|
83
|
+
# Eliminate lines for machines that have been destroyed
|
84
|
+
next if destroyed_entries.any? { |entry| line =~ /^#{entry}\t# VAGRANT ID: .*/ }
|
74
85
|
tmp_file << line unless ids.any? { |id| line =~ /# VAGRANT ID: #{id}/ }
|
75
86
|
end
|
76
87
|
|
@@ -84,12 +95,17 @@ module VagrantPlugins
|
|
84
95
|
end
|
85
96
|
|
86
97
|
def get_ip_address(machine)
|
87
|
-
|
88
|
-
if
|
89
|
-
machine
|
90
|
-
|
91
|
-
|
92
|
-
|
98
|
+
custom_ip_resolver = machine.config.hostmanager.ip_resolver
|
99
|
+
if custom_ip_resolver
|
100
|
+
custom_ip_resolver.call(machine)
|
101
|
+
else
|
102
|
+
ip = nil
|
103
|
+
if machine.config.hostmanager.ignore_private_ip != true
|
104
|
+
machine.config.vm.networks.each do |network|
|
105
|
+
key, options = network[0], network[1]
|
106
|
+
ip = options[:ip] if key == :private_network
|
107
|
+
next if ip
|
108
|
+
end
|
93
109
|
end
|
94
110
|
end
|
95
111
|
ip || (machine.ssh_info ? machine.ssh_info[:host] : nil)
|
@@ -110,6 +126,45 @@ module VagrantPlugins
|
|
110
126
|
@global_env.active_machines
|
111
127
|
end
|
112
128
|
end
|
129
|
+
|
130
|
+
## Windows support for copying files, requesting elevated privileges if necessary
|
131
|
+
module WindowsSupport
|
132
|
+
require 'rbconfig'
|
133
|
+
|
134
|
+
def self.windows?
|
135
|
+
RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
136
|
+
end
|
137
|
+
|
138
|
+
require 'win32ole' if windows?
|
139
|
+
|
140
|
+
def windows_copy_file(source, dest)
|
141
|
+
begin
|
142
|
+
# First, try Ruby copy
|
143
|
+
FileUtils.cp(source, dest)
|
144
|
+
rescue Errno::EACCES
|
145
|
+
# Access denied, try with elevated privileges
|
146
|
+
windows_copy_file_elevated(source, dest)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
def windows_copy_file_elevated(source, dest)
|
153
|
+
# copy command only supports backslashes as separators
|
154
|
+
source, dest = [source, dest].map { |s| s.to_s.gsub(/\//, '\\') }
|
155
|
+
|
156
|
+
# run 'cmd /C copy ...' with elevated privilege, minimized
|
157
|
+
copy_cmd = "copy \"#{source}\" \"#{dest}\""
|
158
|
+
WIN32OLE.new('Shell.Application').ShellExecute('cmd', "/C #{copy_cmd}", nil, 'runas', 7)
|
159
|
+
|
160
|
+
# Unfortunately, ShellExecute does not give us a status code,
|
161
|
+
# and it is non-blocking so we can't reliably compare the file contents
|
162
|
+
# to see if they were copied.
|
163
|
+
#
|
164
|
+
# If the user rejects the UAC prompt, vagrant will silently continue
|
165
|
+
# without updating the hostsfile.
|
166
|
+
end
|
167
|
+
end
|
113
168
|
end
|
114
169
|
end
|
115
170
|
end
|
data/locales/en.yml
CHANGED
@@ -7,3 +7,4 @@ en:
|
|
7
7
|
config:
|
8
8
|
not_a_bool: "A value for %{config_key} can only be true or false, not type '%{value}'"
|
9
9
|
not_an_array_or_string: "A value for %{config_key} must be an Array or String, not type '%{is_class}'"
|
10
|
+
not_a_proc: "A value for %{config_key} must be a Proc, not type '%{is_class}'"
|
data/vagrant-hostmanager.gemspec
CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.email = ['shawn@dahlen.me']
|
12
12
|
gem.description = %q{A Vagrant plugin that manages the /etc/hosts file within a multi-machine environment}
|
13
13
|
gem.summary = gem.description
|
14
|
+
gem.license = 'MIT'
|
14
15
|
|
15
16
|
gem.files = `git ls-files`.split($/)
|
16
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-hostmanager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -73,7 +73,8 @@ files:
|
|
73
73
|
- test/test.sh
|
74
74
|
- vagrant-hostmanager.gemspec
|
75
75
|
homepage:
|
76
|
-
licenses:
|
76
|
+
licenses:
|
77
|
+
- MIT
|
77
78
|
post_install_message:
|
78
79
|
rdoc_options: []
|
79
80
|
require_paths:
|