cfe_internal/update/lib.cf
agent bundles
u_systemd_services
Prototype: u_systemd_services(service, state)
Description: Manage standard systemd services
Arguments:
service
: The name of the servicestate
: The desired state the service should be in.
Implementation:
bundle agent u_systemd_services(service,state)
{
vars:
# We explicitly guard for systemd to avoid unnecessary agent time in
# pre-eval
systemd::
"systemctl" string => "/bin/systemctl";
"call_systemctl" string => "$(systemctl) --no-ask-password --global --system";
"systemd_properties" string => "-pLoadState,CanStop,UnitFileState,ActiveState,LoadState,CanStart,CanReload";
"systemd_service_info" slist => string_split(execresult("$(call_systemctl) $(systemd_properties) show $(service)", "noshell"), "\n", "10");
classes:
systemd::
# define a class named after the desired state
"$(state)" expression => "any";
"non_disabling" or => { "start", "stop", "restart", "reload" };
# A collection of classes to determine the capabilities of a given systemd
# service, then start, stop, etc. the service. Also supports a custom action
# for anything not supported
"service_enabled" expression => reglist(@(systemd_service_info), "UnitFileState=enabled");
"service_active" expression => reglist(@(systemd_service_info), "ActiveState=active");
"service_loaded" expression => reglist(@(systemd_service_info), "LoadState=loaded");
"service_notfound" expression => reglist(@(systemd_service_info), "LoadState=not-found");
"can_stop_service" expression => reglist(@(systemd_service_info), "CanStop=yes");
"can_start_service" expression => reglist(@(systemd_service_info), "CanStart=yes");
"can_reload_service" expression => reglist(@(systemd_service_info), "CanReload=yes");
"request_start" expression => strcmp("start", "$(state)");
"request_stop" expression => strcmp("stop", "$(state)");
"request_reload" expression => strcmp("reload", "$(state)");
"request_restart" expression => strcmp("restart", "$(state)");
"action_custom" expression => "!(request_start|request_stop|request_reload|request_restart)";
"action_start" expression => "request_start.!service_active.can_start_service";
"action_stop" expression => "request_stop.service_active.can_stop_service";
"action_reload" expression => "request_reload.service_active.can_reload_service";
"action_restart" or => {
"request_restart",
# Possibly undesirable... if a reload is
# requested, and the service "can't" be
# reloaded, then we restart it instead.
"request_reload.!can_reload_service.service_active",
};
# Starting a service implicitly enables it
"action_enable" expression => "request_start.!service_enabled";
# Respectively, stopping it implicitly disables it
"action_disable" expression => "request_stop.service_enabled";
commands:
systemd.service_loaded:: # note this class is defined in `inventory/linux.cf`
# conveniently, systemd states map to `services` states, except
# for `enable`
"$(call_systemctl) -q start $(service)" if => "action_start";
"$(call_systemctl) -q stop $(service)" if => "action_stop";
"$(call_systemctl) -q reload $(service)" if => "action_reload";
"$(call_systemctl) -q restart $(service)" if => "action_restart";
"$(call_systemctl) -q enable $(service)" if => "action_enable";
"$(call_systemctl) -q disable $(service)" if => "action_disable";
# Custom action for any of the non-standard systemd actions such a
# status, try-restart, isolate, et al.
"$(call_systemctl) $(state) $(service)" if => "action_custom";
reports:
DEBUG|DEBUG_u_systemd_service::
"DEBUG $(this.bundle): using systemd layer to $(state) $(service)";
"DEBUG $(this.bundle): Service $(service) unit file is not loaded; doing nothing"
if => "systemd.!service_loaded";
"DEBUG $(this.bundle): Could not find service: $(service)"
if => "systemd.service_notfound";
}
classes bodies
u_results
Prototype: u_results(scope, class_prefix)
Description: Define classes prefixed with class_prefix
and suffixed with
appropriate outcomes: _kept, _repaired, _not_kept, _error, _failed,
_denied, _timeout, _reached
Arguments:
scope
: The scope in which the class should be defined (bundle
ornamespace
)class_prefix
: The prefix for the classes defined
This body can be applied to any promise and sets global
(namespace
) or local (bundle
) classes based on its outcome. For
instance, with class_prefix
set to abc
:
if the promise is to change a file's owner to
nick
and the file was already owned bynick
, the classesabc_reached
andabc_kept
will be set.if the promise is to change a file's owner to
nick
and the file was owned byadam
and the change succeeded, the classesabc_reached
andabc_repaired
will be set.
This body is a simpler, more consistent version of the body
scoped_classes_generic
, which see. The key difference is that
fewer classes are defined, and only for outcomes that we can know.
For example this body does not define "OK/not OK" outcome classes,
since a promise can be both kept and failed at the same time.
It's important to understand that promises may do multiple things, so a promise is not simply "OK" or "not OK." The best way to understand what will happen when your specific promises get this body is to test it in all the possible combinations.
Suffix Notes:
_reached
indicates the promise was tried. Any outcome will result in a class with this suffix being defined._kept
indicates some aspect of the promise was kept_repaired
indicates some aspect of the promise was repaired_not_kept
indicates some aspect of the promise was not kept. error, failed, denied and timeout outcomes will result in a class with this suffix being defined_error
indicates the promise repair encountered an error_failed
indicates the promise failed_denied
indicates the promise repair was denied_timeout
indicates the promise timed out
Example:
bundle agent example
{
commands:
"/bin/true"
classes => results("bundle", "my_class_prefix");
reports:
my_class_prefix_kept::
"My promise was kept";
my_class_prefix_repaired::
"My promise was repaired";
}
See also: scope
, scoped_classes_generic
, classes_generic
Implementation:
body classes u_results(scope, class_prefix)
{
scope => "$(scope)";
promise_kept => { "$(class_prefix)_reached",
"$(class_prefix)_kept" };
promise_repaired => { "$(class_prefix)_reached",
"$(class_prefix)_repaired" };
repair_failed => { "$(class_prefix)_reached",
"$(class_prefix)_error",
"$(class_prefix)_not_kept",
"$(class_prefix)_failed" };
repair_denied => { "$(class_prefix)_reached",
"$(class_prefix)_error",
"$(class_prefix)_not_kept",
"$(class_prefix)_denied" };
repair_timeout => { "$(class_prefix)_reached",
"$(class_prefix)_error",
"$(class_prefix)_not_kept",
"$(class_prefix)_timeout" };
}
depth_search bodies
u_cfe_internal_recurse
Prototype: u_cfe_internal_recurse(d)
Description: Search for files recursively to a depth of d
across file system boundaries
Arguments:
d
: Number of levels deep to traverse
Implementation:
body depth_search u_cfe_internal_recurse(d)
{
depth => "$(d)";
xdev => "true";
}
classes bodies
u_kept_successful_command_results
Prototype: u_kept_successful_command_results(scope, class_prefix)
Description: Set command to "kept" instead of "repaired" if it returns 0 and define classes suffixed with the appropriate outcomes.
Arguments:
scope
: The scope in which the class should be defined (bundle
ornamespace
)class_prefix
: The prefix for the classes defined
See also: scope
, scoped_classes_generic
, classes_generic
, results
TODO After cfengine_3_10 is no longer supported inherit from u_results and add
in the return code differences.
Implementation:
body classes u_kept_successful_command_results(scope, class_prefix)
{
kept_returncodes => { "0" };
failed_returncodes => { "1" };
scope => "$(scope)";
promise_kept => { "$(class_prefix)_reached",
"$(class_prefix)_kept" };
promise_repaired => { "$(class_prefix)_reached",
"$(class_prefix)_repaired" };
repair_failed => { "$(class_prefix)_reached",
"$(class_prefix)_error",
"$(class_prefix)_not_kept",
"$(class_prefix)_failed" };
repair_denied => { "$(class_prefix)_reached",
"$(class_prefix)_error",
"$(class_prefix)_not_kept",
"$(class_prefix)_denied" };
repair_timeout => { "$(class_prefix)_reached",
"$(class_prefix)_error",
"$(class_prefix)_not_kept",
"$(class_prefix)_timeout" };
}
service_method bodies
u_systemd_services
Prototype: u_systemd_services
Description: Define service method for systemd
Implementation:
body service_method u_systemd_services
{
service_autostart_policy => "none";
service_dependence_chain => "ignore";
service_type => "generic";
service_args => "";
}
perms bodies
u_mog
Prototype: u_mog(mode, user, group)
Description: Set the file's mode, owner and group
Arguments:
mode
: The new modeuser
: The username of the new ownergroup
: The group name
Implementation:
body perms u_mog(mode,user,group)
{
owners => { "$(user)" };
groups => { "$(group)" };
mode => "$(mode)";
}