Improved deploy lock acquisition
1. Don't raise lock error for non-lock issues during lock acquire (see https://github.com/mrsked/mrsk/pull/181) 2. If there is an error while the lock is held, don't release the lock and send a warning to stderr
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
module Mrsk::Cli
|
module Mrsk::Cli
|
||||||
|
class LockError < StandardError; end
|
||||||
end
|
end
|
||||||
|
|
||||||
# SSHKit uses instance eval, so we need a global const for ergonomics
|
# SSHKit uses instance eval, so we need a global const for ergonomics
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ module Mrsk::Cli
|
|||||||
class Base < Thor
|
class Base < Thor
|
||||||
include SSHKit::DSL
|
include SSHKit::DSL
|
||||||
|
|
||||||
class LockError < StandardError; end
|
|
||||||
|
|
||||||
def self.exit_on_failure?() true end
|
def self.exit_on_failure?() true end
|
||||||
|
|
||||||
class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
|
class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
|
||||||
@@ -82,8 +80,11 @@ module Mrsk::Cli
|
|||||||
acquire_lock
|
acquire_lock
|
||||||
|
|
||||||
yield
|
yield
|
||||||
ensure
|
|
||||||
release_lock
|
release_lock
|
||||||
|
rescue
|
||||||
|
error " \e[31mDeploy lock was not released\e[0m" if MRSK.lock_count > 0
|
||||||
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
def acquire_lock
|
def acquire_lock
|
||||||
@@ -95,9 +96,10 @@ module Mrsk::Cli
|
|||||||
rescue SSHKit::Runner::ExecuteError => e
|
rescue SSHKit::Runner::ExecuteError => e
|
||||||
if e.message =~ /cannot create directory/
|
if e.message =~ /cannot create directory/
|
||||||
invoke "mrsk:cli:lock:status", []
|
invoke "mrsk:cli:lock:status", []
|
||||||
|
raise LockError, "Deploy lock found"
|
||||||
|
else
|
||||||
|
raise e
|
||||||
end
|
end
|
||||||
|
|
||||||
raise LockError, "Deploy lock found"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def release_lock
|
def release_lock
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class Mrsk::Cli::Lock < Mrsk::Cli::Base
|
|||||||
message = options[:message]
|
message = options[:message]
|
||||||
handle_missing_lock do
|
handle_missing_lock do
|
||||||
on(MRSK.primary_host) { execute *MRSK.lock.acquire(message, MRSK.config.version) }
|
on(MRSK.primary_host) { execute *MRSK.lock.acquire(message, MRSK.config.version) }
|
||||||
say "Set the deploy lock"
|
say "Acquired the deploy lock"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ class Mrsk::Cli::Lock < Mrsk::Cli::Base
|
|||||||
def release
|
def release
|
||||||
handle_missing_lock do
|
handle_missing_lock do
|
||||||
on(MRSK.primary_host) { execute *MRSK.lock.release }
|
on(MRSK.primary_host) { execute *MRSK.lock.release }
|
||||||
say "Removed the deploy lock"
|
say "Released the deploy lock"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,8 @@ class CliTestCase < ActiveSupport::TestCase
|
|||||||
def stdouted
|
def stdouted
|
||||||
capture(:stdout) { yield }.strip
|
capture(:stdout) { yield }.strip
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
def stderred
|
||||||
|
capture(:stderr) { yield }.strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -53,6 +53,46 @@ class CliMainTest < CliTestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "deploy when locked" do
|
||||||
|
Thread.report_on_exception = false
|
||||||
|
|
||||||
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
|
.with { |*arg| arg[0..1] == [:mkdir, :mrsk_lock] }
|
||||||
|
.raises(RuntimeError, "mkdir: cannot create directory ‘mrsk_lock’: File exists")
|
||||||
|
|
||||||
|
Mrsk::Cli::Base.any_instance.expects(:invoke).with("mrsk:cli:lock:status", [])
|
||||||
|
|
||||||
|
assert_raises(Mrsk::Cli::LockError) do
|
||||||
|
run_command("deploy")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deploy error when locking" do
|
||||||
|
Thread.report_on_exception = false
|
||||||
|
|
||||||
|
SSHKit::Backend::Abstract.any_instance.stubs(:execute)
|
||||||
|
.with { |*arg| arg[0..1] == [:mkdir, :mrsk_lock] }
|
||||||
|
.raises(SocketError, "getaddrinfo: nodename nor servname provided, or not known")
|
||||||
|
|
||||||
|
assert_raises(SSHKit::Runner::ExecuteError) do
|
||||||
|
run_command("deploy")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deploy errors leave lock in place" do
|
||||||
|
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }
|
||||||
|
|
||||||
|
Mrsk::Cli::Main.any_instance.expects(:invoke)
|
||||||
|
.with("mrsk:cli:server:bootstrap", [], invoke_options)
|
||||||
|
.raises(RuntimeError)
|
||||||
|
|
||||||
|
assert_equal 0, MRSK.lock_count
|
||||||
|
assert_raises(RuntimeError) do
|
||||||
|
stderred { run_command("deploy") }
|
||||||
|
end
|
||||||
|
assert_equal 1, MRSK.lock_count
|
||||||
|
end
|
||||||
|
|
||||||
test "redeploy" do
|
test "redeploy" do
|
||||||
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }
|
invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "skip_broadcast" => false, "version" => "999" }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user