From fbffb41fc4482f19149ea0a2662746e0a525450a Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Wed, 17 Jul 2019 16:44:01 +0200 Subject: [PATCH 1/7] guests: Add unmodified alpine support plugin from maier This has been available as `vagrant-alpine` in the plugin repository so far. --- plugins/guests/alpine/cap/change_host_name.rb | 95 +++++++++++++ .../guests/alpine/cap/configure_networks.rb | 67 +++++++++ plugins/guests/alpine/cap/halt.rb | 21 +++ plugins/guests/alpine/cap/nfs_client.rb | 46 +++++++ plugins/guests/alpine/cap/rsync.rb | 17 +++ plugins/guests/alpine/cap/smb.rb | 13 ++ plugins/guests/alpine/guest.rb | 19 +++ plugins/guests/alpine/plugin.rb | 58 ++++++++ templates/guests/alpine/network_dhcp.erb | 13 ++ templates/guests/alpine/network_static.erb | 7 + .../alpine/cap/change_host_name_spec.rb | 128 ++++++++++++++++++ .../alpine/cap/configure_networks_spec.rb | 40 ++++++ .../plugins/guests/alpine/cap/halt_spec.rb | 24 ++++ .../guests/alpine/cap/nfs_client_spec.rb | 60 ++++++++ .../plugins/guests/alpine/cap/rsync_spec.rb | 37 +++++ 15 files changed, 645 insertions(+) create mode 100644 plugins/guests/alpine/cap/change_host_name.rb create mode 100644 plugins/guests/alpine/cap/configure_networks.rb create mode 100644 plugins/guests/alpine/cap/halt.rb create mode 100644 plugins/guests/alpine/cap/nfs_client.rb create mode 100644 plugins/guests/alpine/cap/rsync.rb create mode 100644 plugins/guests/alpine/cap/smb.rb create mode 100644 plugins/guests/alpine/guest.rb create mode 100644 plugins/guests/alpine/plugin.rb create mode 100644 templates/guests/alpine/network_dhcp.erb create mode 100644 templates/guests/alpine/network_static.erb create mode 100644 test/unit/plugins/guests/alpine/cap/change_host_name_spec.rb create mode 100644 test/unit/plugins/guests/alpine/cap/configure_networks_spec.rb create mode 100644 test/unit/plugins/guests/alpine/cap/halt_spec.rb create mode 100644 test/unit/plugins/guests/alpine/cap/nfs_client_spec.rb create mode 100644 test/unit/plugins/guests/alpine/cap/rsync_spec.rb diff --git a/plugins/guests/alpine/cap/change_host_name.rb b/plugins/guests/alpine/cap/change_host_name.rb new file mode 100644 index 000000000..667fde8a6 --- /dev/null +++ b/plugins/guests/alpine/cap/change_host_name.rb @@ -0,0 +1,95 @@ +module VagrantPlugins + module GuestAlpine + module Cap + class ChangeHostName + def self.change_host_name(machine, name) + new(machine, name).change! + end + + attr_reader :machine, :new_hostname + + def initialize(machine, new_hostname) + @machine = machine + @new_hostname = new_hostname + end + + def change! + return unless should_change? + + update_etc_hostname + update_etc_hosts + refresh_hostname_service + update_mailname + renew_dhcp + end + + def should_change? + new_hostname != current_hostname + end + + def current_hostname + @current_hostname ||= fetch_current_hostname + end + + def fetch_current_hostname + hostname = '' + sudo 'hostname -f' do |type, data| + hostname = data.chomp if type == :stdout && hostname.empty? + end + + hostname + 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 + if 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 #{fqdn} #{short_hostname}" + expression = ['s', search, replace, 'g'].join('@') + + sudo("sed -ri '#{expression}' /etc/hosts") + else + # Current hostname entry isn't in /etc/hosts, just append it + sudo("echo '127.0.1.1 #{fqdn} #{short_hostname}' >>/etc/hosts") + end + end + + def refresh_hostname_service + sudo('hostname -F /etc/hostname') + end + + def update_mailname + sudo('hostname -f > /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 + + def test(cmd) + machine.communicate.test(cmd) + end + end + end + end +end diff --git a/plugins/guests/alpine/cap/configure_networks.rb b/plugins/guests/alpine/cap/configure_networks.rb new file mode 100644 index 000000000..2ac190a68 --- /dev/null +++ b/plugins/guests/alpine/cap/configure_networks.rb @@ -0,0 +1,67 @@ +# rubocop:disable Metrics/MethodLength +# rubocop:disable Metrics/AbcSize +# rubocop:disable Style/BracesAroundHashParameters +# +# FIXME: address disabled warnings +# +require 'set' +require 'tempfile' +require 'pathname' +require 'vagrant/util/template_renderer' + +module VagrantPlugins + module GuestAlpine + module Cap + class ConfigureNetworks + def self.source_root + @source_root ||= Pathname.new(File.expand_path('../../../../', __FILE__)) + end + include Vagrant::Util + def self.configure_networks(machine, networks) + machine.communicate.tap do |comm| + # First, remove any previous network modifications + # from the interface file. + comm.sudo("sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre") + comm.sudo("sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tail -n +2 > /tmp/vagrant-network-interfaces.post") + + # Accumulate the configurations to add to the interfaces file as + # well as what interfaces we're actually configuring since we use that + # later. + interfaces = Set.new + entries = [] + networks.each do |network| + interfaces.add(network[:interface]) + entry = TemplateRenderer.render("guests/alpine/network_#{network[:type]}", { options: network, template_root: source_root.join('templates') }) + entries << entry + end + + # Perform the careful dance necessary to reconfigure + # the network interfaces + temp = Tempfile.new('vagrant') + temp.binmode + temp.write(entries.join("\n")) + temp.close + + comm.upload(temp.path, '/tmp/vagrant-network-entry') + + # Bring down all the interfaces we're reconfiguring. By bringing down + # each specifically, we avoid reconfiguring eth0 (the NAT interface) so + # SSH never dies. + interfaces.each do |interface| + comm.sudo("/sbin/ifdown eth#{interface} 2> /dev/null") + comm.sudo("/sbin/ip addr flush dev eth#{interface} 2> /dev/null") + end + + comm.sudo('cat /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post > /etc/network/interfaces') + comm.sudo('rm -f /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post') + + # Bring back up each network interface, reconfigured + interfaces.each do |interface| + comm.sudo("/sbin/ifup eth#{interface}") + end + end + end + end + end + end +end diff --git a/plugins/guests/alpine/cap/halt.rb b/plugins/guests/alpine/cap/halt.rb new file mode 100644 index 000000000..550c15452 --- /dev/null +++ b/plugins/guests/alpine/cap/halt.rb @@ -0,0 +1,21 @@ +# rubocop:disable Style/RedundantBegin +# rubocop:disable Lint/HandleExceptions +# +# FIXME: address disabled warnings +# +module VagrantPlugins + module GuestAlpine + module Cap + class Halt + def self.halt(machine) + begin + machine.communicate.sudo('poweroff') + rescue Net::SSH::Disconnect, IOError + # Ignore, this probably means connection closed because it + # shut down and SSHd was stopped. + end + end + end + end + end +end diff --git a/plugins/guests/alpine/cap/nfs_client.rb b/plugins/guests/alpine/cap/nfs_client.rb new file mode 100644 index 000000000..f9f065db2 --- /dev/null +++ b/plugins/guests/alpine/cap/nfs_client.rb @@ -0,0 +1,46 @@ +module VagrantPlugins + module GuestAlpine + module Cap + class NFSClient + def self.nfs_client_install(machine) + comm = machine.communicate + comm.sudo <<-EOS.gsub(/^\s+\|\s?/, '') + | # work around defunct repository in configuration + | # box: maier/apline-3.3 + | repo_file="/etc/apk/repositories" + | if [ $(grep -c "repos.dfw.lax-noc.com" $repo_file) -ne 0 ]; then + | repo_file_bak="${repo_file}.orig" + | echo "updating repositories" + | cp $repo_file $repo_file_bak + | sed -e 's/repos.dfw.lax-noc.com/dl-cdn.alpinelinux.org/' $repo_file_bak > $repo_file + | fi + | + | echo "updating repository indices" + | apk update + | if [ $? -ne 0 ]; then + | exit 1 + | fi + | + | echo "installing nfs-utils" + | apk add --upgrade nfs-utils + | if [ $? -ne 0 ]; then + | exit 1 + | fi + | + | echo "installing rpc.statd" + | rc-update add rpc.statd + | if [ $? -ne 0 ]; then + | exit 1 + | fi + | + | echo "starting rpc.statd service" + | rc-service rpc.statd start + | if [ $? -ne 0 ]; then + | exit 1 + | fi + EOS + end + end + end + end +end diff --git a/plugins/guests/alpine/cap/rsync.rb b/plugins/guests/alpine/cap/rsync.rb new file mode 100644 index 000000000..436bfbc20 --- /dev/null +++ b/plugins/guests/alpine/cap/rsync.rb @@ -0,0 +1,17 @@ +module VagrantPlugins + module GuestAlpine + module Cap + class RSync + def self.rsync_installed(machine) + machine.communicate.test('test -f /usr/bin/rsync') + end + + def self.rsync_install(machine) + machine.communicate.tap do |comm| + comm.sudo('apk add rsync') + end + end + end + end + end +end diff --git a/plugins/guests/alpine/cap/smb.rb b/plugins/guests/alpine/cap/smb.rb new file mode 100644 index 000000000..55e52394c --- /dev/null +++ b/plugins/guests/alpine/cap/smb.rb @@ -0,0 +1,13 @@ +module VagrantPlugins + module GuestAlpine + module Cap + class SMB + def self.smb_install(machine) + machine.communicate.tap do |comm| + comm.sudo('apk add cifs-utils') + end + end + end + end + end +end \ No newline at end of file diff --git a/plugins/guests/alpine/guest.rb b/plugins/guests/alpine/guest.rb new file mode 100644 index 000000000..8d0d35912 --- /dev/null +++ b/plugins/guests/alpine/guest.rb @@ -0,0 +1,19 @@ +begin + require 'vagrant' +rescue LoadError + raise 'The Vagrant Alpine Linux Guest plugin must be run within Vagrant.' +end + +if Vagrant::VERSION < '1.7.0' + fail 'The vagrant-alpine plugin is only compatible with Vagrant 1.7+' +end + +module VagrantPlugins + module GuestAlpine + class Guest < Vagrant.plugin('2', :guest) + def detect?(machine) + machine.communicate.test('cat /etc/alpine-release') + end + end + end +end diff --git a/plugins/guests/alpine/plugin.rb b/plugins/guests/alpine/plugin.rb new file mode 100644 index 000000000..fdbd04a1b --- /dev/null +++ b/plugins/guests/alpine/plugin.rb @@ -0,0 +1,58 @@ +begin + require 'vagrant' +rescue LoadError + raise 'The Vagrant Alpine Linux Guest plugin must be run within Vagrant.' +end + +if Vagrant::VERSION < '1.7.0' + fail 'The vagrant-alpine plugin is only compatible with Vagrant 1.7+' +end + +module VagrantPlugins + module GuestAlpine + class Plugin < Vagrant.plugin('2') + name 'Alpine guest' + description 'Alpine Linux guest support.' + + guest('alpine', 'linux') do + require File.expand_path('../guest', __FILE__) + Guest + end + + guest_capability('alpine', 'configure_networks') do + require_relative 'cap/configure_networks' + Cap::ConfigureNetworks + end + + guest_capability('alpine', 'halt') do + require_relative 'cap/halt' + Cap::Halt + end + + guest_capability('alpine', 'change_host_name') do + require_relative 'cap/change_host_name' + Cap::ChangeHostName + end + + guest_capability('alpine', 'nfs_client_install') do + require_relative 'cap/nfs_client' + Cap::NFSClient + end + + guest_capability('alpine', 'rsync_installed') do + require_relative 'cap/rsync' + Cap::RSync + end + + guest_capability('alpine', 'rsync_install') do + require_relative 'cap/rsync' + Cap::RSync + end + + guest_capability('alpine', 'smb_install') do + require_relative 'cap/smb' + Cap::SMB + end + end + end +end diff --git a/templates/guests/alpine/network_dhcp.erb b/templates/guests/alpine/network_dhcp.erb new file mode 100644 index 000000000..5a4ed783c --- /dev/null +++ b/templates/guests/alpine/network_dhcp.erb @@ -0,0 +1,13 @@ +#VAGRANT-BEGIN +# The contents below are automatically generated by Vagrant. Do not modify. +auto eth<%= options[:interface] %> +iface eth<%= options[:interface] %> inet dhcp +<% if !options[:use_dhcp_assigned_default_route] %> + post-up route del default dev $IFACE || true +<% else %> + # We need to disable eth0, see GH-2648 + post-up route del default dev eth0 + post-up dhclient $IFACE + pre-down route add default dev eth0 +<% end %> +#VAGRANT-END diff --git a/templates/guests/alpine/network_static.erb b/templates/guests/alpine/network_static.erb new file mode 100644 index 000000000..fa505afa9 --- /dev/null +++ b/templates/guests/alpine/network_static.erb @@ -0,0 +1,7 @@ +#VAGRANT-BEGIN +# The contents below are automatically generated by Vagrant. Do not modify. +auto eth<%= options[:interface] %> +iface eth<%= options[:interface] %> inet static + address <%= options[:ip] %> + netmask <%= options[:netmask] %> +#VAGRANT-END diff --git a/test/unit/plugins/guests/alpine/cap/change_host_name_spec.rb b/test/unit/plugins/guests/alpine/cap/change_host_name_spec.rb new file mode 100644 index 000000000..180045e6a --- /dev/null +++ b/test/unit/plugins/guests/alpine/cap/change_host_name_spec.rb @@ -0,0 +1,128 @@ + +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 diff --git a/test/unit/plugins/guests/alpine/cap/configure_networks_spec.rb b/test/unit/plugins/guests/alpine/cap/configure_networks_spec.rb new file mode 100644 index 000000000..f74d75af8 --- /dev/null +++ b/test/unit/plugins/guests/alpine/cap/configure_networks_spec.rb @@ -0,0 +1,40 @@ + +require 'spec_helper' + +describe 'VagrantPlugins::GuestAlpine::Cap::ConfigureNetworks' do + let(:described_class) do + VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:configure_networks) + end + let(:machine) { double('machine') } + let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + + before do + allow(machine).to receive(:communicate).and_return(communicator) + end + + after do + communicator.verify_expectations! + end + + it 'should configure networks' do + networks = [ + { type: :static, ip: '192.168.10.10', netmask: '255.255.255.0', interface: 0, name: 'eth0' }, + { type: :dhcp, interface: 1, name: 'eth1' } + ] + + expect(communicator).to receive(:sudo).with("sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre") + expect(communicator).to receive(:sudo).with("sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tail -n +2 > /tmp/vagrant-network-interfaces.post") + expect(communicator).to receive(:sudo).with('/sbin/ifdown eth0 2> /dev/null') + expect(communicator).to receive(:sudo).with('/sbin/ip addr flush dev eth0 2> /dev/null') + expect(communicator).to receive(:sudo).with('/sbin/ifdown eth1 2> /dev/null') + expect(communicator).to receive(:sudo).with('/sbin/ip addr flush dev eth1 2> /dev/null') + expect(communicator).to receive(:sudo).with('cat /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post > /etc/network/interfaces') + expect(communicator).to receive(:sudo).with('rm -f /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post') + expect(communicator).to receive(:sudo).with('/sbin/ifup eth0') + expect(communicator).to receive(:sudo).with('/sbin/ifup eth1') + + allow_message_expectations_on_nil + + described_class.configure_networks(machine, networks) + end +end diff --git a/test/unit/plugins/guests/alpine/cap/halt_spec.rb b/test/unit/plugins/guests/alpine/cap/halt_spec.rb new file mode 100644 index 000000000..2df8ed96e --- /dev/null +++ b/test/unit/plugins/guests/alpine/cap/halt_spec.rb @@ -0,0 +1,24 @@ + +require 'spec_helper' + +describe 'VagrantPlugins::GuestAlpine::Cap::Halt' do + let(:described_class) do + VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:halt) + end + let(:machine) { double('machine') } + let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + + before do + allow(machine).to receive(:communicate).and_return(communicator) + end + + after do + communicator.verify_expectations! + end + + it 'should halt guest' do + expect(communicator).to receive(:sudo).with('poweroff') + allow_message_expectations_on_nil + described_class.halt(machine) + end +end diff --git a/test/unit/plugins/guests/alpine/cap/nfs_client_spec.rb b/test/unit/plugins/guests/alpine/cap/nfs_client_spec.rb new file mode 100644 index 000000000..e9c88658d --- /dev/null +++ b/test/unit/plugins/guests/alpine/cap/nfs_client_spec.rb @@ -0,0 +1,60 @@ + +require 'spec_helper' + +describe 'VagrantPlugins::GuestAlpine::Cap::NFSClient' do + let(:described_class) do + VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:nfs_client_install) + end + + let(:machine) { double('machine') } + let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + + before do + allow(machine).to receive(:communicate).and_return(communicator) + end + + after do + communicator.verify_expectations! + end + + it 'should install nfs client' do + x = <<-EOS.gsub(/^\s+\|\s?/, '') + | # work around defunct repository in configuration + | # box: maier/apline-3.3 + | repo_file="/etc/apk/repositories" + | if [ $(grep -c "repos.dfw.lax-noc.com" $repo_file) -ne 0 ]; then + | repo_file_bak="${repo_file}.orig" + | echo "updating repositories" + | cp $repo_file $repo_file_bak + | sed -e 's/repos.dfw.lax-noc.com/dl-cdn.alpinelinux.org/' $repo_file_bak > $repo_file + | fi + | + | echo "updating repository indices" + | apk update + | if [ $? -ne 0 ]; then + | exit 1 + | fi + | + | echo "installing nfs-utils" + | apk add --upgrade nfs-utils + | if [ $? -ne 0 ]; then + | exit 1 + | fi + | + | echo "installing rpc.statd" + | rc-update add rpc.statd + | if [ $? -ne 0 ]; then + | exit 1 + | fi + | + | echo "starting rpc.statd service" + | rc-service rpc.statd start + | if [ $? -ne 0 ]; then + | exit 1 + | fi + EOS + expect(communicator).to receive(:sudo).with(x) + allow_message_expectations_on_nil + described_class.nfs_client_install(machine) + end +end diff --git a/test/unit/plugins/guests/alpine/cap/rsync_spec.rb b/test/unit/plugins/guests/alpine/cap/rsync_spec.rb new file mode 100644 index 000000000..59d066cea --- /dev/null +++ b/test/unit/plugins/guests/alpine/cap/rsync_spec.rb @@ -0,0 +1,37 @@ + +require 'spec_helper' + +describe 'VagrantPlugins::GuestAlpine::Cap::RSync' do + let(:machine) { double('machine') } + let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + + before do + allow(machine).to receive(:communicate).and_return(communicator) + end + + after do + communicator.verify_expectations! + end + + let(:described_class) do + VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:rsync_install) + end + + it 'should install rsync' do + # communicator.should_receive(:sudo).with('apk add rsync') + expect(communicator).to receive(:sudo).with('apk add rsync') + allow_message_expectations_on_nil + described_class.rsync_install(machine) + end + + let(:described_class) do + VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:rsync_installed) + end + + it 'should verify rsync installed' do + # communicator.should_receive(:test).with('test -f /usr/bin/rsync') + expect(communicator).to receive(:test).with('test -f /usr/bin/rsync') + allow_message_expectations_on_nil + described_class.rsync_installed(machine) + end +end From 2216d23048eb7355e908ee8f7af5290f26774862 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Wed, 17 Jul 2019 16:47:37 +0200 Subject: [PATCH 2/7] alpine: Remove version and out-of-tree checks --- plugins/guests/alpine/guest.rb | 10 +--------- plugins/guests/alpine/plugin.rb | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/plugins/guests/alpine/guest.rb b/plugins/guests/alpine/guest.rb index 8d0d35912..e0330f916 100644 --- a/plugins/guests/alpine/guest.rb +++ b/plugins/guests/alpine/guest.rb @@ -1,12 +1,4 @@ -begin - require 'vagrant' -rescue LoadError - raise 'The Vagrant Alpine Linux Guest plugin must be run within Vagrant.' -end - -if Vagrant::VERSION < '1.7.0' - fail 'The vagrant-alpine plugin is only compatible with Vagrant 1.7+' -end +require 'vagrant' module VagrantPlugins module GuestAlpine diff --git a/plugins/guests/alpine/plugin.rb b/plugins/guests/alpine/plugin.rb index fdbd04a1b..ea71e8987 100644 --- a/plugins/guests/alpine/plugin.rb +++ b/plugins/guests/alpine/plugin.rb @@ -1,12 +1,4 @@ -begin - require 'vagrant' -rescue LoadError - raise 'The Vagrant Alpine Linux Guest plugin must be run within Vagrant.' -end - -if Vagrant::VERSION < '1.7.0' - fail 'The vagrant-alpine plugin is only compatible with Vagrant 1.7+' -end +require 'vagrant' module VagrantPlugins module GuestAlpine From 3b039443313962a22f3343a2c3ef9725c7b41691 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Wed, 17 Jul 2019 16:51:36 +0200 Subject: [PATCH 3/7] alpine: Replace capability strings with symbols Those were introduced upstream in b29864f45097. --- plugins/guests/alpine/plugin.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/guests/alpine/plugin.rb b/plugins/guests/alpine/plugin.rb index ea71e8987..62e8ec6fd 100644 --- a/plugins/guests/alpine/plugin.rb +++ b/plugins/guests/alpine/plugin.rb @@ -6,42 +6,42 @@ module VagrantPlugins name 'Alpine guest' description 'Alpine Linux guest support.' - guest('alpine', 'linux') do + guest(:alpine, :linux) do require File.expand_path('../guest', __FILE__) Guest end - guest_capability('alpine', 'configure_networks') do + guest_capability(:alpine, :configure_networks) do require_relative 'cap/configure_networks' Cap::ConfigureNetworks end - guest_capability('alpine', 'halt') do + guest_capability(:alpine, :halt) do require_relative 'cap/halt' Cap::Halt end - guest_capability('alpine', 'change_host_name') do + guest_capability(:alpine, :change_host_name) do require_relative 'cap/change_host_name' Cap::ChangeHostName end - guest_capability('alpine', 'nfs_client_install') do + guest_capability(:alpine, :nfs_client_install) do require_relative 'cap/nfs_client' Cap::NFSClient end - guest_capability('alpine', 'rsync_installed') do + guest_capability(:alpine, :rsync_installed) do require_relative 'cap/rsync' Cap::RSync end - guest_capability('alpine', 'rsync_install') do + guest_capability(:alpine, :rsync_install) do require_relative 'cap/rsync' Cap::RSync end - guest_capability('alpine', 'smb_install') do + guest_capability(:alpine, :smb_install) do require_relative 'cap/smb' Cap::SMB end From 29362d8af4698133e67a80398e14ce354ffbbcb0 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 18 Jul 2019 03:36:50 +0200 Subject: [PATCH 4/7] alpine: Wire up tests --- .../cap/{change_host_name_spec.rb => change_host_name_test.rb} | 3 +-- .../{configure_networks_spec.rb => configure_networks_test.rb} | 3 +-- .../plugins/guests/alpine/cap/{halt_spec.rb => halt_test.rb} | 3 +-- .../alpine/cap/{nfs_client_spec.rb => nfs_client_test.rb} | 3 +-- .../plugins/guests/alpine/cap/{rsync_spec.rb => rsync_test.rb} | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) rename test/unit/plugins/guests/alpine/cap/{change_host_name_spec.rb => change_host_name_test.rb} (99%) rename test/unit/plugins/guests/alpine/cap/{configure_networks_spec.rb => configure_networks_test.rb} (98%) rename test/unit/plugins/guests/alpine/cap/{halt_spec.rb => halt_test.rb} (94%) rename test/unit/plugins/guests/alpine/cap/{nfs_client_spec.rb => nfs_client_test.rb} (98%) rename test/unit/plugins/guests/alpine/cap/{rsync_spec.rb => rsync_test.rb} (97%) diff --git a/test/unit/plugins/guests/alpine/cap/change_host_name_spec.rb b/test/unit/plugins/guests/alpine/cap/change_host_name_test.rb similarity index 99% rename from test/unit/plugins/guests/alpine/cap/change_host_name_spec.rb rename to test/unit/plugins/guests/alpine/cap/change_host_name_test.rb index 180045e6a..3f159ad75 100644 --- a/test/unit/plugins/guests/alpine/cap/change_host_name_spec.rb +++ b/test/unit/plugins/guests/alpine/cap/change_host_name_test.rb @@ -1,5 +1,4 @@ - -require 'spec_helper' +require_relative "../../../../base" describe 'VagrantPlugins::GuestAlpine::Cap::ChangeHostname' do let(:described_class) do diff --git a/test/unit/plugins/guests/alpine/cap/configure_networks_spec.rb b/test/unit/plugins/guests/alpine/cap/configure_networks_test.rb similarity index 98% rename from test/unit/plugins/guests/alpine/cap/configure_networks_spec.rb rename to test/unit/plugins/guests/alpine/cap/configure_networks_test.rb index f74d75af8..31a361beb 100644 --- a/test/unit/plugins/guests/alpine/cap/configure_networks_spec.rb +++ b/test/unit/plugins/guests/alpine/cap/configure_networks_test.rb @@ -1,5 +1,4 @@ - -require 'spec_helper' +require_relative "../../../../base" describe 'VagrantPlugins::GuestAlpine::Cap::ConfigureNetworks' do let(:described_class) do diff --git a/test/unit/plugins/guests/alpine/cap/halt_spec.rb b/test/unit/plugins/guests/alpine/cap/halt_test.rb similarity index 94% rename from test/unit/plugins/guests/alpine/cap/halt_spec.rb rename to test/unit/plugins/guests/alpine/cap/halt_test.rb index 2df8ed96e..e10c7dc99 100644 --- a/test/unit/plugins/guests/alpine/cap/halt_spec.rb +++ b/test/unit/plugins/guests/alpine/cap/halt_test.rb @@ -1,5 +1,4 @@ - -require 'spec_helper' +require_relative "../../../../base" describe 'VagrantPlugins::GuestAlpine::Cap::Halt' do let(:described_class) do diff --git a/test/unit/plugins/guests/alpine/cap/nfs_client_spec.rb b/test/unit/plugins/guests/alpine/cap/nfs_client_test.rb similarity index 98% rename from test/unit/plugins/guests/alpine/cap/nfs_client_spec.rb rename to test/unit/plugins/guests/alpine/cap/nfs_client_test.rb index e9c88658d..11a03ed9b 100644 --- a/test/unit/plugins/guests/alpine/cap/nfs_client_spec.rb +++ b/test/unit/plugins/guests/alpine/cap/nfs_client_test.rb @@ -1,5 +1,4 @@ - -require 'spec_helper' +require_relative "../../../../base" describe 'VagrantPlugins::GuestAlpine::Cap::NFSClient' do let(:described_class) do diff --git a/test/unit/plugins/guests/alpine/cap/rsync_spec.rb b/test/unit/plugins/guests/alpine/cap/rsync_test.rb similarity index 97% rename from test/unit/plugins/guests/alpine/cap/rsync_spec.rb rename to test/unit/plugins/guests/alpine/cap/rsync_test.rb index 59d066cea..6b305a5f9 100644 --- a/test/unit/plugins/guests/alpine/cap/rsync_spec.rb +++ b/test/unit/plugins/guests/alpine/cap/rsync_test.rb @@ -1,5 +1,4 @@ - -require 'spec_helper' +require_relative "../../../../base" describe 'VagrantPlugins::GuestAlpine::Cap::RSync' do let(:machine) { double('machine') } From 77616b22b339204868c2fbd651cd7f254014d8b9 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Thu, 18 Jul 2019 04:07:15 +0200 Subject: [PATCH 5/7] alpine: Use absolute paths for network configuration templates --- plugins/guests/alpine/cap/configure_networks.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/guests/alpine/cap/configure_networks.rb b/plugins/guests/alpine/cap/configure_networks.rb index 2ac190a68..361e64610 100644 --- a/plugins/guests/alpine/cap/configure_networks.rb +++ b/plugins/guests/alpine/cap/configure_networks.rb @@ -13,9 +13,6 @@ module VagrantPlugins module GuestAlpine module Cap class ConfigureNetworks - def self.source_root - @source_root ||= Pathname.new(File.expand_path('../../../../', __FILE__)) - end include Vagrant::Util def self.configure_networks(machine, networks) machine.communicate.tap do |comm| @@ -31,7 +28,7 @@ module VagrantPlugins entries = [] networks.each do |network| interfaces.add(network[:interface]) - entry = TemplateRenderer.render("guests/alpine/network_#{network[:type]}", { options: network, template_root: source_root.join('templates') }) + entry = TemplateRenderer.render("guests/alpine/network_#{network[:type]}", { options: network }) entries << entry end From a7f09f010c6d6e5bacba3ee95a2b35ccec1e4e36 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Mon, 22 Jul 2019 16:05:48 +0200 Subject: [PATCH 6/7] alpine: Convert nfs_client capability to seperate commands The workaround for the broken repository should be safe to be removed, since the last affected Alpine version (<=3.3) EOL'd in November of 2017. The remaining important commands can be split out into seperate calls of sudo(), which removes the need for manual exit-code checking (since it aborts by itself when a command fails) and makes the code easier to handle in general. --- plugins/guests/alpine/cap/nfs_client.rb | 40 ++---------------- .../guests/alpine/cap/nfs_client_test.rb | 42 +++---------------- 2 files changed, 9 insertions(+), 73 deletions(-) diff --git a/plugins/guests/alpine/cap/nfs_client.rb b/plugins/guests/alpine/cap/nfs_client.rb index f9f065db2..b9d803134 100644 --- a/plugins/guests/alpine/cap/nfs_client.rb +++ b/plugins/guests/alpine/cap/nfs_client.rb @@ -3,42 +3,10 @@ module VagrantPlugins module Cap class NFSClient def self.nfs_client_install(machine) - comm = machine.communicate - comm.sudo <<-EOS.gsub(/^\s+\|\s?/, '') - | # work around defunct repository in configuration - | # box: maier/apline-3.3 - | repo_file="/etc/apk/repositories" - | if [ $(grep -c "repos.dfw.lax-noc.com" $repo_file) -ne 0 ]; then - | repo_file_bak="${repo_file}.orig" - | echo "updating repositories" - | cp $repo_file $repo_file_bak - | sed -e 's/repos.dfw.lax-noc.com/dl-cdn.alpinelinux.org/' $repo_file_bak > $repo_file - | fi - | - | echo "updating repository indices" - | apk update - | if [ $? -ne 0 ]; then - | exit 1 - | fi - | - | echo "installing nfs-utils" - | apk add --upgrade nfs-utils - | if [ $? -ne 0 ]; then - | exit 1 - | fi - | - | echo "installing rpc.statd" - | rc-update add rpc.statd - | if [ $? -ne 0 ]; then - | exit 1 - | fi - | - | echo "starting rpc.statd service" - | rc-service rpc.statd start - | if [ $? -ne 0 ]; then - | exit 1 - | fi - EOS + machine.communicate.sudo('apk update') + machine.communicate.sudo('apk add --upgrade nfs-utils') + machine.communicate.sudo('rc-update add rpc.statd') + machine.communicate.sudo('rc-service rpc.statd start') end end end diff --git a/test/unit/plugins/guests/alpine/cap/nfs_client_test.rb b/test/unit/plugins/guests/alpine/cap/nfs_client_test.rb index 11a03ed9b..9273707c3 100644 --- a/test/unit/plugins/guests/alpine/cap/nfs_client_test.rb +++ b/test/unit/plugins/guests/alpine/cap/nfs_client_test.rb @@ -17,43 +17,11 @@ describe 'VagrantPlugins::GuestAlpine::Cap::NFSClient' do end it 'should install nfs client' do - x = <<-EOS.gsub(/^\s+\|\s?/, '') - | # work around defunct repository in configuration - | # box: maier/apline-3.3 - | repo_file="/etc/apk/repositories" - | if [ $(grep -c "repos.dfw.lax-noc.com" $repo_file) -ne 0 ]; then - | repo_file_bak="${repo_file}.orig" - | echo "updating repositories" - | cp $repo_file $repo_file_bak - | sed -e 's/repos.dfw.lax-noc.com/dl-cdn.alpinelinux.org/' $repo_file_bak > $repo_file - | fi - | - | echo "updating repository indices" - | apk update - | if [ $? -ne 0 ]; then - | exit 1 - | fi - | - | echo "installing nfs-utils" - | apk add --upgrade nfs-utils - | if [ $? -ne 0 ]; then - | exit 1 - | fi - | - | echo "installing rpc.statd" - | rc-update add rpc.statd - | if [ $? -ne 0 ]; then - | exit 1 - | fi - | - | echo "starting rpc.statd service" - | rc-service rpc.statd start - | if [ $? -ne 0 ]; then - | exit 1 - | fi - EOS - expect(communicator).to receive(:sudo).with(x) - allow_message_expectations_on_nil described_class.nfs_client_install(machine) + + expect(communicator.received_commands[0]).to match(/apk update/) + expect(communicator.received_commands[1]).to match(/apk add --upgrade nfs-utils/) + expect(communicator.received_commands[2]).to match(/rc-update add rpc.statd/) + expect(communicator.received_commands[3]).to match(/rc-service rpc.statd start/) end end From 39fb58529553765d5386ba965c6c1c1f0b8a3210 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Fri, 26 Jul 2019 08:28:49 +0200 Subject: [PATCH 7/7] alpine: Remove unneeded aliases in change_host_name --- plugins/guests/alpine/cap/change_host_name.rb | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/plugins/guests/alpine/cap/change_host_name.rb b/plugins/guests/alpine/cap/change_host_name.rb index 667fde8a6..a08086998 100644 --- a/plugins/guests/alpine/cap/change_host_name.rb +++ b/plugins/guests/alpine/cap/change_host_name.rb @@ -33,7 +33,7 @@ module VagrantPlugins def fetch_current_hostname hostname = '' - sudo 'hostname -f' do |type, data| + machine.communicate.sudo 'hostname -f' do |type, data| hostname = data.chomp if type == :stdout && hostname.empty? end @@ -41,54 +41,42 @@ module VagrantPlugins end def update_etc_hostname - sudo("echo '#{short_hostname}' > /etc/hostname") + machine.communicate.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 - if test("grep '#{current_hostname}' /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 #{fqdn} #{short_hostname}" + replace = "\\1 #{new_hostname} #{short_hostname}" expression = ['s', search, replace, 'g'].join('@') - sudo("sed -ri '#{expression}' /etc/hosts") + machine.communicate.sudo("sed -ri '#{expression}' /etc/hosts") else # Current hostname entry isn't in /etc/hosts, just append it - sudo("echo '127.0.1.1 #{fqdn} #{short_hostname}' >>/etc/hosts") + machine.communicate.sudo("echo '127.0.1.1 #{new_hostname} #{short_hostname}' >>/etc/hosts") end end def refresh_hostname_service - sudo('hostname -F /etc/hostname') + machine.communicate.sudo('hostname -F /etc/hostname') end def update_mailname - sudo('hostname -f > /etc/mailname') + machine.communicate.sudo('hostname -f > /etc/mailname') end def renew_dhcp - sudo('ifdown -a; ifup -a; ifup eth0') - end - - def fqdn - new_hostname + machine.communicate.sudo('ifdown -a; ifup -a; ifup eth0') end def short_hostname new_hostname.split('.').first end - - def sudo(cmd, &block) - machine.communicate.sudo(cmd, &block) - end - - def test(cmd) - machine.communicate.test(cmd) - end end end end