diff --git a/plugins/guests/debian/cap/change_host_name.rb b/plugins/guests/debian/cap/change_host_name.rb index 8b563cc21..09ca83d8e 100644 --- a/plugins/guests/debian/cap/change_host_name.rb +++ b/plugins/guests/debian/cap/change_host_name.rb @@ -47,8 +47,8 @@ module VagrantPlugins # 127.0.1.1 host.fqdn.com host.fqdn host def update_etc_hosts ip_address = '([0-9]{1,3}\.){3}[0-9]{1,3}' - search = "^(#{ip_address})\\s+#{current_hostname}\\b.*$" - replace = "\\1\\t#{fqdn} #{short_hostname}" + search = "^(#{ip_address})\\s+#{Regexp.escape(current_hostname)}(\\s.*)?$" + replace = "\\1 #{fqdn} #{short_hostname}" expression = ['s', search, replace, 'g'].join('@') sudo("sed -ri '#{expression}' /etc/hosts") diff --git a/test/unit/plugins/guests/debian/cap/change_host_name_test.rb b/test/unit/plugins/guests/debian/cap/change_host_name_test.rb index 37678b39e..83ba71016 100644 --- a/test/unit/plugins/guests/debian/cap/change_host_name_test.rb +++ b/test/unit/plugins/guests/debian/cap/change_host_name_test.rb @@ -7,10 +7,11 @@ describe "VagrantPlugins::GuestDebian::Cap::ChangeHostName" do end let(:machine) { double("machine") } let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + let(:old_hostname) { 'oldhostname.olddomain.tld' } before do machine.stub(:communicate).and_return(communicator) - communicator.stub_command('hostname -f', stdout: 'oldhostname.olddomain.tld') + communicator.stub_command('hostname -f', stdout: old_hostname) end after do diff --git a/test/unit/plugins/guests/support/shared/debian_like_host_name_examples.rb b/test/unit/plugins/guests/support/shared/debian_like_host_name_examples.rb index a4a945ff4..afa2e63e6 100644 --- a/test/unit/plugins/guests/support/shared/debian_like_host_name_examples.rb +++ b/test/unit/plugins/guests/support/shared/debian_like_host_name_examples.rb @@ -4,15 +4,6 @@ shared_examples "a debian-like host name change" do described_class.change_host_name(machine, 'newhostname.newdomain.tld') end - it "flips out the old hostname in /etc/hosts" do - sed_find = '^(([0-9]{1,3}\.){3}[0-9]{1,3})\s+oldhostname.olddomain.tld\b.*$' - sed_replace = '\1\tnewhostname.newdomain.tld newhostname' - communicator.expect_command( - %Q(sed -ri 's@#{sed_find}@#{sed_replace}@g' /etc/hosts) - ) - described_class.change_host_name(machine, 'newhostname.newdomain.tld') - end - it "updates mailname to prevent problems with the default mailer" do communicator.expect_command(%q(hostname --fqdn > /etc/mailname)) described_class.change_host_name(machine, 'newhostname.newdomain.tld') @@ -22,4 +13,77 @@ shared_examples "a debian-like host name change" do described_class.change_host_name(machine, 'oldhostname.olddomain.tld') communicator.received_commands.should == ['hostname -f'] end + + describe "flipping out the old hostname in /etc/hosts" do + let(:sed_command) do + # Here we run the change_host_name through and extract the recorded sed + # command from the dummy communicator + described_class.change_host_name(machine, 'newhostname.newdomain.tld') + communicator.received_commands.find { |cmd| cmd =~ /^sed/ } + end + + # Now we extract the regexp from that sed command so we can do some + # verification on it + let(:expression) { sed_command.sub(%r{^sed -ri '\(.*\)' /etc/hosts$}, "\1") } + let(:search) { Regexp.new(expression.split('@')[1], Regexp::EXTENDED) } + let(:replace) { expression.split('@')[2] } + + it "works on an simple /etc/hosts file" do + original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '') + 127.0.0.1 localhost + 127.0.1.1 oldhostname.olddomain.tld oldhostname + ETC_HOSTS + + modified_etc_hosts = original_etc_hosts.gsub(search, replace) + + modified_etc_hosts.should == <<-RESULT.gsub(/^ */, '') + 127.0.0.1 localhost + 127.0.1.1 newhostname.newdomain.tld newhostname + RESULT + end + + it "does not modify lines which contain similar hostnames" do + original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '') + 127.0.0.1 localhost + 127.0.1.1 oldhostname.olddomain.tld oldhostname + + # common prefix, but different fqdn + 192.168.12.34 oldhostname.olddomain.tld.different + + # different characters at the dot + 192.168.34.56 oldhostname-olddomain.tld + ETC_HOSTS + + modified_etc_hosts = original_etc_hosts.gsub(search, replace) + + modified_etc_hosts.should == <<-RESULT.gsub(/^ */, '') + 127.0.0.1 localhost + 127.0.1.1 newhostname.newdomain.tld newhostname + + # common prefix, but different fqdn + 192.168.12.34 oldhostname.olddomain.tld.different + + # different characters at the dot + 192.168.34.56 oldhostname-olddomain.tld + RESULT + end + + context "when the old fqdn has a trailing dot" do + let(:old_hostname) { 'oldhostname.withtrailing.dot.' } + + it "modifies /etc/hosts properly" do + original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '') + 127.0.0.1 localhost + 127.0.1.1 oldhostname.withtrailing.dot. oldhostname + ETC_HOSTS + + modified_etc_hosts = original_etc_hosts.gsub(search, replace) + + modified_etc_hosts.should == <<-RESULT.gsub(/^ */, '') + 127.0.0.1 localhost + 127.0.1.1 newhostname.newdomain.tld newhostname + RESULT + end + end + end end diff --git a/test/unit/plugins/guests/ubuntu/cap/change_host_name_test.rb b/test/unit/plugins/guests/ubuntu/cap/change_host_name_test.rb index 1e59bf3c4..2cc631e3d 100644 --- a/test/unit/plugins/guests/ubuntu/cap/change_host_name_test.rb +++ b/test/unit/plugins/guests/ubuntu/cap/change_host_name_test.rb @@ -7,10 +7,11 @@ describe "VagrantPlugins::GuestUbuntu::Cap::ChangeHostName" do end let(:machine) { double("machine") } let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + let(:old_hostname) {'oldhostname.olddomain.tld' } before do machine.stub(:communicate).and_return(communicator) - communicator.stub_command('hostname -f', stdout: 'oldhostname.olddomain.tld') + communicator.stub_command('hostname -f', stdout: old_hostname) end after do