Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions chefctl/sample_hooks/skip_on_battery.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright 2025-present Facebook
# Copyright 2025-present Phil Dibowitz
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This hook file is located at '/etc/chef/chefctl_hooks.rb'
# You can change this location by passing `-p/--plugin-path` to `chefctl`,
# or by setting `plugin_path` in `chefctl-config.rb`

# Below is a sample hook file that will skip runs when the device is on
# battery.
#
# Hook descriptions and empty hooks have been removed. Refer to the hook
# documentation for descriptions of each method.

module SkipOnBattery
def skip_run?
# If a human is requesting the run, they want the run, so don't worry
# about the battery check.
#
# Another option would be to use the cli_options hook to add an
# override flag, if desired.
if Chefctl::Config.immediate
Chefctl.logger.debug('Skipping battery check due to --immediate flag')
return false
end

if File.exist?('/sys/class/power_supply/BAT0/status')
bat_status = File.read(
'/sys/class/power_supply/BAT0/status',
).strip
Chefctl.logger.debug("Battery status: #{bat_status}")
if bat_status == 'Discharging'
Chefctl.logger.warn('Running on battery power, skipping Chef run')
return true
end
end
false
end
end
37 changes: 32 additions & 5 deletions chefctl/src/chefctl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,25 @@ def generate_certs
end
end

# Called after the lock is acquired, before pre_run (and this before
# the chef run is started). This hook is intended to allow suppressing
# Chef runs under specific conditions. Examples might include:
#
# - Device is on battery
# - Device is not connected to VPN/backhaul/etc.
# - Some global service meant to disable runs during an emergency
#
# Defaults, of course, to false. Should be used with care. While we _will_
# log that the chef run was skipped at the request of the plugin, the plugin
# should log _why_ it was skipped so that it appears in the log.
#
# Note that if the return value is an Integer, that integer is used as
# the exit value of chefctl. If it's `true`, the exit value is 0, and
# if it is `false`, chef runs normally.
def skip_run?
false
end

# Called after the lock is acquired, before the chef run is started.
# Parameters:
# - output is the path to the log file for the chef run
Expand Down Expand Up @@ -885,11 +904,19 @@ def chef_run

symlink_output(:chef_cur)

do_splay unless Chefctl::Config.immediate

plugin.pre_run(@paths[:out])

retval = do_chef_runs
ret = plugin.skip_run?
if ret.is_a?(FalseClass)
do_splay unless Chefctl::Config.immediate
plugin.pre_run(@paths[:out])
retval = do_chef_runs
else
Chefctl.logger.info('Plugin requested skipping chef run.')
# if it's an integer, use that as the exit code, otherwise
# we keep it 0, indicating success
if ret.is_a?(Integer)
retval = ret
end
end

plugin.post_run(@paths[:out], retval)

Expand Down
Loading