vagrant-hostmanager 1.5.0 → 1.6.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.
- 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
|