Skip to content

Commit 65cc9b2

Browse files
dafyddcrosbymeta-codesync[bot]
authored andcommitted
Add --clowntown-disable-locking-mechanism flag
Summary: Add a CLI flag that makes acquire_lock and release_lock no-ops, for use in antlir-builds where concurrent runs are not a concern. Reviewed By: vmagro Differential Revision: D93008263 fbshipit-source-id: 517d0e328553db9d32a5561284d62a877bfe4d1f
1 parent bdff718 commit 65cc9b2

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

chefctl/src/chefctl.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ module Config
221221
# Windows values are as follows: "Idle" => 64, "BelowNormal" => 16384,
222222
# "Normal" => 32, "AboveNormal" => 32768, "High" => 128, "Realtime" => 256
223223
priority nil
224+
225+
# When true, acquire_lock and release_lock become no-ops.
226+
disable_locking false
224227
end
225228

226229
# Chefctl plugins are used to define custom behavior for chefctl.
@@ -825,6 +828,11 @@ def keep_testing
825828

826829
# Acquire the lock
827830
def acquire_lock
831+
if Chefctl::Config.disable_locking
832+
Chefctl.logger.warn('Locking is disabled via --clowntown-disable-locking-mechanism')
833+
return
834+
end
835+
828836
if Chefctl::Config.immediate
829837
Chefctl.lib.stop_or_wait_for_chef(@paths[:chef_cur])
830838
end
@@ -862,6 +870,8 @@ def acquire_lock
862870

863871
# Release the lock, if it's being held.
864872
def release_lock
873+
return if Chefctl::Config.disable_locking
874+
865875
if @lock[:fd]
866876
if @lock[:held]
867877
@lock[:fd].flock(File::LOCK_UN)
@@ -1354,6 +1364,15 @@ def parse_both_passes(argv = nil)
13541364
Chefctl.program_name = v
13551365
end
13561366

1367+
parser.on(
1368+
'--clowntown-disable-locking-mechanism',
1369+
'Disable the locking mechanism so acquire_lock and release_lock are no-ops. ' +
1370+
'This should only be used in situations (ie build system one-off jobs) where ' +
1371+
'there is certainty that chefctl will only be called once.',
1372+
) do
1373+
options[:disable_locking] = true
1374+
end
1375+
13571376
parser.
13581377
on(
13591378
'--priority PRIORITY',

chefctl/src/spec/chefctl_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,42 @@ def lib
197197
end
198198
end
199199

200+
RSpec.describe Chefctl::Main, 'locking with disable_locking' do
201+
let(:main) { Chefctl::Main.new('/var/chef/outputs', 'foo') }
202+
203+
around do |example|
204+
original = Chefctl::Config.disable_locking
205+
Chefctl::Config.disable_locking true
206+
example.run
207+
ensure
208+
Chefctl::Config.disable_locking original
209+
end
210+
211+
it 'acquire_lock is a no-op when disable_locking is true' do
212+
expect(main).not_to receive(:wait_for_lock)
213+
main.acquire_lock
214+
end
215+
216+
it 'release_lock is a no-op when disable_locking is true' do
217+
lock_fd = double('lock_fd')
218+
main.instance_variable_get(:@lock)[:fd] = lock_fd
219+
main.instance_variable_get(:@lock)[:held] = true
220+
expect(lock_fd).not_to receive(:flock)
221+
expect(lock_fd).not_to receive(:close)
222+
expect(File).not_to receive(:unlink)
223+
main.release_lock
224+
end
225+
226+
it 'lock still yields the block when locking is disabled' do
227+
# Stub to prevent filesystem access if disable_locking guard fails
228+
allow(File).to receive(:open).with('/var/lock/subsys/chefctl', anything).
229+
and_raise('locking should be disabled')
230+
yielded = false
231+
main.lock { yielded = true }
232+
expect(yielded).to eq(true)
233+
end
234+
end
235+
200236
RSpec.describe TwoPassParser do
201237
it 'should perform two passes' do
202238
n = 0

0 commit comments

Comments
 (0)