rethinc-vagrant-hostmanager 1.8.9.1

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.
@@ -0,0 +1,222 @@
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
+ @logger = Log4r::Logger.new('vagrant::hostmanager::updater')
14
+ @logger.debug("init updater")
15
+ end
16
+
17
+ def update_guest(machine)
18
+ return unless machine.communicate.ready?
19
+
20
+ if (machine.communicate.test("uname -s | grep SunOS"))
21
+ realhostfile = "/etc/inet/hosts"
22
+ is_windows = false
23
+ elsif (machine.communicate.test("test -d $Env:SystemRoot"))
24
+ windir = ""
25
+ machine.communicate.execute("echo %SYSTEMROOT%", {:shell => :cmd}) do |type, contents|
26
+ windir << contents.gsub("\r\n", '') if type == :stdout
27
+ end
28
+ realhostfile = "#{windir}\\System32\\drivers\\etc\\hosts"
29
+ is_windows = true
30
+ else
31
+ realhostfile = "/etc/hosts"
32
+ is_windows = false
33
+ end
34
+
35
+ # download and modify file with Vagrant-managed entries
36
+ file = @global_env.tmp_path.join("hosts.#{machine.name}")
37
+ machine.communicate.download(realhostfile, file)
38
+
39
+ @logger.debug("file is: #{file.to_s}")
40
+ @logger.debug("class of file is: #{file.class}")
41
+
42
+ if update_file(file, machine, false, is_windows)
43
+ # upload modified file and remove temporary file
44
+ machine.communicate.upload(file.to_s, "/tmp/hosts.#{machine.name}")
45
+ if windir
46
+ machine.communicate.sudo("mv -force /tmp/hosts.#{machine.name} #{realhostfile}")
47
+ else
48
+ machine.communicate.sudo("cat /tmp/hosts.#{machine.name} > #{realhostfile} && rm -f /tmp/hosts.#{machine.name}")
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ def update_host
55
+ # copy and modify hosts file on host with Vagrant-managed entries
56
+ file = @global_env.tmp_path.join('hosts.local')
57
+
58
+ if WindowsSupport.windows?
59
+ # lazily include windows Module
60
+ class << self
61
+ include WindowsSupport unless include? WindowsSupport
62
+ end
63
+ hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts"
64
+ copy_proc = Proc.new { windows_copy_file(file, hosts_location) }
65
+ is_windows = true
66
+ else
67
+ hosts_location = '/etc/hosts'
68
+ copy_proc = Proc.new { `[ -w "#{hosts_location}" ] && cat "#{file}" > "#{hosts_location}" || sudo cp "#{file}" "#{hosts_location}"` }
69
+ is_windows = false
70
+ end
71
+
72
+ FileUtils.cp(hosts_location, file)
73
+
74
+ if update_file(file, nil, true, is_windows)
75
+ copy_proc.call
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def update_file(file, resolving_machine = nil, include_id = true, is_windows)
82
+ file = Pathname.new(file)
83
+ old_file_content = file.read
84
+ # Don't care what's been read by Pathname, just convert to universal line endings for comparison
85
+ old_file_content = old_file_content.encode(old_file_content.encoding, universal_newline: true)
86
+ new_file_content = update_content(old_file_content, resolving_machine, include_id)
87
+ is_hosts_file_changed = (old_file_content != new_file_content)
88
+
89
+ if is_hosts_file_changed
90
+ if is_windows
91
+ new_file_content = new_file_content.encode(new_file_content.encoding, :crlf_newline => true)
92
+ end
93
+
94
+ file.open('wb') { |io| io.write(new_file_content) }
95
+ end
96
+ is_hosts_file_changed
97
+ end
98
+
99
+ def update_content(file_content, resolving_machine, include_id)
100
+ id = include_id ? " id: #{read_or_create_id}" : ""
101
+ header = "## vagrant-hostmanager-start#{id}"
102
+ footer = "## vagrant-hostmanager-end"
103
+ body = get_machines
104
+ .map { |machine| get_hosts_file_entry(machine, resolving_machine) }
105
+ .join
106
+ get_new_content(header, footer, body, file_content)
107
+ end
108
+
109
+ def get_hosts_file_entry(machine, resolving_machine)
110
+ ip = get_ip_address(machine, resolving_machine)
111
+ host = machine.config.vm.hostname || machine.name
112
+ aliases = machine.config.hostmanager.aliases
113
+ if ip != nil
114
+ "#{ip}\t#{host}\n" + aliases.map{|a| "#{ip}\t#{a}"}.join("\n") + "\n"
115
+ end
116
+ end
117
+
118
+ def get_ip_address(machine, resolving_machine)
119
+ custom_ip_resolver = machine.config.hostmanager.ip_resolver
120
+ if custom_ip_resolver
121
+ custom_ip_resolver.call(machine, resolving_machine)
122
+ else
123
+ ip = nil
124
+ if machine.config.hostmanager.ignore_private_ip != true
125
+ machine.config.vm.networks.each do |network|
126
+ key, options = network[0], network[1]
127
+ ip = options[:ip] if key == :private_network
128
+ break if ip
129
+ end
130
+ end
131
+ ip || (machine.ssh_info ? machine.ssh_info[:host] : nil)
132
+ end
133
+ end
134
+
135
+ def get_machines
136
+ if @config.hostmanager.include_offline?
137
+ machines = @global_env.machine_names
138
+ else
139
+ machines = @global_env.active_machines
140
+ .select { |name, provider| provider == @provider }
141
+ .collect { |name, provider| name }
142
+ end
143
+ # Collect only machines that exist for the current provider
144
+ machines.collect do |name|
145
+ begin
146
+ machine = @global_env.machine(name, @provider)
147
+ rescue Vagrant::Errors::MachineNotFound
148
+ # ignore
149
+ end
150
+ machine
151
+ end
152
+ .reject(&:nil?)
153
+ end
154
+
155
+ def get_new_content(header, footer, body, old_content)
156
+ if body.empty?
157
+ block = "\n"
158
+ else
159
+ block = "\n\n" + header + "\n" + body + footer + "\n\n"
160
+ end
161
+ # Pattern for finding existing block
162
+ header_pattern = Regexp.quote(header)
163
+ footer_pattern = Regexp.quote(footer)
164
+ pattern = Regexp.new("[\n]*#{header_pattern}.*?#{footer_pattern}[\n]*", Regexp::MULTILINE)
165
+ # Replace existing block or append
166
+ content = old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block
167
+ end
168
+
169
+ def read_or_create_id
170
+ file = Pathname.new("#{@global_env.local_data_path}/hostmanager/id")
171
+ if (file.file?)
172
+ id = file.read.strip
173
+ else
174
+ id = SecureRandom.uuid
175
+ file.dirname.mkpath
176
+ file.open('w') { |io| io.write(id) }
177
+ end
178
+ id
179
+ end
180
+
181
+ ## Windows support for copying files, requesting elevated privileges if necessary
182
+ module WindowsSupport
183
+ require 'rbconfig'
184
+
185
+ def self.windows?
186
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
187
+ end
188
+
189
+ require 'win32ole' if windows?
190
+
191
+ def windows_copy_file(source, dest)
192
+ begin
193
+ # First, try Ruby copy
194
+ FileUtils.cp(source, dest)
195
+ rescue Errno::EACCES
196
+ # Access denied, try with elevated privileges
197
+ windows_copy_file_elevated(source, dest)
198
+ end
199
+ end
200
+
201
+ private
202
+
203
+ def windows_copy_file_elevated(source, dest)
204
+ # copy command only supports backslashes as separators
205
+ source, dest = [source, dest].map { |s| s.to_s.gsub(/\//, '\\') }
206
+
207
+ # run 'cmd /C copy ...' with elevated privilege, minimized
208
+ copy_cmd = "copy \"#{source}\" \"#{dest}\""
209
+ WIN32OLE.new('Shell.Application').ShellExecute('cmd', "/C #{copy_cmd}", nil, 'runas', 7)
210
+
211
+ # Unfortunately, ShellExecute does not give us a status code,
212
+ # and it is non-blocking so we can't reliably compare the file contents
213
+ # to see if they were copied.
214
+ #
215
+ # If the user rejects the UAC prompt, vagrant will silently continue
216
+ # without updating the hostsfile.
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,44 @@
1
+ require 'vagrant-hostmanager/action'
2
+
3
+ module VagrantPlugins
4
+ module HostManager
5
+ class Plugin < Vagrant.plugin('2')
6
+ name 'HostManager'
7
+ description <<-DESC
8
+ This plugin manages the /etc/hosts file for the host and guest machines.
9
+ An entry is created for each running machine using the hostname attribute.
10
+
11
+ You can also use the hostmanager provisioner to update the hosts file.
12
+ DESC
13
+
14
+ config(:hostmanager) do
15
+ require_relative 'config'
16
+ Config
17
+ end
18
+
19
+ action_hook(:hostmanager, :machine_action_up) do |hook|
20
+ hook.after(Vagrant::Action::Builtin::Provision, Action.update_all)
21
+ end
22
+
23
+ action_hook(:hostmanager, :machine_action_destroy) do |hook|
24
+ hook.prepend(Action.update_all)
25
+ end
26
+
27
+ provisioner(:hostmanager) do
28
+ require_relative 'provisioner'
29
+ Provisioner
30
+ end
31
+
32
+ # Work-around for vagrant >= 1.5
33
+ # It breaks without a provisioner config, so we provide a dummy one
34
+ config(:hostmanager, :provisioner) do
35
+ ::Vagrant::Config::V2::DummyConfig.new
36
+ end
37
+
38
+ command(:hostmanager) do
39
+ require_relative 'command'
40
+ Command
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,24 @@
1
+ require 'vagrant-hostmanager/hosts_file/updater'
2
+
3
+ module VagrantPlugins
4
+ module HostManager
5
+ class Provisioner < Vagrant.plugin('2', :provisioner)
6
+
7
+ def initialize(machine, config)
8
+ super(machine, config)
9
+ global_env = machine.env
10
+ @config = Util.get_config(global_env)
11
+ @updater = HostsFile::Updater.new(global_env, machine.provider_name)
12
+ end
13
+
14
+ def provision
15
+ if @config.hostmanager.manage_guest?
16
+ @updater.update_guest(@machine)
17
+ end
18
+ if @config.hostmanager.manage_host?
19
+ @updater.update_host
20
+ end
21
+ end
22
+ end
23
+ end
24
+ 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
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module HostManager
3
+ VERSION = '1.8.9.1'
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ require 'vagrant-hostmanager/plugin'
2
+ require 'vagrant-hostmanager/version'
3
+ require 'vagrant-hostmanager/errors'
4
+
5
+ module VagrantPlugins
6
+ module HostManager
7
+ def self.source_root
8
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
9
+ end
10
+
11
+ I18n.load_path << File.expand_path('locales/en.yml', source_root)
12
+ I18n.reload!
13
+ end
14
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,10 @@
1
+ en:
2
+ vagrant_hostmanager:
3
+ action:
4
+ update_guests: "[vagrant-hostmanager:guests] Updating hosts file on active guest virtual machines..."
5
+ update_guest: "[vagrant-hostmanager:guest] Updating hosts file on the virtual machine %{name}..."
6
+ update_host: "[vagrant-hostmanager:host] Updating hosts file on your workstation (password may be required)..."
7
+ config:
8
+ not_a_bool: "[vagrant-hostmanager:config:error] A value for %{config_key} can only be true or false, not type '%{value}'"
9
+ not_an_array_or_string: "[vagrant-hostmanager:config:error] A value for %{config_key} must be an Array or String, not type '%{is_class}'"
10
+ not_a_proc: "[vagrant-hostmanager:config:error] A value for %{config_key} must be a Proc, not type '%{is_class}'"
data/test/Vagrantfile ADDED
@@ -0,0 +1,42 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ if Gem::Version.new(::Vagrant::VERSION) < Gem::Version.new('1.5')
5
+ Vagrant.require_plugin('vagrant-hostmanager')
6
+ end
7
+
8
+ Vagrant.configure('2') do |config|
9
+
10
+ if ENV.key? 'VAGRANT_BOX'
11
+ config.vm.box = ENV['VAGRANT_BOX']
12
+ else
13
+ config.vm.box = 'precise64'
14
+ config.vm.box_url = 'http://cloud-images.ubuntu.com/precise/current/precise-server-cloudimg-vagrant-amd64-disk1.box'
15
+ end
16
+
17
+ config.hostmanager.enabled = true
18
+ config.hostmanager.manage_host = true
19
+ config.hostmanager.manage_guest = true
20
+
21
+ config.vm.define :server1 do |server|
22
+ server.vm.hostname = 'fry'
23
+ server.vm.network :private_network, :ip => '10.0.5.2'
24
+ server.hostmanager.aliases = %w(test-alias)
25
+ end
26
+
27
+ config.vm.define :server2 do |server|
28
+ server.vm.hostname = 'bender'
29
+ server.vm.network :private_network, :ip => '10.0.5.3'
30
+ end
31
+
32
+ config.vm.define :server3 do |server|
33
+ server.vm.hostname = 'leena'
34
+ server.vm.network :private_network, :ip => '10.0.5.4'
35
+ server.vm.provision :hostmanager
36
+ end
37
+
38
+ config.vm.define :server4 do |server|
39
+ server.vm.hostname = 'scruffy'
40
+ server.vm.provision :hostmanager
41
+ end
42
+ end
data/test/test.sh ADDED
@@ -0,0 +1,14 @@
1
+ cd test
2
+
3
+ vagrant up
4
+
5
+ vagrant hostmanager
6
+
7
+ echo "[server1] /etc/hosts file:"
8
+ vagrant ssh server1 -c 'cat /etc/hosts'
9
+ echo "[server2] /etc/hosts file:"
10
+ vagrant ssh server2 -c 'cat /etc/hosts'
11
+
12
+ vagrant destroy -f
13
+
14
+ cd ..
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'vagrant-hostmanager/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'rethinc-vagrant-hostmanager'
9
+ gem.version = VagrantPlugins::HostManager::VERSION
10
+ gem.authors = ['Shawn Dahlen','Seth Reeser']
11
+ gem.email = ['shawn@dahlen.me','info@devopsgroup.io']
12
+ gem.description = %q{A Vagrant plugin that manages the /etc/hosts file within a multi-machine environment}
13
+ gem.summary = gem.description
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_development_dependency 'bundler', '~> 1.3'
21
+ gem.add_development_dependency 'rake'
22
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rethinc-vagrant-hostmanager
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.8.9.1
5
+ platform: ruby
6
+ authors:
7
+ - Shawn Dahlen
8
+ - Seth Reeser
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2022-09-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: A Vagrant plugin that manages the /etc/hosts file within a multi-machine
43
+ environment
44
+ email:
45
+ - shawn@dahlen.me
46
+ - info@devopsgroup.io
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - ".gitignore"
52
+ - CHANGELOG.md
53
+ - Gemfile
54
+ - LICENSE
55
+ - README.md
56
+ - Rakefile
57
+ - lib/vagrant-hostmanager.rb
58
+ - lib/vagrant-hostmanager/action.rb
59
+ - lib/vagrant-hostmanager/action/update_all.rb
60
+ - lib/vagrant-hostmanager/action/update_guest.rb
61
+ - lib/vagrant-hostmanager/action/update_host.rb
62
+ - lib/vagrant-hostmanager/command.rb
63
+ - lib/vagrant-hostmanager/config.rb
64
+ - lib/vagrant-hostmanager/errors.rb
65
+ - lib/vagrant-hostmanager/hosts_file/updater.rb
66
+ - lib/vagrant-hostmanager/plugin.rb
67
+ - lib/vagrant-hostmanager/provisioner.rb
68
+ - lib/vagrant-hostmanager/util.rb
69
+ - lib/vagrant-hostmanager/version.rb
70
+ - locales/en.yml
71
+ - test/Vagrantfile
72
+ - test/test.sh
73
+ - vagrant-hostmanager.gemspec
74
+ homepage:
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubygems_version: 3.1.6
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: A Vagrant plugin that manages the /etc/hosts file within a multi-machine
97
+ environment
98
+ test_files:
99
+ - test/Vagrantfile
100
+ - test/test.sh