vagrant-hostmanager-rethinc 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,221 @@
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-rethinc::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
+ file.open('wb') { |io| io.write(new_file_content) }
94
+ end
95
+ is_hosts_file_changed
96
+ end
97
+
98
+ def update_content(file_content, resolving_machine, include_id)
99
+ id = include_id ? " id: #{read_or_create_id}" : ""
100
+ header = "## vagrant-hostmanager-rethinc-start#{id}"
101
+ footer = "## vagrant-hostmanager-rethinc-end"
102
+ body = get_machines
103
+ .map { |machine| get_hosts_file_entry(machine, resolving_machine) }
104
+ .join
105
+ get_new_content(header, footer, body, file_content)
106
+ end
107
+
108
+ def get_hosts_file_entry(machine, resolving_machine)
109
+ ip = get_ip_address(machine, resolving_machine)
110
+ host = machine.config.vm.hostname || machine.name
111
+ aliases = machine.config.hostmanager.aliases
112
+ if ip != nil
113
+ "#{ip}\t#{host}\n" + aliases.map{|a| "#{ip}\t#{a}"}.join("\n") + "\n"
114
+ end
115
+ end
116
+
117
+ def get_ip_address(machine, resolving_machine)
118
+ custom_ip_resolver = machine.config.hostmanager.ip_resolver
119
+ if custom_ip_resolver
120
+ custom_ip_resolver.call(machine, resolving_machine)
121
+ else
122
+ ip = nil
123
+ if machine.config.hostmanager.ignore_private_ip != true
124
+ machine.config.vm.networks.each do |network|
125
+ key, options = network[0], network[1]
126
+ ip = options[:ip] if key == :private_network
127
+ break if ip
128
+ end
129
+ end
130
+ ip || (machine.ssh_info ? machine.ssh_info[:host] : nil)
131
+ end
132
+ end
133
+
134
+ def get_machines
135
+ if @config.hostmanager.include_offline?
136
+ machines = @global_env.machine_names
137
+ else
138
+ machines = @global_env.active_machines
139
+ .select { |name, provider| provider == @provider }
140
+ .collect { |name, provider| name }
141
+ end
142
+ # Collect only machines that exist for the current provider
143
+ machines.collect do |name|
144
+ begin
145
+ machine = @global_env.machine(name, @provider)
146
+ rescue Vagrant::Errors::MachineNotFound
147
+ # ignore
148
+ end
149
+ machine
150
+ end
151
+ .reject(&:nil?)
152
+ end
153
+
154
+ def get_new_content(header, footer, body, old_content)
155
+ if body.empty?
156
+ block = "\n"
157
+ else
158
+ block = "\n\n" + header + "\n" + body + footer + "\n\n"
159
+ end
160
+ # Pattern for finding existing block
161
+ header_pattern = Regexp.quote(header)
162
+ footer_pattern = Regexp.quote(footer)
163
+ pattern = Regexp.new("[\n]*#{header_pattern}.*?#{footer_pattern}[\n]*", Regexp::MULTILINE)
164
+ # Replace existing block or append
165
+ content = old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block
166
+ end
167
+
168
+ def read_or_create_id
169
+ file = Pathname.new("#{@global_env.local_data_path}/hostmanager/id")
170
+ if (file.file?)
171
+ id = file.read.strip
172
+ else
173
+ id = SecureRandom.uuid
174
+ file.dirname.mkpath
175
+ file.open('w') { |io| io.write(id) }
176
+ end
177
+ id
178
+ end
179
+
180
+ ## Windows support for copying files, requesting elevated privileges if necessary
181
+ module WindowsSupport
182
+ require 'rbconfig'
183
+
184
+ def self.windows?
185
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
186
+ end
187
+
188
+ require 'win32ole' if windows?
189
+
190
+ def windows_copy_file(source, dest)
191
+ begin
192
+ # First, try Ruby copy
193
+ FileUtils.cp(source, dest)
194
+ rescue Errno::EACCES
195
+ # Access denied, try with elevated privileges
196
+ windows_copy_file_elevated(source, dest)
197
+ end
198
+ end
199
+
200
+ private
201
+
202
+ def windows_copy_file_elevated(source, dest)
203
+ # copy command only supports backslashes as separators
204
+ source, dest = [source, dest].map { |s| s.to_s.gsub(/\//, '\\') }
205
+
206
+ # run 'cmd /C copy ...' with elevated privilege, minimized
207
+ copy_cmd = "copy \"#{source}\" \"#{dest}\""
208
+ WIN32OLE.new('Shell.Application').ShellExecute('cmd', "/C #{copy_cmd}", nil, 'runas', 7)
209
+
210
+ # Unfortunately, ShellExecute does not give us a status code,
211
+ # and it is non-blocking so we can't reliably compare the file contents
212
+ # to see if they were copied.
213
+ #
214
+ # If the user rejects the UAC prompt, vagrant will silently continue
215
+ # without updating the hostsfile.
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,44 @@
1
+ require 'vagrant-hostmanager-rethinc/action'
2
+
3
+ module VagrantPlugins
4
+ module HostManager
5
+ class Plugin < Vagrant.plugin('2')
6
+ name 'HostManagerRethinc'
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-rethinc/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-rethinc/plugin'
2
+ require 'vagrant-hostmanager-rethinc/version'
3
+ require 'vagrant-hostmanager-rethinc/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-rethinc:guests] Updating hosts file on active guest virtual machines..."
5
+ update_guest: "[vagrant-hostmanager-rethinc:guest] Updating hosts file on the virtual machine %{name}..."
6
+ update_host: "[vagrant-hostmanager-rethinc:host] Updating hosts file on your workstation (password may be required)..."
7
+ config:
8
+ not_a_bool: "[vagrant-hostmanager-rethinc:config:error] A value for %{config_key} can only be true or false, not type '%{value}'"
9
+ not_an_array_or_string: "[vagrant-hostmanager-rethinc:config:error] A value for %{config_key} must be an Array or String, not type '%{is_class}'"
10
+ not_a_proc: "[vagrant-hostmanager-rethinc: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-rethinc')
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-rethinc/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'vagrant-hostmanager-rethinc'
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: vagrant-hostmanager-rethinc
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-11-23 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-rethinc.rb
58
+ - lib/vagrant-hostmanager-rethinc/action.rb
59
+ - lib/vagrant-hostmanager-rethinc/action/update_all.rb
60
+ - lib/vagrant-hostmanager-rethinc/action/update_guest.rb
61
+ - lib/vagrant-hostmanager-rethinc/action/update_host.rb
62
+ - lib/vagrant-hostmanager-rethinc/command.rb
63
+ - lib/vagrant-hostmanager-rethinc/config.rb
64
+ - lib/vagrant-hostmanager-rethinc/errors.rb
65
+ - lib/vagrant-hostmanager-rethinc/hosts_file/updater.rb
66
+ - lib/vagrant-hostmanager-rethinc/plugin.rb
67
+ - lib/vagrant-hostmanager-rethinc/provisioner.rb
68
+ - lib/vagrant-hostmanager-rethinc/util.rb
69
+ - lib/vagrant-hostmanager-rethinc/version.rb
70
+ - locales/en.yml
71
+ - test/Vagrantfile
72
+ - test/test.sh
73
+ - vagrant-hostmanager-rethinc.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