Skip to content

Commit

Permalink
Fixes #12593: Add support for BSD-style init scripts services (rc.d) …
Browse files Browse the repository at this point in the history
…(slackware)
  • Loading branch information
victorqrt committed May 29, 2018
1 parent f9e6d56 commit f63011b
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 46 deletions.
1 change: 1 addition & 0 deletions tree/20_cfe_basics/cfengine/common.cf
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,4 @@ body classes kept_successful_command
{
kept_returncodes => { "0" };
}

134 changes: 125 additions & 9 deletions tree/20_cfe_basics/ncf_lib.cf
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,36 @@ body edit_defaults ncf_empty_select(select)
edit_backup => "timestamp";
}

# Copies classes with source_prefix into destination_prefix
# This copies the whole class set
bundle agent ncf_classes_copy(source_prefix, destination_prefix)
{
vars:
"prefix" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout" };
"suffix" slist => { "repaired", "ok", "reached", "failed", "not_ok", "not_kept", "not_repaired", "denied", "timeout", "kept", "error" };

destination_exists::
# Copy result classes prefixes
"${prefix}_local_destination_prefix"
string => "${prefix}_${destination_prefix}",
ifvarclass => "${prefix}_${source_prefix}",
classes => always("${prefix}_${destination_prefix}");

# Copy result classes suffixes
"local_destination_prefix_${suffix}"
string => "${destination_prefix}_${suffix}",
ifvarclass => "${source_prefix}_${suffix}",
classes => always("${destination_prefix}_${suffix}");

classes:
# this line will not be evaluated by cfengine if destination_prefix contains a variable that does not exist
# and it will always be evaluated to true otherwise
"destination_defined" expression => strcmp("${destination_prefix}", "${destination_prefix}");
"destination_not_empty" not => strcmp("${destination_prefix}", "");
"destination_exists" and => { "destination_defined", "destination_not_empty" };

}

# defines ncf_services_${service}_${action}
#
# Standard actions are:
Expand Down Expand Up @@ -987,6 +1017,10 @@ bundle agent ncf_services(service, action)
"action_command" string => "${svc_action_cmd[${action}]}";
"method" string => "svcadm/svcs";

# Slackware
pass1.slackware.!systemctl_utility_present.!is_upstart_service.!svcadm_utility_present::
"method" string => "/etc/rc.d";

###########################################################################
# Boot actions
###########################################################################
Expand Down Expand Up @@ -1014,10 +1048,12 @@ bundle agent ncf_services(service, action)
"method" string => "lsitab/chitab";

# /etc/rcX.d/
pass1.is_boot_action.is_check_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.!chitab_utility_present::
pass1.is_boot_action.is_check_action.(!systemctl_utility_present|is_init_service).!is_upstart_service.!svcadm_utility_present.!chkconfig_utility_present.!chitab_utility_present.!slackware::
"action_command" string => "${paths.path[test]} -f /etc/rc`/sbin/runlevel | ${paths.path[cut]} -d' ' -f2`.d/S??${service}";
"method" string => "/etc/rcX.d/";

# Slackware boot actions are not performed by command, they are implemented in the 'methods' promises

###########################################################################
# Non-boot actions
###########################################################################
Expand Down Expand Up @@ -1052,8 +1088,16 @@ bundle agent ncf_services(service, action)
ifvarclass => "is_check_action";
"method" string => "/etc/init.d/";

# Slackware
pass1.slackware.!is_boot_action::
"action_command" string => "/etc/rc.d/rc.${service} ${action}",
ifvarclass => "!is_check_action";
# is-active is mapped to "status"
"action_command" string => "/etc/rc.d/rc.${service} status",
ifvarclass => "is_check_action";
# windows
# Implementation is done in services promises

windows::
"method" string => "Windows Service Manager";

Expand Down Expand Up @@ -1114,7 +1158,7 @@ bundle agent ncf_services(service, action)
#####
# Actual command - for checks on non-windows systems
#####
pass1.is_check_action.!windows.!is_process_action.method_found::
pass1.is_check_action.!windows.!is_process_action.method_found.!(slackware.is_boot_action)::
"action_ok" expression => returnszero("${action_command} 2>&1 > /dev/null", "useshell");

any::
Expand All @@ -1125,13 +1169,13 @@ bundle agent ncf_services(service, action)
methods:

#####
# Actual command - for actions on non-windows systems, non using systemd
# Actual command - for actions on non-windows systems, non using systemd, non-slackware
#####
pass2.is_check_action.!windows.!is_process_action.method_found.action_ok::
pass2.is_check_action.!windows.!is_process_action.method_found.action_ok.!slackware::
"force_success_class" usebundle => _classes_success("${old_class_prefix}");
"force_success_class" usebundle => _classes_success("${class_prefix}");

pass2.is_check_action.!windows.!is_process_action.method_found.!action_ok::
pass2.is_check_action.!windows.!is_process_action.method_found.!action_ok.!slackware::
"force_failure_class" usebundle => _classes_failure("${old_class_prefix}");
"force_failure_class" usebundle => _classes_failure("${class_prefix}");

Expand All @@ -1151,7 +1195,9 @@ bundle agent ncf_services(service, action)
ifvarclass => "${old_class_prefix}_checked_ok";
"force_success_process" usebundle => _classes_success("${class_prefix}"),
ifvarclass => "${class_prefix}_checked_ok";

# Slackware boot actions
pass2.slackware.is_boot_action::
"action" usebundle => slackware_boot_services("${service}", "${action}", "${old_class_prefix}", "${class_prefix}");
processes:

###########################################################################
Expand Down Expand Up @@ -1199,7 +1245,7 @@ bundle agent ncf_services(service, action)
# because of a CFEngine bug (https://dev.cfengine.com/issues/5840) that causes systemctl
# to fail if it can't find /dev/tty, which is the case unless using no_output => true
# It also avoids reporting on command_execution for all platforms
pass2.!is_check_action.!windows.!is_process_action.method_found::
pass2.!is_check_action.!windows.!is_process_action.method_found.!(slackware.is_boot_action)::
"${action_command}"
contain => in_shell_and_silent,
classes => classes_generic_two("${old_class_prefix}", "${class_prefix}");
Expand Down Expand Up @@ -1251,10 +1297,8 @@ bundle edit_line ncf_remove_parameter_in_list(key, key_value_separator, paramete
replace_patterns:
"^(${escaped_key}\s*${key_value_separator}\s*${escaped_leading_char}.*)(${parameter_separator}+\s*${parameter_regex}|${parameter_regex}\s*${parameter_separator}+)(.*${escaped_closing_char})\s*$"
replace_with => value("${match.1}${match.3}");

}


body replace_with ncf_add_parameter_with_separator(parameter, parameter_separator) {
occurrences => "first";
replace_value => "${match.1}${match.2}${parameter_separator}${parameter}";
Expand All @@ -1265,3 +1309,75 @@ body replace_with ncf_add_parameter_with_separator_and_enclosing_characters(para
replace_value => "${match.1}${match.2}${match.3}${parameter_separator}${parameter}${match.4}";
}

bundle agent slackware_boot_services(service, action, old_class_prefix, class_prefix)
{
vars:
"canon_service" string => canonify("${service}");

classes:

"action_enable" expression => strcmp("enable", ${action});
"action_disable" expression => strcmp("disable", ${action});
"action_is_enabled" expression => strcmp("is-enabled", ${action});

methods:

action_disable::
"chmod 644" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "644", "${old_class_prefix}", "${class_prefix}");

action_enable::
"chmod 755" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "755", "${old_class_prefix}", "${class_prefix}");
"block in init scripts" usebundle => service_block_rc_d("${service}", "${old_class_prefix}", "${class_prefix}");

action_is_enabled::
"enable dry run" usebundle => push_dry_run_mode("true");
"chmod 755" usebundle => perm_on_file("/etc/rc.d/rc.${service}", "755", "${canon_service}_init_script_execmod", "${canon_service}_init_script_execmod");
"block in init scripts" usebundle => service_block_rc_d("${service}", "${old_class_prefix}", "${class_prefix}");
"ifnoexecmod, old" usebundle => _classes_copy("${canon_service}_init_script_execmod", "${old_class_prefix}"),
ifvarclass => "${canon_service}_init_script_execmod_not_ok";
"ifnoexecmod, new" usebundle => _classes_copy("${canon_service}_init_script_execmod", "${class_prefix}"),
ifvarclass => "${canon_service}_init_script_execmod_not_ok";
"disable dry run" usebundle => pop_dry_run_mode();
}

bundle agent perm_on_file(file, mod, old_class_prefix, class_prefix)
{
vars:
"canonfile" string => canonify("${file}");

files:
"${file}"
perms => m("${mod}"),
classes => classes_generic_two("${old_class_prefix}", "${class_prefix}");
}

bundle agent service_block_rc_d(service, old_class_prefix, new_class_prefix)
{
vars:
"canon_service" string => canonify("${service}");

files:
"/etc/rc.d/rc.local"
edit_line => edit_service_block_rc_d("${service}"),
classes => classes_generic("service_${canon_service}_block_in_rc_local");

"/etc/rc.d/rc.M"
edit_line => edit_service_block_rc_d("${service}"),
classes => classes_generic_two("${old_class_prefix}", "${class_prefix}"),
ifvarclass => "service_${canon_service}_block_in_rc_local_not_ok";

methods:
"old classes" usebundle => _classes_copy("service_${canon_service}_block_in_rc_local", "${old_class_prefix}"),
ifvarclass => "service_${canon_service}_block_in_rc_local_ok";
"new classes" usebundle => _classes_copy("service_${service}_block_in_rc_local", "${class_prefix}"),
ifvarclass => "service_${canon_service}_block_in_rc_local_ok";
}

bundle edit_line edit_service_block_rc_d(service)
{
insert_lines:
"if [ -x /etc/rc.d/rc.${service} ]; then
. /etc/rc.d/rc.${service} start
fi"
insert_type =>"preserve_block";
}
26 changes: 2 additions & 24 deletions tree/30_generic_methods/_classes_copy.cf
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,7 @@

bundle agent _classes_copy(source_prefix, destination_prefix)
{
vars:
"prefix" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout" };
"suffix" slist => { "repaired", "ok", "reached", "failed", "not_ok", "not_kept", "not_repaired", "denied", "timeout", "kept", "error" };

destination_exists::
# Copy result classes prefixes
"${prefix}_local_destination_prefix"
string => "${prefix}_${destination_prefix}",
ifvarclass => "${prefix}_${source_prefix}",
classes => always("${prefix}_${destination_prefix}");

# Copy result classes suffixes
"local_destination_prefix_${suffix}"
string => "${destination_prefix}_${suffix}",
ifvarclass => "${source_prefix}_${suffix}",
classes => always("${destination_prefix}_${suffix}");

classes:
# this line will not be evaluated by cfengine if destination_prefix contains a variable that does not exist
# and it will always be evaluated to true otherwise
"destination_defined" expression => strcmp("${destination_prefix}", "${destination_prefix}");
"destination_not_empty" not => strcmp("${destination_prefix}", "");
"destination_exists" and => { "destination_defined", "destination_not_empty" };

methods:
"copy" usebundle => ncf_classes_copy("${source_prefix}", "${destination_prefix}");
}

4 changes: 2 additions & 2 deletions tree/30_generic_methods/package_absent.cf
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
# @parameter_constraint version "allow_empty_string" : true
# @parameter architecture Architecture of the package, can be an architecture name or "default" (defaults to "default")
# @parameter_constraint architecture "allow_empty_string" : true
# @parameter provider Package provider to use, can be "yum", "apt", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter provider Package provider to use, can be "yum", "apt", "slackpkg", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter_constraint provider "allow_empty_string" : true
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "pkg" ]
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "slackpkg", "pkg" ]
#
# @class_prefix package_absent
# @class_parameter name
Expand Down
4 changes: 2 additions & 2 deletions tree/30_generic_methods/package_present.cf
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
# @parameter_constraint version "allow_empty_string" : true
# @parameter architecture Architecture of the package, can be an architecture name or "default" (defaults to "default")
# @parameter_constraint architecture "allow_empty_string" : true
# @parameter provider Package provider to use, can be "yum", "apt", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter provider Package provider to use, can be "yum", "apt", "slackpkg", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter_constraint provider "allow_empty_string" : true
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "pkg" ]
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "slackpkg", "pkg" ]
#
# @class_prefix package_present
# @class_parameter name
Expand Down
9 changes: 7 additions & 2 deletions tree/30_generic_methods/package_state.cf
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@
# *rpm* will be used for all local actions, and *zypper* is only needed to manage update and
# installation from a repository.
#
# ##### slackpkg
#
# This package provider uses Slackware's installpkg and upgradepkg tools to manage
# packages on the system
#
# ##### pkg
#
# This package provider uses FreeBSD's *pkg* to manage packages on the system.
Expand Down Expand Up @@ -110,9 +115,9 @@
# @parameter_constraint version "allow_empty_string" : true
# @parameter architecture Architecture of the package, can be an architecture name or "default" (defaults to "default")
# @parameter_constraint architecture "allow_empty_string" : true
# @parameter provider Package provider to use, can be "yum", "apt", "zypper", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter provider Package provider to use, can be "yum", "apt", "zypper", "slackpkg", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter_constraint provider "allow_empty_string" : true
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "pkg" ]
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "slackpkg", "pkg" ]
# @parameter state State of the package, can be "present" or "absent" (defaults to "present")
# @parameter_constraint state "allow_empty_string" : true
# @parameter_constraint state "select" : [ "", "present", "absent" ]
Expand Down
4 changes: 2 additions & 2 deletions tree/30_generic_methods/package_state_options.cf
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
# @parameter_constraint version "allow_empty_string" : true
# @parameter architecture Architecture of the package, can be an architecture name or "default" (defaults to "default")
# @parameter_constraint architecture "allow_empty_string" : true
# @parameter provider Package provider to use, can be "yum", "apt", "zypper", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter provider Package provider to use, can be "yum", "apt", "zypper", "slackpkg", "pkg" or "default" for system default package manager (defaults to "default")
# @parameter_constraint provider "allow_empty_string" : true
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "pkg" ]
# @parameter_constraint provider "select" : [ "", "default", "yum", "apt", "zypper", "slackpkg", "pkg" ]
# @parameter state State of the package, can be "present" or "absent" (defaults to "present")
# @parameter_constraint state "allow_empty_string" : true
# @parameter_constraint state "select" : [ "", "present", "absent" ]
Expand Down
16 changes: 11 additions & 5 deletions tree/30_generic_methods/service_check_started_at_boot.cf
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ bundle agent service_check_started_at_boot(service_name)
methods:
"check_enabled" usebundle => ncf_services("${service_name}", "is-enabled");

"class copy" usebundle => _classes_copy("ncf_services_${canonified_service_name}_is_enabled", "${old_class_prefix}"),
ifvarclass => "ncf_services_${canonified_service_name}_is_enabled_reached";
"new result classes" usebundle => _classes_copy("${class_prefix}_check_enabled", "${class_prefix}"),
ifvarclass => "${class_prefix}_check_enabled_reached";
"success" usebundle => _classes_success("${old_class_prefix}"),
ifvarclass => "ncf_services_${canonified_service_name}_is_enabled_ok";
"success" usebundle => _classes_success("${class_prefix}"),
ifvarclass => "${class_prefix}_check_enabled_ok";

"failure" usebundle => _classes_failure("${old_class_prefix}"),
ifvarclass => "ncf_services_${canonified_service_name}_is_enabled_not_ok";
"failure" usebundle => _classes_failure("${class_prefix}"),
ifvarclass => "${class_prefix}_check_enabled_not_ok";

"reports" usebundle => _log("Check if service ${service_name} is started at boot", "${old_class_prefix}", "${class_prefix}", @{args});

"reports" usebundle => _log("Check if service ${service_name} is started at boot", "${old_class_prefix}", "${class_prefix}", @{args});
}

0 comments on commit f63011b

Please sign in to comment.