require 'spec_helper' describe 'VagrantPlugins::GuestAlpine::Cap::ChangeHostname' do let(:described_class) do VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:change_host_name) end let(:machine) { double('machine') } let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } let(:old_hostname) { 'oldhostname.olddomain.tld' } before do allow(machine).to receive(:communicate).and_return(communicator) communicator.stub_command('hostname -f', stdout: old_hostname) end after do communicator.verify_expectations! end describe '.change_host_name' do it 'updates /etc/hostname on the machine' do communicator.expect_command("echo 'newhostname' > /etc/hostname") described_class.change_host_name(machine, 'newhostname.newdomain.tld') end it 'does nothing when the provided hostname is not different' do described_class.change_host_name(machine, 'oldhostname.olddomain.tld') expect(communicator.received_commands).to eq(['hostname -f']) end it 'refreshes the hostname service with the hostname command' do communicator.expect_command('hostname -F /etc/hostname') described_class.change_host_name(machine, 'newhostname.newdomain.tld') end it 'renews dhcp on the system with the new hostname' do communicator.expect_command('ifdown -a; ifup -a; ifup eth0') described_class.change_host_name(machine, 'newhostname.newdomain.tld') 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] } let(:grep_command) { "grep '#{old_hostname}' /etc/hosts" } before do communicator.stub_command(grep_command, exit_code: 0) end 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) expect(modified_etc_hosts).to eq <<-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) expect(modified_etc_hosts).to eq <<-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 it "appends 127.0.1.1 if it isn't there" do communicator.stub_command(grep_command, exit_code: 1) described_class.change_host_name(machine, 'newhostname.newdomain.tld') sed = communicator.received_commands.find { |cmd| cmd =~ /^sed/ } expect(sed).to be_nil echo = communicator.received_commands.find { |cmd| cmd =~ /^echo/ } expect(echo).to_not be_nil 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) expect(modified_etc_hosts).to eq <<-RESULT.gsub(/^ */, '') 127.0.0.1 localhost 127.0.1.1 newhostname.newdomain.tld newhostname RESULT end end end end end