Standardized Hooks Management Interface
Summary
Hook action code must be associated with a hookable event so that it is executed in response to the appropriate cPanel & WHM event. You can establish these associates using the Standardized Hooks management CLI utility.
The CLI utility takes Standardized Hooks descriptors and a reference to the hook action code. Using this information, a registry entry is added to the Standardized Hooks database.
You can use this utility to add, delete, or list Standardized Hooks on the local server.
Synopsis
manage_hooks UTILITYACTION [HOOKACTIONTYPE HOOKACTIONREFERENCE] [options]
Arguments
UTILITYACTION
The action the utility should perform against the hook database. Valid actions include
add,
delete,
list, and
fullhelp.
update_db is also a valid action of older hook databases prior to cPanel & WHM 11.32.1. Using this action should not be necessary as pre-existing database entries will be altered properly during the next cPanel & WHM update.
HOOKACTIONTYPE
Valid input values include script and module and correspond to the format of the hook action code in question. This argument is only valid and required when using the add or delete UTILITYACTION.
HOOKACTIONREFERENCE
A string that provides the location of the custom hook action code. If the hook action code is a script, this value should contain an absolute path and filename of the script. If the hook action code is a Perl module, the value will be the same as the package within the Perl module. This argument is only valid and required when using the add or delete UTILITYACTION.
Options
Most of the following options are descriptors and attributes that define when and how the hook action code should be executed. However, some options are used directly by the CLI utility and alter the way the arguments and descriptors are processed.
Like many Linux/GNU CLI utilities, when an option is passed and a value is not provided, an implicit
true value is assigned. While this style of usage functions in a deterministic way, it’s usually best to be explicit, providing an appropriate value to each option.
--category
The category with which the hook action code will be associated.
--event
The category’s event, with which the hook action code will be associated.
--rollback
Additional hook action code that should be executed when another Standardized Hook associated with the same hookable event fails. This option is only applicable to events that have the blocking attribute.
--escalateprivs
A boolean value indicating whether privilege escalation (to root) should occur before executing the hook action code. This option is only applicable for hookable events that have the escalateprivs attribute and for hook action code implemented as a script.
--weight
An integer value for ordering the hook action code when multiple Standardized Hoooks are associated with the same hookable event. Lower values are executed before higher values. By default, the first Standardized Hook associated with a given event will be assigned a weight of 100. Subsequent default values will be 100 points higher than the highest next registered hook. For example, 3 Standardized Hooks added without a defined weight would be assigned values of 100, 200, and 300, respectively. If a Standardized Hook was added later, that defined a specific weight of 455, subsequent auto-assignment weights would be 555, 655, etc.
--check
Additional hook action code that should be executed before the execution of the primary hook action code. If the check hook action code returns a fail status, the primary hook action code will not be performed.
--manual
A boolean value indicating that all descriptors and attributes should be sourced from option flags. If not provided, the CLI utility will attempt to source descriptors and attributes from within the hook action code reference via an implementation of the describe pattern. If a describe pattern is not found, the CLI utility will use any descriptors and attributes provided as options. Furthermore, if not provided, and a describe pattern is not implemented, the CLI utility will attempt to recover and act as if a value of --manual 1 were passed, sourcing any options flags, and producing a warning.The describe pattern descriptors and attributes cannot be mixed with ones pass as option flags. All items must come from one source or the other.
--action
A string value representing a specific sub-action. This option is provided for use in combination with the --manual 1 option and value. If the hook action type is script, the value will be appended to the hook action reference, i.e., a CLI argument used when invoking the hook action code. If the hook action type is module, the value is treated as a function contained within the Perl package that was declared in the hook action reference. The action option is provided to emulate the explicit nature available within a describe pattern implementation. In most cases, developers will be better served by employing a describe pattern instead of using this option to remove potentially ambiguous use.
--output
This option is only available with the list utility action. Passing a string value of JSON here will produce a JSON serialization for programmatic digest instead of the default, human-readable output.
--help
Print basic usage documentation for the CLI utility to STDOUT. This option is assumed if an invalid utility action is provided. More verbose help documentation is available by executing the CLI utility with the fullhelp utility action argument.
Example
This example illustrates the
lists UTILITYACTION, which outputs a list of existing registered hooks. In this example, there are three registered hooks:
[usr/local/cpanel/bin] $ ./manage_hooks list
Cpanel:
Api2::StatsBar::stat:
stage: pre
weight: 1000
id: rA73DrbGgM8QXvypjRkvsuLL
exectype: module
hook: MyApp::TestStatsBar
Whostmgr:
Accounts::Create:
stage: post
escalateprivs: 0
weight: 1000
id: OtAWTxns6w1wuIGTCmdnydcX
exectype: script
hook: /var/cpanel/myapp/testhook_post.php
--
stage: pre
escalateprivs: 0
weight: 1000
id: au9Pf6EdpOKNtWjrQKW_1IZC
exectype: script
hook: /var/cpanel/myapp/testhook_pre.php
In the example above:
- A Perl module subroutine,
MyApp::TestStatsBar, located in /var/cpanel/perl5/lib/MyApp.pm, will execute the cPanel API 2 StatsBar::Stat function.
- A PHP script at
/var/cpanel/myapp/testhook_post.php will be executed after cPanel accounts are created. This script will run regardless of which method was used to create the account, i.e., the WHM interface, the /usr/local/cpanel/scripts/wwwacct script, the remote API createacct, etc.
- A PHP script at
/var/cpanel/myapp/testhook_pre.php will be executed before cPanel accounts are created. This script will run regardless of which method was used to create the account, i.e., the WHM interface, the =/usr/local/cpanel/scripts/wwwacct script, the remote API createacct, etc.
Describe patterns
The Standardized Hooks System provides a robust way to embed details of hookable actions within custom hook action code. If the author utilizes this pattern, he or she is absolved from having to specify all of the details required by the CLI utility when registering the hookable action.
While the Standardized Hooks System does not require a describe pattern, we strongly recommend using this method as it is far simpler than specifying each option to the
manage_hooks utility.
Be aware that current implementation does not allow for individual hook selection in any automated sense. That is, the CLI utility invokes the describe pattern as a single action and digests the return as authoritative and absolute.
Using a describe pattern in a Perl module
Perl modules utilize a subroutine inside the module named
describe(). The
describe() subroutine must return a Perl array reference. This array reference must contain one or more hash references. Each hash reference is related to 1 hookable action and is used for a single entry for the Standardized Hooks database.
The hash reference must, at minimum, contain the
category,
event,
stage,
exectype, and
hook descriptors. You can find examples of this in the appropriate section below.
Using a describe pattern in a script
Authors of scripts must include argument evaluation in the hook action code in order to use describe patterns. The CLI utility will call the script with one CLI script argument,
--describe. The return output, via STDOUT, of the script should be a JSON encoded string. When decoded, the JSON structure should be an array that contains one or more hashes, or associative arrays. Each hash reference is related to one hookable action and is used for a single entry for the Standardized Hooks database.
For scripts that implement the describe pattern, the
hook descriptor should be exactly how the script should be invoked to perform the hookable action.
- If the script is monolithic, and performs internal logic based on the context, simply provide the script's absolute path and filename.
- If the script can parse input arguments via a shell argument array (
$argv or @argv, etc) then it should specify the absolute path and filename, followed by the proper argument required to switch to the proper code block.
You can find examples of this in the appropriate section below.
Examples
Management via CLI options
Managing a Perl module
The following section illustrates how to manually add and delete Standardized Hooks implemented in a Perl module. The examples assume that the
/var/cpanel/perl5/lib/MyApp/ directory contains
WHM.pm. This module contains the
remove() subroutine that will be called prior to an account being removed from the system.
Adding a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks add module MyApp::WHM --manual --category Whostmgr --event 'Accounts::Remove' --stage pre --action remove
Removing a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks delete module MyApp::WHM --manual --category Whostmgr --event 'Accounts::Remove' --stage pre --action remove
Managing a script
The following section illustrates how to manually add and delete a Standardized Hook implemented in a script. The examples assume that the
/var/cpanel/myapp/ directory contains
whm.php. Inside this script, there is logic that can interpret command line arguments, to which a
--do_remove switch is honored.
/var/cpanel/myapp/whm.php --do_remove will be called prior to an account being removed from the system.
Adding a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks add script /var/cpanel/myapp/whm.php --manual --category Whostmgr --event 'Accounts::Remove' --stage pre --action='--do_remove'
Removing a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks delete script /var/cpanel/myapp/whm.php --manual --category Whostmgr --event 'Accounts::Remove' --stage pre --action='--do_remove'
More about the --action option
As observed in the above examples, when using the
--action descriptor option with scripts, you should pay particular attention to how the value is presented. If not properly expressed,
manage_hooks can misinterpret that value as a description option switch. This only occurs for values that lead with one or more hyphens. Some valid expressions are:
--action='--for_hook_script'
--action="--for_hook_script --more_hook_switch"
--action '"--for_hook_script'"
--action ""-one_hyphen_switch” “-more_switches""
The choice of double or single quotes is irrelevant. If the ‘--action’ descriptor is immediately followed by an equal sign, simply quote the entire value once. If it is immediately followed by a space, quote each script switch and encapsulate the entire value in another type of quote
Management via describe patterns
The preferred method for defining hookable actions is to use a describe pattern. Managing the hook with the CLI utility becomes easier, as all of the descriptor options are embedded in the Perl module or script.
Managing a Perl module
In order to use the describe pattern, the Perl module must contain a
describe() subroutine. It must return an array reference which contains one or more hash references.
The following example illustrates two hooks. Both utilize the MyApp::WHM.pm (in /var/cpanel/perl5/lib/). The first will execute MyApp::WHM::add() after an account is created by cPanel & WHM, and the second will execute MyApp::WHM::remove() prior to account deletion:
# file - /var/cpanel/perl5/lib/MyApp/WHM.pm
package MyApp::WHM;
sub describe {
my $my_add = {
'category' => 'Whostmgr',
'event' => 'Accounts::Create',
'stage' => 'post',
'hook' => 'MyApp::WHM::add',
'exectype' => 'module',
};
my $my_remove = {
'category' => 'Whostmgr',
'event' => 'Accounts::Remove',
'stage' => 'post',
'hook' => 'MyApp::WHM::remove',
'exectype' => 'module',
};
return [$my_add, $my_remove];
}
sub add {
# ....
}
sub remove {
# ....
}
1;
Adding a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks add module MyApp::WHM
Removing a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks delete module MyApp::WHM
Managing a script
The same methodologies apply to a describe pattern implemented in a script as do when implementing them in a Perl module. The primary difference is that the describe data will not be returned, but printed to STDOUT as a JSON encoded string.
The following example is of a PHP script, implementing the same hookable events as in the Perl module example above.
#!/usr/bin/php -q
<?php
// file - /var/cpanel/myapp/whm.php
// Any switches passed to this script
$switches = (count($argv) > 1) ? $argv : array();
if (in_array('--describe', $switches)) {
echo json_encode( describe() );
exit;
} elseif (in_array('--add', $switches)) {
list($status, $msg) = add();
echo "$status $msg";
exit;
} elseif (in_array('--remove', $switches)) {
list($status, $msg) = remove();
echo "$status $msg";
exit;
} else {
echo '0 myapp/whm.php needs a valid switch';
exit(1);
}
function describe() {
$my_add = array(
'category' => 'Whostmgr',
'event' => 'Accounts::Create',
'stage' => 'post',
'hook' => '/var/cpanel/myapp/whm.php --add',
'exectype' => 'script',
);
$my_remove = array(
'category' => 'Whostmgr',
'event' => 'Accounts::Remove',
'stage' => 'post',
'hook' => '/var/cpanel/myapp/whm.php --remove',
'exectype' => 'script',
);
return array($my_add, $my_remove);
}
function add() {
//....
}
function remove() {
//....
}
?>
Adding a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks add script /var/cpanel/myapp/whm.php
Removing a Standardized Hook
[usr/local/cpanel/bin] $ ./manage_hooks delete script /var/cpanel/myapp/whm.php
Standardized Hooks database
The Standardized Hooks Database is located at
/var/cpanel/hooks.yaml. It is a YAML datastore. The datastore is the authoritative reference for hooks that should be executed at various hookable events.
This file should not be edited by hand, as accidental errors are easily introduced. Hooks should be managed using a defined utility, such as the CLI utility
/usr/local/cpanel/bin/manage_hooks.
Additionally, the Standardized Hooks System maintains a cached copy of this database,
/var/cpanel/hooks.cache.
If manual changes are made the YAML datastore, the cache file should be deleted. The cache file will be regenerated automatically the next time the Standardized Hooks System is queried internally or by a management utility.