Merge pull request #11718 from soapy1/change-host-name-cap-alpine

Make alpine guest respect 'hostname' network config option
This commit is contained in:
Sophia Castellarin 2020-07-30 11:29:34 -05:00 committed by GitHub
commit 09f2c2716f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 126 deletions

View File

@ -1,7 +1,11 @@
require 'vagrant/util/guest_hosts'
module VagrantPlugins
module GuestAlpine
module Cap
class ChangeHostName
include Vagrant::Util::GuestHosts::Linux
def self.change_host_name(machine, name)
new(machine, name).change!
end
@ -14,10 +18,10 @@ module VagrantPlugins
end
def change!
update_etc_hosts
return unless should_change?
update_etc_hostname
update_etc_hosts
refresh_hostname_service
update_mailname
renew_dhcp
@ -48,17 +52,12 @@ module VagrantPlugins
# 127.0.0.1 localhost
# 127.0.1.1 host.fqdn.com host.fqdn host
def update_etc_hosts
if machine.communicate.test("grep '#{current_hostname}' /etc/hosts")
# Current hostname entry is in /etc/hosts
ip_address = '([0-9]{1,3}\.){3}[0-9]{1,3}'
search = "^(#{ip_address})\\s+#{Regexp.escape(current_hostname)}(\\s.*)?$"
replace = "\\1 #{new_hostname} #{short_hostname}"
expression = ['s', search, replace, 'g'].join('@')
machine.communicate.sudo("sed -ri '#{expression}' /etc/hosts")
comm = machine.communicate
network_with_hostname = machine.config.vm.networks.map {|_, c| c if c[:hostname] }.compact[0]
if network_with_hostname
replace_host(comm, new_hostname, network_with_hostname[:ip])
else
# Current hostname entry isn't in /etc/hosts, just append it
machine.communicate.sudo("echo '127.0.1.1 #{new_hostname} #{short_hostname}' >>/etc/hosts")
add_hostname_to_loopback_interface(comm, new_hostname)
end
end

View File

@ -1,127 +1,70 @@
require_relative "../../../../base"
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' }
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' }
let(:networks) {[
[:forwarded_port, {:guest=>22, :host=>2222, :host_ip=>"127.0.0.1", :id=>"ssh", :auto_correct=>true, :protocol=>"tcp"}]
]}
before do
allow(machine).to receive(:communicate).and_return(communicator)
communicator.stub_command('hostname -f', stdout: old_hostname)
before do
allow(machine).to receive(:communicate).and_return(communicator)
communicator.stub_command('hostname -f', stdout: old_hostname)
allow(machine).to receive_message_chain(:config, :vm, :networks).and_return(networks)
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
after do
communicator.verify_expectations!
it 'only tries to update /etc/hosts when the provided hostname is not different' do
described_class.change_host_name(machine, 'oldhostname.olddomain.tld')
expect(communicator.received_commands[0]).to eq('hostname -f')
expect(communicator.received_commands.length).to eq(2)
end
describe '.change_host_name' do
it 'updates /etc/hostname on the machine' do
communicator.expect_command("echo 'newhostname' > /etc/hostname")
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
context "minimal network config" do
it "sets the hostname" do
described_class.change_host_name(machine, 'newhostname.newdomain.tld')
add_to_loopback_cmd = communicator.received_commands.find { |c| c =~ /127.0.\$\{i\}.1/ }
expect(add_to_loopback_cmd).to_not eq(nil)
end
end
context "multiple networks configured with hostname" do
let(:networks) {[
[:forwarded_port, {:guest=>22, :host=>2222, :host_ip=>"127.0.0.1", :id=>"ssh", :auto_correct=>true, :protocol=>"tcp"}],
[:public_network, {:ip=>"192.168.0.1", :hostname=>true, :protocol=>"tcp", :id=>"93a4ad88-0774-4127-a161-ceb715ff372f"}],
[:public_network, {:ip=>"192.168.0.2", :protocol=>"tcp", :id=>"5aebe848-7d85-4425-8911-c2003d924120"}]
]}
it "sets the hostname" do
described_class.change_host_name(machine, 'newhostname.newdomain.tld')
add_to_loopback_cmd = communicator.received_commands.find { |c| c =~ /sed -i '\/newhostname.newdomain.tld\/d'/ }
expect(add_to_loopback_cmd).to_not eq(nil)
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
end
end