From ab5d82275a9ac7509b4a73e94085e66e664a4d0c Mon Sep 17 00:00:00 2001 From: Paulo Bittencourt Date: Mon, 17 Feb 2014 16:32:52 -0500 Subject: [PATCH 1/2] sync hosts file state in blocks instead of lines --- lib/vagrant-hostmanager/hosts_file.rb | 86 +++++++++++++++------------ 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/lib/vagrant-hostmanager/hosts_file.rb b/lib/vagrant-hostmanager/hosts_file.rb index 94d0933..5f2bb18 100644 --- a/lib/vagrant-hostmanager/hosts_file.rb +++ b/lib/vagrant-hostmanager/hosts_file.rb @@ -19,7 +19,7 @@ module VagrantPlugins # download and modify file with Vagrant-managed entries file = @global_env.tmp_path.join("hosts.#{machine.name}") machine.communicate.download(realhostfile, file) - update_file(file, machine) + update_file(file, machine, false) # upload modified file and remove temporary file machine.communicate.upload(file, '/tmp/hosts') @@ -55,43 +55,29 @@ module VagrantPlugins private - def update_file(file, resolving_machine=nil) - # build array of host file entries from Vagrant configuration - entries = [] - destroyed_entries = [] - ids = [] - get_machines.each do |name, p| - if @provider == p - machine = @global_env.machine(name, p) - host = machine.config.vm.hostname || name - id = machine.id - ip = get_ip_address(machine, resolving_machine) - aliases = machine.config.hostmanager.aliases.join(' ').chomp - if id.nil? - destroyed_entries << "#{ip}\t#{host} #{aliases}" - else - entries << "#{ip}\t#{host} #{aliases}\t# VAGRANT ID: #{id}\n" - ids << id unless ids.include?(id) - end - end - end + def update_file(file, resolving_machine = nil, include_id = true) + file = Pathname.new(file) + new_file_content = update_content(file.read, resolving_machine, include_id) + file.open('w') { |io| io.write(new_file_content) } + end - tmp_file = Tempfile.open('hostmanager', @global_env.tmp_path, 'a') - begin - # copy each line not managed by Vagrant - File.open(file).each_line do |line| - # Eliminate lines for machines that have been destroyed - next if destroyed_entries.any? { |entry| line =~ /^#{entry}\t# VAGRANT ID: .*/ } - tmp_file << line unless ids.any? { |id| line =~ /# VAGRANT ID: #{id}/ } - end + def update_content(file_content, resolving_machine, include_id) + id = include_id ? " id: #{read_or_create_id}" : "" + header = "## vagrant-hostmanager-start#{id}\n" + footer = "## vagrant-hostmanager-end\n" + body = get_machines + .select { |name, provider| provider == @provider} + .collect { |name, _| @global_env.machine(name, @provider) } + .map { |machine| get_hosts_file_entry(machine, resolving_machine) } + .join + get_new_content(header, footer, body, file_content) + end - # write a line for each Vagrant-managed entry - entries.each { |entry| tmp_file << entry } - ensure - tmp_file.close - FileUtils.cp(tmp_file, file) - tmp_file.unlink - end + def get_hosts_file_entry(machine, resolving_machine) + ip = get_ip_address(machine, resolving_machine) + host = machine.config.vm.hostname || machine.name + aliases = machine.config.hostmanager.aliases.join(' ').chomp + "#{ip}\t#{host} #{aliases}\n" end def get_ip_address(machine, resolving_machine) @@ -108,7 +94,7 @@ module VagrantPlugins end end ip || (machine.ssh_info ? machine.ssh_info[:host] : nil) - end + end end def get_machines @@ -127,6 +113,32 @@ module VagrantPlugins end end + def get_new_content(header, footer, body, old_content) + if body.empty? + block = "\n" + else + block = "\n\n" + header + body + footer + "\n" + end + # Pattern for finding existing block + header_pattern = Regexp.quote(header) + footer_pattern = Regexp.quote(footer) + pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE) + # Replace existing block or append + old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block + end + + def read_or_create_id + file = Pathname.new("#{@global_env.local_data_path}/hostmanager/id") + if (file.file?) + id = file.read.strip + else + id = SecureRandom.uuid + file.dirname.mkpath + file.open('w') { |io| io.write(id) } + end + id + end + ## Windows support for copying files, requesting elevated privileges if necessary module WindowsSupport require 'rbconfig' From 8f041f5ef66b7610d66f49396708581f21b0ca3e Mon Sep 17 00:00:00 2001 From: Paulo Bittencourt Date: Mon, 17 Feb 2014 16:32:56 -0500 Subject: [PATCH 2/2] make get_machines return machine instances instead of machine names --- lib/vagrant-hostmanager/hosts_file.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/vagrant-hostmanager/hosts_file.rb b/lib/vagrant-hostmanager/hosts_file.rb index 5f2bb18..56258db 100644 --- a/lib/vagrant-hostmanager/hosts_file.rb +++ b/lib/vagrant-hostmanager/hosts_file.rb @@ -66,8 +66,6 @@ module VagrantPlugins header = "## vagrant-hostmanager-start#{id}\n" footer = "## vagrant-hostmanager-end\n" body = get_machines - .select { |name, provider| provider == @provider} - .collect { |name, _| @global_env.machine(name, @provider) } .map { |machine| get_hosts_file_entry(machine, resolving_machine) } .join get_new_content(header, footer, body, file_content) @@ -99,18 +97,20 @@ module VagrantPlugins def get_machines if @global_env.config_global.hostmanager.include_offline? - machines = [] - @global_env.machine_names.each do |name| - begin - @global_env.machine(name, @provider) - machines << [name, @provider] - rescue Vagrant::Errors::MachineNotFound - end - end - machines + machines = @global_env.machine_names else - @global_env.active_machines + machines = @global_env.active_machines end + # Collect only machines that exist for the current provider + machines.collect do |name, _| + begin + machine = @global_env.machine(name, @provider) + rescue Vagrant::Errors::MachineNotFound + # ignore + end + machine + end + .reject(&:nil?) end def get_new_content(header, footer, body, old_content)