sync hosts file state in blocks instead of lines
This commit is contained in:
		
							parent
							
								
									ef410e6c04
								
							
						
					
					
						commit
						ab5d82275a
					
				|  | @ -19,7 +19,7 @@ module VagrantPlugins | ||||||
|         # download and modify file with Vagrant-managed entries |         # download and modify file with Vagrant-managed entries | ||||||
|         file = @global_env.tmp_path.join("hosts.#{machine.name}") |         file = @global_env.tmp_path.join("hosts.#{machine.name}") | ||||||
|         machine.communicate.download(realhostfile, file) |         machine.communicate.download(realhostfile, file) | ||||||
|         update_file(file, machine) |         update_file(file, machine, false) | ||||||
| 
 | 
 | ||||||
|         # upload modified file and remove temporary file |         # upload modified file and remove temporary file | ||||||
|         machine.communicate.upload(file, '/tmp/hosts') |         machine.communicate.upload(file, '/tmp/hosts') | ||||||
|  | @ -55,43 +55,29 @@ module VagrantPlugins | ||||||
| 
 | 
 | ||||||
|       private |       private | ||||||
| 
 | 
 | ||||||
|       def update_file(file, resolving_machine=nil) |       def update_file(file, resolving_machine = nil, include_id = true) | ||||||
|         # build array of host file entries from Vagrant configuration |         file = Pathname.new(file) | ||||||
|         entries = [] |         new_file_content = update_content(file.read, resolving_machine, include_id) | ||||||
|         destroyed_entries = [] |         file.open('w') { |io| io.write(new_file_content) } | ||||||
|         ids = [] |       end | ||||||
|         get_machines.each do |name, p| | 
 | ||||||
|           if @provider == p |       def update_content(file_content, resolving_machine, include_id) | ||||||
|             machine = @global_env.machine(name, p) |         id = include_id ? " id: #{read_or_create_id}" : "" | ||||||
|             host = machine.config.vm.hostname || name |         header = "## vagrant-hostmanager-start#{id}\n" | ||||||
|             id = machine.id |         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 | ||||||
|  | 
 | ||||||
|  |       def get_hosts_file_entry(machine, resolving_machine) | ||||||
|         ip = get_ip_address(machine, resolving_machine) |         ip = get_ip_address(machine, resolving_machine) | ||||||
|  |         host = machine.config.vm.hostname || machine.name | ||||||
|         aliases = machine.config.hostmanager.aliases.join(' ').chomp |         aliases = machine.config.hostmanager.aliases.join(' ').chomp | ||||||
|             if id.nil? |         "#{ip}\t#{host} #{aliases}\n" | ||||||
|               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 |  | ||||||
| 
 |  | ||||||
|         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 |  | ||||||
| 
 |  | ||||||
|           # 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 |  | ||||||
|       end |       end | ||||||
| 
 | 
 | ||||||
|       def get_ip_address(machine, resolving_machine) |       def get_ip_address(machine, resolving_machine) | ||||||
|  | @ -127,6 +113,32 @@ module VagrantPlugins | ||||||
|         end |         end | ||||||
|       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 |       ## Windows support for copying files, requesting elevated privileges if necessary | ||||||
|       module WindowsSupport |       module WindowsSupport | ||||||
|         require 'rbconfig' |         require 'rbconfig' | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Paulo Bittencourt
						Paulo Bittencourt