Merge pull request #11791 from jbonhag/e/guest-openwrt
Guest support for OpenWrt
This commit is contained in:
commit
a8363db300
19
plugins/guests/openwrt/cap/change_host_name.rb
Normal file
19
plugins/guests/openwrt/cap/change_host_name.rb
Normal file
@ -0,0 +1,19 @@
|
||||
module VagrantPlugins
|
||||
module GuestOpenWrt
|
||||
module Cap
|
||||
class ChangeHostName
|
||||
def self.change_host_name(machine, name)
|
||||
comm = machine.communicate
|
||||
|
||||
if !comm.test("uci get system.@system[0].hostname | grep '^#{name}$'", sudo: false)
|
||||
comm.execute <<~EOH
|
||||
uci set system.@system[0].hostname='#{name}'
|
||||
uci commit system
|
||||
/etc/init.d/system reload
|
||||
EOH
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
plugins/guests/openwrt/cap/halt.rb
Normal file
16
plugins/guests/openwrt/cap/halt.rb
Normal file
@ -0,0 +1,16 @@
|
||||
module VagrantPlugins
|
||||
module GuestOpenWrt
|
||||
module Cap
|
||||
class Halt
|
||||
def self.halt(machine)
|
||||
begin
|
||||
machine.communicate.execute("halt")
|
||||
rescue IOError, Vagrant::Errors::SSHDisconnected
|
||||
# Ignore, this probably means connection closed because it
|
||||
# shut down.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
plugins/guests/openwrt/cap/insert_public_key.rb
Normal file
20
plugins/guests/openwrt/cap/insert_public_key.rb
Normal file
@ -0,0 +1,20 @@
|
||||
require "vagrant/util/shell_quote"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestOpenWrt
|
||||
module Cap
|
||||
class InsertPublicKey
|
||||
def self.insert_public_key(machine, contents)
|
||||
contents = contents.chomp
|
||||
contents = Vagrant::Util::ShellQuote.escape(contents, "'")
|
||||
|
||||
machine.communicate.tap do |comm|
|
||||
comm.execute <<~EOH
|
||||
printf '#{contents}\\n' >> /etc/dropbear/authorized_keys
|
||||
EOH
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
22
plugins/guests/openwrt/cap/remove_public_key.rb
Normal file
22
plugins/guests/openwrt/cap/remove_public_key.rb
Normal file
@ -0,0 +1,22 @@
|
||||
require "vagrant/util/shell_quote"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestOpenWrt
|
||||
module Cap
|
||||
class RemovePublicKey
|
||||
def self.remove_public_key(machine, contents)
|
||||
contents = contents.chomp
|
||||
contents = Vagrant::Util::ShellQuote.escape(contents, "'")
|
||||
|
||||
machine.communicate.tap do |comm|
|
||||
comm.execute <<~EOH
|
||||
if test -f /etc/dropbear/authorized_keys ; then
|
||||
sed -i '/^.*#{contents}.*$/d' /etc/dropbear/authorized_keys
|
||||
fi
|
||||
EOH
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
35
plugins/guests/openwrt/cap/rsync.rb
Normal file
35
plugins/guests/openwrt/cap/rsync.rb
Normal file
@ -0,0 +1,35 @@
|
||||
module VagrantPlugins
|
||||
module GuestOpenWrt
|
||||
module Cap
|
||||
class RSync
|
||||
def self.rsync_installed(machine)
|
||||
machine.communicate.test("which rsync")
|
||||
end
|
||||
|
||||
def self.rsync_install(machine)
|
||||
machine.communicate.tap do |comm|
|
||||
comm.execute <<~EOH
|
||||
opkg update
|
||||
opkg install rsync
|
||||
EOH
|
||||
end
|
||||
end
|
||||
|
||||
def self.rsync_pre(machine, opts)
|
||||
machine.communicate.tap do |comm|
|
||||
comm.execute("mkdir -p '#{opts[:guestpath]}'")
|
||||
end
|
||||
end
|
||||
|
||||
def self.rsync_command(machine)
|
||||
"rsync -zz"
|
||||
end
|
||||
|
||||
def self.rsync_post(machine, opts)
|
||||
# Don't do anything because BusyBox's `find` doesn't support the
|
||||
# syntax in plugins/synced_folders/rsync/default_unix_cap.rb.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
23
plugins/guests/openwrt/guest.rb
Normal file
23
plugins/guests/openwrt/guest.rb
Normal file
@ -0,0 +1,23 @@
|
||||
module VagrantPlugins
|
||||
module GuestOpenWrt
|
||||
class Guest
|
||||
# Name used for guest detection
|
||||
GUEST_DETECTION_NAME = "openwrt".freeze
|
||||
|
||||
def detect?(machine)
|
||||
machine.communicate.test <<~EOH
|
||||
if test -e /etc/openwrt_release; then
|
||||
exit
|
||||
fi
|
||||
if test -r /etc/os-release; then
|
||||
source /etc/os-release && test 'x#{self.class.const_get(:GUEST_DETECTION_NAME)}' = "x$ID" && exit
|
||||
fi
|
||||
if test -r /etc/banner; then
|
||||
cat /etc/banner | grep -qi '#{self.class.const_get(:GUEST_DETECTION_NAME)}' && exit
|
||||
fi
|
||||
exit 1
|
||||
EOH
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
61
plugins/guests/openwrt/plugin.rb
Normal file
61
plugins/guests/openwrt/plugin.rb
Normal file
@ -0,0 +1,61 @@
|
||||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestOpenWrt
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "OpenWrt guest"
|
||||
description "OpenWrt guest support."
|
||||
|
||||
guest(:openwrt, :linux) do
|
||||
require_relative "guest"
|
||||
Guest
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :insert_public_key) do
|
||||
require_relative "cap/insert_public_key"
|
||||
Cap::InsertPublicKey
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :remove_public_key) do
|
||||
require_relative "cap/remove_public_key"
|
||||
Cap::RemovePublicKey
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :change_host_name) do
|
||||
require_relative "cap/change_host_name"
|
||||
Cap::ChangeHostName
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :rsync_installed) do
|
||||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :rsync_install) do
|
||||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :rsync_pre) do
|
||||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :rsync_command) do
|
||||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :rsync_post) do
|
||||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
guest_capability(:openwrt, :halt) do
|
||||
require_relative "cap/halt"
|
||||
Cap::Halt
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
require_relative "../../../../base"
|
||||
|
||||
describe "VagrantPlugins::GuestOpenWrt::Cap::ChangeHostName" do
|
||||
let(:caps) do
|
||||
VagrantPlugins::GuestOpenWrt::Plugin
|
||||
.components
|
||||
.guest_capabilities[:openwrt]
|
||||
end
|
||||
|
||||
let(:machine) { double("machine") }
|
||||
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(comm)
|
||||
end
|
||||
|
||||
after do
|
||||
comm.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".change_host_name" do
|
||||
let(:cap) { caps.get(:change_host_name) }
|
||||
|
||||
it "changes the hostname if appropriate" do
|
||||
cap.change_host_name(machine, "testhost")
|
||||
|
||||
expect(comm.received_commands[0]).to match(/uci get system\.@system\[0\].hostname | grep '^testhost$'/)
|
||||
expect(comm.received_commands[1]).to match(/uci set system.@system\[0\].hostname='testhost'/)
|
||||
expect(comm.received_commands[1]).to match(/uci commit system/)
|
||||
expect(comm.received_commands[1]).to match(/\/etc\/init.d\/system reload/)
|
||||
end
|
||||
end
|
||||
end
|
||||
37
test/unit/plugins/guests/openwrt/cap/halt_test.rb
Normal file
37
test/unit/plugins/guests/openwrt/cap/halt_test.rb
Normal file
@ -0,0 +1,37 @@
|
||||
require_relative "../../../../base"
|
||||
|
||||
describe "VagrantPlugins::GuestOpenWrt::Cap::Halt" do
|
||||
let(:plugin) { VagrantPlugins::GuestOpenWrt::Plugin.components.guest_capabilities[:openwrt].get(:halt) }
|
||||
let(:machine) { double("machine") }
|
||||
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
let(:shutdown_command){ "halt" }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(communicator)
|
||||
end
|
||||
|
||||
after do
|
||||
communicator.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".halt" do
|
||||
it "sends a shutdown signal" do
|
||||
communicator.expect_command(shutdown_command)
|
||||
plugin.halt(machine)
|
||||
end
|
||||
|
||||
it "ignores an IOError" do
|
||||
communicator.stub_command(shutdown_command, raise: IOError)
|
||||
expect {
|
||||
plugin.halt(machine)
|
||||
}.to_not raise_error
|
||||
end
|
||||
|
||||
it "ignores a Vagrant::Errors::SSHDisconnected" do
|
||||
communicator.stub_command(shutdown_command, raise: Vagrant::Errors::SSHDisconnected)
|
||||
expect {
|
||||
plugin.halt(machine)
|
||||
}.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,30 @@
|
||||
require_relative "../../../../base"
|
||||
|
||||
describe "VagrantPlugins::GuestOpenWrt::Cap::InsertPublicKey" do
|
||||
let(:caps) do
|
||||
VagrantPlugins::GuestOpenWrt::Plugin
|
||||
.components
|
||||
.guest_capabilities[:openwrt]
|
||||
end
|
||||
|
||||
let(:machine) { double("machine") }
|
||||
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(comm)
|
||||
end
|
||||
|
||||
after do
|
||||
comm.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".insert_public_key" do
|
||||
let(:cap) { caps.get(:insert_public_key) }
|
||||
|
||||
it "inserts the public key" do
|
||||
cap.insert_public_key(machine, "ssh-rsa ...")
|
||||
|
||||
expect(comm.received_commands[0]).to match(/printf 'ssh-rsa ...\\n' >> \/etc\/dropbear\/authorized_keys/)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,31 @@
|
||||
require_relative "../../../../base"
|
||||
|
||||
describe "VagrantPlugins::GuestOpenWrt::Cap::RemovePublicKey" do
|
||||
let(:caps) do
|
||||
VagrantPlugins::GuestOpenWrt::Plugin
|
||||
.components
|
||||
.guest_capabilities[:openwrt]
|
||||
end
|
||||
|
||||
let(:machine) { double("machine") }
|
||||
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(comm)
|
||||
end
|
||||
|
||||
after do
|
||||
comm.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".remove_public_key" do
|
||||
let(:cap) { caps.get(:remove_public_key) }
|
||||
|
||||
it "removes the public key" do
|
||||
cap.remove_public_key(machine, "ssh-rsa keyvalue comment")
|
||||
expect(comm.received_commands[0]).to match(/if test -f \/etc\/dropbear\/authorized_keys ; then/)
|
||||
expect(comm.received_commands[0]).to match(/sed -i '\/\^.*ssh-rsa keyvalue comment.*\$\/d' \/etc\/dropbear\/authorized_keys/)
|
||||
expect(comm.received_commands[0]).to match(/fi/)
|
||||
end
|
||||
end
|
||||
end
|
||||
76
test/unit/plugins/guests/openwrt/cap/rsync_test.rb
Normal file
76
test/unit/plugins/guests/openwrt/cap/rsync_test.rb
Normal file
@ -0,0 +1,76 @@
|
||||
require_relative "../../../../base"
|
||||
|
||||
describe "VagrantPlugins::VagrantPlugins::Cap::Rsync" do
|
||||
let(:caps) do
|
||||
VagrantPlugins::GuestOpenWrt::Plugin
|
||||
.components
|
||||
.guest_capabilities[:openwrt]
|
||||
end
|
||||
|
||||
let(:machine) { double("machine") }
|
||||
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
let(:guest_directory) { "/guest/directory/path" }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(comm)
|
||||
end
|
||||
|
||||
after do
|
||||
comm.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".rsync_installed" do
|
||||
let(:cap) { caps.get(:rsync_installed) }
|
||||
|
||||
describe "when rsync is in the path" do
|
||||
it "is true" do
|
||||
comm.stub_command("which rsync", stdout: '/usr/bin/rsync', exit_code: 0)
|
||||
expect(cap.rsync_installed(machine)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe "when rsync is not in the path" do
|
||||
it "is false" do
|
||||
comm.stub_command("which rsync", stdout: '', exit_code: 1)
|
||||
expect(cap.rsync_installed(machine)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".rsync_install" do
|
||||
let(:cap) { caps.get(:rsync_install) }
|
||||
|
||||
it "installs rsync" do
|
||||
cap.rsync_install(machine)
|
||||
|
||||
expect(comm.received_commands[0]).to match(/opkg update/)
|
||||
expect(comm.received_commands[0]).to match(/opkg install rsync/)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".rsync_command" do
|
||||
let(:cap) { caps.get(:rsync_command) }
|
||||
|
||||
it "provides the rsync command to use" do
|
||||
expect(cap.rsync_command(machine)).to eq("rsync -zz")
|
||||
end
|
||||
end
|
||||
|
||||
describe ".rsync_pre" do
|
||||
let(:cap) { caps.get(:rsync_pre) }
|
||||
|
||||
it "creates target directory on guest" do
|
||||
cap.rsync_pre(machine, :guestpath => guest_directory)
|
||||
expect(comm.received_commands[0]).to match(/mkdir -p '\/guest\/directory\/path'/)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".rsync_post" do
|
||||
let(:cap) { caps.get(:rsync_post) }
|
||||
|
||||
it "is a no-op" do
|
||||
cap.rsync_post(machine, {})
|
||||
expect(comm).to_not receive(:execute)
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
x
Reference in New Issue
Block a user