vagrant-hostmanager 1.2.3 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|