vagrant-hostmanager 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -2
- data/README.md +3 -3
- data/lib/vagrant-hostmanager/action/update_all.rb +6 -12
- data/lib/vagrant-hostmanager/action/update_guest.rb +4 -13
- data/lib/vagrant-hostmanager/action/update_host.rb +9 -15
- data/lib/vagrant-hostmanager/command.rb +5 -1
- data/lib/vagrant-hostmanager/hosts_file/updater.rb +205 -0
- data/lib/vagrant-hostmanager/provisioner.rb +7 -13
- data/lib/vagrant-hostmanager/util.rb +14 -0
- data/lib/vagrant-hostmanager/version.rb +1 -1
- metadata +5 -4
- data/lib/vagrant-hostmanager/hosts_file.rb +0 -195
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4140a59a7a487a11e115847cd60c1d6d1ca2ca4
|
4
|
+
data.tar.gz: 93c851ddc092c8720c523db1b59848830864d6c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f5f80c76f81ac426dd3f253ba64ea62b9f9b29b82c8aec5b516844ae7d752ec1252db1a067146e298c997364f616d5e5da639d250f7969ecf042f4f7573d1d0
|
7
|
+
data.tar.gz: 110477f3d3ac045f8fd673242bc24588a0627409befcfcc928999593adeb7867d1a3d94209e32f5ea98946669dd05838c54fe3109ae7be59981bc771d1816284
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.6.0
|
4
|
+
### Features
|
5
|
+
* splits hostnames across many lines [[#67](https://github.com/smdahlen/vagrant-hostmanager/pull/103)]
|
6
|
+
|
7
|
+
### Bug fixes
|
8
|
+
* show description for hostmanager when vagrant list-commands is triggered [[#105](https://github.com/smdahlen/vagrant-hostmanager/pull/105)]
|
9
|
+
|
10
|
+
### Miscelaneous
|
11
|
+
* extract old vagrant version compatibility code into util method [[#97](https://github.com/smdahlen/vagrant-hostmanager/pull/97)]
|
12
|
+
* migrate HostsFile code into its own class [[#98](https://github.com/smdahlen/vagrant-hostmanager/pull/97)]
|
13
|
+
|
14
|
+
[Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.5.0...v1.6.0)
|
15
|
+
|
16
|
+
|
3
17
|
## 1.5.0
|
4
18
|
### Features
|
5
19
|
* hostmanager now runs *before* provisioning takes place, on `up` action [[#73](https://github.com/smdahlen/vagrant-hostmanager/issues/73)]
|
@@ -13,7 +27,7 @@
|
|
13
27
|
### Miscelaneous
|
14
28
|
* add passwordless sudo instructions to README [[#95](https://github.com/smdahlen/vagrant-hostmanager/pull/95)]
|
15
29
|
|
16
|
-
[Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.4.0...v1.5.0)
|
30
|
+
[Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.4.0...v1.5.0)
|
17
31
|
|
18
32
|
|
19
33
|
## 1.4.0
|
@@ -27,7 +41,7 @@
|
|
27
41
|
* when multiple private_networks are configured, the first one is used [[#64](https://github.com/smdahlen/vagrant-hostmanager/pull/64)]
|
28
42
|
* destroyed machines are now removed from hosts file [[#52](https://github.com/smdahlen/vagrant-hostmanager/pull/52)]
|
29
43
|
|
30
|
-
[Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.3.0...v1.4.0)
|
44
|
+
[Full diff](https://github.com/smdahlen/vagrant-hostmanager/compare/v1.3.0...v1.4.0)
|
31
45
|
|
32
46
|
|
33
47
|
## 1.3.0
|
data/README.md
CHANGED
@@ -42,7 +42,7 @@ attribute to `true`.
|
|
42
42
|
|
43
43
|
A machine's IP address is defined by either the static IP for a private
|
44
44
|
network configuration or by the SSH host configuration. To disable
|
45
|
-
using the private network IP address, set `config.
|
45
|
+
using the private network IP address, set `config.hostmanager.ignore_private_ip`
|
46
46
|
to true.
|
47
47
|
|
48
48
|
A machine's host name is defined by `config.vm.hostname`. If this is not
|
@@ -72,8 +72,8 @@ end
|
|
72
72
|
|
73
73
|
### Provisioner
|
74
74
|
|
75
|
-
Starting at version 1.5.0,
|
76
|
-
would like hostmanager to run after or during your provisioning stage,
|
75
|
+
Starting at version 1.5.0, `vagrant up` runs hostmanager before any provisioning occurs.
|
76
|
+
If you would like hostmanager to run after or during your provisioning stage,
|
77
77
|
you can use hostmanager as a provisioner. This allows you to use the provisioning
|
78
78
|
order to ensure that hostmanager runs when desired. The provisioner will collect
|
79
79
|
hosts from boxes with the same provider as the running box.
|
@@ -1,24 +1,18 @@
|
|
1
|
-
require 'vagrant-hostmanager/hosts_file'
|
1
|
+
require 'vagrant-hostmanager/hosts_file/updater'
|
2
|
+
require 'vagrant-hostmanager/util'
|
2
3
|
|
3
4
|
module VagrantPlugins
|
4
5
|
module HostManager
|
5
6
|
module Action
|
6
7
|
class UpdateAll
|
7
|
-
include HostsFile
|
8
8
|
|
9
9
|
def initialize(app, env)
|
10
10
|
@app = app
|
11
11
|
@machine = env[:machine]
|
12
12
|
@global_env = @machine.env
|
13
13
|
@provider = @machine.provider_name
|
14
|
-
|
15
|
-
|
16
|
-
if Gem::Version.new(::Vagrant::VERSION) >= Gem::Version.new('1.5')
|
17
|
-
@config = @global_env.vagrantfile.config
|
18
|
-
else
|
19
|
-
@config = @global_env.config_global
|
20
|
-
end
|
21
|
-
|
14
|
+
@config = Util.get_config(@global_env)
|
15
|
+
@updater = HostsFile::Updater.new(@global_env, @provider)
|
22
16
|
@logger = Log4r::Logger.new('vagrant::hostmanager::update_all')
|
23
17
|
end
|
24
18
|
|
@@ -37,14 +31,14 @@ module VagrantPlugins
|
|
37
31
|
@global_env.active_machines.each do |name, p|
|
38
32
|
if p == @provider
|
39
33
|
machine = @global_env.machine(name, p)
|
40
|
-
update_guest(machine)
|
34
|
+
@updater.update_guest(machine)
|
41
35
|
end
|
42
36
|
end
|
43
37
|
|
44
38
|
# update /etc/hosts files on host if enabled
|
45
39
|
if @machine.config.hostmanager.manage_host?
|
46
40
|
env[:ui].info I18n.t('vagrant_hostmanager.action.update_host')
|
47
|
-
update_host
|
41
|
+
@updater.update_host
|
48
42
|
end
|
49
43
|
end
|
50
44
|
end
|
@@ -1,24 +1,15 @@
|
|
1
|
-
require 'vagrant-hostmanager/hosts_file'
|
1
|
+
require 'vagrant-hostmanager/hosts_file/updater'
|
2
|
+
require 'vagrant-hostmanager/util'
|
2
3
|
|
3
4
|
module VagrantPlugins
|
4
5
|
module HostManager
|
5
6
|
module Action
|
6
7
|
class UpdateGuest
|
7
|
-
include HostsFile
|
8
8
|
|
9
9
|
def initialize(app, env)
|
10
10
|
@app = app
|
11
11
|
@machine = env[:machine]
|
12
|
-
@
|
13
|
-
@provider = env[:provider]
|
14
|
-
|
15
|
-
# config_global is deprecated from v1.5
|
16
|
-
if Gem::Version.new(::Vagrant::VERSION) >= Gem::Version.new('1.5')
|
17
|
-
@config = @global_env.vagrantfile.config
|
18
|
-
else
|
19
|
-
@config = @global_env.config_global
|
20
|
-
end
|
21
|
-
|
12
|
+
@updater = HostsFile::Updater.new(@machine.env, env[:provider])
|
22
13
|
@logger = Log4r::Logger.new('vagrant::hostmanager::update_guest')
|
23
14
|
end
|
24
15
|
|
@@ -26,7 +17,7 @@ module VagrantPlugins
|
|
26
17
|
env[:ui].info I18n.t('vagrant_hostmanager.action.update_guest', {
|
27
18
|
:name => @machine.name
|
28
19
|
})
|
29
|
-
update_guest(@machine)
|
20
|
+
@updater.update_guest(@machine)
|
30
21
|
|
31
22
|
@app.call(env)
|
32
23
|
end
|
@@ -1,30 +1,25 @@
|
|
1
|
-
require 'vagrant-hostmanager/hosts_file'
|
1
|
+
require 'vagrant-hostmanager/hosts_file/updater'
|
2
|
+
require 'vagrant-hostmanager/util'
|
2
3
|
|
3
4
|
module VagrantPlugins
|
4
5
|
module HostManager
|
5
6
|
module Action
|
6
7
|
class UpdateHost
|
7
|
-
include HostsFile
|
8
8
|
|
9
9
|
def initialize(app, env)
|
10
10
|
@app = app
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@config = @global_env.vagrantfile.config
|
17
|
-
else
|
18
|
-
@config = @global_env.config_global
|
19
|
-
end
|
20
|
-
|
11
|
+
|
12
|
+
global_env = env[:global_env]
|
13
|
+
@config = Util.get_config(global_env)
|
14
|
+
@updater = HostsFile::Updater.new(global_env, env[:provider])
|
15
|
+
|
21
16
|
@logger = Log4r::Logger.new('vagrant::hostmanager::update_host')
|
22
17
|
end
|
23
18
|
|
24
19
|
def call(env)
|
25
20
|
if @config.hostmanager.manage_host?
|
26
21
|
env[:ui].info I18n.t('vagrant_hostmanager.action.update_host')
|
27
|
-
update_host
|
22
|
+
@updater.update_host
|
28
23
|
end
|
29
24
|
|
30
25
|
@app.call(env)
|
@@ -32,5 +27,4 @@ module VagrantPlugins
|
|
32
27
|
end
|
33
28
|
end
|
34
29
|
end
|
35
|
-
end
|
36
|
-
|
30
|
+
end
|
@@ -1,7 +1,11 @@
|
|
1
1
|
module VagrantPlugins
|
2
2
|
module HostManager
|
3
3
|
class Command < Vagrant.plugin('2', :command)
|
4
|
-
|
4
|
+
|
5
|
+
# Show description when `vagrant list-commands` is triggered
|
6
|
+
def self.synopsis
|
7
|
+
"manages the /etc/hosts file within a multi-machine environment"
|
8
|
+
end
|
5
9
|
|
6
10
|
def execute
|
7
11
|
options = {}
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module HostManager
|
5
|
+
module HostsFile
|
6
|
+
|
7
|
+
class Updater
|
8
|
+
|
9
|
+
def initialize(global_env, provider)
|
10
|
+
@global_env = global_env
|
11
|
+
@config = Util.get_config(@global_env)
|
12
|
+
@provider = provider
|
13
|
+
end
|
14
|
+
|
15
|
+
def update_guest(machine)
|
16
|
+
return unless machine.communicate.ready?
|
17
|
+
|
18
|
+
if (machine.communicate.test("uname -s | grep SunOS"))
|
19
|
+
realhostfile = '/etc/inet/hosts'
|
20
|
+
move_cmd = 'mv'
|
21
|
+
elsif (machine.communicate.test("test -d $Env:SystemRoot"))
|
22
|
+
windir = ""
|
23
|
+
machine.communicate.execute("echo %SYSTEMROOT%", {:shell => :cmd}) do |type, contents|
|
24
|
+
windir << contents.gsub("\r\n", '') if type == :stdout
|
25
|
+
end
|
26
|
+
realhostfile = "#{windir}\\System32\\drivers\\etc\\hosts"
|
27
|
+
move_cmd = 'mv -force'
|
28
|
+
else
|
29
|
+
realhostfile = '/etc/hosts'
|
30
|
+
move_cmd = 'mv -f'
|
31
|
+
end
|
32
|
+
# download and modify file with Vagrant-managed entries
|
33
|
+
file = @global_env.tmp_path.join("hosts.#{machine.name}")
|
34
|
+
machine.communicate.download(realhostfile, file)
|
35
|
+
if update_file(file, machine, false)
|
36
|
+
|
37
|
+
# upload modified file and remove temporary file
|
38
|
+
machine.communicate.upload(file, '/tmp/hosts')
|
39
|
+
machine.communicate.sudo("#{move_cmd} /tmp/hosts #{realhostfile}")
|
40
|
+
end
|
41
|
+
|
42
|
+
# i have no idea if this is a windows competibility issue or not, but sometimes it dosen't work on my machine
|
43
|
+
begin
|
44
|
+
FileUtils.rm(file)
|
45
|
+
rescue Exception => e
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_host
|
50
|
+
# copy and modify hosts file on host with Vagrant-managed entries
|
51
|
+
file = @global_env.tmp_path.join('hosts.local')
|
52
|
+
|
53
|
+
if WindowsSupport.windows?
|
54
|
+
# lazily include windows Module
|
55
|
+
class << self
|
56
|
+
include WindowsSupport unless include? WindowsSupport
|
57
|
+
end
|
58
|
+
|
59
|
+
hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
|
60
|
+
copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
|
61
|
+
else
|
62
|
+
hosts_location = '/etc/hosts'
|
63
|
+
copy_proc = Proc.new { `sudo cp #{file} #{hosts_location}` }
|
64
|
+
end
|
65
|
+
|
66
|
+
FileUtils.cp(hosts_location, file)
|
67
|
+
if update_file(file)
|
68
|
+
copy_proc.call
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def update_file(file, resolving_machine = nil, include_id = true)
|
75
|
+
file = Pathname.new(file)
|
76
|
+
old_file_content = file.read
|
77
|
+
new_file_content = update_content(old_file_content, resolving_machine, include_id)
|
78
|
+
file.open('w') { |io| io.write(new_file_content) }
|
79
|
+
old_file_content != new_file_content
|
80
|
+
end
|
81
|
+
|
82
|
+
def update_content(file_content, resolving_machine, include_id)
|
83
|
+
id = include_id ? " id: #{read_or_create_id}" : ""
|
84
|
+
header = "## vagrant-hostmanager-start#{id}\n"
|
85
|
+
footer = "## vagrant-hostmanager-end\n"
|
86
|
+
body = get_machines
|
87
|
+
.map { |machine| get_hosts_file_entry(machine, resolving_machine) }
|
88
|
+
.join
|
89
|
+
get_new_content(header, footer, body, file_content)
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_hosts_file_entry(machine, resolving_machine)
|
93
|
+
ip = get_ip_address(machine, resolving_machine)
|
94
|
+
host = machine.config.vm.hostname || machine.name
|
95
|
+
aliases = machine.config.hostmanager.aliases
|
96
|
+
if ip != nil
|
97
|
+
"#{ip}\t#{host}\n" + aliases.map{|a| "#{ip}\t#{a}"}.join("\n") + "\n"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_ip_address(machine, resolving_machine)
|
102
|
+
custom_ip_resolver = machine.config.hostmanager.ip_resolver
|
103
|
+
if custom_ip_resolver
|
104
|
+
custom_ip_resolver.call(machine, resolving_machine)
|
105
|
+
else
|
106
|
+
ip = nil
|
107
|
+
if machine.config.hostmanager.ignore_private_ip != true
|
108
|
+
machine.config.vm.networks.each do |network|
|
109
|
+
key, options = network[0], network[1]
|
110
|
+
ip = options[:ip] if key == :private_network
|
111
|
+
break if ip
|
112
|
+
end
|
113
|
+
end
|
114
|
+
ip || (machine.ssh_info ? machine.ssh_info[:host] : nil)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def get_machines
|
119
|
+
if @config.hostmanager.include_offline?
|
120
|
+
machines = @global_env.machine_names
|
121
|
+
else
|
122
|
+
machines = @global_env.active_machines
|
123
|
+
.select { |name, provider| provider == @provider }
|
124
|
+
.collect { |name, provider| name }
|
125
|
+
end
|
126
|
+
# Collect only machines that exist for the current provider
|
127
|
+
machines.collect do |name|
|
128
|
+
begin
|
129
|
+
machine = @global_env.machine(name, @provider)
|
130
|
+
rescue Vagrant::Errors::MachineNotFound
|
131
|
+
# ignore
|
132
|
+
end
|
133
|
+
machine
|
134
|
+
end
|
135
|
+
.reject(&:nil?)
|
136
|
+
end
|
137
|
+
|
138
|
+
def get_new_content(header, footer, body, old_content)
|
139
|
+
if body.empty?
|
140
|
+
block = "\n"
|
141
|
+
else
|
142
|
+
block = "\n\n" + header + body + footer + "\n"
|
143
|
+
end
|
144
|
+
# Pattern for finding existing block
|
145
|
+
header_pattern = Regexp.quote(header)
|
146
|
+
footer_pattern = Regexp.quote(footer)
|
147
|
+
pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE)
|
148
|
+
# Replace existing block or append
|
149
|
+
old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block
|
150
|
+
end
|
151
|
+
|
152
|
+
def read_or_create_id
|
153
|
+
file = Pathname.new("#{@global_env.local_data_path}/hostmanager/id")
|
154
|
+
if (file.file?)
|
155
|
+
id = file.read.strip
|
156
|
+
else
|
157
|
+
id = SecureRandom.uuid
|
158
|
+
file.dirname.mkpath
|
159
|
+
file.open('w') { |io| io.write(id) }
|
160
|
+
end
|
161
|
+
id
|
162
|
+
end
|
163
|
+
|
164
|
+
## Windows support for copying files, requesting elevated privileges if necessary
|
165
|
+
module WindowsSupport
|
166
|
+
require 'rbconfig'
|
167
|
+
|
168
|
+
def self.windows?
|
169
|
+
RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
170
|
+
end
|
171
|
+
|
172
|
+
require 'win32ole' if windows?
|
173
|
+
|
174
|
+
def windows_copy_file(source, dest)
|
175
|
+
begin
|
176
|
+
# First, try Ruby copy
|
177
|
+
FileUtils.cp(source, dest)
|
178
|
+
rescue Errno::EACCES
|
179
|
+
# Access denied, try with elevated privileges
|
180
|
+
windows_copy_file_elevated(source, dest)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def windows_copy_file_elevated(source, dest)
|
187
|
+
# copy command only supports backslashes as separators
|
188
|
+
source, dest = [source, dest].map { |s| s.to_s.gsub(/\//, '\\') }
|
189
|
+
|
190
|
+
# run 'cmd /C copy ...' with elevated privilege, minimized
|
191
|
+
copy_cmd = "copy \"#{source}\" \"#{dest}\""
|
192
|
+
WIN32OLE.new('Shell.Application').ShellExecute('cmd', "/C #{copy_cmd}", nil, 'runas', 7)
|
193
|
+
|
194
|
+
# Unfortunately, ShellExecute does not give us a status code,
|
195
|
+
# and it is non-blocking so we can't reliably compare the file contents
|
196
|
+
# to see if they were copied.
|
197
|
+
#
|
198
|
+
# If the user rejects the UAC prompt, vagrant will silently continue
|
199
|
+
# without updating the hostsfile.
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -1,26 +1,20 @@
|
|
1
|
+
require 'vagrant-hostmanager/hosts_file/updater'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module HostManager
|
3
5
|
class Provisioner < Vagrant.plugin('2', :provisioner)
|
4
|
-
include HostsFile
|
5
6
|
|
6
7
|
def initialize(machine, config)
|
7
8
|
super(machine, config)
|
8
|
-
|
9
|
-
@
|
10
|
-
|
11
|
-
# config_global is deprecated from v1.5
|
12
|
-
if Gem::Version.new(::Vagrant::VERSION) >= Gem::Version.new('1.5')
|
13
|
-
@config = @global_env.vagrantfile.config
|
14
|
-
else
|
15
|
-
@config = @global_env.config_global
|
16
|
-
end
|
17
|
-
|
9
|
+
global_env = machine.env
|
10
|
+
@config = Util.get_config(global_env)
|
11
|
+
@updater = HostsFile::Updater.new(global_env, machine.provider_name)
|
18
12
|
end
|
19
13
|
|
20
14
|
def provision
|
21
|
-
update_guest(@machine)
|
15
|
+
@updater.update_guest(@machine)
|
22
16
|
if @config.hostmanager.manage_host?
|
23
|
-
update_host
|
17
|
+
@updater.update_host
|
24
18
|
end
|
25
19
|
end
|
26
20
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module HostManager
|
3
|
+
module Util
|
4
|
+
def self.get_config(env)
|
5
|
+
# config_global has been removed from v1.5
|
6
|
+
if Gem::Version.new(::Vagrant::VERSION) >= Gem::Version.new('1.5')
|
7
|
+
env.vagrantfile.config
|
8
|
+
else
|
9
|
+
env.config_global
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-hostmanager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shawn Dahlen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -60,9 +60,10 @@ files:
|
|
60
60
|
- lib/vagrant-hostmanager/command.rb
|
61
61
|
- lib/vagrant-hostmanager/config.rb
|
62
62
|
- lib/vagrant-hostmanager/errors.rb
|
63
|
-
- lib/vagrant-hostmanager/hosts_file.rb
|
63
|
+
- lib/vagrant-hostmanager/hosts_file/updater.rb
|
64
64
|
- lib/vagrant-hostmanager/plugin.rb
|
65
65
|
- lib/vagrant-hostmanager/provisioner.rb
|
66
|
+
- lib/vagrant-hostmanager/util.rb
|
66
67
|
- lib/vagrant-hostmanager/version.rb
|
67
68
|
- locales/en.yml
|
68
69
|
- test/Vagrantfile
|
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
89
|
version: '0'
|
89
90
|
requirements: []
|
90
91
|
rubyforge_project:
|
91
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.4.6
|
92
93
|
signing_key:
|
93
94
|
specification_version: 4
|
94
95
|
summary: A Vagrant plugin that manages the /etc/hosts file within a multi-machine
|
@@ -1,195 +0,0 @@
|
|
1
|
-
require 'tempfile'
|
2
|
-
|
3
|
-
module VagrantPlugins
|
4
|
-
module HostManager
|
5
|
-
module HostsFile
|
6
|
-
def update_guest(machine)
|
7
|
-
return unless machine.communicate.ready?
|
8
|
-
|
9
|
-
if (machine.communicate.test("uname -s | grep SunOS"))
|
10
|
-
realhostfile = '/etc/inet/hosts'
|
11
|
-
move_cmd = 'mv'
|
12
|
-
elsif (machine.communicate.test("test -d $Env:SystemRoot"))
|
13
|
-
windir = ""
|
14
|
-
machine.communicate.execute("echo %SYSTEMROOT%", {:shell => :cmd}) do |type, contents|
|
15
|
-
windir << contents.gsub("\r\n", '') if type == :stdout
|
16
|
-
end
|
17
|
-
realhostfile = "#{windir}\\System32\\drivers\\etc\\hosts"
|
18
|
-
move_cmd = 'mv -force'
|
19
|
-
else
|
20
|
-
realhostfile = '/etc/hosts'
|
21
|
-
move_cmd = 'mv -f'
|
22
|
-
end
|
23
|
-
# download and modify file with Vagrant-managed entries
|
24
|
-
file = @global_env.tmp_path.join("hosts.#{machine.name}")
|
25
|
-
machine.communicate.download(realhostfile, file)
|
26
|
-
if update_file(file, machine, false)
|
27
|
-
|
28
|
-
# upload modified file and remove temporary file
|
29
|
-
machine.communicate.upload(file, '/tmp/hosts')
|
30
|
-
machine.communicate.sudo("#{move_cmd} /tmp/hosts #{realhostfile}")
|
31
|
-
end
|
32
|
-
|
33
|
-
# i have no idea if this is a windows competibility issue or not, but sometimes it dosen't work on my machine
|
34
|
-
begin
|
35
|
-
FileUtils.rm(file)
|
36
|
-
rescue Exception => e
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def update_host
|
41
|
-
# copy and modify hosts file on host with Vagrant-managed entries
|
42
|
-
file = @global_env.tmp_path.join('hosts.local')
|
43
|
-
|
44
|
-
if WindowsSupport.windows?
|
45
|
-
# lazily include windows Module
|
46
|
-
class << self
|
47
|
-
include WindowsSupport unless include? WindowsSupport
|
48
|
-
end
|
49
|
-
|
50
|
-
hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
|
51
|
-
copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
|
52
|
-
else
|
53
|
-
hosts_location = '/etc/hosts'
|
54
|
-
copy_proc = Proc.new { `sudo cp #{file} #{hosts_location}` }
|
55
|
-
end
|
56
|
-
|
57
|
-
FileUtils.cp(hosts_location, file)
|
58
|
-
if update_file(file)
|
59
|
-
copy_proc.call
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def update_file(file, resolving_machine = nil, include_id = true)
|
66
|
-
file = Pathname.new(file)
|
67
|
-
old_file_content = file.read
|
68
|
-
new_file_content = update_content(old_file_content, resolving_machine, include_id)
|
69
|
-
file.open('w') { |io| io.write(new_file_content) }
|
70
|
-
old_file_content != new_file_content
|
71
|
-
end
|
72
|
-
|
73
|
-
def update_content(file_content, resolving_machine, include_id)
|
74
|
-
id = include_id ? " id: #{read_or_create_id}" : ""
|
75
|
-
header = "## vagrant-hostmanager-start#{id}\n"
|
76
|
-
footer = "## vagrant-hostmanager-end\n"
|
77
|
-
body = get_machines
|
78
|
-
.map { |machine| get_hosts_file_entry(machine, resolving_machine) }
|
79
|
-
.join
|
80
|
-
get_new_content(header, footer, body, file_content)
|
81
|
-
end
|
82
|
-
|
83
|
-
def get_hosts_file_entry(machine, resolving_machine)
|
84
|
-
ip = get_ip_address(machine, resolving_machine)
|
85
|
-
host = machine.config.vm.hostname || machine.name
|
86
|
-
aliases = machine.config.hostmanager.aliases.join(' ').chomp
|
87
|
-
if ip != nil
|
88
|
-
"#{ip}\t#{host} #{aliases}\n"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def get_ip_address(machine, resolving_machine)
|
93
|
-
custom_ip_resolver = machine.config.hostmanager.ip_resolver
|
94
|
-
if custom_ip_resolver
|
95
|
-
custom_ip_resolver.call(machine, resolving_machine)
|
96
|
-
else
|
97
|
-
ip = nil
|
98
|
-
if machine.config.hostmanager.ignore_private_ip != true
|
99
|
-
machine.config.vm.networks.each do |network|
|
100
|
-
key, options = network[0], network[1]
|
101
|
-
ip = options[:ip] if key == :private_network
|
102
|
-
break if ip
|
103
|
-
end
|
104
|
-
end
|
105
|
-
ip || (machine.ssh_info ? machine.ssh_info[:host] : nil)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def get_machines
|
110
|
-
if @config.hostmanager.include_offline?
|
111
|
-
machines = @global_env.machine_names
|
112
|
-
else
|
113
|
-
machines = @global_env.active_machines
|
114
|
-
.select { |name, provider| provider == @provider }
|
115
|
-
.collect { |name, provider| name }
|
116
|
-
end
|
117
|
-
# Collect only machines that exist for the current provider
|
118
|
-
machines.collect do |name|
|
119
|
-
begin
|
120
|
-
machine = @global_env.machine(name, @provider)
|
121
|
-
rescue Vagrant::Errors::MachineNotFound
|
122
|
-
# ignore
|
123
|
-
end
|
124
|
-
machine
|
125
|
-
end
|
126
|
-
.reject(&:nil?)
|
127
|
-
end
|
128
|
-
|
129
|
-
def get_new_content(header, footer, body, old_content)
|
130
|
-
if body.empty?
|
131
|
-
block = "\n"
|
132
|
-
else
|
133
|
-
block = "\n\n" + header + body + footer + "\n"
|
134
|
-
end
|
135
|
-
# Pattern for finding existing block
|
136
|
-
header_pattern = Regexp.quote(header)
|
137
|
-
footer_pattern = Regexp.quote(footer)
|
138
|
-
pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE)
|
139
|
-
# Replace existing block or append
|
140
|
-
old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block
|
141
|
-
end
|
142
|
-
|
143
|
-
def read_or_create_id
|
144
|
-
file = Pathname.new("#{@global_env.local_data_path}/hostmanager/id")
|
145
|
-
if (file.file?)
|
146
|
-
id = file.read.strip
|
147
|
-
else
|
148
|
-
id = SecureRandom.uuid
|
149
|
-
file.dirname.mkpath
|
150
|
-
file.open('w') { |io| io.write(id) }
|
151
|
-
end
|
152
|
-
id
|
153
|
-
end
|
154
|
-
|
155
|
-
## Windows support for copying files, requesting elevated privileges if necessary
|
156
|
-
module WindowsSupport
|
157
|
-
require 'rbconfig'
|
158
|
-
|
159
|
-
def self.windows?
|
160
|
-
RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
161
|
-
end
|
162
|
-
|
163
|
-
require 'win32ole' if windows?
|
164
|
-
|
165
|
-
def windows_copy_file(source, dest)
|
166
|
-
begin
|
167
|
-
# First, try Ruby copy
|
168
|
-
FileUtils.cp(source, dest)
|
169
|
-
rescue Errno::EACCES
|
170
|
-
# Access denied, try with elevated privileges
|
171
|
-
windows_copy_file_elevated(source, dest)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
private
|
176
|
-
|
177
|
-
def windows_copy_file_elevated(source, dest)
|
178
|
-
# copy command only supports backslashes as separators
|
179
|
-
source, dest = [source, dest].map { |s| s.to_s.gsub(/\//, '\\') }
|
180
|
-
|
181
|
-
# run 'cmd /C copy ...' with elevated privilege, minimized
|
182
|
-
copy_cmd = "copy \"#{source}\" \"#{dest}\""
|
183
|
-
WIN32OLE.new('Shell.Application').ShellExecute('cmd', "/C #{copy_cmd}", nil, 'runas', 7)
|
184
|
-
|
185
|
-
# Unfortunately, ShellExecute does not give us a status code,
|
186
|
-
# and it is non-blocking so we can't reliably compare the file contents
|
187
|
-
# to see if they were copied.
|
188
|
-
#
|
189
|
-
# If the user rejects the UAC prompt, vagrant will silently continue
|
190
|
-
# without updating the hostsfile.
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|