Chris Roberts 4751353a5f Fetch reboot env var at run time and keep constant values constant
Keep the default duration as a constant and fetch the custom environment
variable at run time with a fallback to the default. Set the sleep duration
into a constant and add tests covering the expected behaviors when the
default duration is in use as well as the override value. Also match the
environment variable up with the constant just for consistency.
2020-11-03 15:11:10 -08:00

149 lines
5.5 KiB
Ruby

require_relative "../../../../base"
require Vagrant.source_root.join("plugins/guests/windows/cap/reboot")
describe "VagrantPlugins::GuestWindows::Cap::Reboot" do
let(:described_class) do
VagrantPlugins::GuestWindows::Plugin.components.guest_capabilities[:windows].get(:wait_for_reboot)
end
let(:vm) { double("vm") }
let(:config) { double("config") }
let(:machine) { double("machine", ui: ui) }
let(:guest) { double("guest") }
let(:communicator) { double("communicator") }
let(:ui) { double("ui") }
before do
allow(machine).to receive(:communicate).and_return(communicator)
allow(machine).to receive(:guest).and_return(guest)
allow(machine.guest).to receive(:ready?).and_return(true)
allow(machine).to receive(:config).and_return(config)
allow(config).to receive(:vm).and_return(vm)
allow(ui).to receive(:info)
end
describe ".reboot" do
before do
allow(vm).to receive(:communicator).and_return(:winrm)
end
it "reboots the vm" do
allow(communicator).to receive(:execute)
expect(communicator).to receive(:test).with(/# Function/, { error_check: false, shell: :powershell }).and_return(0)
expect(communicator).to receive(:execute).with(/shutdown/, { shell: :powershell }).and_return(0)
expect(described_class).to receive(:wait_for_reboot)
described_class.reboot(machine)
end
context "user output" do
before do
allow(communicator).to receive(:execute)
allow(described_class).to receive(:wait_for_reboot)
end
after { described_class.reboot(machine) }
it "sends message to user that guest is rebooting" do
expect(communicator).to receive(:test).and_return(true)
expect(ui).to receive(:info)
end
end
context "with exceptions while waiting for reboot" do
before { allow(described_class).to receive(:sleep) }
it "should retry on any standard error" do
allow(communicator).to receive(:execute)
expect(communicator).to receive(:test).with(/# Function/, { error_check: false, shell: :powershell }).and_return(0)
expect(communicator).to receive(:execute).with(/shutdown/, { shell: :powershell }).and_return(0)
expect(described_class).to receive(:wait_for_reboot).and_raise(StandardError)
expect(described_class).to receive(:wait_for_reboot)
described_class.reboot(machine)
end
it "should not retry when exception is not a standard error" do
allow(communicator).to receive(:execute)
expect(communicator).to receive(:test).with(/# Function/, { error_check: false, shell: :powershell }).and_return(0)
expect(communicator).to receive(:execute).with(/shutdown/, { shell: :powershell }).and_return(0)
expect(described_class).to receive(:wait_for_reboot).and_raise(Exception)
expect { described_class.reboot(machine) }.to raise_error(Exception)
end
end
end
describe "winrm communicator" do
before do
allow(vm).to receive(:communicator).and_return(:winrm)
end
describe ".wait_for_reboot" do
it "runs reboot detect script" do
expect(communicator).to receive(:execute).with(/# Function/, { error_check: false, shell: :powershell }).and_return(0)
allow(communicator).to receive(:execute)
described_class.wait_for_reboot(machine)
end
it "fixes symlinks to network shares" do
allow(communicator).to receive(:execute).and_return(0)
expect(communicator).to receive(:execute).with('net use', { error_check: false, shell: :powershell })
described_class.wait_for_reboot(machine)
end
end
end
describe "ssh communicator" do
before do
allow(vm).to receive(:communicator).and_return(:ssh)
end
describe ".wait_for_reboot" do
it "does execute Windows reboot detect script" do
expect(communicator).to receive(:execute).with(/# Function/, { error_check: false, shell: :powershell }).and_return(0)
expect(communicator).to receive(:execute).with('net use', { error_check: false, shell: :powershell })
described_class.wait_for_reboot(machine)
end
end
end
context "reboot configuration" do
before do
allow(communicator).to receive(:execute)
expect(communicator).to receive(:test).with(/# Function/, { error_check: false, shell: :powershell }).and_return(0)
expect(communicator).to receive(:execute).with(/shutdown/, { shell: :powershell }).and_return(0)
allow(described_class).to receive(:sleep)
allow(described_class).to receive(:wait_for_reboot).and_raise(StandardError)
end
context "default retry duration value" do
let(:max_retries) { (described_class::DEFAULT_MAX_REBOOT_RETRY_DURATION / described_class::WAIT_SLEEP_TIME) + 2 }
it "should receive expected number of wait_for_reboot calls" do
expect(described_class).to receive(:wait_for_reboot).exactly(max_retries).times
expect { described_class.reboot(machine) }.to raise_error(StandardError)
end
end
context "with custom retry duration value" do
let(:duration) { 10 }
let(:max_retries) { (duration / described_class::WAIT_SLEEP_TIME) + 2 }
before do
expect(ENV).to receive(:fetch).with("VAGRANT_MAX_REBOOT_RETRY_DURATION", anything).and_return(duration)
end
it "should receive expected number of wait_for_reboot calls" do
expect(described_class).to receive(:wait_for_reboot).exactly(max_retries).times
expect { described_class.reboot(machine) }.to raise_error(StandardError)
end
end
end
end