Ensure domain removal/halt limited to provider error (#1420)

Switch to dedicated actions to trigger destroy/halt via the recovery
mechanism if the VM bring up has failed to complete the bring up of the
machine.

Fixes: #1328
This commit is contained in:
Darragh Bailey
2021-12-04 16:55:50 +00:00
committed by GitHub
parent 380b3c2096
commit 1f9fd6dc2e
5 changed files with 204 additions and 67 deletions

View File

@@ -0,0 +1,130 @@
# frozen_string_literal: true
require 'spec_helper'
require 'support/sharedcontext'
require 'vagrant/action/runner'
require 'vagrant-libvirt/action'
require 'vagrant-libvirt/action/cleanup_on_failure'
describe VagrantPlugins::ProviderLibvirt::Action::CleanupOnFailure do
subject { described_class }
let(:callable_error) do
Class.new do
def initialize(app, env)
end
def self.name
"TestAction"
end
def call(env)
raise Exception, "some action failed"
end
end
end
include_context 'libvirt'
include_context 'unit'
let(:libvirt_domain) { double('libvirt_domain') }
let(:runner) { Vagrant::Action::Runner.new(env) }
let(:state) { double('state') }
before do
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
.to receive(:connection).and_return(connection)
allow(machine).to receive(:id).and_return('test-machine-id')
allow(machine).to receive(:state).and_return(state)
allow(logger).to receive(:info)
allow(logger).to receive(:error)
allow(runner).to receive(:run).and_call_original
env[:action_runner] = runner
env[:destroy_on_error] = true
end
describe '#recover' do
let(:action_chain) do
Vagrant::Action::Builder.new.tap do |b|
b.use subject
b.use callable_error
end
end
context 'not created' do
before do
expect(state).to receive(:id).and_return(:not_created)
end
it 'should return early' do
expect(logger).to_not receive(:info).with('VM completed provider setup, no need to teardown')
expect { runner.run(action_chain) }.to raise_error(Exception, "some action failed")
end
end
context 'running' do
before do
allow(state).to receive(:id).and_return(:running)
end
it 'should destroy' do
expect(VagrantPlugins::ProviderLibvirt::Action).to_not receive(:action_halt)
expect(VagrantPlugins::ProviderLibvirt::Action).to receive(:action_destroy).and_return(Vagrant::Action::Builder.new)
expect(logger).to_not receive(:info).with('VM completed provider setup, no need to teardown')
expect { runner.run(action_chain) }.to raise_error(Exception, "some action failed")
end
context 'halt on error enabled' do
before do
env[:halt_on_error] = true
end
it 'should halt' do
expect(VagrantPlugins::ProviderLibvirt::Action).to receive(:action_halt).and_return(Vagrant::Action::Builder.new)
expect(VagrantPlugins::ProviderLibvirt::Action).to_not receive(:action_destroy)
expect(logger).to_not receive(:info).with('VM completed provider setup, no need to teardown')
expect { runner.run(action_chain) }.to raise_error(Exception, "some action failed")
end
end
context 'destroy on error disabled' do
before do
env[:destroy_on_error] = false
end
it 'should not destroy' do
expect(VagrantPlugins::ProviderLibvirt::Action).to_not receive(:action_halt)
expect(VagrantPlugins::ProviderLibvirt::Action).to_not receive(:action_destroy)
expect(logger).to_not receive(:info).with('VM completed provider setup, no need to teardown')
expect { runner.run(action_chain) }.to raise_error(Exception, "some action failed")
end
end
context 'completed setup' do
let(:action_chain) do
Vagrant::Action::Builder.new.tap do |b|
b.use subject
b.use VagrantPlugins::ProviderLibvirt::Action::SetupComplete
b.use callable_error
end
end
it 'should not perform halt or destroy' do
expect(VagrantPlugins::ProviderLibvirt::Action).to_not receive(:action_halt)
expect(VagrantPlugins::ProviderLibvirt::Action).to_not receive(:action_destroy)
expect(logger).to receive(:info).with('VM completed provider setup, no need to teardown')
expect { runner.run(action_chain) }.to raise_error(Exception, "some action failed")
end
end
end
end
end

View File

@@ -86,46 +86,4 @@ describe VagrantPlugins::ProviderLibvirt::Action::WaitTillUp do
end
end
end
describe '#recover' do
before do
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver).to receive(:get_domain).and_return(machine)
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver).to receive(:state)
.and_return(:not_created)
allow(env).to receive(:[]).and_call_original
end
it 'should do nothing by default' do
expect(env).to_not receive(:[]).with(:action_runner) # cleanup
expect(subject.recover(env)).to be_nil
end
context 'with machine coming up' do
before do
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver).to receive(:state)
.and_return(:running)
env[:destroy_on_error] = true
end
context 'and user has disabled destroy on failure' do
before do
env[:destroy_on_error] = false
end
it 'skips terminate on failure' do
expect(env).to_not receive(:[]).with(:action_runner) # cleanup
expect(subject.recover(env)).to be_nil
end
end
context 'and using default settings' do
let(:runner) { double('runner') }
it 'deletes VM on failure' do
expect(env).to receive(:[]).with(:action_runner).and_return(runner) # cleanup
expect(runner).to receive(:run)
expect(subject.recover(env)).to be_nil
end
end
end
end
end