Merge pull request #2534 from phinze/2333-debian-ubuntu-change-host-name-refactor
guests/debian,ubuntu: refactoring ubuntu/debian change_host_name
This commit is contained in:
commit
305af26fa2
|
@ -3,33 +3,79 @@ module VagrantPlugins
|
||||||
module Cap
|
module Cap
|
||||||
class ChangeHostName
|
class ChangeHostName
|
||||||
def self.change_host_name(machine, name)
|
def self.change_host_name(machine, name)
|
||||||
machine.communicate.tap do |comm|
|
new(machine, name).change!
|
||||||
|
|
||||||
# Get the current hostname
|
|
||||||
# if existing fqdn setup improperly, this returns just hostname
|
|
||||||
old = ''
|
|
||||||
comm.sudo "hostname -f" do |type, data|
|
|
||||||
if type == :stdout
|
|
||||||
old = data.chomp
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# this works even if they're not both fqdn
|
attr_reader :machine, :new_hostname
|
||||||
if old.split('.')[0] != name.split('.')[0]
|
|
||||||
|
|
||||||
comm.sudo("sed -i 's/.*$/#{name.split('.')[0]}/' /etc/hostname")
|
def initialize(machine, new_hostname)
|
||||||
|
@machine = machine
|
||||||
# hosts should resemble:
|
@new_hostname = new_hostname
|
||||||
# 127.0.0.1 localhost host.fqdn.com host
|
|
||||||
# 127.0.1.1 host.fqdn.com host
|
|
||||||
comm.sudo("sed -ri 's@^(([0-9]{1,3}\.){3}[0-9]{1,3})\\s+(localhost)\\b.*$@\\1\\t\\3 #{name} #{name.split('.')[0]}@g' /etc/hosts")
|
|
||||||
comm.sudo("sed -ri 's@^(([0-9]{1,3}\.){3}[0-9]{1,3})\\s+(#{old.split('.')[0]})\\b.*$@\\1\\t#{name} #{name.split('.')[0]}@g' /etc/hosts")
|
|
||||||
|
|
||||||
comm.sudo("hostname -F /etc/hostname")
|
|
||||||
comm.sudo("hostname --fqdn > /etc/mailname")
|
|
||||||
comm.sudo("ifdown -a; ifup -a; ifup eth0")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def change!
|
||||||
|
return unless should_change?
|
||||||
|
|
||||||
|
update_etc_hostname
|
||||||
|
update_etc_hosts
|
||||||
|
refresh_hostname_service
|
||||||
|
update_mailname
|
||||||
|
renew_dhcp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def should_change?
|
||||||
|
new_hostname != current_hostname
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_hostname
|
||||||
|
@current_hostname ||= get_current_hostname
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_current_hostname
|
||||||
|
sudo "hostname -f" do |type, data|
|
||||||
|
return data.chomp if type == :stdout
|
||||||
|
end
|
||||||
|
''
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_etc_hostname
|
||||||
|
sudo("echo '#{short_hostname}' > /etc/hostname")
|
||||||
|
end
|
||||||
|
|
||||||
|
# /etc/hosts should resemble:
|
||||||
|
# 127.0.0.1 localhost
|
||||||
|
# 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}"
|
||||||
|
expression = ['s', search, replace, 'g'].join('@')
|
||||||
|
|
||||||
|
sudo("sed -ri '#{expression}' /etc/hosts")
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh_hostname_service
|
||||||
|
sudo("hostname -F /etc/hostname")
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_mailname
|
||||||
|
sudo("hostname --fqdn > /etc/mailname")
|
||||||
|
end
|
||||||
|
|
||||||
|
def renew_dhcp
|
||||||
|
sudo("ifdown -a; ifup -a; ifup eth0")
|
||||||
|
end
|
||||||
|
|
||||||
|
def fqdn
|
||||||
|
new_hostname
|
||||||
|
end
|
||||||
|
|
||||||
|
def short_hostname
|
||||||
|
new_hostname.split('.').first
|
||||||
|
end
|
||||||
|
|
||||||
|
def sudo(cmd, &block)
|
||||||
|
machine.communicate.sudo(cmd, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,45 +1,26 @@
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module GuestUbuntu
|
module GuestUbuntu
|
||||||
module Cap
|
module Cap
|
||||||
class ChangeHostName
|
class ChangeHostName < VagrantPlugins::GuestDebian::Cap::ChangeHostName
|
||||||
def self.change_host_name(machine, name)
|
def self.change_host_name(machine, name)
|
||||||
machine.communicate.tap do |comm|
|
super
|
||||||
|
|
||||||
# Get the current hostname
|
|
||||||
# if existing fqdn setup improperly, this returns just hostname
|
|
||||||
old = ''
|
|
||||||
comm.sudo "hostname -f" do |type, data|
|
|
||||||
if type == :stdout
|
|
||||||
old = data.chomp
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# this works even if they're not both fqdn
|
def refresh_hostname_service
|
||||||
if old.split('.')[0] != name.split('.')[0]
|
if hardy?
|
||||||
|
# hostname.sh returns 1, so use `true` to get a 0 exitcode
|
||||||
comm.sudo("sed -i 's/.*$/#{name.split('.')[0]}/' /etc/hostname")
|
sudo("/etc/init.d/hostname.sh start; true")
|
||||||
|
|
||||||
# hosts should resemble:
|
|
||||||
# 127.0.0.1 localhost
|
|
||||||
# 127.0.1.1 host.fqdn.com host
|
|
||||||
if name.split('.').length > 1
|
|
||||||
# if there's an FQDN, put it in the right format
|
|
||||||
comm.sudo("sed -ri 's@^(([0-9]{1,3}\.){3}[0-9]{1,3})\\s+(#{old.split('.')[0]})\\b.*$@\\1\\t#{name} #{name.split('.')[0]}@g' /etc/hosts")
|
|
||||||
else
|
else
|
||||||
# if there's not an FQDN, don't print the hostname twice
|
sudo("service hostname start")
|
||||||
comm.sudo("sed -ri 's@^(([0-9]{1,3}\.){3}[0-9]{1,3})\\s+(#{old.split('.')[0]})\\b.*$@\\1\\t#{name}@g' /etc/hosts")
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if comm.test("[ `lsb_release -c -s` = hardy ]")
|
def hardy?
|
||||||
# hostname.sh returns 1, so I grep for the right name in /etc/hostname just to have a 0 exitcode
|
machine.communicate.test("[ `lsb_release -c -s` = hardy ]")
|
||||||
comm.sudo("/etc/init.d/hostname.sh start; grep '#{name}' /etc/hostname")
|
|
||||||
else
|
|
||||||
comm.sudo("service hostname start")
|
|
||||||
end
|
|
||||||
comm.sudo("hostname --fqdn > /etc/mailname")
|
|
||||||
comm.sudo("ifdown -a; ifup -a; ifup -a --allow=hotplug")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def renew_dhcp
|
||||||
|
sudo("ifdown -a; ifup -a; ifup -a --allow=hotplug")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,8 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
guest_capability("ubuntu", "change_host_name") do
|
guest_capability("ubuntu", "change_host_name") do
|
||||||
|
# ubuntu is just just a specialization of the debian code for this capability
|
||||||
|
require_relative "../debian/cap/change_host_name"
|
||||||
require_relative "cap/change_host_name"
|
require_relative "cap/change_host_name"
|
||||||
Cap::ChangeHostName
|
Cap::ChangeHostName
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ $:.unshift File.expand_path("../../", __FILE__)
|
||||||
|
|
||||||
# Load in helpers
|
# Load in helpers
|
||||||
require "support/tempdir"
|
require "support/tempdir"
|
||||||
|
require "unit/support/dummy_communicator"
|
||||||
require "unit/support/dummy_provider"
|
require "unit/support/dummy_provider"
|
||||||
require "unit/support/shared/base_context"
|
require "unit/support/shared/base_context"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
require File.expand_path("../../../../../base", __FILE__)
|
||||||
|
require File.expand_path("../../../support/shared/debian_like_host_name_examples", __FILE__)
|
||||||
|
|
||||||
|
describe "VagrantPlugins::GuestDebian::Cap::ChangeHostName" do
|
||||||
|
let(:described_class) do
|
||||||
|
VagrantPlugins::GuestDebian::Plugin.components.guest_capabilities[:debian].get(:change_host_name)
|
||||||
|
end
|
||||||
|
let(:machine) { double("machine") }
|
||||||
|
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
machine.stub(:communicate).and_return(communicator)
|
||||||
|
communicator.stub_command('hostname -f', stdout: 'oldhostname.olddomain.tld')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
communicator.verify_expectations!
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".change_host_name" do
|
||||||
|
it_behaves_like "a debian-like host name change"
|
||||||
|
|
||||||
|
it "refreshes the hostname service with the hostname command" do
|
||||||
|
communicator.expect_command(%q(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(%q(ifdown -a; ifup -a; ifup eth0))
|
||||||
|
described_class.change_host_name(machine, 'newhostname.newdomain.tld')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,25 @@
|
||||||
|
shared_examples "a debian-like host name change" do
|
||||||
|
it "updates /etc/hostname on the machine" do
|
||||||
|
communicator.expect_command(%q(echo 'newhostname' > /etc/hostname))
|
||||||
|
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')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does nothing when the provided hostname is not different" do
|
||||||
|
described_class.change_host_name(machine, 'oldhostname.olddomain.tld')
|
||||||
|
communicator.received_commands.should == ['hostname -f']
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,33 @@
|
||||||
|
require File.expand_path("../../../../../base", __FILE__)
|
||||||
|
require File.expand_path("../../../support/shared/debian_like_host_name_examples", __FILE__)
|
||||||
|
|
||||||
|
describe "VagrantPlugins::GuestUbuntu::Cap::ChangeHostName" do
|
||||||
|
let(:described_class) do
|
||||||
|
VagrantPlugins::GuestUbuntu::Plugin.components.guest_capabilities[:ubuntu].get(:change_host_name)
|
||||||
|
end
|
||||||
|
let(:machine) { double("machine") }
|
||||||
|
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
machine.stub(:communicate).and_return(communicator)
|
||||||
|
communicator.stub_command('hostname -f', stdout: 'oldhostname.olddomain.tld')
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
communicator.verify_expectations!
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".change_host_name" do
|
||||||
|
it_behaves_like "a debian-like host name change"
|
||||||
|
|
||||||
|
it "refreshes the hostname service with upstart" do
|
||||||
|
communicator.expect_command(%q(service hostname start))
|
||||||
|
described_class.change_host_name(machine, 'newhostname.newdomain.tld')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "renews dhcp on the system with the new hostname (with hotplug allowed)" do
|
||||||
|
communicator.expect_command(%q(ifdown -a; ifup -a; ifup -a --allow=hotplug))
|
||||||
|
described_class.change_host_name(machine, 'newhostname.newdomain.tld')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,79 @@
|
||||||
|
module VagrantTests
|
||||||
|
module DummyCommunicator
|
||||||
|
class Communicator < Vagrant.plugin("2", :communicator)
|
||||||
|
def ready?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :known_commands
|
||||||
|
|
||||||
|
def initialize(machine)
|
||||||
|
@known_commands = Hash.new do |hash, key|
|
||||||
|
hash[key] = { expected: 0, received: 0, response: nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def expected_commands
|
||||||
|
known_commands.select do |command, info|
|
||||||
|
info[:expected] > 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def received_commands
|
||||||
|
known_commands.select do |command, info|
|
||||||
|
info[:received] > 0
|
||||||
|
end.keys
|
||||||
|
end
|
||||||
|
|
||||||
|
def stub_command(command, response)
|
||||||
|
known_commands[command][:response] = response
|
||||||
|
end
|
||||||
|
|
||||||
|
def expect_command(command)
|
||||||
|
known_commands[command][:expected] += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def received_summary
|
||||||
|
received_commands.map { |cmd| " - #{cmd}" }.unshift('received:').join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify_expectations!
|
||||||
|
expected_commands.each do |command, info|
|
||||||
|
if info[:expected] != info[:received]
|
||||||
|
fail([
|
||||||
|
"expected to receive '#{command}' #{info[:expected]} times",
|
||||||
|
"got #{info[:received]} times instead",
|
||||||
|
received_summary
|
||||||
|
].join("\n"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(command, opts=nil)
|
||||||
|
known = known_commands[command]
|
||||||
|
known[:received] += 1
|
||||||
|
response = known[:response]
|
||||||
|
return unless response
|
||||||
|
|
||||||
|
if block_given?
|
||||||
|
[:stdout, :stderr].each do |type|
|
||||||
|
Array(response[type]).each do |line|
|
||||||
|
yield type, line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if response[:raise]
|
||||||
|
raise response[:raise]
|
||||||
|
end
|
||||||
|
|
||||||
|
response[:exit_code]
|
||||||
|
end
|
||||||
|
|
||||||
|
def sudo(command, opts=nil, &block)
|
||||||
|
execute(command, opts, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue