Explicitly define LF or CRLF line endings for hosts and guests when defining the hosts file content.
This commit is contained in:
		
							parent
							
								
									e97bc6fd16
								
							
						
					
					
						commit
						42bfe1f82b
					
				
							
								
								
									
										2
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										2
									
								
								Gemfile
								
								
								
								
							|  | @ -1,7 +1,7 @@ | ||||||
| source 'https://rubygems.org' | source 'https://rubygems.org' | ||||||
| 
 | 
 | ||||||
| group :development do | group :development do | ||||||
|   gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.6.2' |   gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git', :tag => 'v1.9.4' | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| group :plugins do | group :plugins do | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								README.md
								
								
								
								
							
							
						
						
									
										33
									
								
								README.md
								
								
								
								
							|  | @ -6,7 +6,7 @@ Vagrant Host Manager | ||||||
| [](https://rubygems.org/gems/vagrant-hostmanager) | [](https://rubygems.org/gems/vagrant-hostmanager) | ||||||
| [](https://twitter.com/intent/tweet?text=Check%20out%20this%20awesome%20Vagrant%20plugin%21&url=https%3A%2F%2Fgithub.com%devopsgroup-io%2Fvagrant-hostmanager&hashtags=vagrant%hostmanager&original_referer=) | [](https://twitter.com/intent/tweet?text=Check%20out%20this%20awesome%20Vagrant%20plugin%21&url=https%3A%2F%2Fgithub.com%devopsgroup-io%2Fvagrant-hostmanager&hashtags=vagrant%hostmanager&original_referer=) | ||||||
| 
 | 
 | ||||||
| `vagrant-hostmanager` is a plugin that manages the `hosts` file on guest machines (and optionally the host). Its goal is to enable resolution of multi-machine environments deployed with a cloud provider where IP addresses are not known in advance. | `vagrant-hostmanager` is a plugin that manages the `/etc/hosts` file on guest machines (and optionally the host). Its goal is to enable resolution of multi-machine environments deployed with a cloud provider where IP addresses are not known in advance. | ||||||
| 
 | 
 | ||||||
| Installation | Installation | ||||||
| ------------ | ------------ | ||||||
|  | @ -16,7 +16,7 @@ Install the plugin following the typical Vagrant 1.1 procedure: | ||||||
| 
 | 
 | ||||||
| Usage | Usage | ||||||
| ----- | ----- | ||||||
| To update the `hosts` file on each active machine, run the following | To update the `/etc/hosts` file on each active machine, run the following | ||||||
| command: | command: | ||||||
| 
 | 
 | ||||||
|     $ vagrant hostmanager |     $ vagrant hostmanager | ||||||
|  | @ -24,14 +24,14 @@ command: | ||||||
| The plugin hooks into the `vagrant up` and `vagrant destroy` commands | The plugin hooks into the `vagrant up` and `vagrant destroy` commands | ||||||
| automatically. | automatically. | ||||||
| When a machine enters or exits the running state , all active | When a machine enters or exits the running state , all active | ||||||
| machines with the same provider will have their `hosts` file updated | machines with the same provider will have their `/etc/hosts` file updated | ||||||
| accordingly. Set the `hostmanager.enabled` attribute to `true` in the | accordingly. Set the `hostmanager.enabled` attribute to `true` in the | ||||||
| Vagrantfile to activate this behavior. | Vagrantfile to activate this behavior. | ||||||
| 
 | 
 | ||||||
| To update the host's `hosts` file, set the `hostmanager.manage_host` | To update the host's `/etc/hosts` file, set the `hostmanager.manage_host` | ||||||
| attribute to `true`. | attribute to `true`. | ||||||
| 
 | 
 | ||||||
| To update the guests' `hosts` file, set the `hostmanager.manage_guest` | To update the guests' `/etc/hosts` file, set the `hostmanager.manage_guest` | ||||||
| attribute to `true`. | attribute to `true`. | ||||||
| 
 | 
 | ||||||
| A machine's IP address is defined by either the static IP for a private | A machine's IP address is defined by either the static IP for a private | ||||||
|  | @ -90,14 +90,14 @@ config.vm.provision :hostmanager | ||||||
| Custom IP resolver | Custom IP resolver | ||||||
| ------------------ | ------------------ | ||||||
| 
 | 
 | ||||||
| You can customize how vagrant-hostmanager resolves IP address | You can customize way, how host manager resolves IP address | ||||||
| for each machine. This might be handy in the case of the AWS provider, | for each machine. This might be handy in case of aws provider, | ||||||
| where the host name is stored in the ssh_info hash of each machine. | where host name is stored in ssh_info hash of each machine. | ||||||
| This causes a generation of an invalid `hosts` file. | This causes generation of invalid /etc/hosts file. | ||||||
| 
 | 
 | ||||||
| A custom IP resolver gives you the oportunity to calculate IP address | Custom IP resolver gives you oportunity to calculate IP address | ||||||
| for each machine by yourself, giving you access to the machine that is | for each machine by yourself, giving You also access to the machine that is | ||||||
| updating `hosts`. For example: | updating /etc/hosts. For example: | ||||||
| 
 | 
 | ||||||
| ```ruby | ```ruby | ||||||
| config.hostmanager.ip_resolver = proc do |vm, resolving_vm| | config.hostmanager.ip_resolver = proc do |vm, resolving_vm| | ||||||
|  | @ -188,11 +188,12 @@ To contribute, fork then clone the repository, and then the following: | ||||||
| 
 | 
 | ||||||
| **Developing** | **Developing** | ||||||
| 
 | 
 | ||||||
| 1. Install [Bundler](http://bundler.io/) | 1. Ideally, install the version of Vagrant as defined in the `Gemfile` | ||||||
| 2. Currently the Bundler version is locked to 1.6.9, please install this version. | 1. Install [Ruby](https://www.ruby-lang.org/en/documentation/installation/) | ||||||
|     * `sudo gem install bundler -v '1.6.9'` | 2. Currently the Bundler version is locked to 1.14.6, please install this version. | ||||||
|  |     * `gem install bundler -v '1.14.6'` | ||||||
| 3. Then install vagrant-hostmanager dependancies: | 3. Then install vagrant-hostmanager dependancies: | ||||||
|     * `bundle _1.6.9_ install` |     * `bundle _1.14.6_ install` | ||||||
| 
 | 
 | ||||||
| **Testing** | **Testing** | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,16 +18,20 @@ module VagrantPlugins | ||||||
|           return unless machine.communicate.ready? |           return unless machine.communicate.ready? | ||||||
| 
 | 
 | ||||||
|           if (machine.communicate.test("uname -s | grep SunOS")) |           if (machine.communicate.test("uname -s | grep SunOS")) | ||||||
|             realhostfile = '/etc/inet/hosts' |             realhostfile = "/etc/inet/hosts" | ||||||
|  |             line_endings = "lf" | ||||||
|           elsif (machine.communicate.test("test -d $Env:SystemRoot")) |           elsif (machine.communicate.test("test -d $Env:SystemRoot")) | ||||||
|             windir = "" |             windir = "" | ||||||
|             machine.communicate.execute("echo %SYSTEMROOT%", {:shell => :cmd}) do |type, contents| |             machine.communicate.execute("echo %SYSTEMROOT%", {:shell => :cmd}) do |type, contents| | ||||||
|               windir << contents.gsub("\r\n", '') if type == :stdout |               windir << contents.gsub("\r\n", '') if type == :stdout | ||||||
|             end |             end | ||||||
|             realhostfile = "#{windir}\\System32\\drivers\\etc\\hosts" |             realhostfile = "#{windir}\\System32\\drivers\\etc\\hosts" | ||||||
|  |             line_endings = "crlf" | ||||||
|           else |           else | ||||||
|             realhostfile = '/etc/hosts' |             realhostfile = "/etc/hosts" | ||||||
|  |             line_endings = "lf" | ||||||
|           end |           end | ||||||
|  | 
 | ||||||
|           # 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) | ||||||
|  | @ -35,8 +39,7 @@ module VagrantPlugins | ||||||
|           @logger.debug("file is: #{file.to_s}") |           @logger.debug("file is: #{file.to_s}") | ||||||
|           @logger.debug("class of file is: #{file.class}") |           @logger.debug("class of file is: #{file.class}") | ||||||
| 
 | 
 | ||||||
|           if update_file(file, machine, false) |           if update_file(file, machine, false, line_endings) | ||||||
| 
 |  | ||||||
|             # upload modified file and remove temporary file |             # upload modified file and remove temporary file | ||||||
|             machine.communicate.upload(file.to_s, '/tmp/hosts') |             machine.communicate.upload(file.to_s, '/tmp/hosts') | ||||||
|             if windir |             if windir | ||||||
|  | @ -57,38 +60,40 @@ module VagrantPlugins | ||||||
|             class << self |             class << self | ||||||
|               include WindowsSupport unless include? WindowsSupport |               include WindowsSupport unless include? WindowsSupport | ||||||
|             end |             end | ||||||
| 
 |  | ||||||
|             hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts" |             hosts_location = "#{ENV['WINDIR']}\\System32\\drivers\\etc\\hosts" | ||||||
|             copy_proc = Proc.new { windows_copy_file(file, hosts_location) } |             copy_proc = Proc.new { windows_copy_file(file, hosts_location) } | ||||||
|  |             line_endings = "crlf" | ||||||
|           else |           else | ||||||
|             hosts_location = '/etc/hosts' |             hosts_location = '/etc/hosts' | ||||||
|             copy_proc = Proc.new { `[ -w #{hosts_location} ] && cat #{file} > #{hosts_location} || sudo cp #{file} #{hosts_location}` } |             copy_proc = Proc.new { `[ -w #{hosts_location} ] && cat #{file} > #{hosts_location} || sudo cp #{file} #{hosts_location}` } | ||||||
|  |             line_endings = "lf" | ||||||
|           end |           end | ||||||
| 
 | 
 | ||||||
|           FileUtils.cp(hosts_location, file) |           FileUtils.cp(hosts_location, file) | ||||||
|           if update_file(file) | 
 | ||||||
|  |           if update_file(file, nil, true, line_endings) | ||||||
|             copy_proc.call |             copy_proc.call | ||||||
|           end |           end | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         private |         private | ||||||
| 
 | 
 | ||||||
|         def update_file(file, resolving_machine = nil, include_id = true) |         def update_file(file, resolving_machine = nil, include_id = true, line_endings) | ||||||
|           file = Pathname.new(file) |           file = Pathname.new(file) | ||||||
|           old_file_content = file.read |           old_file_content = file.read | ||||||
|           new_file_content = update_content(old_file_content, resolving_machine, include_id) |           new_file_content = update_content(old_file_content, resolving_machine, include_id, line_endings) | ||||||
|           file.open('wb') { |io| io.write(new_file_content) } |           file.open('wb') { |io| io.write(new_file_content) } | ||||||
|           old_file_content != new_file_content |           old_file_content != new_file_content | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         def update_content(file_content, resolving_machine, include_id) |         def update_content(file_content, resolving_machine, include_id, line_endings) | ||||||
|           id = include_id ? " id: #{read_or_create_id}" : "" |           id = include_id ? " id: #{read_or_create_id}" : "" | ||||||
|           header = "## vagrant-hostmanager-start#{id}\n" |           header = "## vagrant-hostmanager-start#{id}\n" | ||||||
|           footer = "## vagrant-hostmanager-end\n" |           footer = "## vagrant-hostmanager-end\n" | ||||||
|           body = get_machines |           body = get_machines | ||||||
|             .map { |machine| get_hosts_file_entry(machine, resolving_machine) } |             .map { |machine| get_hosts_file_entry(machine, resolving_machine) } | ||||||
|             .join |             .join | ||||||
|           get_new_content(header, footer, body, file_content) |           get_new_content(header, footer, body, file_content, line_endings) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         def get_hosts_file_entry(machine, resolving_machine) |         def get_hosts_file_entry(machine, resolving_machine) | ||||||
|  | @ -137,7 +142,7 @@ module VagrantPlugins | ||||||
|             .reject(&:nil?) |             .reject(&:nil?) | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         def get_new_content(header, footer, body, old_content) |         def get_new_content(header, footer, body, old_content, line_endings) | ||||||
|           if body.empty? |           if body.empty? | ||||||
|             block = "\n" |             block = "\n" | ||||||
|           else |           else | ||||||
|  | @ -148,7 +153,14 @@ module VagrantPlugins | ||||||
|           footer_pattern = Regexp.quote(footer) |           footer_pattern = Regexp.quote(footer) | ||||||
|           pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE) |           pattern = Regexp.new("\n*#{header_pattern}.*?#{footer_pattern}\n*", Regexp::MULTILINE) | ||||||
|           # Replace existing block or append |           # Replace existing block or append | ||||||
|           old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block |           content = old_content.match(pattern) ? old_content.sub(pattern, block) : old_content.rstrip + block | ||||||
|  |           if line_endings == "crlf" | ||||||
|  |             content.encode(content.encoding, :universal_encoding => true).encode(content.encoding, :crlf_newline => true) | ||||||
|  |           elsif line_endings == "lf" | ||||||
|  |             content.encode(content.encoding, :universal_encoding => true) | ||||||
|  |           else | ||||||
|  |             content.encode(content.encoding, :universal_encoding => true) | ||||||
|  |           end | ||||||
|         end |         end | ||||||
| 
 | 
 | ||||||
|         def read_or_create_id |         def read_or_create_id | ||||||
|  |  | ||||||
|  | @ -1,10 +1,10 @@ | ||||||
| en: | en: | ||||||
|   vagrant_hostmanager: |   vagrant_hostmanager: | ||||||
|     action: |     action: | ||||||
|       update_guests: "Updating /etc/hosts file on active guest machines..." |       update_guests: "[vagrant-hostmanager:guests] Updating hosts file on active guest virtual machines..." | ||||||
|       update_guest: "[%{name}] Updating /etc/hosts file..." |       update_guest: "[vagrant-hostmanager:guest] Updating hosts file on the virtual machine %{name}..." | ||||||
|       update_host: "Updating /etc/hosts file on host machine (password may be required)..." |       update_host: "[vagrant-hostmanager:host] Updating hosts file on your workstation (password may be required)..." | ||||||
|     config: |     config: | ||||||
|       not_a_bool: "A value for %{config_key} can only be true or false, not type '%{value}'" |       not_a_bool: "[vagrant-hostmanager:config:error] A value for %{config_key} can only be true or false, not type '%{value}'" | ||||||
|       not_an_array_or_string: "A value for %{config_key} must be an Array or String, not type '%{is_class}'" |       not_an_array_or_string: "[vagrant-hostmanager:config:error] A value for %{config_key} must be an Array or String, not type '%{is_class}'" | ||||||
|       not_a_proc: "A value for %{config_key} must be a Proc, not type '%{is_class}'" |       not_a_proc: "[vagrant-hostmanager:config:error] A value for %{config_key} must be a Proc, not type '%{is_class}'" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Seth Reeser
						Seth Reeser